# HealthProbe - Implementation Status

**Last Updated:** 2026-05-31

## Current Reality

The app currently contains a working SwiftUI + SwiftData prototype with HealthKit capture, snapshot/delta screens, and an initial SQLite archive store.

The product direction has changed. The target architecture is now:
- iOS 15-era compatible;
- direct SQLite archive/analysis database as source of truth;
- differential observation storage;
- Core Data UI/report cache;
- Time Machine UI and scoped exports;
- recovery-compatible archive/export format;
- no in-app restore, backup patching, or HealthKit re-publication.

Current SwiftData models and anomaly-oriented naming are legacy/prototype implementation details.

There are no real deployments, only test installations. Existing prototype databases are disposable: the archive v2 refactor should reset, ignore, or reinitialize old SwiftData/prototype SQLite stores instead of preserving backward compatibility with them.

## Status By Area

| Area | Current Status | Target / Next Work |
|------|----------------|--------------------|
| Product docs | Updated | Keep `HealthProbe/Doc/README.md` as canonical index |
| HealthKit capture | Capture now opens one archive observation per user-visible snapshot, attaches HealthKit pages, deleted-object evidence, and type verification to that observation id before finishing it, no longer aborts initial full-history imports after a fixed 30-minute wall-clock cap while page-level HealthKit timeouts remain in place, defers grouped observation summary/daily aggregate rebuilds until per-type verification instead of rebuilding after every imported page, and persists large HealthKit pages in smaller archive chunks while using smaller and more conservative initial-import page sizes for high-volume types, adaptive write chunk sizing, explicit task yields, and lower-allocation streaming loops to avoid long monolithic SQLite stalls | Continue moving UI/cache reads to archive-backed observation ids and revisit full checkpoint/resume and background collection separately |
| SQLite archive | Archive v2 schema, snapshot-level observation grouping, differential write path, v2 verification/delete bookkeeping, daily aggregate rebuilds, integrity report, v2 record reads, SQL diff/count/aggregate/provenance/consolidation-evidence APIs, large synthetic diff pagination coverage, formal timing/memory metrics, and XCTest coverage are in place; the legacy `archive_samples` mirror has been removed, the hot write path now reuses prepared SQLite statements within grouped page writes instead of reparsing the same SQL for every sample, processes sample rows in a lower-allocation streaming loop, and opens SQLite connections with import-friendly busy timeout / synchronous / temp-store pragmas | Continue moving capture/Dashboard actions to archive/cache DTOs |
| Core Data cache | Initial programmatic Core Data model, full-cache rebuild service, read DTOs for observation/type/diff/health rows, and Dashboard archive-cache status wiring are in place | Move remaining export/report paths to cache DTOs and add targeted partial invalidation |
| SwiftData cache | Exists; test builds now reset legacy prototype UI/archive/cache stores once for archive v2 so old SwiftData-only snapshots are not treated as backed-up observations. Metric timeout calibration, local device profile settings, operation logging, ContentView preview, Settings data maintenance, legacy detail/PDF views, unused legacy repair/observer services, Dashboard view/view-model access, and legacy anomaly/count-drop review have moved outside SwiftData or been removed. Remaining SwiftData imports are inventoried in [`SwiftData-Retirement-Inventory.md`](SwiftData-Retirement-Inventory.md) | Treat as disposable prototype data; stop returning/storing `HealthSnapshot` bridge handles before removing `ModelContainer` |
| UI | Prototype exists; Dashboard status reads archive/cache observation rows and shows cache health, and Dashboard view/view-model code no longer imports SwiftData or reads `ModelContext`; capture/review actions now route through DTOs and snapshot ids, with the remaining legacy bridge isolated in `HealthKitService`. Snapshots and Data Types tab roots no longer import SwiftData, load Core Data cached observation rows, and open archive/cache-backed detail rows; `SnapshotArchiveDetailView` and `DataTypeArchiveDetailView` read Core Data type/diff summaries and page record drill-down through SQLite; unused legacy SwiftData snapshot/type detail and PDF views have been deleted; record-change evolution and temporal distribution screens now receive DTO rows/cache input instead of querying SwiftData directly; export preview reads the archive export API before showing/exporting JSON; simplified detail mode replaces heavy charts with summary rows on small/accessibility layouts or when enabled in Settings; visible change labels now use neutral new/missing/change-review language | Stop writing prototype `HealthSnapshot` bridge rows during capture/review |
| Diff/change explanation | SQL diff summaries, paged diff records, aggregate comparisons, and consolidation-evidence labels exist; legacy anomaly/count-drop review has been removed from active flows; the old direct `HealthSnapshot.typeCounts` diff helper has been retired | Keep active diff/count views on archive/cache DTOs |
| Export | SQLite export preview, paged JSON writing, SHA256 manifest hashing, and `export_manifests` rows are in place for selected records and observation diffs | Fill remaining recovery-compatible envelope metadata, CSV export, relationship preservation, and reproducibility checks |
| Legacy device support | Simplified detail UI mode is implemented for small/accessibility layouts and as a Settings toggle | Remove SwiftData dependency and validate lower deployment targets |
| Recovery workflows | Not supported | Preserve export/archive structure for external recovery tools only |

