docs: reconcile Future.md against R30 + the 2026-07-08 functions v2 deploy

The R29 games-review section had drifted — most of it shipped in R30 (batches C1–C4) and
went live with today's deploy. Reconciled against the git record, not memory:

- Shipped block added: server daily-question pool seeded + server-authoritative/mode-aware/
  deterministic selection (f2321d35, kills DQ-MISMATCH + cross-timezone splits); banner
  lifecycle BANNER-LIFE-001 (C1); retention set — HowWell role-swap rematch, NextBeatCard
  return-tomorrow beat, DS seen-question memory, deterministic Date Match shuffle +
  skip-swiped, daily_fun_mc excluded from HowWell pool, Challenges day-N+1 teaser (C2).
- Still-open list trimmed to what's genuinely open: the game-engine/replay/composable
  dedup refactors, premium-check helper, GameConstants, DispatcherProvider, error-surfacing,
  retention analytics events (the one unbuilt retention piece), the daily_fun_mc sex retag
  (now DS-only hygiene post-C3), npm audit (firebase-admin transitives).
- partner_joined_game push: "pending deploy" → BUILT + LIVE (2026-07-08); noted the
  abandoned-session false-finish guard that shipped in the same deploy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
null 2026-07-08 03:53:13 -05:00
parent 2d1d89ecc7
commit 661f391582
1 changed files with 21 additions and 9 deletions

View File

