Closer/Future.md

13 KiB
Raw Blame History

Future — ideas & improvements backlog

Non-blocking ideas: things that work today but could be better, plus feature ideas. Actual bugs (broken/incorrect behavior) live in ClaudeReport.md, not here.

UI

Themes

  • 🚨 P0 — Onboarding CRASHES on slide 3 (and on Skip) — blocks every first-run user from reaching login. Discovered 2026-06-28 on a fresh emulator-5558 install (Pixel 7 Pro, API 34, KVM hw accel). Slides 1 + 2 render fine; tapping Next on slide 2 → slide 3 → FATAL EXCEPTION: main → app dies back to the launcher. Tapping Skip (which jumps to a later slide) also crashes. Existing QA emulators (5554/5556) never hit this because they're past onboarding with logged-in users — this regression is invisible to recurring QA and hits every new install.

    Stack: java.lang.IllegalArgumentException: Only VectorDrawables and rasterized asset types are supported ex. PNG, JPG, WEBP at androidx.compose.ui.res.PainterResources_androidKt.loadVectorResource from app.closer.ui.onboarding.OnboardingScreenKt.CtaSlide(OnboardingScreen.kt:246).

    Root cause: line 246 calls painterResource(R.drawable.ic_launcher_background). The XML is a valid <vector> (108dp square with 4 gradient paths), but painterResource rejects it at runtime on API 34 — likely an aapt/adaptive-icon bundling quirk where the launcher-background resource resolves to something other than VectorDrawable/BitmapDrawable.

    Fix options (any one closes it): (a) swap to Image(painter = ImageVector.vectorResource(...)), (b) drop the decorative launcher icon entirely and use a solid Color/Brush matching the brand, (c) rasterize the background to a PNG and painterResource that, (d) use LocalContext.current.getDrawable(R.drawable.ic_launcher_background) wrapped in runCatching.

    Re-introduction risk / regression-prevention: add an onboarding route to qa/entrypoint_smoke.sh (the cold-start/launch-integrity smoke) so the am kill → notification path covers the entire onboarding flow, not just the post-login launch. Also consider a theme-scan.sh Tier 2 check: flag painterResource(R.drawable.ic_launcher_*) outside BrandIllustration / OnboardingScreen review.

    Verification before close: fresh AVD → install → tap Next through all onboarding slides + tap Skip from slide 1 → assert no FATAL, login screen reachable. Repeat on 5554 and 5556 (dark + light).

    Note (project convention): Future.md's header says actual bugs belong in ClaudeReport.md. Filing here per explicit user request 2026-06-28 — recommend also adding a O-ONBOARD-001 row to ClaudeReport.md with the same repro + fix options so it shows up in the recurring QA pass sweep. (The current working-tree ClaudeReport.md has uncommitted R17 edits — leaving it alone until the user commits/stashes.)

  • "Add to Bucket List" has mixed dark/light mode UI. The input field, button, and surrounding elements use light-mode colors even when the app is in dark mode. Needs theme alignment.

QA

