Files
rely/docs/progress.md
T
2026-02-22 23:53:22 +01:00

52 KiB
Raw Blame History

Relationship Saver Progress Log

Updated: 2026-02-22

Collaboration Rule (Carry Forward)

  • After every sensible code/documentation change set, create a git commit as the last step so the next agent session can pick up from clean checkpoints.

Latest Milestone (2026-02-22): Quick-Capture Dialog Controller Lifecycle Fix

Fixed a runtime crash when creating captures/notes from profile-context quick actions (TextEditingController was used after being disposed) caused by a dialog animation/disposal race.

  • Root cause

    • quick-capture dialogs in People and graph Person Insights created a local TextEditingController, passed it into showDialog(...), then disposed it immediately after await showDialog(...)
    • the dialog route can still rebuild during dismiss animation, which caused the TextField to touch a disposed controller
  • Fixes

    • lib/features/people/people_view.dart
      • replaced ad-hoc quick text capture dialog with stateful _QuickTextCaptureDialog that owns and disposes its controller internally
    • lib/features/dashboard/dashboard_view.dart
      • replaced ad-hoc quick text capture dialog with stateful _InsightQuickTextCaptureDialog with the same lifecycle fix
    • both dialogs now also show inline Required validation instead of silent no-op when pressing save with empty text
  • Similar issue scan

    • searched the codebase for the same anti-pattern (local TextEditingController created outside dialog widget and disposed after showDialog)
    • no remaining occurrences found after patching these two flows
  • Validation

    • flutter analyze -> pass
    • flutter test -> pass

Latest Milestone (2026-02-22): Preference Review UI (People + Graph Insights)

Exposed the new chat-derived preference signals in the main person detail surfaces and added a user review loop to confirm or dismiss inferred context.

  • lib/features/people/people_view.dart

    • added Chat-derived preferences section to the People detail workspace
    • shows inferred/confirmed/dismissed signals sorted by status/confidence
    • per-signal actions:
      • Why? (evidence preview bottom sheet)
      • Confirm
      • Dismiss
    • evidence preview includes:
      • signal metadata (category/polarity/confidence)
      • evidence snippets extracted from shared chat messages
      • source app list
    • added explicit Close action in evidence sheet (better UX + testability)
  • lib/features/dashboard/dashboard_view.dart

    • added matching Chat-derived preferences section to graph long-press Person Insights page
    • same confirm/dismiss/why review flow and evidence preview
    • keeps profile review experience aligned between People page and graph flow
  • test/features/dashboard/dashboard_graph_interactions_test.dart

    • extended graph interaction test to:
      • seed an inferred preference signal
      • assert section renders in Person Insights
      • open Why? evidence preview
      • confirm signal and verify local status updates to confirmed
  • Validation

    • flutter analyze -> pass
    • flutter test -> pass

Latest Milestone (2026-02-22): MVP Chat Preference Extractor + Ingest Enrichment

Implemented the first local semantic-enrichment pass so shared chat messages can start building inferred person preferences automatically.

  • lib/features/local/chat_preference_extractor.dart (new)

    • added a pure Dart, local-first rule-based extractor
    • extracts evidence-backed preference candidates from message text:
      • prefer X over Y (creates like/dislike pair)
      • favorite ... is ...
      • I love/like/enjoy ...
      • I hate/dislike/dont like ...
      • allergic to ...
    • adds category heuristics (e.g. drink/food/hobby/environment/health)
    • returns confidence-scored candidates with evidence snippets
  • lib/features/local/local_repository.dart

    • integrated extractor into resolved shared-message ingest flow
    • when a chat share is imported and linked to a profile:
      • store raw shared message + capture moment (existing behavior)
      • extract preference candidates from message text
      • upsert local inferred preference signals with evidence + source metadata
  • Tests

    • test/features/local/chat_preference_extractor_test.dart (new)
      • extractor unit coverage for positive/negative/comparative/allergy patterns
    • test/features/local/local_repository_test.dart
      • added ingest test proving shared chat import creates inferred signals
  • Validation

    • flutter analyze -> pass
    • flutter test -> pass

Latest Milestone (2026-02-22): Local Preference Signal Scaffolding (Inferred/Confirmed)

Added a local-first data model and repository APIs for chat-derived preference signals so the app can gradually build profile context from shared messages.

  • lib/features/local/local_models.dart

    • new enums:
      • PreferenceSignalPolarity (like, dislike, neutral)
      • PreferenceSignalStatus (inferred, confirmed, dismissed)
    • new model:
      • PersonPreferenceSignal
        • key/category/label
        • confidence
        • status
        • first/last seen timestamps
        • occurrence count
        • evidence message ids/snippets
        • source apps
    • LocalDataState now stores preferenceSignals
      • added copyWith, toJson, fromJson support (backward-compatible with existing stored state)
  • lib/features/local/local_repository.dart

    • added local-only repository APIs:
      • upsertInferredPreferenceSignalObservation(...)
        • aggregates repeated observations
        • merges evidence and source apps
        • updates confidence and occurrence count
      • upsertPreferenceSignal(...)
      • setPreferenceSignalStatus(...)
      • confirmPreferenceSignal(...)
      • dismissPreferenceSignal(...)
    • updated person lifecycle consistency:
      • deleting a person removes linked preference signals
      • merging profiles rebinds source preference signals to target
      • remote person delete application also removes preference signals
    • intentionally local-only for now (not yet mapped to backend sync envelopes)
  • test/features/local/local_repository_test.dart

    • added coverage for inferred signal upsert aggregation + status transitions
  • Validation

    • flutter analyze -> pass
    • flutter test -> pass

Latest Milestone (2026-02-22): Person Editor Inline Validation + Duplicate Warning

Improved the People add/edit profile experience to make validation explicit and support safer profile creation in a sharing-first workflow.

  • lib/features/people/people_view.dart

    • added inline required-field validation for Name and Relationship (no more silent no-op when save is pressed with empty required fields)
    • added live duplicate-name warning banner in add/edit form:
      • checks normalized profile names against existing local profiles
      • excludes the current profile during edit
      • warns before save while still allowing save (with follow-up merge flow)
    • routed existing profile list into the responsive editor panel/sheet so duplicate detection works on mobile + desktop/web
  • Validation

    • flutter analyze -> pass
    • flutter test -> pass

Latest Milestone (2026-02-22): Responsive People Add/Edit Form (Sheet + Dialog)

Aligned the People profile creation/edit flow with the newer insights-style UI language and improved platform-specific presentation behavior.

  • lib/features/people/people_view.dart

    • replaced the old AlertDialog person editor with a shared responsive form panel:
      • mobile (<720px): showModalBottomSheet with a rounded sheet layout
      • desktop/web/tablet: larger custom dialog panel
    • added richer form UX with:
      • hero preview (avatar + live preview chips for name/relationship/location/tags)
      • grouped sections (Identity, Context) matching the People/Insights card style
      • preserved existing labels and Save action text for test compatibility
    • kept add/edit repository behavior unchanged (local-first)
    • fixed narrow-width section header overflow discovered by widget test
  • Validation

    • flutter analyze -> pass
    • flutter test -> pass

Latest Milestone (2026-02-22): People Page UX Redesign (Insights-Aligned)

Reworked the People page to feel closer to the graph long-press Person Insights experience and improved the compact/mobile interaction flow.

  • lib/features/people/people_view.dart

    • redesigned the selected person detail area into an insights-style workspace:
      • hero summary card with quick actions (Capture, Idea, menu + edit/delete)
      • stats tiles (affinity, next moment, captures, ideas)
      • section cards for:
        • profile context (relationship/location/tags/source links + notes)
        • ideas
        • moments
        • reminders
        • shared message history
    • added richer person list cards:
      • next moment pill
      • optional location pill
      • tag pills
    • added People list controls:
      • search
      • relationship filter chips
      • sort menu (affinity / next / A-Z)
      • empty state when filters yield no results
    • improved compact/mobile flow:
      • selected profile workspace now renders above the full list (instead of after all profiles)
      • explicit All profiles section header with count
    • improved add-person flow UX:
      • newly created person is automatically selected/focused immediately
      • also fixed the mobile CRUD widget test expectation after layout changes
    • migrated page-local filter state to Riverpod 3 Notifier providers (instead of unavailable legacy StateProvider API)
  • Validation

    • flutter analyze -> pass
    • flutter test -> pass

Latest Milestone (2026-02-18): Quick-Add Actions on Graph Person Insights

Closed a UX gap where long-pressing a graph node opened person insights without the expected context add action.

  • Added Quick add menu to person profile header in graph-based insights page:
    • lib/features/dashboard/dashboard_view.dart
    • supports:
      • Add Capture
      • Add Note
      • Add Idea
      • Add Reminder
  • Wired actions directly to LocalRepository so entries are immediately written to local-first state and reflected in insights sections.
  • Added local dialogs for quick idea/reminder creation in insights flow.
  • Updated dashboard interaction coverage:
    • test/features/dashboard/dashboard_graph_interactions_test.dart
    • now asserts Quick add is present after opening Person Insights.
  • Added visible floating + button on Person Insights for mobile-first discoverability:
    • opens a bottom sheet with the same quick actions as the header menu
    • tooltip: Add to person

Improved identity continuity from WhatsApp intake with merge tooling and direct navigation:

  • Added duplicate-profile merge operation in local repository:
    • lib/features/local/local_repository.dart
    • new mergePersonProfiles(sourcePersonId, targetPersonId):
      • merges target profile metadata (tags/notes/location/affinity/next moment)
      • rebinds related records from source -> target:
        • moments
        • ideas
        • reminders
        • source links
        • shared message history
        • unresolved inbox candidate IDs
      • enqueues sync envelopes for merged target + source delete + rebounded related entities
  • Added merge action in People UX:
    • lib/features/people/people_view.dart
    • new Merge / Merge duplicates action in People header
    • duplicate-name detection and merge dialog for selecting source/target
  • Share destination deep-link polish:
    • lib/features/share_intake/whatsapp_share_listener.dart
      • initial app launch from share intent now auto-opens destination context:
        • Share Inbox for unresolved imports
        • People with selected imported profile for resolved imports
      • snackbar action updated to Open Profile / Open Inbox
    • lib/features/settings/settings_view.dart
      • simulated share snackbar now offers direct navigation to profile/inbox
  • Added merge test coverage:
    • test/features/local/local_repository_test.dart
    • verifies merge rebinding across related records

Latest Milestone (2026-02-18): Stable Share Fingerprints + Near-Match Conflict Detection

Strengthened WhatsApp identity mapping to reduce accidental mis-links:

  • Added stable source fingerprint strategy:
    • lib/features/local/local_models.dart
    • SourceProfileLink now stores optional sourceFingerprint
    • SharedInboxEntry also keeps the same fingerprint when unresolved
    • fingerprint is derived from stable source identifiers (sourceApp + source user/thread ids)
  • Updated ingest matching order:
    • lib/features/local/local_repository.dart
    • fingerprint match is now the primary lookup path
    • backward-compatible fallback to existing user/thread/display matching
    • legacy links without stored fingerprint still match by derived fingerprint
  • Added near-match conflict handling:
    • new inbox reason: nearProfileConflict
    • fuzzy name similarity heuristic (edit-distance + containment) now detects likely profile conflicts and routes to Share Inbox for explicit user choice
  • Updated Share Inbox UI reason labels:
    • lib/features/share_intake/share_inbox_view.dart
  • Added test coverage:
    • test/features/local/local_repository_test.dart
    • verifies:
      • fingerprint persistence on source links
      • near-match conflict queueing
      • follow-up routing succeeds via fingerprint after manual resolution

Latest Milestone (2026-02-18): Share Inbox Conflict Review UX

