- Add EncryptionVersion.kt with constants PLAINTEXT(0), MIGRATING(1), STRICT(2)
- Route CoupleEncryptionManager through the new constants and add explicit v2 branch
- Comment acceptInviteCallable.ts:91 explaining the version and sync contract
- Add TODO in iOS FirestoreService.swift warning that iOS MVP creates v0 couples
Fixes Risk #2 from review.md.
- Replace TODO placeholders with real data source calls
- Add hasWaitingGame, hasActiveChallenge, hasUpcomingDatePlan, hasUnlockedCapsule, weeklyRecapReady
- Parallel async fetches in loadHome(), failures default to false
- FirestoreCapsuleDataSource.getCapsules() for capsule status checks
- PartnerNotificationManagerTest: notification creation, type mapping, deep links
- build.gradle.kts: enable Robolectric and default return values for unit tests
- AppRoute: fix NPE in asRouteArg when android.net.Uri is stubbed on test classpath
- ChallengeState data model with 6 states: not started, started, waiting, both complete, missed, complete
- ChallengeStateMachine: pure Kotlin, configurable missed-day behavior
- 12 unit tests covering all states and edge cases
- Fix pre-existing missing import in AnswerRevealViewModel
- PendingActionCard data class with priority-ordered cards
- 6 card types: reveal ready, partner answered, game, challenge, date, capsule
- Max 3 cards, highest priority first, deep link to correct screen
- Placeholder guards for game/challenge/date/capsule (wired in later batches)
- Compact cards with purple/pink palette, no private text leaked
- Streak data models: Couple, Personal, WeeklyRhythm streaks
- StreakCalculator: pure Kotlin, no Android deps, deterministic
- Milestone copy at 1/3/7/14/30 days
- Streak repair: 1 missed day per 7-day window, requires both partners
- 23 unit tests covering all streak types, milestones, repair, timezone
- Add DailyQuestionState enum to HomeViewModel with 5 states
- Real-time Firestore listener for partner's daily answer
- Home card shows correct copy/CTA per state
- CTAs: answer, gentle reminder (no-op), reveal, follow-up (placeholder)
- Cleanup listener on onCleared()
- New SecurePreferencesFactory handles EncryptedSharedPreferences creation
- Auto-resets and recreates on corruption (unreadable prefs)
- CoupleKeyStore and SharedPreferencesLocalAnswerRepository use the factory
- Removes duplicated EncryptedSharedPreferences boilerplate
- Replace android.util.Base64 with java.util.Base64 in RecoveryKeyManager
- Crypto layer now has zero Android SDK dependencies — portable to iOS/shared testing
- Replace SimpleDateFormat/Calendar UTC date key with java.time LocalDate in device timezone
- FirestoreAnswerDataSource: todayLocalDateString() with injectable Clock, localDateString() helper
- DailyQuestionViewModel: pass date through submit flow so sync uses same date key
- AnswerRevealViewModel: use todayLocalDateString() for partner answer lookup
- Add FirestoreAnswerDataSourceTest: verifies timezone-aware date boundaries (Chicago vs Tokyo, LA vs London)
- Replace smart quotes, em dash, prime, right arrow in comments with ASCII equivalents
- Affected: CoupleEncryptionManager.kt, FieldEncryptor.kt, RecoveryKeyManager.kt
- Add to CloserBrandCopy: 'Not even Closer can read your answers.', 'End to end encrypted private responses.', 'Built for trust, not tracking.'
- Update visual-identity.md: add new slogans to approved rotation, remove migration gating note (all legacy couples migrated)