Files
rely/docs/progress.md
T
2026-05-17 00:17:03 +02:00

1407 lines
55 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Relationship Saver Progress Log
Updated: 2026-02-23
## 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-23): Relationship Graph Preview + Full-Screen Explorer
Reworked the graph interaction model to be mobile-friendly on the dashboard and
still support smooth pan/zoom exploration.
- `lib/features/dashboard/dashboard_view.dart`
- refactored graph rendering into a shared canvas widget with two modes:
- `preview` (dashboard, scroll-first)
- `explorer` (full-screen, pan/zoom-first)
- dashboard graph card is now a scroll-safe preview:
- keeps node long-press for `Person Insights`
- disables pan/zoom interaction on the dashboard canvas
- adds explicit `Explore` / `Open Explorer` CTA button
- updated helper copy to clarify dashboard preview vs explorer behavior
- added full-screen `Relationship Graph` explorer page:
- pan enabled
- pinch-to-zoom enabled
- `Reset view` control
- same long-press-to-open-person-insights behavior
- shared legend display
- extracted shared graph helpers (legend + navigation helpers) to keep the
preview and explorer behavior consistent
- `test/features/dashboard/dashboard_graph_interactions_test.dart`
- extended coverage to verify:
- dashboard preview renders `Explore` CTA
- explorer page opens from dashboard
- `Reset view` action is available and works
- returning to dashboard still works
- UX decision captured in implementation
- dashboard remains scroll-first on mobile (no hidden pan-mode toggle)
- graph exploration happens in a dedicated full-screen context
- Validation
- `flutter analyze` -> pass
- `flutter test` -> pass
## Latest Milestone (2026-02-22): Quick-Capture Dialog Regression Test (People)
Added explicit widget-test coverage so controller lifecycle issues in quick
capture dialogs are caught automatically in CI/local runs.
- `test/features/people/people_quick_capture_dialog_test.dart` (new)
- mounts `PeopleView` in mobile layout
- opens profile-context `Capture` quick action dialog
- exercises `Cancel` path and pumps through dismissal frames
- reopens dialog, saves a capture, and pumps through dismissal frames
- asserts:
- no framework exceptions surfaced (`tester.takeException() == null`)
- local moments count increases after save
- specifically protects against the disposed `TextEditingController` race
- Validation
- `flutter analyze` -> pass
- `flutter test` -> pass
## 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`
## Latest Milestone (2026-02-18): Duplicate Profile Merge + Share Deep-Link Polish
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 `ChangeEnvelope`s, 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>`