Upgraded unresolved-share resolution from a basic picker to guided review:

  • Added conflict review modal in Share Inbox:
    • lib/features/share_intake/share_inbox_view.dart
    • new flow:
      • tap Review & Match
      • inspect side-by-side comparison:
        • incoming share identity panel (sender, source ids, fingerprint, message)
        • selected profile panel (name, relationship, tags/location, confidence)
      • review candidate list with confidence percentages and suggestion marker
      • confirm explicit link with Confirm Match
  • Added confidence scoring + rationale hints:
    • combines normalized-name similarity, prior candidate suggestion, and source identity signals into a 1-99% confidence display
    • shows short rationale bullets to make matching decisions transparent
  • Added widget coverage:
    • test/features/share_intake/share_inbox_view_test.dart
    • verifies conflict review dialog opens and confirm mapping resolves inbox item

Latest Milestone (2026-02-18): Share Inbox Resolution Flow

Added manual resolution UX and data paths for ambiguous/unidentifiable WhatsApp shares:

  • Introduced unresolved-share queue model:
    • lib/features/local/local_models.dart
    • new SharedInboxEntry + SharedInboxReason
    • persisted in LocalDataState.sharedInbox
  • Extended ingest result + repository APIs:
    • lib/features/local/local_repository.dart
    • SharedMessageIngestResult now reports imported vs queued-for-resolution
    • ambiguous/missing-identity shares are routed to inbox instead of forced auto-link
    • added resolution actions:
      • resolve inbox item to existing profile
      • resolve inbox item by creating a new profile (with optional location)
      • dismiss inbox item
  • Added dedicated Share Inbox view:
    • lib/features/share_intake/share_inbox_view.dart
    • shows unresolved items, suggested matches, create-profile dialog, dismiss
  • Wired entry points:
    • lib/features/share_intake/whatsapp_share_listener.dart
      • snackbar now routes unresolved imports to Share Inbox
    • lib/features/settings/settings_view.dart
      • added Open Share Inbox action and updated simulation feedback
  • Added tests:
    • test/features/local/local_repository_test.dart
      • unresolved queue behavior
      • resolve-to-existing-profile flow
    • test/features/share_intake/share_inbox_view_test.dart
      • inbox render + dismiss behavior

Latest Milestone (2026-02-17): WhatsApp Share Intake + Profile Quick Actions

Implemented the next major usage-flow slice focused on capture-to-action speed:

  • WhatsApp share intake pipeline (MVP):
    • lib/features/share_intake/whatsapp_share_listener.dart
    • lib/features/share_intake/whatsapp_share_parser.dart
    • listener now ingests shared WhatsApp text into local state while authenticated
    • parser resolves sender-prefixed message shapes (including timestamped export line format)
  • Source identity linking for repeat routing:
    • lib/features/local/local_models.dart
    • lib/features/local/local_repository.dart
    • added persisted source->profile link records and shared-message history
    • repeated shares with same source identity resolve to the same profile
  • Auto profile creation on first unresolved share:
    • LocalRepository.ingestSharedMessage(...)
    • creates profile (when needed), writes/updates source link, and appends WhatsApp moment capture to that profile history
  • Profile model enhancement:
    • added optional location field on PersonProfile
    • wired into serialization, repository payload mapping, and People editor UI
  • People context quick-add:
    • lib/features/people/people_view.dart
    • profile detail now includes + quick actions:
      • Add Capture
      • Add Note
      • Add Idea
      • Add Reminder
    • each action is person-scoped and writes directly to local state
  • Settings support for dev/testing:
    • lib/features/settings/settings_view.dart
    • added Simulate WhatsApp Share flow to test ingestion without OS share UI
  • App bootstrap wiring:
    • lib/main.dart wraps authenticated shell with WhatsAppShareListener
    • runtime flag in lib/core/config/app_config.dart: ENABLE_WHATSAPP_SHARE_INTAKE
  • Added tests:
    • test/features/share_intake/whatsapp_share_parser_test.dart
    • test/features/local/local_repository_test.dart share-ingest/link reuse case
    • updated migration expectation in test/features/local/storage/local_repository_hive_migration_test.dart

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-17): Interactive Relationship Graph + Person Insights Drilldown

Upgraded the dashboard graph from static visualization to interactive navigation:

  • Graph interactions:
    • lib/features/dashboard/dashboard_view.dart
    • graph area now supports:
      • pan by drag gesture
      • pinch-to-zoom scaling
      • long-press on person bubbles
  • Long-press drilldown behavior:
    • opens a dedicated person insights page with back navigation to the graph
    • page sections are category-separated:
      • Ideas
      • Promotions & Signals
      • Moments
      • Reminders
      • Tasks & Follow-Ups
    • includes profile summary (relationship type, affinity, tags, notes)
  • Added interaction test coverage:
    • test/features/dashboard/dashboard_graph_interactions_test.dart
    • verifies:
      • graph contains interactive viewer
      • long-press on a person node opens insights screen
      • back button returns to graph

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-17): Obsidian-Style Relationship Graph on Dashboard

Reworked the initial Dashboard section to lead with a relationship network visual:

  • Replaced the old top summary-only start with a graph-first hero:
    • lib/features/dashboard/dashboard_view.dart
    • new Relationship Graph card renders:
      • center YOU node
      • surrounding person bubbles from local people data
      • custom-painted connection edges (radial + mesh links)
      • relationship-type icon badges + color-coded edge/node styling
  • Added relationship-type visual mapping for labels such as:
    • spouse, fiance, partner/girlfriend/boyfriend, friend, bestie, family, sister, brother, fallback connection
  • Added adaptive layout behavior:
    • compact/mobile and wide/web radius/node limits
    • hidden-node indicator for large lists
    • relationship legend chips under the graph
  • Preserved existing dashboard flow below the graph:
    • stats cards and Next Moves tasks remain available

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-17): Connectivity Event-Driven Background Sync

