1 contributor
# HealthProbe – Claude Code Instructions
## Project Context
**HealthProbe** is an iOS app that audits Apple HealthKit data integrity.
It detects anomalies: data loss, historical insertions, duplicates, divergence trends.
Full specification: `HealthProbe/Doc/HealthProbe – Complete Specification & Motivations.md`
**Current state:** Xcode scaffold only. `ContentView.swift` and `Item.swift` are default templates — replace them entirely.
---
## Claude Code Scope: UI Layer
Claude Code is responsible for:
- All **SwiftUI Views** (`Views/` directory)
- All **ViewModels** (`ViewModels/` directory)
- **Navigation structure** and tab/split layout
- **Design system** (colors, typography, spacing)
- **Preview providers** for all views
- **Accessibility** (VoiceOver, Dynamic Type)
Claude Code does NOT own:
- `Services/` — HealthKit queries, anomaly detection, sync monitoring (see AGENTS.md)
- `Models/` — SwiftData models (see AGENTS.md)
- Entitlements, Info.plist, project configuration
When services are not yet implemented, **consume their protocols and use mock implementations** for UI development.
---
## Target Screen Structure
```
App (TabView)
├── Tab 1: Dashboard → DashboardView
├── Tab 2: Anomalies → AnomalyListView → AnomalyDetailView
├── Tab 3: Audit Trail → AuditTrailView
├── Tab 4: Sync Status → SyncStatusView
└── Tab 5: Settings → SettingsView
```
### DashboardView
- Large status indicator: ✅ Healthy / ⚠️ Check / 🚨 Critical
- Last check timestamp
- Summary cards: samples tracked, anomalies found (all-time)
- Up to 3 recent active alerts (tappable → AnomalyDetailView)
- "Check Now" button (calls monitoring service)
### AnomalyListView
- List of `DetectedAnomaly` sorted by date (most recent first)
- Filter: All / Critical / Warning / Info
- Filter: by type (deletion, insertion, duplicate, divergence)
- Each row: severity badge, type, sample type, date
- Swipe to mark resolved
### AnomalyDetailView
- Full anomaly details
- Evidence dictionary displayed as key-value rows
- Severity badge
- Share button → exports as Markdown (for bug reports)
- "Mark Resolved" action
### AuditTrailView
- Chronological list of `AuditTrailEntry`
- Each row: timestamp, event type chip, message
- Search/filter by event type
- Export button → JSON
### SyncStatusView
- Current iCloud sync state (chip: enabled / local-only)
- Last sync timestamp
- List of `SyncStateChange` events (most recent first)
- Visual indicator when sync is stalled (no event in > 48h)
### SettingsView
- Check frequency: 2h / 6h / 12h / 24h (Picker)
- Sample types to monitor (MultiSelect toggle list)
- Alert thresholds (severity level for push notifications)
- CloudKit sync toggle (off by default, with privacy disclaimer)
- Export all data (JSON)
- Delete all audit data (destructive, confirm alert)
---
## Design Guidelines
**Tone:** Professional, calm, medical-adjacent. Not alarming unless critical.
**Color System:**
```swift
// Status colors
.healthyGreen // SF: green — all clear
.warningAmber // SF: yellow — attention needed
.criticalRed // SF: red — action required
.neutralGray // SF: gray — informational / resolved
```
**Typography:** SF Pro (system font). No custom fonts.
**Spacing:** 8pt grid. Use `VStack(spacing: 12)` as baseline.
**Icons:** SF Symbols only. No third-party icon sets.
**Key SF Symbols:**
- `checkmark.shield.fill` — healthy status
- `exclamationmark.triangle.fill` — warning
- `xmark.shield.fill` — critical
- `clock.arrow.circlepath` — audit trail
- `antenna.radiowaves.left.and.right` — sync
- `waveform.path.ecg` — health data
- `doc.text.magnifyingglass` — anomaly detail
**Dark mode:** Required. Test in both modes.
**Privacy-first UI:**
- Health metric values are **never shown in plain text** in list rows
- Values visible only in `AnomalyDetailView` after tap
- Evidence dictionary values shown as monospace text, not highlighted
---
## SwiftData Integration
Models are defined in `Models/`. Reference them read-only from views:
```swift
// In views, use @Query — never write directly from a View
@Query(sort: \DetectedAnomaly.detectedAt, order: .reverse)
private var anomalies: [DetectedAnomaly]
// Mutations go through ViewModels or services only
```
Until `Models/` are implemented, use mock data via `PreviewProvider`.
---
## ViewModel Pattern
```swift
// Pattern for all ViewModels
@MainActor
@Observable
final class DashboardViewModel {
private let monitor: HealthMonitorProtocol // protocol, not concrete type
var status: HealthStatus = .unknown
var recentAnomalies: [DetectedAnomaly] = []
var lastChecked: Date?
init(monitor: HealthMonitorProtocol = HealthMonitorService.shared) {
self.monitor = monitor
}
func refresh() async {
await monitor.runCheck()
}
}
```
Always inject dependencies via protocols — makes previews and tests possible without real HealthKit.
---
## Mock Data Protocol
Until services are ready, define preview mocks in `Utilities/Mocks.swift`:
```swift
struct MockHealthMonitor: HealthMonitorProtocol {
func runCheck() async { }
var status: HealthStatus { .warning }
}
extension DetectedAnomaly {
static var preview: DetectedAnomaly {
DetectedAnomaly(
detectedAt: .now,
type: "silent_deletion",
severity: "warning",
sampleType: "Steps",
summary: "72 samples missing without deletion event",
evidence: ["loss_count": "72", "loss_percent": "23.4"]
)
}
}
```
---
## File Organization
```
HealthProbe/
├── Views/
│ ├── Dashboard/
│ │ ├── DashboardView.swift
│ │ └── StatusCardView.swift
│ ├── Anomalies/
│ │ ├── AnomalyListView.swift
│ │ └── AnomalyDetailView.swift
│ ├── AuditTrail/
│ │ └── AuditTrailView.swift
│ ├── Sync/
│ │ └── SyncStatusView.swift
│ └── Settings/
│ └── SettingsView.swift
├── ViewModels/
│ ├── DashboardViewModel.swift
│ ├── AnomalyListViewModel.swift
│ └── SyncViewModel.swift
├── Models/ ← NOT owned by Claude Code
├── Services/ ← NOT owned by Claude Code
└── Utilities/
├── Mocks.swift
├── DateFormatters.swift
└── DesignSystem.swift
```
---
## Privacy Directives
**Mandatory — no exceptions:**
- No credentials, tokens, or API keys in any file
- No personal data, device identifiers, or account identifiers
- No real health values in code, comments, previews, or tests
- Synthetic preview data only (see Mocks.swift above)
---
## Before Marking a Task Complete
- [ ] View renders in both Light and Dark mode (use Preview)
- [ ] VoiceOver labels set on interactive elements
- [ ] Dynamic Type tested (at least xSmall and AX3)
- [ ] Works with mock data (no real HealthKit dependency in View layer)
- [ ] No health values displayed without explicit user tap
- [ ] Compiles without warnings