Skip to content

Commit 3084f81

Browse files
committed
Update all AGENTS.md files with current architecture
Main changes documented: - Hybrid classifier (audio + vitals fusion) - REM-optimized classifier with learned parameters - Health Connect integration (working on Android) - Auto-training on session start when model is stale - REM confidence gating (>= 0.5) for playback - New services: hybridClassifier, remOptimizedClassifier, vitalsClassifier - Classifier analysis scripts documentation
1 parent 84256d1 commit 3084f81

3 files changed

Lines changed: 296 additions & 101 deletions

File tree

AGENTS.md

Lines changed: 96 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,54 @@ const baseUrl =
9999
const audioUrl = `${baseUrl}/audio/dreams/${dreamId}_combined.opus`;
100100
```
101101

102-
### Sleep Detection Flow
102+
### Sleep Detection Flow (Hybrid Classifier)
103103

104-
1. `services/sleep.ts` captures microphone via Web Audio API
105-
2. Meyda extracts RMS, spectral features for breathing analysis
106-
3. Breathing regularity + RRV (respiratory rate variability) → sleep stage
107-
4. `onRemStart`/`onRemEnd` callbacks fire when REM detected
108-
5. `SleepModePlayer` plays queued dreams during REM windows
104+
The app uses a hybrid classifier that fuses audio-based breathing analysis with wearable vitals (via HealthConnect/HealthKit):
105+
106+
```
107+
┌─────────────────────────────────────────────────────────────────┐
108+
│ SLEEP SESSION START │
109+
├─────────────────────────────────────────────────────────────────┤
110+
│ 1. Load existing model (or create empty) │
111+
│ 2. Start hybrid session │
112+
│ 3. [Background] Auto-retrain if model >24h old │
113+
└─────────────────────────────────────────────────────────────────┘
114+
115+
┌───────────────────┴───────────────────┐
116+
▼ ▼
117+
┌─────────────────────┐ ┌─────────────────────┐
118+
│ AUDIO SOURCE │ │ VITALS SOURCE │
119+
│ (Microphone) │ │ (HealthConnect) │
120+
├─────────────────────┤ ├─────────────────────┤
121+
│ Web Audio API │ │ HR, HRV, RR │
122+
│ → Meyda features │ │ → 30s polling │
123+
│ → Breathing analysis│ │ → RMSSD/CV analysis │
124+
└─────────────────────┘ └─────────────────────┘
125+
│ │
126+
└───────────────────┬───────────────────┘
127+
128+
┌─────────────────────────────────────────────────────────────────┐
129+
│ HYBRID CLASSIFIER │
130+
│ • Fuses audio + vitals with weighted probabilities │
131+
│ • Applies temporal priors (awake more likely at start/end) │
132+
│ • Two-stage: Awake detection → REM vs NREM │
133+
│ • Computes remConfidence for playback gating │
134+
└─────────────────────────────────────────────────────────────────┘
135+
136+
137+
┌─────────────────────────────────────────────────────────────────┐
138+
│ REM PLAYBACK GATE │
139+
│ if (stage === 'rem' && remConfidence >= 0.5) → play dream │
140+
│ else → log and skip │
141+
└─────────────────────────────────────────────────────────────────┘
142+
```
143+
144+
**Key Components:**
145+
146+
- `services/sleep.ts` - Session management, audio capture, stage transitions
147+
- `services/hybridClassifier.ts` - Fuses audio + vitals sources
148+
- `services/remOptimizedClassifier.ts` - REM-focused classification with learned parameters
149+
- `services/healthConnect.ts` - Android Health Connect integration
109150

110151
### State Sharing (Launch Queue)
111152

@@ -217,21 +258,24 @@ export function useLaunchQueue() {
217258
- Browse/Search with transcript content matching
218259
- Audio playback with progress persistence
219260
- Favorites system (local storage)
220-
- Sleep tracking UI with audio-based detection
221261
- Queue management with shared state
222262
- CI audio generation (Edge TTS + procedural music)
263+
- **Health Connect integration** (Android) - HR, HRV, respiratory rate, sleep stages
264+
- **Hybrid sleep classifier** - fuses audio + vitals for stage detection
265+
- **Auto-training classifier** - learns from user's HealthConnect history
266+
- **REM confidence gating** - prevents false positive dream playback
223267

224268
### Partial
225269

226270
- Auth (UI complete, uses mock data)
227271
- Offline indicator (component exists, not integrated)
228-
- HealthKit/Health Connect (stub only)
272+
- HealthKit (iOS) - stub only, Health Connect (Android) is complete
229273

230274
### Not Started
231275

232276
- Supabase backend integration
233277
- Deep link handling
234-
- Wearable device sync
278+
- watchOS/WearOS companion apps
235279

236280
## Audio Generation
237281

@@ -250,18 +294,53 @@ See `scripts/AGENTS.md` for detailed audio pipeline documentation.
250294
4. Generate audio: `python scripts/generate_audio.py --dream dream-N`
251295
5. Commit only `*_combined.opus` files
252296

253-
## Sleep Detection Thresholds
297+
## Sleep Classifier Configuration
298+
299+
### Two-Stage Classification (Option A+C)
300+
301+
```typescript
302+
// services/remOptimizedClassifier.ts
303+
304+
// Stage 1: Awake Detection
305+
const AWAKE_MEAN_DIFF_BASE_THRESHOLD = 3.0; // HR beat-to-beat variability
306+
const AWAKE_CONSECUTIVE_REQUIRED = 1; // Signals before awake confirmed
307+
308+
// Learned awake priors by 30-min time bins (from Fitbit analysis)
309+
// 0-30min: 38.1%, 30-60min: 4.8%, 60-90min: 1.6%, ...330-360min: 30.9%
310+
311+
// Dynamic threshold adjustment based on time prior:
312+
// prior > 25% → threshold * 0.85 (more sensitive at sleep onset/wake)
313+
// prior < 5% → threshold * 1.3 (less sensitive mid-sleep)
314+
315+
// Stage 2: REM vs NREM
316+
const CV_THRESHOLD = 0.2; // RMSSD coefficient of variation
317+
const REM_CONSECUTIVE_REQUIRED = 2; // Consecutive signals for REM
318+
319+
// Blended awake score: 0.7 * hr_signal + 0.3 * time_prior > 0.4
320+
```
321+
322+
### REM Playback Gating
254323

255324
```typescript
256325
// services/sleep.ts
257-
const BREATHING_RATE_MIN = 8; // BPM
258-
const BREATHING_RATE_MAX = 25; // BPM
259-
const REM_RRV_THRESHOLD = 0.25; // High variability = REM
260-
const DEEP_SLEEP_RRV_THRESHOLD = 0.1; // Low variability = deep
261-
const DROWSY_BREATHING_REGULARITY = 0.7;
262-
const SLEEP_BREATHING_REGULARITY = 0.85;
326+
const MIN_REM_CONFIDENCE_FOR_PLAYBACK = 0.5;
327+
328+
// remConfidence computed from:
329+
// - REM probability from classifier
330+
// - Time bonus (>70 min since sleep start)
331+
// - REM window bonus (in expected REM portion of cycle)
332+
// - Consecutive REM signals
333+
// - REM propensity (increases through night)
263334
```
264335

336+
### Expected Performance (Best Balanced)
337+
338+
| Metric | Value |
339+
| ----------------- | ----- |
340+
| REM Sensitivity | 79.8% |
341+
| Awake Sensitivity | 31.0% |
342+
| Awake Precision | 30.8% |
343+
265344
## Deployment
266345

267346
- **Web**: GitHub Pages at https://context-lab.com/dream-stream/
@@ -333,4 +412,4 @@ Health Connect is integrated and working:
333412

334413
---
335414

336-
_Last updated: 2026-01-13_
415+
_Last updated: 2026-01-15_

scripts/AGENTS.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,46 @@ pip install edge-tts numpy soundfile
170170
# Requires: ffmpeg (system)
171171
```
172172