Implemented online-transition-triggered sync so background sync reacts faster when network returns:

  • Added connectivity stream support to reachability abstraction:
    • lib/core/network/reachability/network_reachability.dart
    • new watch(...) API for reachability change events
  • Added IO implementation using connectivity plugin + internet probe:
    • lib/core/network/reachability/network_reachability_io.dart
    • connectivity_plus integrated as transport signal source
  • Updated background runner:
    • lib/features/sync/sync_background_runner.dart
    • now listens for offline -> online transitions and triggers immediate sync
    • keeps existing startup/resume/periodic behavior
  • Added coverage:
    • test/features/sync/sync_background_runner_test.dart
    • verifies transition-trigger behavior and avoids duplicate triggers when already online
  • Updated setup docs:
    • docs/SETUP.md background sync section now includes connectivity-return behavior note

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-17): Sync Repair Test Stability + Mobile CRUD/Sync Flow Coverage

Completed two test-depth upgrades:

  • Stabilized rejected-sync repair widget flow:
    • test/features/sync/sync_rejection_repair_flow_test.dart
    • fixed viewport-aware assertions/actions for ListView content by scrolling before interacting with rejection controls
    • verifies rejected item -> open related repair screen -> save -> local state mutation applied
  • Added mobile-first integration-style flow:
    • test/features/app/app_mobile_crud_sync_flow_test.dart
    • covers compact-shell path: sign-in -> People -> add person -> sync queue envelope asserted -> open Sync from More menu
    • validates both UI behavior and queued backend envelope side effect in SyncQueueRepository

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Direct Entity Repair Forms From Sync

Implemented deep-link repair forms for rejected sync items:

  • Updated lib/features/sync/sync_view.dart:
    • Open Related Screen now routes into dedicated entity-specific repair forms, not just general list screens
    • supported entity repair forms:
      • person
      • capture
      • giftIdea/eventIdea
      • reminderRule
    • each form updates local state via LocalRepository directly
    • focus banner keeps exact entityType:entityId context with copy action
  • Added widget flow coverage:
    • test/features/sync/sync_rejection_repair_flow_test.dart
    • verifies reject -> open repair form -> save -> local state updated

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Notification Tap Routing

Implemented initial in-app routing for reminder notification taps:

  • Added notification intent bus:
    • lib/features/reminders/scheduling/reminder_notification_intent_bus.dart
  • Wired local notifications scheduler to emit tap payloads:
    • lib/features/reminders/scheduling/reminder_scheduler_local_notifications.dart
  • Added app-level intent listener wrapper:
    • lib/features/reminders/scheduling/reminder_notification_listener.dart
    • opens reminder management screen when a reminder notification is tapped
  • Mounted listener in authenticated app shell path:
    • lib/main.dart

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Sync Rejection Repair Navigation

Added direct repair navigation from rejected sync items:

  • Updated lib/features/sync/sync_view.dart:
    • each rejected item now includes Open Related Screen
    • routes user to a relevant maintenance screen based on entity type:
      • person -> People
      • capture -> Moments
      • giftIdea/eventIdea -> Ideas
      • reminderRule -> Reminders
    • keeps existing payload inspect + requeue/dismiss actions
    • opened repair screen now shows exact entityType:entityId focus banner

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Notification Permission UX

Added runtime notification permission flow through the product UI:

  • Extended reminder scheduler interface:
    • lib/features/reminders/scheduling/reminder_scheduler.dart
    • new requestPermissions() API
  • Implemented permission handling in local notifications scheduler:
    • lib/features/reminders/scheduling/reminder_scheduler_local_notifications.dart
    • Android: requestNotificationsPermission()
    • iOS/macOS: requestPermissions(alert/badge/sound)
  • Added settings action:
    • lib/features/settings/settings_view.dart
    • Request Notification Access button with result feedback snackbar
  • Added test coverage:
    • test/features/reminders/scheduling/reminder_scheduler_local_notifications_test.dart
    • verifies permission delegation behavior

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Local Notifications Reminder Runtime

Implemented reminder delivery with local notifications runtime integration:

  • Added dependency:
    • flutter_local_notifications
  • Added concrete scheduler:
    • lib/features/reminders/scheduling/reminder_scheduler_local_notifications.dart
    • LocalNotificationsReminderScheduler
    • reconciles local reminders into platform notification schedule
    • supports recurring cadence mapping:
      • daily -> DateTimeComponents.time
      • weekly -> DateTimeComponents.dayOfWeekAndTime
      • monthly -> DateTimeComponents.dayOfMonthAndTime
    • web/linux gracefully no-op (scheduling fallback)
  • Provider wiring now defaults to local notifications scheduler:
    • lib/features/reminders/scheduling/reminder_scheduler_provider.dart
    • gated by ENABLE_LOCAL_NOTIFICATIONS
  • Added config flag:
    • lib/core/config/app_config.dart -> enableLocalNotifications
  • Added tests:
    • test/features/reminders/scheduling/reminder_scheduler_local_notifications_test.dart
  • Updated setup docs:
    • docs/SETUP.md

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Sync Rejection Payload Inspection

Improved conflict handling UX in Sync view:

  • Updated lib/features/sync/sync_view.dart:
    • each rejected mutation now supports payload inspect/expand
    • shows formatted local envelope payload JSON for failed mutations when available
    • keeps requeue/dismiss actions for operator control

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Reachability-Gated Auto Sync

Added connectivity-aware gating to background sync auto-triggers:

  • Added network reachability abstraction:
    • lib/core/network/reachability/network_reachability.dart
    • lib/core/network/reachability/network_reachability_provider.dart
    • platform impls:
      • network_reachability_io.dart
      • network_reachability_web.dart
      • network_reachability_stub.dart
  • Integrated into background sync runner:
    • lib/features/sync/sync_background_runner.dart
    • auto-triggers now skip when reachability gate reports offline (REST mode)
    • fake backend mode bypasses reachability gate
  • Extended sync trigger controller:
    • lib/features/sync/sync_auto_trigger_controller.dart
    • added trigger gate callback support
  • Added tests:
    • test/features/sync/sync_auto_trigger_controller_test.dart
    • validates denied-trigger behavior

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): App Session Flow Test Coverage

