# HealthProbe - Core Data Cache Design

**Last Updated:** 2026-05-23
**Status:** Initial programmatic model and full-cache rebuild implemented; UI wiring and targeted invalidation pending

## 1. Purpose

Core Data is not the forensic archive. It is the bounded, UI-friendly store for values already derived from the SQLite archive.

Use Core Data for:
- observation rows shown in timelines;
- type summaries and expensive counts;
- daily/monthly aggregate display rows;
- diff summary rows;
- export history/status rows;
- archive health/status rows;
- local app state and settings that are not forensic evidence.

Do not use Core Data for:
- the only copy of HealthKit samples;
- raw record payload history;
- relationship evidence;
- point-in-time reconstruction truth;
- large record tables.

SQLite wins on disagreement.

## 2. Store Categories

Core Data may contain two categories of entities.

**Rebuildable cache entities**
Can be deleted and rebuilt from SQLite:
- `CachedObservationRow`;
- `CachedTypeSummary`;
- `CachedDailyAggregate`;
- `CachedDiffSummary`;
- `CachedExportManifest`;
- `CachedArchiveHealth`.

**Local app state/settings**
Not forensic, not necessarily rebuildable:
- selected type preferences;
- UI display preferences;
- last opened screen/state;
- feature flags for legacy-device UI simplification.

Cache rebuild must not delete settings unless the user explicitly resets the app.

## 3. Entity Contracts

### CachedObservationRow

Purpose: timeline/list display.

Required fields:
- `observationID`;
- `observedAt`;
- `status`;
- `triggerReason`;
- `timeZoneIdentifier`;
- `trackedTypeCount`;
- `visibleRecordCount`;
- `appearedCount`;
- `disappearedCount`;
- `representationChangedCount`;
- `archiveSchemaVersion`;
- `cacheSchemaVersion`;
- `sourceAggregateHash`;
- `computedAt`.

### CachedTypeSummary

Purpose: per-observation/per-type summary cards and reports.

Required fields:
- `observationID`;
- `sampleTypeIdentifier`;
- `displayName`;
- `visibleRecordCount`;
- `appearedCount`;
- `disappearedCount`;
- `representationChangedCount`;
- `earliestStartDate`;
- `latestEndDate`;
- `valueSum`;
- `valueMax`;
- `aggregateHash`;
- `computedAt`.

### CachedDailyAggregate

Purpose: charts and report tables.

Required fields:
- `observationID`;
- `sampleTypeIdentifier`;
- `bucketStart`;
- `bucketEnd`;
- `timeZoneIdentifier`;
- `visibleRecordCount`;
- `valueSum`;
- `valueMax`;
- `sourceRevisionDisplayHash`;
- `aggregateHash`;
- `computedAt`.

### CachedDiffSummary

Purpose: observation comparison list/detail.

Required fields:
- `fromObservationID`;
- `toObservationID`;
- `sampleTypeIdentifier`;
- `appearedCount`;
- `disappearedCount`;
- `representationChangedCount`;
- `consolidationLikely`;
- `uncertaintyReason`;
- `sourceAggregateHash`;
- `computedAt`.

### CachedExportManifest

Purpose: export history/status display.

Required fields:
- `exportID`;
- `exportKind`;
- `createdAt`;
- `fromObservationID`;
- `toObservationID`;
- `filterSummary`;
- `recordCount`;
- `manifestHash`;
- `fileURLBookmarkData`;
- `status`;
- `computedAt`.

### CachedArchiveHealth

Purpose: archive status screen.

Required fields:
- `archiveSchemaVersion`;
- `cacheSchemaVersion`;
- `lastIntegrityCheckAt`;
- `lastIntegrityStatus`;
- `lastErrorKind`;
- `lastErrorMessageHash`;
- `cacheBuildID`;
- `computedAt`.

## 4. Invalidation

Invalidate/rebuild cache rows when:
- archive schema version changes;
- archive reset/reinitialization occurs;
- selected type registry changes;
- a new observation commits in SQLite;
- aggregate hashes change;
- cache schema version changes.

Rebuild order:
1. archive health/status;
2. observation rows;
3. type summaries;
4. daily/monthly aggregates;
5. diff summaries;
6. export status rows.

Partial rebuild is allowed when SQLite can identify affected observations/types. Full rebuild must remain available for repair and tests.

Implementation note, 2026-05-24: `CoreDataArchiveCacheStore` defines the cache model programmatically and can rebuild all cache entities from the SQLite archive. The first implementation rebuilds observation rows, type summaries, daily aggregates, adjacent-observation diff summaries, export manifest rows, and archive health rows. It is intentionally rebuildable: deleting the Core Data cache must not touch the SQLite archive.

## 5. Legacy Device Mode

Legacy or low-memory UI should still use the same Core Data cache. It may reduce:
- chart density;
- default date range;
- preview row count;
- simultaneous loaded detail panes.

It must preserve:
- capture;
- cached summaries;
- report generation;
- paged SQLite detail/export access.
