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>
Translate 24 previously missing strings for de, es, fr, ja, ko, pt-BR:
- CBT/ACT therapeutic step labels (Situation, Reframe, Defusion, etc.)
- Guided reflection info view content and disclaimer
- Temperature format string, Continue, Get Started
- Debug digest button description
676/676 strings now translated across all languages.
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>
Negative Q4 (Reframe): Moved cognitive reframes to top row (challenge
worst-case, separate facts from feelings, etc.) and demoted action
chips (take a walk, get rest) to expanded. Added two new reframe chips.
Positive Q2 (Awareness): Replaced single emotion words (Joy, Gratitude)
with moment-oriented suggestions (A conversation that made me smile,
Something I accomplished) to match "what moment stands out?" question.
Added translations for 14 new localization keys across all 7 languages.
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.
Enables parallel UI test execution via per-session data isolation:
- Each test class gets a unique session ID (UUID) for isolated UserDefaults
and in-memory SwiftData containers — no shared on-disk state
- Rewrote all 60+ UI test files following fail-fast TEST_RULES patterns
(2s default timeout, no sleep, no coordinate taps, no retry loops)
- Added missing accessibility IDs to MonthView, YearView, onboarding pages
- Added Next buttons to onboarding flow for reliable programmatic navigation
- Added ParallelUITests.xctestplan with class-level parallelism
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
- Added month_grid accessibility ID to MonthView ScrollView
- Added year_heatmap accessibility ID to YearView ScrollView
- Fixed DayScreen.assertVisible() to accept entry rows OR mood header
- Fixed DataPersistenceTests for in-memory storage (fixture re-seeds)
- Fixed AppLaunchTests to use week_of_moods fixture (empty has no grid)
- Fixed SettingsScreen segmented control tap with multi-strategy fallback
- Improved settings scroll with coordinate-based swipe for deep elements
- OnboardingScreen swipeToNext uses slow velocity for paged TabView
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>
Each test class now gets a unique session ID (UUID) passed to the app
via UI_TEST_SESSION_ID environment variable. The app uses this to:
- Route GroupUserDefaults to a session-specific UserDefaults suite,
preventing tests from clobbering each other's AppStorage state
- Create an in-memory SwiftData container instead of the shared
on-disk App Group store, eliminating SQLite contention
Refactored 8 test classes that bypassed BaseUITestCase.setUp() with
custom launch args — they now use overridable `localeArguments` and
`extraLaunchArguments` properties, keeping session ID injection
centralized. Added `relaunchApp(resetState:bypassSubscription:)` to
BaseUITestCase for tests that need mid-test relaunch with different
subscription state.
Includes a ParallelUITests.xctestplan with class-level parallelism
enabled and random execution ordering.
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>
All 86 guided reflection chip strings now have translations for all
6 supported languages alongside English.
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>
The new reflection section pushed the delete button below the fold
in the entry detail sheet, causing the tap to miss.
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>
- Disable captureElementInteractions (UIKit-only, duplicates manual events)
- Disable captureScreenViews (meaningless SwiftUI names, duplicates trackScreen())
- Opt out entirely in DEBUG builds to prevent test data polluting production
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set personProfiles to .always so PostHog creates anonymous person
profiles for every user, fixing inaccurate unique user counts in
dashboards without requiring identify() calls.
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>
Add "THE" translations for ja/ko in the subscription magazine header, and fix
broken string interpolation in BGTask error logging.
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>