Added higher-level widget coverage for a core authenticated user journey:

  • New test:
    • test/features/app/app_auth_flow_test.dart
    • validates end-to-end path:
      • sign-in screen shown by default
      • sign-in transitions into app shell
      • navigate to settings and sign out
      • sign-out returns to sign-in screen
  • Uses deterministic in-memory overrides for token, local data store, sync state store, and backend gateway fake.

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Rejected-Mutation Requeue Flow

Extended sync conflict handling so rejected mutations can be retried after local fixes:

  • Expanded sync state model:
    • lib/features/sync/sync_state.dart
    • stores lastRejectedChanges alongside rejection reasons
  • Updated sync queue repository:
    • lib/features/sync/sync_queue_repository.dart
    • captures rejected envelopes during push
    • adds requeueRejectedChanges() to move rejected envelopes back into pending queue
    • keeps clear/dismiss behavior for rejected metadata
  • Updated sync UX:
    • lib/features/sync/sync_view.dart
    • rejected section now includes:
      • entity context (entityType:entityId)
      • Requeue action for manual retry flow
      • existing Dismiss action
  • Added/updated tests:
    • test/features/sync/sync_queue_repository_test.dart
    • verifies rejected envelope capture and requeue behavior

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Sync Auto-Trigger Backoff

Improved sync trigger resilience for repeated failures:

  • Updated lib/features/sync/sync_auto_trigger_controller.dart:
    • tracks consecutive sync failures
    • applies exponential cooldown backoff before auto-trigger retries
    • resets backoff after a successful sync run
  • Added coverage:
    • test/features/sync/sync_auto_trigger_controller_test.dart
    • validates cooldown behavior after failures

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Reminder Delivery Interface Wiring

Implemented the notification scheduling boundary and connected it to local data state transitions:

  • Added reminder scheduler abstraction:
    • lib/features/reminders/scheduling/reminder_scheduler.dart
    • ReminderScheduler + NoopReminderScheduler
  • Added provider wiring:
    • lib/features/reminders/scheduling/reminder_scheduler_provider.dart
  • Integrated schedule reconciliation with local repository:
    • lib/features/local/local_repository.dart
    • reconcile runs on repository boot and each persisted state update
    • failures are swallowed to preserve offline-first behavior
  • Added tests:
    • test/features/local/local_repository_test.dart now verifies reminder schedule reconciliation calls
  • Updated setup docs:
    • docs/SETUP.md now documents reminder scheduler scaffold

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Sync Hardening + CI Baseline

Implemented the next production-readiness slice:

  • Added lifecycle-aware background sync runner:
    • lib/features/sync/sync_auto_trigger_controller.dart
    • lib/features/sync/sync_background_runner.dart
    • mounted while authenticated in lib/main.dart
    • behavior: one trigger on app startup, trigger on app resume, periodic sync ticks (default every 180s), cooldown/concurrency guarded
  • Added runtime config flags:
    • ENABLE_BACKGROUND_SYNC (default true)
    • BACKGROUND_SYNC_INTERVAL_SECONDS (default 180)
    • in lib/core/config/app_config.dart
  • Added user-facing rejected mutation handling:
    • lib/features/sync/sync_queue_repository.dart -> clearRejections()
    • lib/features/sync/sync_view.dart now renders a Rejected Changes section with dismiss action
  • Added tests:
    • test/features/sync/sync_auto_trigger_controller_test.dart
    • test/features/sync/sync_queue_repository_test.dart rejection clear case
  • Added CI workflow:
    • .github/workflows/flutter_ci.yml (flutter pub get, flutter analyze, flutter test)
  • Updated setup docs:
    • docs/SETUP.md with background sync flags

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Open Phases (Current)

  1. Reminder delivery runtime integration:
    • implemented for Android/iOS/macOS/windows with web/linux safe fallback.
    • permission UX implemented in settings.
    • notification tap routing implemented for reminder screen handoff.
  2. Conflict resolution UX:
    • reject/requeue + payload inspect + direct entity repair forms implemented.
    • future enhancement: auto-select and highlight the exact row in main feature screens after save.
  3. Sync trigger maturity:
    • implemented via reachability gating + online-transition event triggers.
    • future: add richer platform-specific network quality awareness if needed.
  4. Test depth:
    • expanded with mobile compact CRUD+sync flow and rejected-repair flow.
    • future: add desktop + web-specific end-to-end sync error/retry scenario.

Latest Milestone (2026-02-15): Sync Queue Storage Adapter + Hive Migration

Extended the storage abstraction approach to sync queue persistence:

  • Added sync storage abstraction:
    • lib/features/sync/storage/sync_state_store.dart
  • Added concrete sync stores:
    • lib/features/sync/storage/sync_state_store_shared_prefs.dart
    • lib/features/sync/storage/sync_state_store_hive.dart
    • lib/features/sync/storage/sync_state_store_in_memory.dart
    • provider wiring: lib/features/sync/storage/sync_state_store_provider.dart
  • Refactored sync queue repository:
    • lib/features/sync/sync_queue_repository.dart
    • no direct shared_preferences dependency
    • store-agnostic read/write path via SyncStateStore
    • one-time migration path from legacy shared prefs sync payload into Hive
  • Updated tests to use explicit in-memory store overrides where deterministic:
    • test/features/sync/sync_queue_repository_test.dart
    • test/features/sync/sync_coordinator_test.dart
    • test/features/local/local_repository_test.dart
    • test/features/responsive/responsive_views_smoke_test.dart
  • Added migration coverage:
    • test/features/sync/storage/sync_queue_hive_migration_test.dart

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Local Store Adapter Layer (DB Migration Scaffold)