@ -83,8 +83,19 @@ tokens R16, add-FAB `Color(0xFFB98AF4)`→`primary` R18.)_
## QA ## QA
### From R29 games review (2026-07-07) ### From R29 games review (2026-07-07) — reconciled 2026-07-08 after R30 (C1C4) + the functions v2 deploy
- **Seed the server daily-question pool**`assignDailyQuestion` still assigns the `q_default_daily` rollout fallback for every couple (Firestore `questions` empty), so clients always use the local fallback. Seed real ids (synced with the asset DB) so the assignment actually pins the couple's question. (Client-side premium-independence fix landed in R29; this is the durable half.)
**✅ Shipped since filed (R30 batches C1C4 + `f2321d35`; server-side pieces live as of the 2026-07-08 deploy):**
server daily-question pool **seeded** and selection made **server-authoritative, mode-aware, deterministic**
(mirrors the client's `DailyModeResolver` weekday modes + epochDay offset — kills the DQ-MISMATCH class and
cross-timezone partner splits at the root) · **banner lifecycle BANNER-LIFE-001** (entering a session consumes
its banner via `GamePromptController.consumeForSession`; stale banners replaceable — C1) · **retention set:**
HowWell role-swap rematch CTA ("Your turn — let {name} guess you") · `NextBeatCard` return-tomorrow beat under
every game's results · Desire Sync per-couple seen-question memory (`SeenDesireQuestionStore`) · deterministic
per-couple Date Match deck shuffle + skip-already-swiped · `daily_fun_mc` excluded from the HowWell prediction
pool · Challenges "Day N unlocks tomorrow 🌙" teaser instead of spoiling day-N+1 (C2 `statusDay`).
Still open:
- **Generic session-game engine** — ThisOrThat/HowWell/DesireSync embedded VMs are ~80% clones of one ~250-line state machine (load/create/join/submit/retry/observe/abandon) and their data sources are structural copies (`EncryptedAnswerMapDataSource<T>`). Migrate one game first (ToT), full live regression, then the rest. - **Generic session-game engine** — ThisOrThat/HowWell/DesireSync embedded VMs are ~80% clones of one ~250-line state machine (load/create/join/submit/retry/observe/abandon) and their data sources are structural copies (`EncryptedAnswerMapDataSource<T>`). Migrate one game first (ToT), full live regression, then the rest.
- **Generic replay VM/screen** — 3× ~60-line clones (ToT/DS/HW replay). - **Generic replay VM/screen** — 3× ~60-line clones (ToT/DS/HW replay).
- **Shared waiting/length-picker/error composables** — each game re-implements WaitingForPartner/length chips/error screens despite shared components existing. - **Shared waiting/length-picker/error composables** — each game re-implements WaitingForPartner/length chips/error screens despite shared components existing.
@ -92,10 +103,9 @@ tokens R16, add-FAB `Color(0xFFB98AF4)`→`primary` R18.)_
- **GameConstants** — divergent ADVANCE_DELAY_MS (420 vs 380), QUESTION_COUNT, SPIN_DURATION_MS per file; follow SessionLength's pattern. - **GameConstants** — divergent ADVANCE_DELAY_MS (420 vs 380), QUESTION_COUNT, SPIN_DURATION_MS per file; follow SessionLength's pattern.
- **DispatcherProvider injection** — Dispatchers.IO/Default hardcoded everywhere (testability). - **DispatcherProvider injection** — Dispatchers.IO/Default hardcoded everywhere (testability).
- **Error-surfacing standardization** — BucketList/MessagesInbox/PlayHub/AnswerHistory/WeeklyRecap/Onboarding VMs swallow load errors (blank screens); adopt uiState.error + ErrorState for reads, _events snackbar for writes (ConversationViewModel pattern). - **Error-surfacing standardization** — BucketList/MessagesInbox/PlayHub/AnswerHistory/WeeklyRecap/Onboarding VMs swallow load errors (blank screens); adopt uiState.error + ErrorState for reads, _events snackbar for writes (ConversationViewModel pattern).
- **Retention (from ClaudeGamesReview.md):** HowWell role-swap rematch CTA · return-tomorrow beat on all results screens · per-couple seen-question memory for DS (102-item pool) + shuffle Date Match deck (deterministic first card for every couple) · exclude daily_fun_mc from HowWell prediction pool · hide Challenges day-N+1 prompt until its day · analytics: first-answer/reveal-viewed/waiting-abandoned/notif-tap events. - **Retention analytics** — first-answer / reveal-viewed / waiting-abandoned / notif-tap events: the one piece of the R29 retention list not built.
- **Content retag**`daily_fun_mc` rows carry `sex='neutral'` (benign today only via the binary filter; retag to keep Desire Sync's pool clean). 48/150 sexual_preferences items are non-binary configs (Wheel-only) — intended? - **Content retag**`daily_fun_mc` rows still carry `sex='neutral'` in the asset DB; after C3's HowWell-side exclusion this is purely Desire Sync pool hygiene (benign today via the binary filter). 48/150 sexual_preferences items are non-binary configs (Wheel-only) — intended?
- **npm audit** — 9 moderate remain after the 2026-07-08 firebase-functions v7 bump (retry-request/teeny-request via @google-cloud/storage, i.e. **firebase-admin** transitive — untouched by the functions bump); revisit on the next firebase-admin major. - **npm audit** — 9 moderate remain after the 2026-07-08 firebase-functions v7 bump (retry-request/teeny-request via @google-cloud/storage, i.e. **firebase-admin** transitive — untouched by the functions bump); revisit on the next firebase-admin major.
- **Banner lifecycle** — GamePromptController results banner should dismiss once results are viewed (BANNER-LIFE-001).
Improvement & feature ideas surfaced while QA-testing as a consumer (each works today — none are defects). Improvement & feature ideas surfaced while QA-testing as a consumer (each works today — none are defects).
@ -129,10 +139,12 @@ Improvement & feature ideas surfaced while QA-testing as a consumer (each works
Codex C-DARK-UI-001.)_ Codex C-DARK-UI-001.)_
- **Minor proactive-notification gaps (low priority).** ~~No push when a partner *joins* your active game - **Minor proactive-notification gaps (low priority).** ~~No push when a partner *joins* your active game
(`partner_joined_game`)~~ → **BUILT (2026-06-28, pending deploy):** the non-starter opening an active session (`partner_joined_game`)~~ → **BUILT + LIVE (deployed 2026-07-08 with the functions v2 round):** the non-starter
writes `joinedByUsers` (rule-gated), `onGameSessionUpdate` notifies the starter "<Name> joined your game" with the opening an active session writes `joinedByUsers` (rule-gated), `onGameSessionUpdate` notifies the starter
joiner's avatar (one-time `joinNotifiedAt`); foreground shows the standardized in-app banner. **Still open:** no push "<Name> joined your game" with the joiner's avatar (one-time `joinNotifiedAt`); foreground shows the standardized
when a partner *ends/abandons* a game (`game_ended`/`game_abandoned`) — the other partner sees it in-session / in-app banner. (Same deploy also stopped the false "X finished — see your results!" push for abandoned/quit
sessions — a real completion requires both uids in `completedByUsers`.) **Still open:** no push when a partner
*ends/abandons* a game (`game_ended`/`game_abandoned`) — the other partner sees it in-session /
on WaitingForPartner, so nothing's broken, just less proactive. *Prompted by:* Pass E (R8) inventory. on WaitingForPartner, so nothing's broken, just less proactive. *Prompted by:* Pass E (R8) inventory.
- **Clarify Connection Challenges day-progress when partners are out of step.** If one partner catches up a *missed* day ("Pick it back up") while the other doesn't, the two devices show different **"Day N of 7"** (seen R10: QA Day 4 vs Sam Day 3) even though the 🔥 streak stays in sync on both. Not broken (plausibly individual-pace-through-the-series by design), but two people in the same shared challenge seeing different day numbers is confusing — consider a shared "you're on Day N together" framing or a clearer caught-up/ahead indicator. *Prompted by:* Pass B (R10) Connection Challenges playthrough. - **Clarify Connection Challenges day-progress when partners are out of step.** If one partner catches up a *missed* day ("Pick it back up") while the other doesn't, the two devices show different **"Day N of 7"** (seen R10: QA Day 4 vs Sam Day 3) even though the 🔥 streak stays in sync on both. Not broken (plausibly individual-pace-through-the-series by design), but two people in the same shared challenge seeing different day numbers is confusing — consider a shared "you're on Day N together" framing or a clearer caught-up/ahead indicator. *Prompted by:* Pass B (R10) Connection Challenges playthrough.