What problem does this solve?
The Colmi big-data timeline (stage 0x04) and the YCBT timeline (tag 3) both report REM, and both decoders already store it as a SleepStageBlock. It just never gets any further:
SleepSummary carries light/deep/awake only, so REM never reaches the sleep score, the Sleep tab, or the coach.
DataQualityAnalyzer.sleepDecoderNote hard-codes "light/deep/awake only, no REM" into the coach's context on every ring, including the ones that do report it.
There's also a scoring side-effect. hasAwakeSignal falls back to asking whether the stage timeline accounted for essentially the whole night (coveredStageMin >= total * 0.95), and REM is excluded from that sum. On a REM-capable ring REM is typically 20–25% of the night, so a fully-described night looks ~80% covered, fails the gate, and has its awake reading discarded as "no signal" — costing it 45% of the 15-point awake sub-score.
Proposed solution
Carry remMinutes through SleepSummary, collapseByDay and averageStages; report remPct; include REM in the coverage sum; and pick the coach's caveat per night from that night's own blocks rather than from a constant.
Nil rather than zero throughout when the ring reported no REM stage — a jring's 0x11 timeline genuinely has none, and "absent" and "you slept no REM" are different claims.
Area
Data / decoding / sync
What problem does this solve?
The Colmi big-data timeline (stage
0x04) and the YCBT timeline (tag3) both report REM, and both decoders already store it as aSleepStageBlock. It just never gets any further:SleepSummarycarries light/deep/awake only, so REM never reaches the sleep score, the Sleep tab, or the coach.DataQualityAnalyzer.sleepDecoderNotehard-codes "light/deep/awake only, no REM" into the coach's context on every ring, including the ones that do report it.There's also a scoring side-effect.
hasAwakeSignalfalls back to asking whether the stage timeline accounted for essentially the whole night (coveredStageMin >= total * 0.95), and REM is excluded from that sum. On a REM-capable ring REM is typically 20–25% of the night, so a fully-described night looks ~80% covered, fails the gate, and has its awake reading discarded as "no signal" — costing it 45% of the 15-point awake sub-score.Proposed solution
Carry
remMinutesthroughSleepSummary,collapseByDayandaverageStages; reportremPct; include REM in the coverage sum; and pick the coach's caveat per night from that night's own blocks rather than from a constant.Nil rather than zero throughout when the ring reported no REM stage — a jring's
0x11timeline genuinely has none, and "absent" and "you slept no REM" are different claims.Area
Data / decoding / sync