Skip to content

diagnostics: REM funnel names the stager it replays vs the one that staged the screen - #2366

Open
ayiskakov wants to merge 1 commit into
ryanbr:mainfrom
ayiskakov:fix/rem-funnel-stager-label
Open

ayiskakov wants to merge 1 commit into
ryanbr:mainfrom
ayiskakov:fix/rem-funnel-stager-label

Conversation

@ayiskakov

Copy link
Copy Markdown

What

The strap-log REM funnel replays the V1 classifier, while every shipped install stages the
displayed hypnogram with V2 (the selector flag is default-on). The funnel's summary therefore
reads as an explanation of a hypnogram the app does not show — and on a 5/MG the two numbers can be
far apart, because V1's primary REM gate needs the raw resp channel that hardware never emits, while
V2 recovers respiration regularity from R-R.

Field observation that motivated this (details in #2365): two consecutive nights on a WHOOP MG
(fw 50.39.1.0) where the funnel reported ~42–46 min REM against 4h54 / 3h51 on the sleep screen.

This PR makes the diagnostic name what it ran: the funnel line gains the suffix
· funnel replays V1; screen staged by V2 — totals can differ (V2 keyed off the actual
PuffinExperiment flag; when the flag selects V1 the suffix names V1 and drops the caveat). It
changes no analytics value and no displayed metric — only the diagnostic sentence, per the
"two readouts of one fact must not be able to disagree" rule.

Both platforms

The suffix is byte-identical in Strand/System/DebugDataDiagnostics.swift and
android/…/testcentre/AndroidDiagnostics.kt, keyed off the same default-on flag on each side.

Verification

  • Swift: built the Strand (macOS) scheme locally with xcodebuild … CODE_SIGNING_ALLOWED=NO build
    — succeeds. (The NOOPiOS leg is not buildable on my machine — watchOS 26.2 SDK absent — the file
    is shared and has no platform conditionals in the touched region.)
  • Kotlin: no local Android toolchain here; android.yml covers compile + unit tests on this PR.
    The change is a string suffix on an existing diagnostic line; no test asserts the summary's exact
    tail (the partition-sum pins in SleepStagerTests / the Kotlin twin are untouched).
  • Diagnostics-only: no stored value, score, or UI metric changes.

Refs #2365.

…taged the screen

The funnel replays V1's classifier while every shipped install stages with V2
(default-on flag), and its summary read as an explanation of the displayed
hypnogram. On a 5/MG the gap is maximal — V1's primary REM gate needs the raw
resp channel that hardware never emits, while V2 recovers respiration from R-R —
observed in the field as 46 min funnel vs 231 min screen for one night. Suffix
the summary with both stager identities, byte-identical on both platforms, so
the two readouts can no longer be mistaken for one fact.

Refs ryanbr#2365
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.

1 participant