## Refactoring Priorities

Detailed checkable milestones live in [`Refactoring-Plan.md`](Refactoring-Plan.md).

1. Stop writing prototype `HealthSnapshot` bridge rows during capture/review.
2. Add targeted cache invalidation for affected observation/type ranges.
3. Finish remaining UI language cleanup from anomaly/status to observation/diff/export where legacy model names still leak into active flows.
4. Complete recovery-compatible export metadata, CSV output, and reproducibility checks.
5. Remove SwiftData dependency and validate lower deployment targets.

## Known Prototype Mismatches

- SwiftData currently blocks iOS 15-era device support.
- Some screens still imply snapshot-count monitoring rather than Time Machine inspection.
- Current UI/cache layers still depend on 4 SwiftData-backed files for launch container, capture bridge writes, and remaining model definitions.
- Snapshots timeline/detail rows, Data Types list/detail rows, and record drill-down are archive/cache-backed for new archive v2 observations when cache rows exist.
- Legacy SwiftData-only snapshots are reset for archive v2 test installs rather than migrated.
- Capture strategy and some legacy SwiftData transition paths may still decode or cache too much data for low-end devices.
- Very large first-run HealthKit imports may still require adaptive paging, retryable partial progress, and background-friendly collection beyond the current smaller pages, chunked persistence, and prepared-statement reuse.
- Old prototype database compatibility is no longer required.
- Initial SQLite archive tests cover open/init/reset/idempotency, snapshot-level observation grouping, legacy mirror removal, small observation diffs, large synthetic diff pagination, formal timing/memory metrics, materialized aggregate comparison, source/provenance breakdowns, consolidation-evidence labels, export preview, paged JSON output, and manifest row persistence.
- Initial Core Data cache tests cover full rebuild from SQLite and delete-cache-then-rebuild without losing archive data.

## Verification Checklist

- [x] SQLite archive v2 can reconstruct records visible at observation T.
- [ ] No recurring complete snapshot copies are written for high-volume types.
- [x] SQL diff between two observations runs without loading full datasets into Swift arrays.
- [x] Snapshots timeline rows use Core Data cached observation counts/change summaries when cache rows are available.
- [x] Snapshot tab navigation/detail rows use Core Data cached summaries plus SQLite diff summaries when archive observation ids are available.
- [x] Data Types list rows use Core Data cached counts plus SQLite diff summaries when archive observation ids are available.
- [x] Data type new/missing drill-down pages records from SQLite diff queries when archive observation ids are available.
- [x] Data type diff detail and evolution summaries prefer Core Data cache rows when archive observation ids are available.
- [x] Expensive counts used by reports/UI are cached and rebuildable.
- [x] Deleting Core Data cache and rebuilding from SQLite restores UI/report summaries.
- [x] Dashboard surfaces SQLite/Core Data cache health, cache schema, cache errors, and latest archive observation counts.
- [x] Export can stream/page selected record sets without materializing the full record list.
- [x] Export manifests include hashes and diff observation metadata when applicable.
- [ ] iOS app remains read-only with respect to HealthKit.
- [ ] Docs and UI do not claim in-app restore/re-publication support.
- [x] Legacy/small-device UI mode preserves capture/report/export.

## Historical Notes

Older status docs described a completed snapshot/anomaly/SwiftData system. That was true for the prototype direction, but it is no longer the target architecture.
