107 lines
4.1 KiB
Markdown
107 lines
4.1 KiB
Markdown
# Data Model
|
|
|
|
The app stores most relationship data in `LocalDataState`, persisted by
|
|
`LocalRepository`.
|
|
|
|
## Aggregate State
|
|
|
|
Source: `lib/app/state/local_data_state.dart`
|
|
|
|
| Field | Type | Meaning |
|
|
| --- | --- | --- |
|
|
| `people` | `List<PersonProfile>` | primary relationship profiles |
|
|
| `moments` | `List<RelationshipMoment>` | interaction and capture history |
|
|
| `ideas` | `List<RelationshipIdea>` | gift, activity, and follow-up ideas |
|
|
| `reminders` | `List<ReminderRule>` | local reminder rules |
|
|
| `tasks` | `List<DashboardTask>` | dashboard task surface |
|
|
| `dismissedSignalIds` | `List<String>` | dismissed generated signal IDs |
|
|
| `sourceLinks` | `List<SourceProfileLink>` | external sender/thread to profile mapping |
|
|
| `sharedMessages` | `List<SharedMessageEntry>` | imported shares attached to profiles |
|
|
| `sharedInbox` | `List<SharedInboxEntry>` | unresolved or ambiguous shares |
|
|
| `personFacts` | `List<PersonFact>` | structured relationship facts |
|
|
| `importantDates` | `List<PersonImportantDate>` | birthdays, anniversaries, events |
|
|
| `preferenceSignals` | `List<PersonPreferenceSignal>` | inferred/confirmed likes/dislikes |
|
|
| `aiSuggestionDrafts` | `List<AiSuggestionDraft>` | pending AI review items |
|
|
|
|
## Profile Model
|
|
|
|
Source: `lib/features/people/domain/person_models.dart`
|
|
|
|
`PersonProfile` is the stable profile root. Important fields:
|
|
|
|
- `id`: internal local ID
|
|
- `name`, `aliases`: local identity only
|
|
- `relationship`: user-facing relationship category
|
|
- `affinityScore`: rough closeness score
|
|
- `nextMoment`: next planned contact or relationship moment
|
|
- `tags`, `notes`, `location`: user-authored context
|
|
- `lastUpdatedAt`, `lastInteractedAt`: operational recency fields
|
|
|
|
`SourceProfileLink` maps an external source to a local profile. It is used by
|
|
share intake to avoid asking again after the user resolves a source identity.
|
|
|
|
## Share Models
|
|
|
|
Source: `lib/features/share_intake/domain/share_models.dart`
|
|
|
|
`SharedPayload` is normalized input from share sheets, action extensions, or
|
|
simulation tools.
|
|
|
|
Key timestamp fields:
|
|
|
|
- `createdAt`: when the app created the normalized payload
|
|
- `receivedAt`: when the app received/imported the share
|
|
- `sharedMessageDateTime`: best-effort original message timestamp extracted
|
|
from shared text, or null
|
|
|
|
Use `sharedMessageDateTime` as temporal evidence. Do not assume it exists. Do
|
|
not infer it from arbitrary content dates such as "birthday is May 20".
|
|
|
|
`CapturedFactDraft` is the review/edit draft before a share becomes a durable
|
|
fact or important date.
|
|
|
|
`SharedMessageEntry` is the durable record attached to a person. Its `sharedAt`
|
|
getter prefers `sharedMessageDateTime` when present.
|
|
|
|
`SharedInboxEntry` is unresolved intake. Reasons include missing identity,
|
|
ambiguous profile match, near-profile conflict, and manual selection needs.
|
|
|
|
## Facts, Dates, And Signals
|
|
|
|
`PersonFact` is durable structured context:
|
|
|
|
- `type`: note, like, dislike, importantDate, giftIdea, placeIdea,
|
|
activityIdea, misc
|
|
- `sourceKind`: manual, shareSheet, or shareInbox
|
|
- `sharedMessageId` or `inboxEntryId`: provenance
|
|
- `needsReview` and `isSensitive`: prompt and UI filtering controls
|
|
|
|
`PersonImportantDate` is a dated profile-owned record. It can come from manual
|
|
input, share review, or AI-assisted extraction.
|
|
|
|
`PersonPreferenceSignal` is inferred or confirmed preference evidence. It
|
|
tracks first/last seen timestamps, occurrence count, source apps, message IDs,
|
|
and evidence snippets.
|
|
|
|
## AI Suggestion Drafts
|
|
|
|
Source: `lib/features/ai_digest/domain/ai_digest_models.dart`
|
|
|
|
AI suggestions are saved as drafts first. Accepted drafts can become local
|
|
ideas, reminders, or tasks. Dismissed drafts stay in history so future digest
|
|
prompts can avoid repeats.
|
|
|
|
## Schema Versioning
|
|
|
|
`LocalRepository` owns `_schemaVersion`. When adding persisted fields:
|
|
|
|
1. Add nullable/defaulted fields where possible.
|
|
2. Update `toJson`, `fromJson`, and `copyWith`.
|
|
3. Increase `_schemaVersion` only when a migration has meaning beyond default
|
|
compatible parsing.
|
|
4. Add repository and serialization tests.
|
|
5. Verify legacy/missing field behavior.
|
|
|
|
The current `fromJson` patterns are intentionally tolerant for many optional
|
|
lists and fields. Keep that property.
|