173+
## Classifier Analysis Scripts
174+
175+
These scripts analyze Fitbit/HealthConnect data to optimize the sleep classifier:
176+
177+
| Script | Purpose |
178+
| ---------------------------- | -------------------------------------------- |
179+
| `parse_fitbit_takeout.py` | Parse Fitbit Takeout data for analysis |
180+
| `compare_all_options.py` | Compare classifier configurations |
181+
| `adaptive_classifier.py` | Test adaptive classifier with learned params |
182+
| `two_stage_classifier.py` | Two-stage awake/REM classifier |
183+
| `analyze_awake.py` | Analyze awake detection features |
184+
| `analyze_temporal_priors.py` | Compute time-based awake priors |
185+
186+
### Running Classifier Evaluation
187+
188+
```bash
189+
# Compare all classifier options (requires notes/raw_sleep_data.json)
190+
python scripts/compare_all_options.py
191+
192+
# Run adaptive classifier with learned parameters
193+
python scripts/adaptive_classifier.py
194+
```
195+
196+
### Data Requirements
197+
198+
Classifier scripts expect `notes/raw_sleep_data.json` with:
199+
200+
- `hrSamples`: Array of `{bpm, time}` objects
201+
- `sleepStages`: Array of `{stage, startTime, endTime}` objects
202+
203+
This data is gitignored (personal health data).
204+
173205
## DO NOT
174206

175207
- Commit `_full.opus`, `_music.opus`, or `_preview.opus` files
176208
- Modify voice/rate/pitch without testing full playback
177209
- Remove [PAUSE] markers without updating pause duration
178210
- Edit dreamData.ts directly (regenerate via build_dream_data.py)
211+
- Commit personal health data (notes/raw_sleep_data.json, etc.)
212+
213+
---
214+
215+
_Last updated: 2026-01-15_

0 commit comments

Comments
 (0)