💪 Wellness Daily — Notion (Life OS)¶
DB ID: 3500950b-d7a9-811c-8e10-f3065f763b35
URL: https://www.notion.so/3500950bd7a9811c8e10f3065f763b35
Parent: Life OS page (37e5e724-ba79-4182-a270-9949b714fab8)
Created: 2026-04-28
Filled by: scripts/integrations/wellness/daily-summary.py cron at 03:00 UTC = 22:00 CT (CDT) / 21:00 CT (CST)
Read by: brain tool_wellness_history(days=N) in inbox_brain.py
Schema¶
| Property | Type | Source |
|---|---|---|
| Date | title | YYYY-MM-DD string |
| Day | date | unique key for upsert |
| Sleep Score | number | Eight Sleep sleep_fitness_score; falls back to Garmin sleep_score if Eight Sleep is partial |
| Sleep Source | select (Eight Sleep / Garmin / Both) | which source primary |
| Duration (h) | number | hours, rounded 0.01 |
| Deep / Light / REM / Awake (min) | numbers | Garmin sleep_*_min |
| HRV (ms) | number | Eight Sleep hrv (preferred) or Garmin hrv_overnight |
| HRV Δ 7d | number | current minus 7d Eight Sleep avg |
| HRV Status | select (Balanced / Unbalanced / Low / High) | Garmin hrv_status |
| RHR (bpm) | number | Eight Sleep rhr or Garmin rhr |
| Body Battery Start / End | numbers | placeholder + Garmin body_battery |
| Stress Avg | number | Garmin stress_avg |
| Training Readiness | number | Garmin training_readiness |
| Steps | number | Garmin steps |
| Active kcal | number | Garmin kcal_active |
| Notes | rich_text | Sonnet-generated 1-2 sentence coach note |
| Tags | multi_select | Recovery / Hard Day / Sleep Debt / Peak / Partial Bed / Travel / Sick |
| Flags | multi_select | partial-bed / watch-no-sync / anomaly-hrv-low / anomaly-hrv-high / anomaly-stress-high / missing-data |
| Journal | rich_text | Justin's manual reflection (left blank by summarizer) |
Tag heuristics (in compute_metrics())¶
- Recovery — HRV ≥ 7d_avg + 5 AND training_readiness ≥ 75
- Hard Day — HRV ≤ 7d_avg - 5 OR stress_avg ≥ 50
- Sleep Debt — duration < 360 min
- Peak — training_readiness ≥ 85 AND HRV ≥ 7d_avg
- Partial Bed — Eight Sleep duration < 240 min (Garmin stepped in as primary)
Flag heuristics¶
- partial-bed — Eight Sleep duration < 240 min, Garmin filled in
- anomaly-hrv-low — HRV Δ7d ≤ -15 ms
- anomaly-hrv-high — HRV Δ7d ≥ +15 ms
- anomaly-stress-high — stress_avg > 60
- missing-data — Eight Sleep partial AND Garmin duration < 240 (no good source)
Idempotency¶
The summarizer queries by Day date property. If a row exists for today's date, it updates that row (notion-update-page); else creates one (notion-create-page). Safe to run multiple times per day — each run refreshes Notes + numbers.
Manual run¶
infra/context-api/.venv/bin/python scripts/integrations/wellness/daily-summary.py
tail -3 logs/integrations/wellness-daily.log
Journaling pattern¶
Tap a day's row → write in the Journal field (free text). Summarizer doesn't touch that field on update. Justin's journal entries stay forever.
Schema changes¶
Use the n8n notion-patch-database workflow to add/modify properties. The summarizer only writes the properties it knows; new fields can be added in Notion UI without breaking the script.