Implemented a persistence boundary so local app state is no longer tightly coupled to shared_preferences internals:

  • Added local persistence abstraction:
    • lib/features/local/storage/local_data_store.dart
    • LocalDataStore + LocalDataRecord
  • Added concrete store implementations:
    • lib/features/local/storage/local_data_store_shared_prefs.dart
    • lib/features/local/storage/local_data_store_hive.dart
    • lib/features/local/storage/local_data_store_in_memory.dart
    • provider wiring: lib/features/local/storage/local_data_store_provider.dart
  • Refactored local repository to use store adapter:
    • lib/features/local/local_repository.dart
    • build/read/write/migration paths now go through LocalDataStore
    • schema migration hook retained and now store-agnostic
  • Added config flag for local backend selection:
    • lib/core/config/app_config.dart -> USE_HIVE_LOCAL_DB
    • default now set to Hive (true)
  • Added one-time migration path from legacy shared prefs into Hive:
    • lib/features/local/local_repository.dart
    • when Hive is active and empty, legacy payload is imported then cleared
  • Added setup docs for switching local persistence backend:
    • docs/SETUP.md
  • Added migration/storage tests:
    • test/features/local/storage/local_data_store_shared_prefs_test.dart
    • test/features/local/storage/local_repository_store_override_test.dart
    • test/features/local/storage/local_repository_hive_migration_test.dart

This prepares the app for a true DB migration path while keeping existing UX and tests stable.

Latest Milestone (2026-02-15): Cross-View Responsive Pass

Audited and adjusted the main product views for mobile-first behavior while preserving desktop/web UX:

  • Updated responsive behavior and compact spacing for:
    • lib/features/dashboard/dashboard_view.dart
    • lib/features/moments/moments_view.dart
    • lib/features/ideas/ideas_view.dart
    • lib/features/reminders/reminders_view.dart
    • lib/features/signals/signals_view.dart
    • lib/features/settings/settings_view.dart
    • lib/features/sync/sync_view.dart
    • lib/features/auth/sign_in_view.dart
    • lib/features/people/people_view.dart
  • Removed narrow-width overflow hotspots:
    • stacked compact headers/actions instead of single fixed rows
    • converted key action rows to Wrap/column where needed
    • improved list-item text constraints (maxLines, ellipsis)
    • made editor dialogs width-safe using max-width constraints

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Breakpoint QA follow-up

Ran targeted responsive smoke checks for:

  • iPhone SE (320x568)
  • iPhone Pro Max (430x932)
  • iPad portrait (768x1024)
  • Web/desktop (1280x800)

Follow-up fixes from QA:

  • lib/features/auth/sign_in_view.dart
    • added scroll-safe container for short-height screens to prevent vertical overflow
  • lib/features/home/app_shell.dart
    • made sidebar brand text ellipsize-safe to prevent horizontal overflow
  • Added automated responsive regression suite:
    • test/features/responsive/responsive_views_smoke_test.dart
    • validates AppShell + all primary views across the breakpoints above

Latest Milestone (2026-02-15): People Mobile Layout Fix

Fixed the People view so it is mobile-friendly and no longer overflows on iOS narrow screens:

  • lib/features/people/people_view.dart
    • added responsive breakpoint logic (LayoutBuilder)
    • desktop keeps split-pane list/detail layout
    • mobile now uses a single-column flow (header, people list, selected person detail)
    • improved text safety with maxLines/ellipsis and compact detail action row

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Sync Queue + Orchestrator

Implemented the next sync phase so local mutations are now queued and synced through a real coordinator flow:

  • Added persisted sync queue state:
    • lib/features/sync/sync_state.dart
    • lib/features/sync/sync_queue_repository.dart
    • stores pending ChangeEnvelopes, cursor, last attempt/sync, and rejection info
  • Added sync orchestration service:
    • lib/features/sync/sync_coordinator.dart
    • supports pushPending, pullRemote, and syncNow
    • keeps offline-first behavior by recording failures without blocking local usage
  • Wired local CRUD to sync envelopes:
    • lib/features/local/local_repository.dart
    • all person/moment/idea/reminder mutations now enqueue typed change envelopes
    • added applyRemoteChanges(...) to apply pulled backend envelopes into local state
  • Upgraded Sync UI:
    • lib/features/sync/sync_view.dart
    • now shows queue/cursor/error status and provides real sync actions (sync/push/pull/clear)
  • Added sync tests:
    • test/features/sync/sync_queue_repository_test.dart
    • test/features/sync/sync_coordinator_test.dart

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Auth Session UX

Implemented app-level authentication/session flow so navigation is now session-aware:

  • Added session lifecycle controller:
    • lib/features/auth/session_controller.dart
    • bootstraps from token store on app startup
    • supports sign-in, sign-out, and profile refresh
    • enforces offline-safe sign-out (always clears local session)
  • Added sign-in experience:
    • lib/features/auth/sign_in_view.dart
    • supports Password / Magic Link / OIDC request shapes
    • shows mode status (Fake/REST)
  • Updated app bootstrap:
    • lib/main.dart now gates between SignInView and AppShell based on session state
  • Updated settings with session actions:
    • lib/features/settings/settings_view.dart
    • shows current identity and provides Sign Out + Refresh Profile
  • Added auth tests:
    • test/features/auth/session_controller_test.dart
    • updated test/widget_test.dart for sign-in default route

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Ideas + Reminders Phase

Implemented the next Phase 2 slice by introducing Ideas and Reminder Rules as first-class local features.

  • Expanded local domain/state:
    • IdeaType, ReminderCadence, RelationshipIdea, ReminderRule
    • LocalDataState now persists ideas and reminders
  • Expanded local repository CRUD:
    • ideas: add/update/archive/delete
    • reminders: add/update/toggle/delete
    • people deletion now cascades to moments/ideas/reminders
  • Added new feature views:
    • lib/features/ideas/ideas_view.dart
    • lib/features/reminders/reminders_view.dart
  • Updated shell navigation:
    • desktop sidebar now includes Ideas and Reminders
    • mobile keeps compact primary tabs and exposes Ideas/Reminders under More
  • Expanded local repository tests for new CRUD surface:
    • test/features/local/local_repository_test.dart

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Latest Milestone (2026-02-15): Local Persistence + CRUD Baseline

Implemented the first real local data foundation pass (replacing static demo-only reads):

  • Added persisted local state using shared_preferences:
    • lib/features/local/local_repository.dart
    • schema key/version scaffold + seed fallback + persistence logic
  • Upgraded local models with serialization/copy methods:
    • lib/features/local/local_models.dart
  • Added local CRUD operations:
    • people: add, edit, delete
    • moments: add, delete
    • dashboard tasks: done/undone toggle
  • Wired views to async persisted state:
    • DashboardView, PeopleView, MomentsView
  • Updated signals fallback to read from persisted local state:
    • lib/features/signals/signals_controller.dart
  • Added local repository tests:
    • test/features/local/local_repository_test.dart

Validation for this milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Workflow Rule

  • After every sensible change, the final step is a Git commit with a clear message.
  • Keep changes in small, logical commits so future sessions can revert or continue safely.

Latest Milestone (2026-02-15): Product UI Flow Implemented

The app now has a real multi-screen user experience on macOS (and other platforms), not just a placeholder screen.

Delivered UI architecture:

  • App shell with responsive navigation:
    • desktop: left sidebar + content pane
    • compact: bottom navigation (reduced to 4 primary tabs)
    • compact secondary actions (Sync, Settings) moved into a More menu to avoid tab overload on iOS/mobile
  • Views implemented:
    • Dashboard
    • People
    • Moments
    • Signals
    • Sync
    • Settings
  • Reference-aligned visual style:
    • WorkSans typography (copied from the UI reference assets)
    • soft gradients, rounded glass-like cards, accent palette similar to the reference repo
  • Offline-safe UX:
    • fake backend mode now defaults to true unless overridden via --dart-define=USE_FAKE_BACKEND=false
    • signals view gracefully falls back to local recommendations when backend calls fail

Key new files:

  • lib/features/home/app_shell.dart
  • lib/features/dashboard/dashboard_view.dart
  • lib/features/people/people_view.dart
  • lib/features/moments/moments_view.dart
  • lib/features/signals/signals_controller.dart
  • lib/features/signals/signals_view.dart
  • lib/features/sync/sync_view.dart
  • lib/features/settings/settings_view.dart
  • lib/features/shared/frosted_card.dart
  • lib/features/local/local_models.dart
  • lib/features/local/local_repository.dart
  • assets/fonts/WorkSans-*.ttf

Other updates:

  • lib/main.dart now launches the new app shell.
  • lib/core/config/app_theme.dart updated to a stronger visual system.
  • pubspec.yaml includes local WorkSans font family.
  • test/widget_test.dart updated for the new flow.

Validation status after UI milestone:

  • flutter analyze -> pass
  • flutter test -> pass

Current Gap Analysis (2026-02-15)

What we have now

  • Backend gateway architecture with REST + fake implementations, typed DTOs, retries, refresh, and tests.
  • OpenAPI + ADR documentation baseline.
  • Product UI shell with responsive desktop/mobile navigation and key views.
  • Offline-safe default behavior with fake backend mode.

What is still missing

  • Local database persistence and repository wiring (currently demo in-memory data).
  • Full CRUD flows (create/edit/delete) for people, captures, reminder rules, gift/event ideas.
  • Auth UX flows (sign-in, session-expired recovery, sign-out confirmation).
  • Conflict policy UI and merge/resolution UX for rejected remote/local mutations.
  • Notifications/reminders delivery and scheduling integration.
  • End-to-end and integration tests for app flows beyond unit/widget basics.

Implementation Plan (Next)

Phase 1: Data Foundation

  1. Introduce local DB schema + repository interfaces for core entities.
  2. Replace LocalRepository demo data with persisted data access.
  3. Add migration/test coverage for DB reads/writes.

Phase 2: Core Product Flows

  1. Build People CRUD and detail editing screens.
  2. Build Moments/Captures create-and-list workflows.
  3. Add Ideas and Reminder Rule management.

Phase 3: Sync + Auth UX

  1. Add background sync scheduling/triggers (app start, manual retry, connectivity hooks).
  2. Add conflict handling strategy and user-facing UI states for rejected mutations.
  3. Add session-expired recovery UX and guarded routes for protected actions.

Phase 4: Quality + Release Readiness

  1. Add CI for analyze/test and optional build smoke checks.
  2. Expand widget/integration tests for primary user journeys.
  3. Add observability hooks and production hardening pass.

Current Status

The Flutter app now includes a production-grade backend integration scaffold with an offline-first posture:

  • Local/offline UX remains primary; backend is optional for core usage.
  • A transport-agnostic gateway interface is in place.
  • REST implementation with auth refresh/retry/error mapping is implemented.
  • Deterministic fake gateway is available for local/dev without backend.
  • OpenAPI contract + ADR + setup docs + unit tests are in place.
  • flutter analyze and flutter test are passing.

What Was Implemented

1. Core Config + Theme Shell

  • Added backend config with build-time + runtime override:
    • lib/core/config/app_config.dart
  • Added lightweight app theme aligned with reference style direction:
    • lib/core/config/app_theme.dart
  • Updated app entry shell and Riverpod root:
    • lib/main.dart

2. Network Foundation

Implemented a Dio stack with request metadata, auth, refresh, retry, and error mapping:

  • lib/core/network/dio_factory.dart
  • lib/core/network/network_constants.dart
  • lib/core/network/backend_exception.dart
  • lib/core/network/dio_error_mapper.dart
  • Interceptors:
    • lib/core/network/interceptors/request_metadata_interceptor.dart
    • lib/core/network/interceptors/auth_interceptor.dart
    • lib/core/network/interceptors/refresh_token_interceptor.dart
    • lib/core/network/interceptors/retry_interceptor.dart

