Skip to content

fix(sleep): select the stager by device family only; remove the V2 toggle - #347

Closed
tanarchytan wants to merge 1 commit into
ryanbr:mainfrom
tanarchytan:fix/sleep-v2-family-only
Closed

fix(sleep): select the stager by device family only; remove the V2 toggle#347
tanarchytan wants to merge 1 commit into
ryanbr:mainfrom
tanarchytan:fix/sleep-v2-family-only

Conversation

@tanarchytan

Copy link
Copy Markdown

What

Removes the per-user "Experimental sleep staging (V2)" toggle and selects the staging engine purely by device family.

V2 is right on 5.0/MG and wrong on WHOOP 4.0 (the #319 sparse-motion inflation, fixed by #327), so the family gate already decided the engine. The toggle only added confusion — a 4.0 owner "enabling V2" changed nothing yet looked broken (issue #345).

Changes

Verification

  • Android: :app:testFullDebugUnitTest green — the family-gate SleepV2FamilyGateTest and the self-heal SleepStagerV2Test are updated and passing.
  • Swift: mirrored byte-identically. App-target Swift (IntelligenceEngine / Repository / SettingsView / PuffinExperiment) has no CI, so it needs a Mac build to confirm compile — flagged for a maintainer with Xcode.

Completes the #327 self-heal follow-up; addresses the #345 confusion.

…ggle

V2 is objectively right on 5.0/MG and wrong on WHOOP 4.0 (the ryanbr#319
sparse-motion inflation), so the staging engine is already chosen by
device family (ryanbr#327). The per-user "Experimental sleep staging (V2)"
toggle was therefore redundant and confusing: a 4.0 owner "enabling V2"
changed nothing yet looked broken (issue ryanbr#345).

- Remove the toggle end to end: PuffinExperiment.experimentalSleepV2
  (+ its key), the Settings UI, and the AppViewModel / WhoopBleClient
  threading, on both platforms.
- sleepStagerV2ForFamily(family) is now the sole selector
  (family != WHOOP4). Behaviour is unchanged for the default: the flag
  already defaulted true, so 5.0/MG stays on V2 and 4.0 stays on V1.
- Family-gate the self-heal restage too, resolving the healed strap's
  OWN family (correct for a multi-device 4.0 + 5.0/MG user) - the small
  follow-up ryanbr#327 noted, so an edited 4.0 night now stays on V1 as well.
- Document in-code that unifying 4.0 on a motion-robust V2 needs real
  4.0 raw first (ryanbr#271, ryanbr#319); no 4.0+PSG data exists, so 4.0 keeps V1.

Android: :app:testFullDebugUnitTest green (family-gate + self-heal
tests). Swift twin mirrored byte-identically; the app-target Swift has
no CI, so it needs a Mac build to confirm compile.
@kavemang

Copy link
Copy Markdown

For me on the 4.0 the sleep stages were messed up until I turned on V2. I was getting about 20 to 40 mins of deep and rem for an 8 hour period until I turned on V2

ryanbr added a commit that referenced this pull request Jul 13, 2026
…revert toggle (#351)

Reworks #347. #327 hard-gated WHOOP 4.0 to V1 (V2 over-stages on sparse motion,
#319) and #347 would have removed the toggle entirely. But a 4.0 user (kavemang,
#347) reported the opposite: V1 UNDER-stages badly — ~20-40 min deep+REM for an
8 h night (should be ~150-230) — and V2 fixed it. Neither engine is validated on
4.0, so forcing either is wrong; the honest answer is a sensible default plus an
escape.

- Drop the #327 family gate: the selector is now just the toggle on both the
  normal detected-night path and the self-heal restage (already toggle-driven),
  so V2 is the default for EVERY strap and a user can turn it off to fall back to
  V1. The toggle defaulted true already, so 5/MG is unchanged; 4.0 flips to V2.
- Remove the now-trivial sleepStagerV2ForFamily helper + its family-gate test.
- Fix the stale Android toggle comment; the Swift blurb already read correctly.

Byte-parity: both platforms resolve useSleepStagerV2 straight from the toggle.
Android compile + com.noop.analytics.* tests green; app-target Swift via app-build.
@ryanbr ryanbr closed this Jul 13, 2026
@tanarchytan
tanarchytan deleted the fix/sleep-v2-family-only branch July 14, 2026 12:21
DX23876 pushed a commit to DX23876/noop that referenced this pull request Jul 22, 2026
…revert toggle (ryanbr#351)

Reworks ryanbr#347. ryanbr#327 hard-gated WHOOP 4.0 to V1 (V2 over-stages on sparse motion,
ryanbr#319) and ryanbr#347 would have removed the toggle entirely. But a 4.0 user (kavemang,
ryanbr#347) reported the opposite: V1 UNDER-stages badly — ~20-40 min deep+REM for an
8 h night (should be ~150-230) — and V2 fixed it. Neither engine is validated on
4.0, so forcing either is wrong; the honest answer is a sensible default plus an
escape.

- Drop the ryanbr#327 family gate: the selector is now just the toggle on both the
  normal detected-night path and the self-heal restage (already toggle-driven),
  so V2 is the default for EVERY strap and a user can turn it off to fall back to
  V1. The toggle defaulted true already, so 5/MG is unchanged; 4.0 flips to V2.
- Remove the now-trivial sleepStagerV2ForFamily helper + its family-gate test.
- Fix the stale Android toggle comment; the Swift blurb already read correctly.

Byte-parity: both platforms resolve useSleepStagerV2 straight from the toggle.
Android compile + com.noop.analytics.* tests green; app-target Swift via app-build.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants