You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Today: HRV and Resting HR cards read "No data" while the tile above shows a value #1842
On one screen, the Key Metrics tiles show HRV 35 ms and REST HR 58 bpm, while the cards below in
YOUR CARDS read No data for the same two metrics. Tapping either card opens a detail screen with a
full graph.
Cause: two carry policies on one screen
The tile carries the last scored day; the card does not.
// Key Metrics tileval v = d?.restingHr ?: carriedDay?.restingHr
// Dashboard card, same screen
withUnit((day?.restingHr ?: vitalsDay?.restingHr)?.toString() ?:NO_DATA)
carriedDay (lastScoredRecoveryDay) is passed into the card resolver, which even computes val vd = carriedDay ?: day — the HRV and Resting HR branches simply do not use it. Before today's row is
scored, the tile shows last night's value and the card, falling back to vitalsDay instead, has nothing.
The detail screen reads history directly, which is why tapping through shows a graph.
The Blood Oxygen branch a few lines down already states this precedence as deliberate:
Candidate LAST, after the carries — the exact precedence the dashboard Blood Oxygen card uses two
sections down this same screen
So the intent was established; HRV and Resting HR were missed. Same family as the Fitness Age divergence
(#140 / #139 / #134), where the engine held a value the card gated away.
Also: Skin Temp shows "-0.0 Δ°C"
Different bug, same card list. numberString formats deviations with %+, which prints a sign
unconditionally — so any deviation in (-0.05, 0) renders as -0.0. A deviation that rounds to zero
means "no change from your baseline", and "-0.0" reads as a fault instead.
Present on both platforms: SkinTempDisplay is a twin.
Fix
Put carriedDay in the HRV and Resting HR card chains, matching the tile.
Drop the sign when a deviation rounds to zero, keeping it for a real -0.1. Both platforms, with twin
tests.
Done. PR #1843 landed the per-field carries and they are wired on main, not merely defined:
lastHrvRow / lastRestingHrRow in LogicalDay.kt
both called from TodayScreen.kt at the card sites (guarded to selectedDayOffset == 0)
unit-tested in LastHrvRowTest.kt
Swift twins lastHrvDay / lastRestingHrDay in MetricsCache.swift, so the two platforms resolve the same way
The cause was an OR-predicate: the shared "last vitals row" carried a day forward if it had ANY vital, so a row with a value for one metric and nothing for the other made the tile and the card disagree. Resolving each field independently removes that.
Closing on a stronger basis than "it merged": this is deterministic data resolution with no firmware or timing dependency, so the tests and the wiring are the whole story. If a card still reads "No data" while the tile above shows a value, that is a different bug and worth a fresh report with the day in question.
Activity
today: per-field HRV / Resting HR carry on both platforms, and stop p…
today: lead skin temp with the measured temperature, with a Settings …
ryanbr commentedon Sep 4, 2026
Done. PR #1843 landed the per-field carries and they are wired on
main, not merely defined:lastHrvRow/lastRestingHrRowinLogicalDay.ktTodayScreen.ktat the card sites (guarded toselectedDayOffset == 0)LastHrvRowTest.ktlastHrvDay/lastRestingHrDayinMetricsCache.swift, so the two platforms resolve the same wayThe cause was an OR-predicate: the shared "last vitals row" carried a day forward if it had ANY vital, so a row with a value for one metric and nothing for the other made the tile and the card disagree. Resolving each field independently removes that.
Closing on a stronger basis than "it merged": this is deterministic data resolution with no firmware or timing dependency, so the tests and the wiring are the whole story. If a card still reads "No data" while the tile above shows a value, that is a different bug and worth a fresh report with the day in question.
merge: bring in 95 upstream RyanBR commits (through 64ddc81)