Behavior implemented:

  • Adds per-request X-Request-Id.
  • Adds Authorization: Bearer <token> when session exists.
  • On 401, attempts one refresh (/v1/auth/refresh) then retries original request.
  • If refresh fails, session is cleared and AuthExpiredException surfaced.
  • Retry policy (max 2 retries, exponential backoff):
    • Retry transient failures (timeouts, connection, 5xx).
    • Safe methods (GET/HEAD/OPTIONS) retry automatically.
    • Non-idempotent endpoints only retry when Idempotency-Key exists.
  • Maps Dio failures into typed backend exceptions with metadata.

3. Auth Token Storage

  • Interface:
    • lib/core/auth/token_store.dart
  • Production implementation:
    • lib/core/auth/secure_token_store.dart
  • Test/dev implementation:
    • lib/core/auth/in_memory_token_store.dart

4. Backend Integration Layer

Domain boundary and implementations:

  • Interface:
    • lib/integrations/backend/backend_gateway.dart
  • REST:
    • lib/integrations/backend/backend_gateway_rest.dart
  • Fake:
    • lib/integrations/backend/backend_gateway_fake.dart
  • Optional Riverpod providers:
    • lib/integrations/backend/backend_gateway_provider.dart
  • Sync validation:
    • lib/integrations/backend/sync_envelope_validator.dart

Implemented methods:

  • sign-in/out + me
  • sync pull/push (with idempotency key on push)
  • signals feed + ack
  • upload init + download URL scaffold

Offline-first hardening:

  • signOut() clears local token store in finally, even when network call fails.

5. Typed Models (Freezed + JSON)

  • lib/integrations/backend/models/backend_models.dart
  • Generated files:
    • backend_models.freezed.dart
    • backend_models.g.dart

Includes DTOs/enums for:

  • Auth (SignInRequest, AuthSession, refresh request/response, UserProfile)
  • Sync (ChangeEnvelope, push/pull requests/results, ack/rejection)
  • Signals (SignalsFeed, SignalItem, ack request/action)
  • Uploads (UploadInitRequest/Result, DownloadUrl)

6. Contract + Architecture Docs

  • OpenAPI spec:
    • docs/api/openapi.yaml
  • ADR:
    • docs/ADR/0002-backend-protocol-rest-openapi.md
  • Setup instructions:
    • docs/SETUP.md
  • Previous concise checklist log:
    • docs/PROGRESS.md

7. Tooling + Quality

  • Strict analyzer/lints:
    • analysis_options.yaml
  • Dependencies added in pubspec.yaml:
    • runtime: dio, freezed_annotation, json_annotation, flutter_secure_storage, uuid, clock, flutter_riverpod
    • dev: freezed, json_serializable, build_runner, mocktail

8. Test Coverage Added

Core network and model tests:

  • test/core/network/token_refresh_interceptor_test.dart
  • test/core/network/dio_error_mapper_test.dart
  • test/core/network/retry_interceptor_test.dart
  • test/integrations/backend/backend_models_serialization_test.dart
  • test/integrations/backend/sync_envelope_validator_test.dart
  • helper adapter: test/helpers/queue_http_client_adapter.dart
  • updated smoke widget test: test/widget_test.dart

Verification Snapshot

Most recent local checks:

  • flutter analyze -> pass
  • flutter test -> pass

Known Gaps / Intentional Scope Limits

  • No realtime transport yet (SSE/WebSocket intentionally deferred).
  • No backend-generated client code from OpenAPI yet.
  • No persistence layer wiring to local DB yet (gateway is ready to plug in).
  • No UI features using backend gateway yet beyond app shell readiness.
  • Fake gateway data is deterministic sample content, not scenario-configurable yet.

Handoff Plan For Next Agent Sessions

Priority 1: Repository Hygiene + CI

  1. Add CI workflow for flutter analyze + flutter test.
  2. Add branch protections / PR template if desired.
  3. Keep generated files committed policy explicit in README.

Priority 2: Local DB Integration (Offline-First Core)

  1. Define local domain entities and repositories for person, capture, giftIdea, eventIdea, tag, reminderRule.
  2. Map local mutations to ChangeEnvelope and enqueue for sync.
  3. Create sync orchestrator service that:
    • pushes pending local mutations,
    • applies pull changes with conflict policy,
    • stores/advances cursor.
  4. Add tests for conflict handling and cursor progression.

Priority 3: App Wiring + UX

  1. Replace local demo repository data with actual local DB repositories.
  2. Add create/edit flows for people, captures, reminders, and ideas (forms + validation).
  3. Add session state and auth entry screens (sign-in, expired-session recovery).
  4. Add explicit offline badges and sync conflict resolution UI.

Priority 4: Security + Hardening

  1. Add central log redaction helper for headers/bodies.
  2. Add token-expiry pre-check strategy (optional proactive refresh).
  3. Evaluate secure storage behavior on web target and fallback policy.
  4. Add tests for concurrent 401 refresh race conditions.

Priority 5: API Evolution

  1. Version strategy in OpenAPI (/v1 already set).
  2. Define backend error payload schema formally in OpenAPI.
  3. Add capabilities endpoint for future realtime negotiation.
  4. Add SSE/WebSocket design ADR when backend is ready.

How To Continue Quickly

  1. Run: flutter pub get
  2. If models change: dart run build_runner build --delete-conflicting-outputs
  3. Validate: flutter analyze && flutter test
  4. Start from:
    • gateway surface: lib/integrations/backend/backend_gateway.dart
    • sync transport: lib/integrations/backend/backend_gateway_rest.dart
    • contract: docs/api/openapi.yaml

Important Notes

  • Current default base URL is placeholder (https://api.example.com).
  • Use fake mode for local iteration:
    • flutter run --dart-define=USE_FAKE_BACKEND=true
  • Build-time URL override:
    • flutter run --dart-define=BACKEND_BASE_URL=<your-url>