Files
rely/docs/progress.md
T

23 KiB

Relationship Saver Progress Log

Updated: 2026-02-15

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:
    • replace no-op scheduler with platform local notifications implementation for Android/iOS/macOS/Windows/Linux/Web-safe fallback.
  2. Conflict resolution UX:
    • current UX shows and dismisses rejections; still missing guided resolve/retry/inspect flows per entity.
  3. Sync trigger maturity:
    • add connectivity-aware triggers and backoff policy for repeated failures.
  4. Test depth:
    • add integration tests for auth + sync + CRUD end-to-end app flows.

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>