Skip to content

NOOP 11.5.0

Choose a tag to compare

@github-actions github-actions released this 09 Sep 13:26

NOOP v11.5.0

A release about NOOP holding a thread: in the coach, in the charts, and in what the strap log is willing
to claim.

A coach that keeps the thread

The coach was a single question and a single answer. It now behaves like something you can return to.

Replies stream in as they are written, so a long answer starts being readable immediately instead of
appearing all at once at the end. The conversation persists between sessions, so you can put the phone
down and pick the thread back up. It can speak its answers, and take a question by voice. A morning brief
sums up the night behind you without being asked.

There are home-screen widgets and Siri shortcuts for the things worth reaching in one step, and an
optional Today launcher card, requested in #1862 by @kggreco11, which stays off until you turn it on.

Your heart rate on the home screen

A widget showing live bpm with the recent trace behind it, on both platforms. It lets the launcher decide
the layout rather than assuming a size, so it sits properly wherever you put it.

Charts that claim less

Four things were wrong at once, and each made the others harder to see.

Points were spaced evenly regardless of date, so a fortnight you did not wear the strap looked the same
as two consecutive nights. Points are now spaced by date, and a gap takes the width it spans.

Every metric was drawn as though it were maximally volatile, which flattened the ones that genuinely move
and exaggerated the ones that do not. Scales are anchored per metric now.

Daily scores were drawn as lines. A line between two daily scores asserts the value travelled through
everything between them, and for a score computed once a day that is simply false. On a series that
swings twenty points overnight it is most of what reads as noise. They are bars now, and a day with no
reading is an empty slot of the right width rather than a plunge to zero.

And the Line and Bars setting in Settings only ever reached the Trends tab. It now applies to the detail
chart you reach by tapping a ring on Today, which is where most people were looking at it.

Alongside that, HRV and Resting HR carry a dashed rule at your own baseline. An absolute HRV number says
little on its own: 42 only means something once you know your normal is 54. The rule is drawn from the
same fold the vitals grid bands against, so the chart and the tile beside it cannot disagree, and it stays
hidden until the baseline has enough nights to be worth trusting.

Skin temperature, as a temperature

Skin temperature was shown as a deviation from baseline, which is the right number for spotting illness
and the wrong one for answering what your temperature is. It now leads with the measured value, with a
Settings choice if you prefer the difference, and the preference applies across the window rather than
only the newest night. Reported in #622 by @bartmuskala.

A Fahrenheit import used to be stored as though it were Celsius. It is converted on the way in now, which
was #111 from @whisp0.

Sleep

A night that the detector chopped into fragments, each too short to count on its own, scored as no night
at all. Those fragments are bridged back into the night they were, reported in #1937 by @bartmuskala.

The filled hypnogram can be dragged to read the clock time under your finger, asked for in #1855 by
@AussieFries. Its axis no longer mislabels a partial timeline as beginning at onset.

A night measured from heart rate alone now reports the HRV it actually measured rather than nothing, and
the Sleep tab stamps a carried value with the day it came from, so an older night can no longer read as
yesterday.

Steps and the day boundary

Step counting and the day boundary now follow your own sleep rather than the clock, so a late night stops
splitting one day's activity across two. The steps calibration also says which half of its input is
missing: asking for phone-step days is no help when what is absent is strap movement.

A wake time for each day

Weekday and weekend wake times can differ. The per-day override drives the strap alarm and the backup
notification too, not only the phone alarm.

Re-scores that take a fraction of the time

Re-scoring re-read sixty days of movement on every pass to fit one steps coefficient, whether or not any
of it had changed, and threw the answer away on every restart. It now re-folds only the days whose
movement actually moved, and keeps what it learned across launches. On a worn library that phase dropped
from roughly thirty-three seconds to under three. Reported in #1538 by @justinjor-bit.

The per-day work behind it is measured now rather than estimated, so the next thing worth speeding up can
be chosen from a number instead of a guess.

The strap log stops guessing

A connection your own phone was holding could be reported as the strap refusing to pair, which sent
people chasing a pairing problem that did not exist. Reported in #1997 by @semoi.

A non-active strap could be scanned, connected and drained while the one you selected sat idle. The strap
you chose is the one that gets connected and credited, from #1881 by @pipiche38.

A bond that ends now records why, in wording that reads the same in every language, and a disconnect
records how long the link held and whether anything was banked. Serial numbers are masked wherever a log
might be shared, including the hex-hidden ones.

Languages

Russian joins the supported locales. The German copy has been converted from the formal Sie to the
informal du throughout. A Portuguese string that a find and replace had corrupted is correct again.

Smaller things

Routes import from Apple Health and Health Connect (#1205). The battery pack reports its own charge
without overriding the strap's gauge, from #1935 by @Zebsi235. Body measurements and exercise distance
carry separate unit preferences, asked for in #1913 by @kavemang. The readings table prints each unit
once, reported in #1942 by @Geg0r. Rest says it is provisional while history is still syncing rather than
hiding itself. Tapping a hero ring on Today opens that metric's detail. The bottom bar can overlay the
content and hide itself as you scroll, on both platforms.


What's Changed

  • ble: light the charging pill on a 5/MG, which listens for events nobody sends it by @Zebsi235 in #1826
  • ble: handle the pack-attach events on Apple too (#1826) in #1831
  • perf(clock): memoise the resolved clock instead of rebuilding it per label (#1829) in #1830
  • ble: redact a hex-hidden serial on Apple too (#1833) in #1834
  • test centre: log every pushed strap EVENT under the Connection domain by @Zebsi235 in #1825
  • android: draw the bottom bar as an overlay so its glass has a backdrop (#1836) in #1837
  • android: make the overlay bar actually overlay something (#1836) in #1838
  • android: hide the bottom bar while scrolling down (#1839) in #1840
  • ios: hide the tab bar on scroll, from the same setting Android uses (#1841) in #1841
  • today: carry HRV and Resting HR on the cards, and stop printing -0.0 (#1842) in #1843
  • today: lead skin temp with the measured temperature, with a Settings choice (#1844, #1846) in #1845
  • health: say when skin temp could not honour the Settings choice (#1847) in #1847
  • health: apply the skin-temp preference across the window, not just the newest night in #1850
  • health: backfill the skin-temp absolutes the 21-night window never reaches (#1851) in #1852
  • health: the absolutes backfill never ran on the installs that need it in #1854
  • health: stop predicting which device a night belongs to — read it off the row in #1856
  • Revert the skin-temp absolutes backfill (#1852, #1854, #1856) in #1857
  • alarm: per-day wake times for the phone alarm (#1858) in #1859
  • ble: re-arm a WHOOP 5/MG realtime stream that has lapsed (#1865) in #1866
  • ble: stop skipping the handshake once the unbonded probe has retired (#1867) in #1868
  • fix(l10n): restore pt-PT Restaurar corrupted by Rest→Descanso by @kvnloo in #1861
  • fix(oura): break the resume-cursor ↔ time-anchor deadlock that re-serves the same history forever by @pipiche38 in #1846
  • alarm: log what the smart-alarm detector actually saw in #1870
  • docs(ios): name the on-device AltStore Error Log shape, not just the desktop one in #1860
  • coupled: show the optimal strain band as a tube on Android, matching Apple in #1871
  • i18n: add a Russian locale to Android, and backfill Apple's from it in #1872
  • i18n(android): park the partial Arabic translation as data, not a locale in #1873
  • sleep: drag the filled hypnogram to read the clock time under your finger in #1875
  • backup: say WHICH folder backups go to, iCloud Drive included in #1876
  • android(backup): clear the busy flag in a finally, as the Apple twin does in #1877
  • ble: say what an unbonded strap actually costs, not just history sync in #1878
  • today: say why Recovery Vitals is blank on a night with no motion in #1879
  • connection: say which streams actually banked on a finished link in #1880
  • Fix daily energy integration for sparse HR by @fadkeprasad in #1692
  • connection: split the banked line by PATH, so it says something in #1882
  • sleep: report the HRV an HR-only night actually measures (#1884) in #1885
  • ble: connect and attribute the strap the user actually selected (#1881) in #1886
  • feat: add sleep-aware steps and physiological day cycles by @bhelm in #1572
  • daycycle: drop the reliableAwakeCoverage parameter nothing reads (#1572 follow-up) in #1887
  • analytics: retrospective TDEE from logged intake and the weight trend in #1889
  • ble: give the battery-pack decoder a caller, and a sanity check before it is believed in #1890
  • ble: stop telling a strap that refuses pairing to try pairing again (#1635) in #1891
  • build: restore the Apple targets, and the app-target tests that never compiled in #1892
  • today: add an optional, default-OFF Coach launcher card (#1862) in #1888
  • settings: stop claiming an unpaired strap costs you HRV and resting HR in #1893
  • ble: stop the suppression log telling a refusing strap to retry, on both platforms in #1894
  • ble: give a WHOOP 4.0 the stable serial identity the 5/MG already has (#1193) in #1896
  • Mask WHOOP serials that start with a letter in #1897
  • analytics: cap HR and R-R reads separately, so a night is not scored on a clipped stream in #1899
  • today: let the Recovery Vitals rows open their trends, like the cards do (Android + Apple) in #1902
  • settings: give the bottom bar its own card, with a size and a transparency in #1904
  • Require continuous effort for heart-rate recovery eligibility by @bhelm in #1901
  • Fix Python capture-tool encoding and SQLite cleanup by @bhelm in #1900
  • ci: only run the Python tools workflow when the Python tools change in #1905
  • settings: centre the bar's own transparency on the slider, and add notches in #1906
  • analytics: say when a night's stream came back at its read cap in #1908
  • Invalidate daily analysis cache when late scored streams arrive by @bhelm in #1907
  • today: stop the Liquid Effort tile calling a load index a percentage in #1909
  • tests: repin the frozen-Rest tests on what the shipping stager does in #1910
  • feat: AI Coach — streaming, voice, brief, history, widgets, Siri (K1-K15) by @evoveotech in #1547
  • coach: localize the voice controller's last two strings, pin CRLF on Kotlin too in #1915
  • skin-temp: explorer leads with the absolute and honours the Settings choice (#1848) by @evoveotech in #1914
  • Split body and exercise distance unit preferences by @kavemang in #1916
  • storage: let the Apple footprint name the tables that can actually be large in #1918
  • wind-down: pin the per-day nudge trigger to the nudge's day, not the wake's (#1863) by @evoveotech in #1912
  • alarm: per-day wake overrides now drive the strap alarm and backup notification (#1864) by @evoveotech in #1917
  • storage: estimate bytes per table, and stop saying v18Aux is unpruned in #1920
  • import: convert Fahrenheit skin-temp on the way in, not alias it to °C (#1849) by @evoveotech in #1921
  • steps: the Today tile names the right missing half when no motion is banked (#1816) by @evoveotech in #1923
  • today: the calibrating ring counts nights, so say nights in #1925
  • health: drop the active strap id from Apple Health external UUID keys (#1503) by @evoveotech in #1922
  • skin-temp: backfill absolutes for nights outside the 21-night rescore window (#1853) by @evoveotech in #1919
  • Bound ppgWaveformSample with rolling newest-N retention in #1928
  • Close the final resting-HR bin on the window end so an admitted endpoint sample is not dropped by @bhelm in #1927
  • test centre: a read-only cmd-151 battery-pack probe, and what an MG answers by @Zebsi235 in #1930
  • test centre: keep the pack probe's serial and address out of both its sinks in #1931
  • devices: show the battery pack's charge, from an event the strap already sends in #1932
  • hrv: withhold RMSSD on a night whose R-R over-counts in #1940
  • Improve German translation by @andigandhi in #1939
  • Close the final HR/HRV window on the shipped SleepStager path, and drop the unused RecoveryScorer helpers by @bhelm in #1936
  • ecg: the pure research modules — allow-list, stats and log by @Zebsi235 in #1941
  • Add a zone-based local day-window helper with a Kotlin twin and a committed oracle by @bhelm in #1938
  • import: read GPS routes from Apple Health and Health Connect (#1205) by @evoveotech in #1924
  • test centre: keep the pack's BT address out of the event census by @Zebsi235 in #1934
  • today: surface Rest as Pending sync while the strap has un-offloaded history (#1164) by @evoveotech in #1926
  • rhr: measure what an artefact gate would do, before gating anything in #1944
  • charging: stop pack presence from overriding the strap gauge in #1945
  • explorer: stop the readings table printing the unit twice in #1947
  • connection: say why the unbonded probe was skipped, and what we hold on the link in #1950
  • battery: stop asking a 5/MG for battery it refuses to answer in #1951
  • ci: trigger the app build on the app-target tests it runs in #1955
  • widget: heart rate with the recent trace (Android) in #1958
  • widget: let the launcher lay out the heart-rate card in #1961
  • widget: heart rate with the recent trace (iOS) in #1964
  • iOS: poll 0x2A19 battery for an unbonded 5/MG on the keep-alive tick (#1953) by @evoveotech in #1959
  • backfill: name the unbonded-offload probe in the deferral diagnostic (#1802) by @evoveotech in #1963
  • backfill: distinguish no-flash-cursor from writing-but-recording-nothing in the empty-offload banner (#1754) by @evoveotech in #1965
  • widget: measure what the home-screen widgets cost, and stop sending updates that change nothing in #1970
  • widget: measure the rates after the startup burst, and give the counters an iOS twin in #1971
  • diagnostics: three lines that told triage the wrong thing in #1972
  • sleep: the night label counted from the newest record, not from today in #1973
  • ble: add a timing tell for Apple's unverified bond state (#1883) by @evoveotech in #1966
  • unbonded-offload probe: a local teardown is inconclusive, not a strap refusal (#1804) by @evoveotech in #1962
  • Sleep tab: stamp carried prior-night metric values with their day (#1946) by @evoveotech in #1956
  • sessionRestingHR: gate bins on sample count + plausibility before letting them win the floor (#1943) by @evoveotech in #1952
  • fix(sleep): drop a stagesJSON write that would make a stored night less complete by @pipiche38 in #1974
  • sleep: bridge nights fragmented under minSleepMin (#1937) in #1984
  • test: import WhoopProtocol in SleepFragmentedNightTests in #1986
  • fix(sleep): Hypnogram axis no longer mislabels a partial timeline as starting at onset by @pipiche38 in #1975
  • Gate watch recovery on a usable RHR baseline and valid HRV nights by @bhelm in #1982
  • Round recovery-trace values in the double domain on Android by @bhelm in #1979
  • Hold the strap ack when the Android trim cursor fails to commit by @bhelm in #1980
  • Retire the duplicate Gregorian day formatter in TrainingLoadEngine by @bhelm in #1981
  • recovery: treat an unusable resting-HR baseline as absent (#1988) in #1990
  • recovery: close the doc and comment gaps left by the resting-HR gate in #1991
  • ble: point the unmapped-layout report line at the right issue in #1993
  • diag: spend the reject hex dump from a session budget, not per chunk in #1994
  • today: tap a hero ring to open its metric detail in #1995
  • fix: let a tap on a liquid vessel reach the action its parent is wired to in #1996
  • diag: carry the bytes for an unmapped packet type, and sample every layout in #1998
  • diag: say WHY a bond ended, and make the refusal readable in any locale in #1999
  • diag: name the BLE integers the strap log printed bare in #2000
  • perf: bound the RE dump's search, and stop formatting hex a byte at a time in #2001
  • fix: a connection the phone is holding is not a strap refusing to pair in #2002
  • fix: only claim a held connection when the OS actually reports one in #2003
  • fix(charts): stop drawing every metric as if it were maximally volatile in #2004
  • fix(charts): anchor the Rest chart, which the wrong key left untouched in #2005
  • feat(charts): space points by date, so a gap takes the width it spans in #2007
  • fix(charts): a continuous line with a zero floor and visible readings in #2009
  • fix(today): make the Arrange affordance read as a control in #2010
  • feat(today): draw the daily scores as bars, not as a line in #2011
  • diag: census what a re-score carries, not just how many nights it visited in #2014
  • Reject an out-of-domain strain denominator on both platforms by @bhelm in #1977
  • Require an HRV baseline in the raw recovery overload by @bhelm in #1978
  • Re-fold a day's motion only when that day's gravity moved in #2015
  • Say a Rest score is provisional instead of hiding it in #2016
  • Stop reporting a mapped historical layout as undecodable in #2017
  • Decode the 5/MG optical and raw-IMU historical layouts on Android in #2018
  • Keep the v26 optical window's absolute base, not just its deltas in #2020
  • Read the v26 per-burst counter as the u16 it is in #2021
  • Ask the day-owner question once, and ask it as a bit in #2022
  • perf(steps): persist the steps-calibration motion folds across launches in #2023
  • Count and time the per-day probe queries in #2024
  • Count the day-owner lookup that runs in front of the probe in #2025
  • The vital detail chart follows the chart-style setting on both platforms in #2027
  • Annotate the HRV and resting-HR detail charts with the personal baseline in #2028

New Contributors

Full Changelog: v11.1.0...v11.5.0


Downloads — NOOP Staging identity, installs beside the official app (separate data):

  • Android — NOOP-android-v11.5.0.apk (com.noop.whoop.staging)
  • macOS — NOOP-macos-v11.5.0.zip (unzip, then right-click → Open)
  • iOS — NOOP-ios-unsigned-v11.5.0.ipa (AltStore / Sideloadly)