Skip to content

v0.9.1 — Resting heart rate alarm was inverted

Choose a tag to compare

@schimmmi schimmmi released this 29 Aug 18:25
· 3 commits to main since this release
4d9f8ae

⛔ The illness alarm ran backwards

daily_readiness.contributors.resting_heart_rate looks like a heart rate. It is a 0–100 score where higher is better — the inverse of a pulse. alert_system read it as bpm, so:

What actually happened Score Old alarm
Pulse falls 73 → 58 bpm (recovery) rises 🔴 "CRITICAL — possible illness, consult doctor"
Pulse rises during an infection falls silent

The alarm that exists to catch illness was quiet precisely when it should fire.

On 15 days of real data the score and the true resting pulse correlate at −0.920. The statistics report printed a resting-HR "median 97 bpm" while the actual nightly pulse was 61 — bpm do not cap at exactly 100.

What changed

Resting heart rate now comes from the nightly trough (sleep.lowest_heart_rate) in real bpm, through one shared helper (utils/resting_hr.py) so the consumers cannot drift apart again.

  • alert_system — direction corrected; thresholds were already documented in bpm and now mean what they say.
  • illness_detection — the direction was already handled correctly here, but the score saturates at 100 (where most healthy nights sit), so deterioration barely moved it. Real bpm has no ceiling.
  • analytics_tools — now fetches detailed sleep sessions; daily_sleep carries scores only.

🐛 Second bug, found while verifying

Naps report average_heart_rate = 0 and the daily aggregate averaged them in, turning a real 67.75 bpm into 22.58. The guard tested is not None, which 0 passes.

🧪 Tests

9 new cases pin the direction, including one asserting that a falling pulse stays silent — verified to fail against the old logic.

tests/conftest.py makes src/ importable everywhere: two pre-existing files lacked the path insert, which aborted collection, so the suite ran zero tests. It now runs 21.

Version bumped to 0.9.1 — it still read 0.8.0, missed during the 0.9.0 release.

Full Changelog: v0.9.0...v0.9.1