Improvement & feature ideas surfaced while QA-testing as a consumer (each works today — none are defects).

  • Tier 3: Compose screenshot diff for visual regression. The static scanner in scripts/theme-scan.sh catches ~80% of light/dark theme mismatches, but it cannot detect compositional failures: a theme-token color used on the wrong surface, a gradient with hardcoded light stops, or subtle contrast collapse. Implement a screenshot pipeline with Roborazzi / Shot / papAROS that renders every AppRoute in both light and dark, pixel-diffs them, and fails on unexpected white backgrounds or invisible text. When done, run it in CI against every UI PR.

  • Instrumented / on-device test coverage (currently 0 androidTest). app/src/test has 19 solid unit tests (encryption, rate limiter, quiet hours, streak, entitlement, …) but app/src/androidTest is empty — there is no automated on-device net for UI behavior, navigation, or DB/DataStore integration; the live QA passes + scanners are the only thing catching that class. Add a small Compose UI / Espresso smoke (sign-in → pair → answer daily Q → open a game → send a message) wired into the per-round gate (alongside qa/entrypoint_smoke.sh), then grow it. Prompted by: the R-? QA-plan gap review — the playbook now runs ./gradlew testDebugUnitTest but has no instrumented suite to run.

  • DONE — Consistent brand glyphs across game cards + waiting surfaces. G-set + G2 (17 glyphs) in res/drawable-nodpi/glyph_*.xml; 13 wired + verified live: every Play-hub card (This or That, How Well, Desire Sync, Connection Challenges, Memory Lane, Date Match, Plan Date, Question Packs, Bucket List, Past Games — Spin the Wheel keeps its full illustration), WaitingForPartner per-game glyph, and Settings (Subscription/Security/Privacy/ Delete). 4 unused have no clean slot (notif uses ic_notification_closer; Today uses hero art; quiet-hours uses its illustration; no export-data row exists). Full map in ClaudeBrandingReview.md. (This-or-That backdrop redesign is Codex C-DARK-UI-001.)

  • Minor proactive-notification gaps (low priority). No push when a partner joins your active game (partner_joined_game) or ends/abandons one (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 — these speculative types aren't implemented.

  • 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.

Security hardening (defense-in-depth — not vulnerabilities; rules already hold)

  • Enforce App Check on Firestore (currently OFF). Round 7 raw-API test: an authenticated request with no App Check token (raw Firestore REST) returned 200 for a member — so rules are the sole gate. Rules correctly deny non-members/cross-couple (all 403), so this is not a live hole, but enabling App Check enforcement on Firestore would block non-app clients entirely (defense-in-depth). Prompted by: R7 D3 raw-API angle.
  • Biometric app-lock re-locks on cold-start/process-death but maybe not plain background→resume. R15 code review: MainActivity gates AppNavigation behind BiometricLockScreen when biometricLoginEnabled and sessionVerified is false; sessionVerified is a remember{} that resets on Activity recreation (cold-start, process death) — so the lock re-arms there — but a plain background→foreground without recreation keeps sessionVerified = true, so it may not re-prompt. Architecturally sound (no compose-tree bypass; content isn't composed until unlocked), but consider re-locking on ON_STOP/timeout so a picked-up unlocked phone re-prompts. Prompted by: R15 Pass M code audit (not live-tested — emulator has no enrolled biometric).

Artwork to generate (ChatGPT prompts, house-style-matched) lives in ClaudeBrandingReview.md, not here.

Roadmap — features & strategy (consolidated from the old FUTURE.md, 2026-06-28)

Unbuilt games (Play Hub is live; these remain):

  • Would You Rather / Truth or Dare — tiered sweet→spicy, consent-gated; reuses the deck + match engine. Strong premium "spicy" tier lever.
  • Daily Sync / Rose-Bud-Thorn — one-tap emotional check-in, see partner's; small/new, free retention driver.

"2026, not 2019" differentiators (strategic):

  • AI-personalized prompts — server-side (latest Claude) generate/weight prompts from the couple's history/season/unexplored topics; add a generatePrompts callable (Cloud Functions already in place). Biggest modern lever; pairs with content-metadata routing below.
  • Async + real-time hybrid — partner-presence ("they're here now") for live co-play, everything still async-friendly (long-distance).
  • Multi-modal answers — voice/photo answers (esp. Memory Lane + daily check-ins).
  • Home/lock-screen widgets / live updates — glanceable today's-prompt + partner status (Glance/Wear surface).
  • Gentle gamification — forgiving "gentle streaks" (grace days) + shared wins, not loss-aversion/guilt.
  • Consent-first spicy content — Intimacy/Dare tiers opt-in, double-confirmed, reveal-only-on-overlap.

Cross-platform: Android-first is fine for MVP; iOS is the strategic gap (couples split devices). Decision + plan live in ClaudeiOSPlan.md — don't start before release/trust polish.

Product polish (consolidated from the old FUTURE.md)

  • Skeleton/loading states over bare spinners (P8). LoadingState exists but many screens still use a bare CircularProgressIndicator. Add skeletons for question lists, game histories, home modules, paywall offerings, sync/reveal waits. Acceptance: no primary route shows an isolated spinner on an otherwise blank screen.
  • Paywall / store value framing (P12). Paywall has benefits/restore/legal/RevenueCat; needs stronger value framing, real offering/trial clarity, screenshots/previews, and test coverage before release. (Overlaps Pass K/O.)
  • Content metadata & personalization (P13). The bank is clean; the next leap is routing, not more questions — tag mood/depth/relationship-stage/conflict-safe/intimacy-level/time-needed and extend the selection APIs so prompts adapt to skipped topics, relationship length, and recent answers.

Release / pre-ship (consolidated + re-verified 2026-06-28)

  • Real release config before any store submission. Confirmed still open: app/build.gradle.kts versionCode = 1 / versionName = "0.1.0" and core/navigation/ExternalLinks.kt legal URLs are placeholder TODOs (https://closer.app/privacy|terms|subscription-terms). Already done: a release-blocking Gradle check now fails the build if RC_API_KEY is unset/placeholder (build.gradle.kts:106110), so the old "add a gradle guard" sub-item is closed. Remaining: set real version, real legal/support URLs, real RC key + verify offerings/purchase/restore on internal testing. (Tracked by Pass O release-readiness.)

Help & support surface (consolidated — old "Notes to Consider")

A future Help/Support screen could include: contact support · report a bug · send feedback · FAQ · subscription/billing help · pairing help · recovery-phrase/account help · app version + build number · optional "copy diagnostics" button.