Skip to content

💪 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.