docs: add project orientation notes
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
# AGENTS.md
|
||||
|
||||
This file is the fastest orientation doc for future coding agents working in
|
||||
this repository.
|
||||
|
||||
## Project Summary
|
||||
|
||||
`relationship_saver` is a Flutter app for capturing and maintaining
|
||||
relationship context locally. The app already supports:
|
||||
|
||||
- people profiles with aliases, notes, tags, facts, important dates, and
|
||||
preference signals
|
||||
- moments, ideas, reminders, and dashboard tasks
|
||||
- Android/in-app share-intake flows with inbox-first review for ambiguous
|
||||
content
|
||||
- local notification scheduling for reminders
|
||||
- fake-backend auth/sync flows and REST/OpenAPI scaffolding for later backend
|
||||
work
|
||||
|
||||
The current product posture is local-first and prototype-oriented, not a fully
|
||||
server-backed production app.
|
||||
|
||||
## Canonical Code Paths
|
||||
|
||||
Start here before changing behavior:
|
||||
|
||||
- `lib/main.dart`: app entry
|
||||
- `lib/app/relationship_saver_app.dart`: root widget, auth gate, global
|
||||
listeners
|
||||
- `lib/app/presentation/app_shell.dart`: responsive shell and navigation
|
||||
- `lib/app/data/relationship_repository.dart`: aggregate local-first write
|
||||
boundary
|
||||
- `lib/features/sync/data/sync_queue_repository.dart`: queued mutation store
|
||||
- `lib/integrations/backend/backend_gateway_provider.dart`: fake vs REST
|
||||
gateway selection
|
||||
- `lib/core/config/app_config.dart`: runtime flags
|
||||
|
||||
## Architecture Reality
|
||||
|
||||
The repo is in a vertical-slice migration.
|
||||
|
||||
- Canonical structure is `lib/app`, `lib/features`, `lib/core`,
|
||||
`lib/integrations`
|
||||
- Many older files at slice roots are compatibility exports
|
||||
- Prefer editing canonical files under:
|
||||
- `presentation/`
|
||||
- `application/`
|
||||
- `domain/`
|
||||
- `data/`
|
||||
- Avoid expanding legacy compatibility files unless the task is specifically
|
||||
about keeping old imports working
|
||||
|
||||
Useful orientation docs:
|
||||
|
||||
- `lib/README.md`
|
||||
- `lib/app/README.md`
|
||||
- `lib/features/README.md`
|
||||
- `lib/core/README.md`
|
||||
- slice READMEs inside `lib/features/*`
|
||||
|
||||
## Main Product Slices
|
||||
|
||||
- `people`: primary relationship workspace and richest data model
|
||||
- `share_intake`: normalized shared payloads, review flows, inbox routing
|
||||
- `sync`: queued changes, push/pull orchestration, rejection repair
|
||||
- `reminders`: local reminder rules and notification scheduling
|
||||
- `dashboard`: overview metrics and graph preview/explorer
|
||||
- `settings`: trust/privacy copy, AI config, share simulation, environment
|
||||
diagnostics
|
||||
- `auth`: sign-in UI and session lifecycle
|
||||
|
||||
## Storage And Data Flow
|
||||
|
||||
- Local state is centered on `LocalDataState` in `lib/app/state/`
|
||||
- `LocalRepository` persists a mostly single aggregate snapshot
|
||||
- Default local store is Hive; shared preferences remains as legacy fallback
|
||||
and migration path
|
||||
- Sync queue state is persisted separately through the sync store abstraction
|
||||
- The app is intentionally offline-safe in fake-backend mode
|
||||
|
||||
## Runtime Flags
|
||||
|
||||
Defined in `lib/core/config/app_config.dart`:
|
||||
|
||||
- `USE_FAKE_BACKEND=true` by default
|
||||
- `BACKEND_BASE_URL`
|
||||
- `USE_HIVE_LOCAL_DB=true` by default
|
||||
- `ENABLE_BACKGROUND_SYNC=true` by default
|
||||
- `BACKGROUND_SYNC_INTERVAL_SECONDS=180` by default
|
||||
- `ENABLE_LOCAL_NOTIFICATIONS=true` by default
|
||||
- `ENABLE_WHATSAPP_SHARE_INTAKE=true` by default
|
||||
|
||||
If behavior seems surprising, check the active `--dart-define` values first.
|
||||
|
||||
## Backend Boundary
|
||||
|
||||
- Transport contract is documented in `docs/api/openapi.yaml`
|
||||
- Architectural rationale lives in
|
||||
`docs/ADR/0002-backend-protocol-rest-openapi.md`
|
||||
- `BackendGatewayFake` is still the default development path
|
||||
- `BackendGatewayRest` is the real transport boundary when fake mode is off
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- iOS share extension work is deferred; see `docs/open-tasks.md`
|
||||
- Native share-entry support is stronger on Android than iOS
|
||||
- Sync scaffolding exists, but not all newer local entities are mapped to the
|
||||
backend protocol yet
|
||||
- The repo currently contains a lot of in-flight migration work and
|
||||
compatibility exports
|
||||
|
||||
## Working Guidance
|
||||
|
||||
- Read the relevant slice README before changing a feature
|
||||
- Treat existing uncommitted changes as user work unless you created them
|
||||
- Prefer canonical slice files over compatibility exports
|
||||
- Keep docs aligned with the verified code, not with older plans
|
||||
- When changing architecture-level behavior, update the nearest README or this
|
||||
file if it affects future orientation
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
flutter test
|
||||
flutter analyze
|
||||
dart run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
@@ -1,17 +1,120 @@
|
||||
# relationship_saver
|
||||
# Relationship Saver
|
||||
|
||||
A new Flutter project.
|
||||
`relationship_saver` is a local-first Flutter app for managing relationship
|
||||
context: people, moments, ideas, reminders, share-intake, and lightweight
|
||||
signals that can later support sync and AI-assisted workflows.
|
||||
|
||||
## Getting Started
|
||||
The app currently runs as a prototype-friendly single-client build:
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
- Flutter + Material UI
|
||||
- Riverpod for app state
|
||||
- Hive-backed local persistence by default
|
||||
- fake backend enabled by default for offline-safe development
|
||||
- REST/OpenAPI scaffolding for future auth + sync work
|
||||
- local notifications for reminders
|
||||
- Android text-share entry and in-app share simulation tools
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
## Current Architecture
|
||||
|
||||
- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter)
|
||||
- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources)
|
||||
The codebase is mid-migration from an older horizontal structure to a
|
||||
vertical-slice layout.
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
- `lib/app/`: app bootstrap, shell navigation, aggregate persistence, shared
|
||||
app state
|
||||
- `lib/features/`: product slices such as `people`, `share_intake`, `sync`,
|
||||
`reminders`, `dashboard`, and `settings`
|
||||
- `lib/core/`: cross-cutting primitives like config, auth, networking, theme,
|
||||
and shared presentation helpers
|
||||
- `lib/integrations/backend/`: backend-facing gateway contracts, REST/fake
|
||||
implementations, DTOs, and mappers
|
||||
|
||||
Many older root-level files under `lib/features/*` still exist as compatibility
|
||||
exports. New work should generally target the canonical files in `app/`,
|
||||
`core/`, or slice subfolders such as `presentation/`, `application/`,
|
||||
`domain/`, and `data/`.
|
||||
|
||||
## Key Runtime Behavior
|
||||
|
||||
- Entry point: `lib/main.dart`
|
||||
- Root widget: `lib/app/relationship_saver_app.dart`
|
||||
- Authenticated shell: `lib/app/presentation/app_shell.dart`
|
||||
- Local-first aggregate repository:
|
||||
`lib/app/data/relationship_repository.dart`
|
||||
- Queued sync persistence:
|
||||
`lib/features/sync/data/sync_queue_repository.dart`
|
||||
|
||||
Notable build-time flags live in `lib/core/config/app_config.dart`:
|
||||
|
||||
- `USE_FAKE_BACKEND` defaults to `true`
|
||||
- `BACKEND_BASE_URL`
|
||||
- `USE_HIVE_LOCAL_DB`
|
||||
- `ENABLE_BACKGROUND_SYNC`
|
||||
- `BACKGROUND_SYNC_INTERVAL_SECONDS`
|
||||
- `ENABLE_LOCAL_NOTIFICATIONS`
|
||||
- `ENABLE_WHATSAPP_SHARE_INTAKE`
|
||||
|
||||
## Run
|
||||
|
||||
Install packages:
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
Run with the default fake backend:
|
||||
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
Run against a REST backend:
|
||||
|
||||
```bash
|
||||
flutter run \
|
||||
--dart-define=USE_FAKE_BACKEND=false \
|
||||
--dart-define=BACKEND_BASE_URL=https://api.example.com
|
||||
```
|
||||
|
||||
Run tests:
|
||||
|
||||
```bash
|
||||
flutter test
|
||||
```
|
||||
|
||||
Generate code:
|
||||
|
||||
```bash
|
||||
dart run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
## Current Product Areas
|
||||
|
||||
- `Dashboard`: overview cards and relationship graph preview/explorer
|
||||
- `People`: primary workspace for profiles, notes, facts, dates, tags, and
|
||||
preference signals
|
||||
- `Moments`: interaction/capture history
|
||||
- `Signals`: lightweight prompts derived from local relationship context
|
||||
- `Ideas`: follow-up and gift/activity/place ideas
|
||||
- `Reminders`: reminder rules plus local notification scheduling
|
||||
- `Sync`: queued change diagnostics and repair surface
|
||||
- `Settings`: environment flags, trust/privacy copy, AI config, share
|
||||
simulation, and notification permission actions
|
||||
|
||||
## Docs
|
||||
|
||||
- [Setup](docs/SETUP.md)
|
||||
- [Progress Log](docs/progress.md)
|
||||
- [Open Tasks](docs/open-tasks.md)
|
||||
- [Client Audit](docs/client-audit-relationship-app.md)
|
||||
- [Client Implementation Plan](docs/client-implementation-plan.md)
|
||||
- [Client Iteration Summary](docs/client-iteration-summary.md)
|
||||
- [Backend ADR](docs/ADR/0002-backend-protocol-rest-openapi.md)
|
||||
- [OpenAPI Contract](docs/api/openapi.yaml)
|
||||
- [Contributor Notes](AGENTS.md)
|
||||
|
||||
## Known Gaps
|
||||
|
||||
- iOS share-sheet integration is still deferred; see `docs/open-tasks.md`
|
||||
- sync/backend contracts exist, but the product remains primarily local-first
|
||||
- the repository layer still persists one aggregate snapshot for most local
|
||||
state while the slice migration continues
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
# Client Audit: Relationship Assistant App
|
||||
|
||||
Date: 2026-04-01
|
||||
|
||||
## Current implementation summary
|
||||
|
||||
The client is a Flutter app using Riverpod for state management and a single
|
||||
`MaterialApp` rooted at `lib/main.dart`. Authenticated users land in a custom
|
||||
shell with index-based navigation across dashboard, people, moments, signals,
|
||||
ideas, reminders, sync, and settings.
|
||||
|
||||
The app is already local-first in practice. Product state lives in
|
||||
`LocalRepository` and is persisted through a `LocalDataStore` abstraction with
|
||||
Hive as the default backend and shared preferences as a fallback/migration
|
||||
path. There is also background sync scaffolding, notification scheduling, and a
|
||||
fake backend mode for offline development.
|
||||
|
||||
Share intake exists, but the implementation is narrow. Flutter-side logic
|
||||
supports a WhatsApp-oriented share parser, source-link resolution, and a manual
|
||||
share inbox. Native platform wiring is incomplete for production-grade cross-app
|
||||
sharing, especially on iOS and likely also on Android for text share intents.
|
||||
|
||||
## A. Current implementation inventory
|
||||
|
||||
| Feature Area | Current State |
|
||||
| --- | --- |
|
||||
| Client technology | Flutter |
|
||||
| State management | Riverpod (`Notifier`, `AsyncNotifier`, provider overrides in tests) |
|
||||
| Navigation | Single `MaterialApp`, custom shell, route pushes for secondary flows |
|
||||
| Local persistence | Hive by default, shared preferences fallback/migration |
|
||||
| Auth | Local/fake-friendly sign-in flow with token-store abstractions |
|
||||
| People list/detail | Implemented, responsive, searchable, editable |
|
||||
| Person creation/editing | Implemented with validation and duplicate-name warning |
|
||||
| Notes/profile context | Implemented as a single freeform notes field plus tags |
|
||||
| Moments/captures | Implemented |
|
||||
| Ideas | Implemented |
|
||||
| Reminders | Implemented with local notification scaffold |
|
||||
| Shared message history | Implemented per profile |
|
||||
| Share intake | Implemented in Flutter, but WhatsApp-specific and not fully generalized |
|
||||
| Share inbox | Implemented for unresolved profile matching |
|
||||
| Source linking | Implemented for repeated source-to-profile matching |
|
||||
| Preference inference | Implemented locally from shared chat text |
|
||||
| Search/filtering | Implemented for people; limited elsewhere |
|
||||
| Theming/design system | Implemented via `AppTheme`, custom frosted cards, responsive layouts |
|
||||
| Tests | Good targeted widget/unit coverage, no true end-to-end native share tests |
|
||||
| Backend sync readiness | Good scaffolding, still fake/offline-friendly |
|
||||
| Privacy/trust UX | Limited; local-first behavior exists more in code than in user-facing copy |
|
||||
| Cross-platform share viability | Partial; Flutter layer exists, native integration incomplete |
|
||||
|
||||
## B. Grading
|
||||
|
||||
| Feature Area | Status | Grade | Notes | Risk / Missing Pieces | Recommended Next Step |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| App architecture | Present | B | Clear enough separation between UI, local repository, sync, and integrations | Some large UI files, especially `PeopleView` | Add smaller share/fact modules instead of broad refactors |
|
||||
| Local-first persistence | Present | A- | Hive-backed state with migration path and test coverage | Still JSON-in-Hive rather than richer queryable store | Keep current approach for this iteration |
|
||||
| People management | Present | B | Good responsive UI, editing, duplicate warning, merge flow | Person model is too thin for relationship intelligence | Extend model with aliases, facts, dates, timestamps |
|
||||
| Moments / history | Present | B | Useful local activity log | History is not yet strongly typed for preferences/dates/fact provenance | Add structured facts on top rather than replacing moments |
|
||||
| Ideas / reminders | Present | B | Solid founder-mode utility already | Not tightly connected to share capture | Reuse future share classification to feed these areas later |
|
||||
| Share intake pipeline | Partial | C | Flutter-side ingest and inbox exist | WhatsApp-specific, no generic text/URL pipeline, native wiring incomplete | Generalize payload normalization and improve clarification UX |
|
||||
| Person resolution | Partial | B- | Exact/near-match logic and source links already exist | Resolution is tied to sender matching and not broader share assignment | Add explicit assign/create/save-to-inbox review flow |
|
||||
| Inbox / triage | Partial | C+ | Resolves ambiguous source matching | Cannot yet classify into structured facts/dates/preferences | Add fact classification and later reassignment/edit support |
|
||||
| Search / discoverability | Partial | C+ | People search/filter exists | No real inbox/fact/date search | Keep scope limited; prepare data for later search expansion |
|
||||
| Privacy / trust UX | Weak | D | Local-first architecture exists | App does not clearly explain on-device storage or future AI sharing controls | Add clear local-first settings copy and sensitive-data affordances |
|
||||
| Cross-platform share readiness | Weak | D | Plugin added, listener implemented | Android manifest missing share intent filters; iOS share extension not configured | Fix Android now, document iOS as deferred native work |
|
||||
| Test posture | Present | B+ | Good unit/widget coverage for local repo and share inbox | Missing tests for generalized share parsing and structured triage | Add targeted parser/repository/widget tests |
|
||||
|
||||
## C. Product readiness assessment
|
||||
|
||||
### Solo founder daily use
|
||||
|
||||
Current usefulness is moderate. The app already supports keeping people,
|
||||
captures, reminders, and ideas locally, which is enough for founder testing.
|
||||
However, the most important real-world capture path, sharing snippets from other
|
||||
apps, is not yet strong enough to rely on daily.
|
||||
|
||||
### Friction of data entry
|
||||
|
||||
Manual entry is acceptable. Cross-app capture still has too much friction
|
||||
because it is optimized around one parser path instead of a general intake
|
||||
flow. Ambiguous content can be saved, but not yet shaped into structured,
|
||||
reviewable facts.
|
||||
|
||||
### Trust / privacy feel
|
||||
|
||||
The implementation is local-first, but the UX does not communicate that clearly
|
||||
enough. For a relationship app, trust is part of the product. The app should
|
||||
say what stays on device, what is not yet shared, and how users can correct or
|
||||
delete imported facts.
|
||||
|
||||
### Extensibility for future LLM support
|
||||
|
||||
Reasonably good. The repository pattern, fake backend mode, and local inferred
|
||||
preference signals create a workable foundation. The main gap is data shape:
|
||||
profile context is still too flat, and shared content is not normalized into a
|
||||
recommendation-ready structure.
|
||||
|
||||
### Cross-platform viability
|
||||
|
||||
Good at the Flutter layer, incomplete at the native share-entry layer. Android
|
||||
needs explicit share intent wiring. iOS still lacks a real share extension.
|
||||
|
||||
### Likely adoption blocker
|
||||
|
||||
The biggest blocker is not “AI quality”; it is capture friction. If sharing a
|
||||
snippet from WhatsApp, Safari, Notes, or Messages into the app is unreliable or
|
||||
too manual, the product will not accumulate enough high-value context to become
|
||||
habit-forming.
|
||||
|
||||
## D. Top implementation priorities
|
||||
|
||||
1. Generalize share capture into a platform-aware text/URL pipeline with a
|
||||
clear internal payload model and Android native entry wiring.
|
||||
2. Add an inbox-first clarification flow that lets the user assign to an
|
||||
existing person, create a new person quickly, or save unresolved data for
|
||||
later.
|
||||
3. Extend the local person knowledge model with aliases, structured facts,
|
||||
important dates, timestamps, and source traceability.
|
||||
4. Upgrade the inbox from “resolve person only” to “triage into note / like /
|
||||
dislike / date / idea-ish fact”.
|
||||
5. Improve privacy/trust wording and make correction paths more obvious.
|
||||
|
||||
## Recommended scope for this iteration
|
||||
|
||||
Implement a disciplined client-only slice:
|
||||
|
||||
- generic shared text / URL normalization
|
||||
- Android text share intent support
|
||||
- share clarification sheet for assign/create/inbox
|
||||
- richer local fact/date models with provenance
|
||||
- inbox triage into structured facts or important dates
|
||||
- person detail UI for reviewing captured facts/dates
|
||||
- targeted tests
|
||||
|
||||
Explicitly defer:
|
||||
|
||||
- native iOS share extension target work
|
||||
- real backend sync of new fact/date entities
|
||||
- real LLM or recommendation calls
|
||||
- large navigation or persistence rewrites
|
||||
@@ -0,0 +1,173 @@
|
||||
# Client Implementation Plan
|
||||
|
||||
Date: 2026-04-01
|
||||
|
||||
## Chosen scope for this iteration
|
||||
|
||||
This iteration focuses on the smallest slice that materially improves founder
|
||||
testing:
|
||||
|
||||
1. Generalize intake from WhatsApp-only text import to a broader shared payload
|
||||
pipeline that supports:
|
||||
- plain text
|
||||
- URL
|
||||
- text + URL
|
||||
2. Add an explicit clarification flow for ambiguous shares:
|
||||
- assign to existing person
|
||||
- create person quickly
|
||||
- save to inbox for later
|
||||
3. Improve the local person knowledge model with:
|
||||
- aliases
|
||||
- structured captured facts
|
||||
- important dates
|
||||
- timestamps
|
||||
- source/provenance metadata
|
||||
4. Upgrade inbox triage so unresolved shares can be converted into:
|
||||
- note
|
||||
- like
|
||||
- dislike
|
||||
- important date
|
||||
- gift idea
|
||||
- place idea
|
||||
- activity idea
|
||||
- misc fact
|
||||
5. Add trust-facing settings copy and targeted tests.
|
||||
|
||||
## Why this scope
|
||||
|
||||
- It directly improves the most important product workflow: fast capture from
|
||||
outside the app.
|
||||
- It stays client-side and local-first.
|
||||
- It does not require a storage rewrite or backend coupling.
|
||||
- It produces data structures that future LLM/recommendation work can consume.
|
||||
- It keeps risk contained by extending the existing repository and views rather
|
||||
than replacing them.
|
||||
|
||||
## Affected files / modules
|
||||
|
||||
### Expected to change
|
||||
|
||||
- `lib/main.dart`
|
||||
- `lib/features/local/local_models.dart`
|
||||
- `lib/features/local/local_repository.dart`
|
||||
- `lib/features/people/people_view.dart`
|
||||
- `lib/features/settings/settings_view.dart`
|
||||
- `lib/features/share_intake/share_inbox_view.dart`
|
||||
- `lib/features/share_intake/whatsapp_share_listener.dart` or replacement
|
||||
- `android/app/src/main/AndroidManifest.xml`
|
||||
- `test/features/local/local_repository_test.dart`
|
||||
- `test/features/share_intake/share_inbox_view_test.dart`
|
||||
|
||||
### Expected to add
|
||||
|
||||
- generic share payload parser / models
|
||||
- share review sheet / dialog component
|
||||
- parser unit tests
|
||||
- iteration summary doc
|
||||
|
||||
## Architecture decisions
|
||||
|
||||
### 1. Keep `LocalRepository` as the orchestration layer
|
||||
|
||||
Reason:
|
||||
- It already owns local persistence, entity updates, and ingestion logic.
|
||||
- Extending it is safer than introducing a second persistence coordinator.
|
||||
|
||||
Tradeoff:
|
||||
- The file remains large.
|
||||
|
||||
Mitigation:
|
||||
- Add focused helpers/models for share parsing and captured-fact typing rather
|
||||
than pushing more UI logic into the repository.
|
||||
|
||||
### 2. Add structured fact/date entities instead of overloading `notes`
|
||||
|
||||
Reason:
|
||||
- Future recommendation features need provenance, timestamps, and type-safe
|
||||
context.
|
||||
- Users need auditability and correction, not just a bigger notes blob.
|
||||
|
||||
Tradeoff:
|
||||
- More model surface area now.
|
||||
|
||||
Mitigation:
|
||||
- Keep entity types intentionally small and local-only for this iteration.
|
||||
|
||||
### 3. Prefer inbox-first safety over aggressive auto-assignment
|
||||
|
||||
Reason:
|
||||
- Wrong person attachment is worse than extra triage work in this domain.
|
||||
|
||||
Decision:
|
||||
- Only auto-assign when confidence is genuinely high.
|
||||
- Otherwise open clarification UI or save to inbox.
|
||||
|
||||
### 4. Fix Android share entry now, defer iOS native extension
|
||||
|
||||
Reason:
|
||||
- Android manifest support is low-cost and unblocks real testing.
|
||||
- Proper iOS share extension work is native-project-heavy and should be treated
|
||||
as a separate scoped task.
|
||||
|
||||
## UX flows
|
||||
|
||||
### Flow A: direct share received with high-confidence target
|
||||
|
||||
1. Normalize incoming share into `SharedPayload`.
|
||||
2. If a stable source link or clear unique alias/name match exists, allow direct
|
||||
save to the person.
|
||||
3. Persist the payload history plus a structured fact defaulting to `note`
|
||||
unless a better classification is explicitly chosen.
|
||||
4. Show confirmation snackbar and navigate to the relevant destination on cold
|
||||
start.
|
||||
|
||||
### Flow B: share received without safe target
|
||||
|
||||
1. Normalize into `SharedPayload`.
|
||||
2. Open a lightweight review sheet when possible.
|
||||
3. Offer:
|
||||
- recent people / candidate people
|
||||
- quick create person
|
||||
- save to inbox
|
||||
4. If the user saves to inbox, persist payload + draft classification and leave
|
||||
the item unresolved.
|
||||
|
||||
### Flow C: inbox triage later
|
||||
|
||||
1. Open `Share Inbox`.
|
||||
2. Review the preview text/URL and suggested candidates.
|
||||
3. Choose person or create one.
|
||||
4. Choose classification and edit the extracted content.
|
||||
5. Save as structured fact/date.
|
||||
|
||||
## Risks
|
||||
|
||||
### Risk: model expansion causes migration issues
|
||||
|
||||
Fallback:
|
||||
- Keep new JSON fields backward-compatible with defaults in `fromJson`.
|
||||
|
||||
### Risk: generic share parsing creates false confidence
|
||||
|
||||
Fallback:
|
||||
- Default to inbox / manual clarification for unclear payloads.
|
||||
|
||||
### Risk: too much UI churn in `PeopleView`
|
||||
|
||||
Fallback:
|
||||
- Add new review sections for facts/dates without reworking the whole people
|
||||
editor architecture.
|
||||
|
||||
### Risk: native plugin behavior differs across platforms
|
||||
|
||||
Fallback:
|
||||
- Keep settings-based share simulation path for deterministic local testing.
|
||||
|
||||
## Intentionally deferred
|
||||
|
||||
- iOS share extension target creation and App Group setup
|
||||
- image/file share support
|
||||
- sync mapping for new fact/date entities
|
||||
- AI-driven classification/recommendations
|
||||
- full-text search across inbox/facts/dates
|
||||
- notification engine hooks for new entities
|
||||
@@ -0,0 +1,146 @@
|
||||
# Client Iteration Summary
|
||||
|
||||
Date: 2026-04-01
|
||||
|
||||
## What was implemented
|
||||
|
||||
This iteration focused on client-side share capture, local-first structure, and
|
||||
safer person assignment.
|
||||
|
||||
Implemented:
|
||||
|
||||
- generic shared payload normalization for:
|
||||
- plain text
|
||||
- URL
|
||||
- text + URL
|
||||
- a review-first share capture sheet for:
|
||||
- assign to existing person
|
||||
- create person quickly
|
||||
- save to inbox
|
||||
- richer local person model support:
|
||||
- aliases / nicknames
|
||||
- last updated / last interacted timestamps
|
||||
- richer local knowledge entities:
|
||||
- structured captured facts
|
||||
- important dates
|
||||
- source/provenance metadata
|
||||
- sensitive flag scaffolding
|
||||
- inbox triage improvements:
|
||||
- draft mapping to note / like / dislike / date / gift / place / activity / misc
|
||||
- create person directly from inbox
|
||||
- resolve to existing person with fact mapping
|
||||
- people profile UI improvements:
|
||||
- aliases visible in profile context
|
||||
- captured facts section
|
||||
- important dates section
|
||||
- edit/delete support for facts and dates
|
||||
- Android native text share entry:
|
||||
- `ACTION_SEND` text intent filter added to `AndroidManifest.xml`
|
||||
- trust/privacy wording:
|
||||
- clearer local-first copy in settings
|
||||
- tests:
|
||||
- generic share payload parser tests
|
||||
- repository tests for inbox-to-fact and date persistence
|
||||
- updated share inbox widget test flow
|
||||
|
||||
## Architecture decisions
|
||||
|
||||
### Kept the existing repository-centered local architecture
|
||||
|
||||
`LocalRepository` remains the orchestrator for local persistence and ingest.
|
||||
This avoided a risky refactor and let the new share pipeline build on existing
|
||||
person/source-link/moment infrastructure.
|
||||
|
||||
### Added structured fact/date entities instead of overloading notes
|
||||
|
||||
This creates a cleaner bridge to future recommendation, summarization, and sync
|
||||
work. Shared captures can now produce auditable, typed local knowledge instead
|
||||
of only raw note blobs.
|
||||
|
||||
### Used a review-first share flow for safety
|
||||
|
||||
Rather than silently guessing in generic share cases, the app now asks for a
|
||||
target person or lets the user save to inbox. This is the safer default for a
|
||||
relationship product.
|
||||
|
||||
## Known limitations
|
||||
|
||||
- iOS still does not have a real share extension target configured. The Flutter
|
||||
share logic exists, but native iOS share-sheet presence remains deferred.
|
||||
- Android share support added here is text-focused only.
|
||||
- Generic share flows do not infer advanced semantic structure automatically
|
||||
beyond the existing preference extractor.
|
||||
- Captured facts and important dates are local-only and not yet mapped into the
|
||||
backend sync protocol.
|
||||
- Inbox triage currently converts one structured draft per inbox item. It does
|
||||
not yet split a single payload into multiple facts.
|
||||
- Search is still strongest in People and not yet expanded across facts/dates/
|
||||
inbox.
|
||||
|
||||
## What should happen next in a backend / LLM session
|
||||
|
||||
1. Define backend entity contracts for:
|
||||
- person aliases
|
||||
- structured facts
|
||||
- important dates
|
||||
- shared payload provenance
|
||||
2. Add sync-envelope mappings for the new local entities.
|
||||
3. Introduce optional AI-assisted extraction that proposes:
|
||||
- multiple facts from one payload
|
||||
- date detection
|
||||
- confidence scoring
|
||||
- recommendation context packaging
|
||||
4. Add server-compatible merge/reconciliation rules for conflicting profile
|
||||
facts and dates.
|
||||
5. Implement explicit privacy controls for any future cloud or AI sharing.
|
||||
|
||||
## Manual walkthrough
|
||||
|
||||
### 1. Create person
|
||||
|
||||
- Open `People`.
|
||||
- Tap `Add person`.
|
||||
- Enter:
|
||||
- `Name`
|
||||
- `Relationship`
|
||||
- optional `Aliases`
|
||||
- optional notes/tags/location
|
||||
- Save.
|
||||
|
||||
### 2. Share text into app
|
||||
|
||||
- On Android, share any text snippet into the app from another app.
|
||||
- Or use `Settings` -> `Simulate Share Capture`.
|
||||
- The review sheet should open showing the parsed text/URL preview.
|
||||
|
||||
### 3. Resolve ambiguity
|
||||
|
||||
- In the review sheet, choose a fact type such as `Like` or `Note`.
|
||||
- Pick an existing person from recent chips or the full dropdown.
|
||||
- Save to that person.
|
||||
|
||||
### 4. Save to inbox
|
||||
|
||||
- Repeat with another shared snippet.
|
||||
- In the review sheet, choose `Save To Inbox`.
|
||||
- Open `Share Inbox`.
|
||||
|
||||
### 5. Assign later
|
||||
|
||||
- In `Share Inbox`, open the queued item.
|
||||
- Confirm or change the fact mapping.
|
||||
- Choose `Review & Save` to match an existing person, or `Create Person`.
|
||||
- Complete the flow.
|
||||
|
||||
### 6. Edit captured fact
|
||||
|
||||
- Open `People`.
|
||||
- Select the person.
|
||||
- In `Captured facts`, tap `Edit` on the new fact.
|
||||
- Change the text/label/type or sensitive flag and save.
|
||||
|
||||
### 7. Edit captured date
|
||||
|
||||
- If the capture was saved as a date, open `Important dates`.
|
||||
- Tap `Edit`.
|
||||
- Adjust label/classification/date and save.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Relationship Saver Progress Log
|
||||
|
||||
Updated: 2026-02-22
|
||||
Updated: 2026-02-23
|
||||
|
||||
## Collaboration Rule (Carry Forward)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user