Compare commits
2 Commits
3cd3195e3f
...
661f391582
| Author | SHA1 | Date |
|---|---|---|
|
|
661f391582 | |
|
|
2d1d89ecc7 |
39
Future.md
39
Future.md
|
|
@ -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 (C1–C4) + 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 C1–C4 + `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.
|
||||||
|
|
||||||
|
|
@ -177,9 +189,12 @@ no `auth.user().onDelete`). Deploy-day learnings + deferred items:
|
||||||
stray, then redeploy it. Diagnose with `firebase functions:list` — healthy Firestore triggers show
|
stray, then redeploy it. Diagnose with `firebase functions:list` — healthy Firestore triggers show
|
||||||
`google.cloud.firestore.document.v1.*`, strays show `https`. (First-ever gen-2 deploy also needs Eventarc
|
`google.cloud.firestore.document.v1.*`, strays show `https`. (First-ever gen-2 deploy also needs Eventarc
|
||||||
service-agent IAM to propagate — the "retry in a few minutes" failures were this.)
|
service-agent IAM to propagate — the "retry in a few minutes" failures were this.)
|
||||||
- **Node runtime bump — hard deadline 2026-10-30.** Node 20 was deprecated 2026-04-30 and is **decommissioned
|
- **✅ DONE (2026-07-08) — Node runtime bumped 20 → 22.** All 35 functions redeployed in-place on **nodejs22**
|
||||||
2026-10-30**, after which deploys fail. Bump `functions/package.json` `engines.node` to 22 (verify the gen-1
|
(incl. the gen-1 `onUserDelete` — accepted cleanly); both `backend-ci.yml` node pins bumped to match. Verified:
|
||||||
`onUserDelete` supports it), build, redeploy. Every deploy currently prints the warning.
|
`functions:list` runtime column, callable cold-boot smoke (UNAUTHENTICATED JSON = our code running), clean logs.
|
||||||
|
nodejs24 was evaluated and rejected: **2nd-gen only**, and the runtime is codebase-wide (gen-1 `onUserDelete`
|
||||||
|
blocks it). **Next forced bump:** Node 22 is deprecated 2027-04-30 / decommissioned 2027-10-31 — by then either
|
||||||
|
nodejs24 supports gen 1, or `onUserDelete` needs migrating off the gen-1 auth trigger first.
|
||||||
- **RevenueCat webhook re-enable (when billing is set up).** RevenueCat has no account yet, so the migrated v2
|
- **RevenueCat webhook re-enable (when billing is set up).** RevenueCat has no account yet, so the migrated v2
|
||||||
`revenueCatWebhook` is **not deployed** — its export is commented out in `functions/src/index.ts` because
|
`revenueCatWebhook` is **not deployed** — its export is commented out in `functions/src/index.ts` because
|
||||||
`defineSecret('REVENUECAT_SIGNING_KEY')` is validated codebase-wide at deploy (a missing secret fails *every*
|
`defineSecret('REVENUECAT_SIGNING_KEY')` is validated codebase-wide at deploy (a missing secret fails *every*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue