Adds a 5-step negative-mood reflection flow with an evidence-examination
step, Socratic templated questions that back-reference prior answers, and
a deterministic cognitive-distortion detector that routes the perspective-
check prompt to a distortion-specific reframe. Includes CBT plan docs,
flowchart, stats research notes, and MCP config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set all three loading states to .loading upfront before entering the
task group, and remove .idle from the modal visibility condition. This
prevents the overlay from staying visible when tasks complete at
different rates while others remain in .idle state.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show specific guidance when Apple Intelligence is unavailable:
- Device not eligible: "iPhone 15 Pro or later required"
- Not enabled: step-by-step path + "Open Settings" button
- Model downloading: "Please wait" + "Try Again" button
- Pre-iOS 26: "Update required"
Auto re-checks availability when app returns to foreground so enabling
Apple Intelligence in Settings immediately triggers insight generation.
Adds translations for all new AI strings across de, es, fr, ja, ko, pt-BR.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Speed optimizations:
- Add session.prewarm() in InsightsViewModel and ReportsViewModel init
for 40% faster first-token latency
- Cap maximumResponseTokens on all 8 AI respond() calls (100-600 per use case)
- Add prompt brevity constraints ("1-2 sentences", "2 sentences")
- Reduce report batch concurrency from 4 to 2 to prevent device contention
- Pre-fetch health data once and share across all 3 insight periods
Richer insight data in MoodDataSummarizer:
- Tag-mood correlations: overall frequency + good day vs bad day tag breakdown
- Weather-mood correlations: avg mood by condition and temperature range
- Absence pattern detection: logging gap count with pre/post-gap mood averages
- Entry source breakdown: % of entries from App, Widget, Watch, Siri, etc.
- Update insight prompt to leverage tags, weather, and gap data when available
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove #if DEBUG from all debug settings, exporters, and IAP bypass so
debug options are available in TestFlight builds
- Weekly digest card: replace dismiss X with collapsible chevron caret
- Weekly digest: generate on-demand when opening Insights tab if no cached
digest exists (BGTask + notification kept as bonus path)
- Fix digest intention text color (was .secondary, now uses theme textColor)
- Add "Generate Weekly Digest" debug button in Settings
- Add generating overlay on Insights tab with pulsing sparkles icon that
stays visible until all sections finish loading (content at 0.2 opacity)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three new Foundation Models features to deepen user engagement with mental wellness:
1. AI Reflection Companion — personalized feedback after completing guided reflections,
referencing the user's actual words with personality-pack-adapted tone
2. Mood Pattern Tags — auto-extracts theme tags (work, family, stress, etc.) from notes
and reflections, displayed as colored pills on entries
3. Weekly Emotional Digest — BGTask-scheduled Sunday digest with headline, summary,
highlight, and intention; shown as card in Insights tab with notification
All features: on-device (zero cost), premium-gated, iOS 26+ with graceful degradation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap 30+ production print() statements in #if DEBUG guards across 18 files
- Add VoiceOver labels, hints, and traits to Watch app, Live Activities, widgets
- Add .accessibilityAddTraits(.isButton) to 15+ onTapGesture views
- Add text alternatives for color-only indicators (progress dots, mood circles)
- Localize raw string literals in NoteEditorView, EntryDetailView, widgets
- Replace 25+ silent try? with do/catch + AppLogger error logging
- Replace hardcoded font sizes with semantic Dynamic Type fonts
- Fix FIXME in IconPickerView (log icon change errors)
- Extract magic animation delays to named constants across 8 files
- Add widget empty state "Log your first mood!" messaging
- Hide decorative images from VoiceOver, add labels to ColorPickers
- Remove stale TODO in Color+Codable (alpha change deferred for migration)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The parent container's .accessibilityElement(children: .contain) and
.accessibilityLabel were collapsing individual mood buttons into a single
group, making them invisible to accessibility tools like AXe and VoiceOver.
Fix: Add .accessibilityElement(children: .ignore) and .accessibilityAddTraits
(.isButton) to each individual mood button, and remove the group-level
accessibility modifiers. Applied to all 6 voting layouts (Horizontal, Card,
Stacked, Aura, Orbit, Neon).
Exhaustive file-by-file audit of every Swift file in the project (iOS app,
Watch app, Widget extension). Every interactive UI element — buttons, toggles,
pickers, links, menus, tap gestures, text editors, color pickers, photo
pickers — now has an accessibilityIdentifier for XCUITest automation.
46 files changed across Shared/, Onboarding/, Watch App/, and Widget targets.
Added ~100 new ID definitions covering settings debug controls, export/photo
views, sharing templates, customization subviews, onboarding flows, tip
modals, widget voting buttons, and watch mood buttons.
App-side changes:
- Added "Get Started" / "Continue" next buttons to all onboarding pages
(Welcome, Day, Time, Style) with onboarding_next_button accessibility ID
- Added onNext callback plumbing from OnboardingMain to each page
- OnboardingMain now uses TabView(selection:) for programmatic page navigation
- Added .accessibilityElement(children: .contain) to all onboarding pages
to fix iOS 26 paged TabView not exposing child elements
- Added settings_segmented_picker accessibility ID to Settings Picker
- Reduced padding on onboarding pages to keep buttons in visible area
Test-side changes:
- OnboardingScreen: replaced unreliable swipeToNext() with tapNext()
that taps the accessibility-identified next button
- OnboardingScreen: multi-strategy skip button detection for subscription page
- SettingsScreen: scoped segment tap to picker element to avoid tab bar collision
- CustomizeScreen: simplified horizontal scroll to plain app.swipeLeft()
- OnboardingVotingTests: uses tapNext() to advance to Day page
Passing: OnboardingTests.CompleteFlow, OnboardingVotingTests
Remaining: OnboardingTests.DoesNotRepeat (session state issue),
Settings scroll (deep elements), Customize horizontal pickers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrote 60+ test files to follow honeydue-style test guidelines:
- defaultTimeout=2s, navigationTimeout=5s — fail fast, no long waits
- No coordinate taps (except onboarding paged TabView swipes)
- No sleep(), no retry loops
- No guard...else { return } silent passes — XCTFail everywhere
- All elements by accessibility ID via UITestID constants
- Screen objects for all navigation/actions/assertions
- One logical assertion per test method
Added missing accessibility identifiers to app views:
- MonthView.swift: added AccessibilityID.MonthView.grid to ScrollView
- YearView.swift: added AccessibilityID.YearView.heatmap to ScrollView
Framework rewrites:
- BaseUITestCase: added session ID, localeArguments, extraLaunchArguments
- WaitHelpers: waitForExistenceOrFail, waitUntilHittableOrFail,
waitForNonExistence, scrollIntoView, forceTap
- All 7 screen objects rewritten with fail-fast semantics
- TEST_RULES.md added with non-negotiable rules
Known remaining issues:
- OnboardingTests: paged TabView swipes unreliable on iOS 26 simulator
- SettingsLegalLinksTests: EULA/Privacy buttons too deep in DEBUG scroll
- Customization horizontal picker scrolling needs further tuning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove Back/Next/Done buttons from keyboard toolbar to eliminate
confusion with the bottom action bar. Toolbar now shows only a
keyboard.chevron.compact.down dismiss icon.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Users without Apple Intelligence can now export their mood data as a
visual PDF with charts and statistics instead of seeing a disabled
Generate button. The existing ExportService.exportPDF is reused for
the non-AI path, gated behind the same privacy confirmation dialog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Display weather inline next to the date in a compact HStack layout
(icon | condition + temps) instead of a separate Weather section.
Removes the standalone weatherSection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace generic journaling prompts with evidence-based therapeutic
techniques: CBT thought record for negative moods, ACT cognitive
defusion for neutral, and behavioral activation for positive. Each
question now shows a clinical step label (e.g. SITUATION, REFRAME).
Added info button linking to a new sheet explaining the techniques
with citations to Beck, Harris, and Martell/Dimidjian.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add force parameter to checkSubscriptionStatus to bypass 5-minute
throttle when called from transaction listener, purchase completion,
and restore purchases
- Remove early return for expired/revoked states that prevented
fallback to trial
- Only trust cached subscription expiration when offline (products
failed to load); when StoreKit returns products successfully, treat
the live entitlement check as authoritative
- Add debug logging throughout IAP state machine for diagnostics
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Populate debug test data with random notes, guided reflections, and weather
- Fix PDF export to use UIPrintPageRenderer for proper multi-page pagination
- Add journal/reflection indicator icons to day list entry cells
- Fix weather card icon contrast by using secondarySystemBackground
- Align Generate Report and Export PDF button widths in ReportsView
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add authorization pre-check and 15s timeout to LocationManager to
prevent hanging continuations. WeatherManager now skips retry queue
when location permission is denied. Settings weather toggle shows
alert directing users to Settings when location is denied. Fill
remaining 32 untranslated strings to reach 100% localization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Walks users through 3-4 guided questions based on mood category:
positive (great/good) gets gratitude-oriented questions, neutral
(average) gets exploratory questions, and negative (bad/horrible)
gets empathetic questions. Stored as JSON in MoodEntryModel,
integrated into PDF reports, AI summaries, and CSV export.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a Reports tab to the Insights view with date range selection, two report
types (Quick Summary / Detailed), Foundation Models AI generation with batched
concurrent processing, and clinical PDF export via WKWebView HTML rendering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fetch and display weather data (temp, condition, hi/lo, humidity) when
users log a mood. Weather is stored as JSON on MoodEntryModel and shown
as a card in EntryDetailView. Premium-gated with location permission
prompt. Includes BGTask retry for failed fetches and full analytics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite all 10 celebration haptic patterns to match visual timing and
feel distinct: confetti gets playful falling taps, explosion gets a deep
boom, shatter gets glassy cracks, morph gets liquid breathing, etc.
Play the matching haptic when selecting a new vote animation in
customization (respects haptic feedback toggle).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace non-existent "tunnel.circle" SF Symbol with "circle.dashed" for
the tunnel vote animation. Add missing translations for haptic feedback
strings and "Close" across all 6 languages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace HStack layout with LazyVGrid for uniform card sizing, remove
lineLimit(1) to allow multiline subtitles, and add 1:1 aspect ratio
so all four feature cards are identical squares across all 12 themes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The .containerRelativeFrame(.horizontal) on the marketing content
caused an infinite layout loop inside SubscriptionStoreView's scroll
container. Replaced with .frame(maxWidth: .infinity).
Also fixes leading space in StoreKit config display name, adds
debug logging to product loading, and reverts to groupID initializer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch from groupID to productIDs for more reliable product loading
- Add dismiss button overlay so users aren't trapped if products fail to load
- Make productIdentifiers static for shared access
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove all fatalError/force unwrap/force cast crash points from production
paths (ShowBasedOnVoteLogics, Random, ReflectApp, NoteEditorView). Fix
actor-isolation warnings by wrapping off-main-thread AnalyticsManager calls
in Task { @MainActor in } (LocalNotification) and replacing DispatchQueue
with Task.detached + MainActor.run (LiveActivityPreviewView). Update legal
URLs from feels.88oakapps.com to reflect.88oakapps.com in SettingsView.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace random animation selection with a user-configurable picker on
the Customize tab between Mood Style and Notifications. Confetti is
the default. Selecting a style shows an inline preview that auto-plays
the animation then dismisses itself. Remove Animation Lab from Settings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add containerRelativeFrame to paywall marketing content so feature cards
fit within screen width on iOS 18. Update onboarding tip text and all
localizations (DE, ES, FR, JA, KO, PT-BR).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Broadens installable audience to iOS 18+ while keeping AI insights available on iOS 26.
Foundation Models types and service wrapped in @available(iOS 26, *), InsightsViewModel
conditionally instantiates the service with fallback UI on older versions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Animation Lab moved out of #if DEBUG so it's available in release builds
- Add Test Data moved into #if DEBUG debug section
- Removed #if DEBUG wrapper from DebugAnimationSettingsView.swift
- Added 58 missing translations across all 6 languages (de, es, fr, ja, ko, pt-BR)
- Localization coverage restored from 87% to 100% (473/473 keys)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- TC-148: Year View heatmap grid renders with data (added accessibility ID)
- TC-143: App navigable with Reduce Motion enabled
- TC-144: App navigable with High Contrast mode enabled
- Marked 89 blocked tests RED in QA spreadsheet
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ZStack-with-gradient patterns with idiomatic .background() modifier
across onboarding, customize, and settings views. Add accessibility identifiers
to Year View charts for UI test automation. Mark 67 impossible-to-automate
tests RED in QA plan and scaffold initial Year View and Settings onboarding tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Revert key-by-key UserDefaults iteration that removed system keys
causing kAXErrorServerNotFound crashes; restore removePersistentDomain
with explicit subscription key clearing
- Add .accessibilityElement(children: .contain) to UpgradeBannerView
so subscribe button is discoverable by XCUITest
- Fix AllDayViewStylesTests to use coordinate-based tapping instead of
button.isHittable/button.tap() for iOS 26 Liquid Glass compatibility
- Improve OnboardingTests with multiple swipe retries and label-based
fallback for skip button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- resetAppState: use correct suite name to clear group defaults (fixes stale subscription state)
- Reorder configureIfNeeded: set expireTrial before IAPManager init
- Add browse_themes_button identifier to CustomizeView Browse Themes button
- Add mood_button_* identifiers to Entry Detail mood grid in NoteEditorView
- Use coordinate-based tap throughout all test screens (iOS 26 Liquid Glass hittability)
- Fix HeaderMoodLogging date format: M/d/yyyy → yyyy/MM/dd to match entry_row identifiers
- AppLaunchTests: wait for isSelected state with NSPredicate instead of immediate check
- OnboardingTests: add waits between swipes and retry logic for skip button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
App fixes:
- Remove empty_state identifier from EmptyHomeView VStack (was overriding mood_header)
- Fix resetAppState to set needsOnboarding=true (fresh state) instead of false
- Set bypassSubscription explicitly based on launch arg presence (was defaulting to true in DEBUG)
Test fixes:
- TabBarScreen: use coordinate tap to avoid iOS 26 Liquid Glass hittability issues
- SettingsScreen: use coordinate tap for segments, handle Settings label ambiguity with tab bar
- EntryDetailScreen: use mood_button_ identifiers instead of label matching (was matching entry rows)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>