Skip to content

HRV: default the nightly window to deep sleep, once deep staging holds up against PSG #1008

Description

@ryanbr

What

NOOP already has a WHOOP-comparable HRV setting, and does not default to it. Both HRV defaults currently sit on the less WHOOP-like, more expensive side.

The two defaults

1. HRV window — WHOLE_NIGHT, where WHOOP uses slow-wave sleep.

HrvWindow (Units.kt) already carries both, and the enum's own doc comments say it plainly:

  • WHOLE_NIGHT("whole") — "RMSSD averaged over every 5-min window of the night (NOOP's long-standing value)."
  • DEEP_SLEEP("deep") — "RMSSD over DEEP (slow-wave) sleep windows only — comparable to WHOOP's reading."

An unset value resolves to WHOLE_NIGHT, so every install reads on the axis that does not line up with the number people compare against. The Settings copy already tells the user Deep sleep is the one "matching WHOOP", which makes the default the odd choice rather than the safe one.

2. continuousHrvOvernight defaults to false, so continuous capture runs 24/7.

Turning on "Continuous HRV capture" gives an all-day beat-to-beat stream unless the user separately finds and enables "Overnight only". WHOOP publishes no daytime HRV figure at all — its reading is an overnight one — so a 24/7 stream has no official-app analogue, and the setting's own copy says overnight-only "roughly halves the battery cost". The expensive option is the one you get by default.

(continuousHrv itself defaults to false, which is right and should stay.)

Proposed

Keep both configurable; move the defaults to the WHOOP-like side.

  • continuousHrvOvernight → default true. Low risk: it only narrows a stream the user has explicitly opted into, matches what WHOOP actually reports, and halves the cost of the opt-in. Existing users who already enabled continuous capture should keep whatever they have set rather than silently narrowing.
  • HrvWindow → default DEEP_SLEEP for new installs only. See below.

The part that needs care

Changing the HRV window is not cosmetic: setHrvWindow's own comment notes it "re-scores + re-baselines (the value itself moves)". Flipping the default under existing users would move every HRV number and every baseline built on it, in a direction they did not ask for — the same retroactive-score problem #963 and #983 caused, which is the kind of change that costs trust even when it is more correct.

So: persist the current value explicitly for existing installs on upgrade, and let only fresh installs pick up the new default. That means "default matches WHOOP" applies going forward rather than retroactively. Anyone who wants to move can, and the Settings copy already explains what changes.

Blocker to check first: DEEP_SLEEP pools RMSSD over deep-sleep windows, so it is only as trustworthy as deep-sleep detection. Staging changed in #987, and 5/MG staging is still being worked out. Defaulting to a window that depends on staging quality is only defensible once the benchmark says that staging holds — Tools/SleepPSG scoring the shipped stager against PSG truth is the check that would say so. If deep-sleep detection is not solid on a given strap, whole-night is the more honest default for that strap and the default may need to be family-aware rather than global.

Not in scope here

This does not address the underlying battery cost, which is #1007 — history offload spends ~2.4 h of radio a day regardless of any HRV setting. Narrowing continuous capture to overnight is worth doing on its own merits, but it is not the fix for #1005.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions