Skip to content

NOOP AI 10.1.0

Latest

Choose a tag to compare

@github-actions github-actions released this 15 Aug 22:21

NOOP AI 10.1.0

The first release of this fork on the 10.x line, and it carries two of them: everything upstream
shipped in 10.0.0 and 10.1.0 since the 9.3.3 beta, plus this fork's own work on heart-rate zones and
the coach.

The release identity changes with it. Builds are no longer branded "DX Beta" — the tag is
v10.1.0-dx, the title is plain, and the version the app reports is what it always was: a number.
The -dx suffix stays because upstream tags vX.Y.Z in the same namespace this fork fetches into;
it separates the two, and nothing more is meant by it.

Added — your own heart-rate zones

  • Three modes, one resolver. The conventional 50/60/70/80/90 % of maximum, your own percentages,
    or absolute BPM boundaries from a threshold or lactate test. Percentages move when your maximum is
    re-estimated; absolute beats stay put, which is the whole reason both exist. Both sets of numbers
    survive a mode switch, so trying one costs nothing. Editor under Profile › Heart-rate zones.
  • Display-only, deliberately. Custom bands change the live readout, a workout's zone split and
    what the coach prescribes in. They never reach your Effort score, which is measured against your
    heart-rate reserve on a published method with fixed thresholds — re-basing it on a band you edited
    yesterday would silently rewrite every Effort you have ever been shown. Old workouts show the new
    bands immediately; there is no migration.
  • A backup written by upstream's build still restores its bands. Their single custom-zone key is
    read and adopted into this fork's absolute mode when you have set none of your own.

Added — the coach

  • A prescribed session's Effort is computed, not asserted. "20 minutes in Zone 2" is evaluated
    against your own bands and the shipped Edwards maths before the coach may quote a figure. A value
    it supplies survives only within five points of that — leaning easy inside a band is judgement; a
    15-point target for a session that produces 30 is arithmetic, and it was the reported bug.
  • The morning brief waits for a night the data can support. When last night's window is still
    truncated because your strap hasn't finished offloading, the brief is withheld and the day is not
    stamped as briefed. You get a card that says so and takes you to the sleep editor in one tap;
    correcting the night re-runs the brief on the corrected numbers. A mere suspicion never withholds —
    it travels as a caveat wherever a Charge is quoted.

Added — from upstream

  • Polish joins the languages the app ships, and the ~1300 strings that exist only in this fork were
    translated for it too, so the app speaks one language throughout rather than two.
  • Background syncing now shows in the Today header: the battery ring becomes the sync indicator while
    your strap is offloading history (@Quaii, ryanbr#837).
  • Home Screen quick actions (@Quaii, ryanbr#1294), five WHOOP-catalogue sports that were missing, VO₂max
    telling you what it needs before it can appear, and a strap switcher plus a two-strap comparison.
  • Considerable Oura work — hypnogram-scored nights, reversed HRV buckets, a partial night no longer
    reading 36 % efficiency, and a reconnect that survives suspension (@pipiche38).
  • Rest and readiness now use the methodology that was computed but never connected (@vishk23, ryanbr#456),
    and the daytime stress timeline masks exertion instead of scoring it as stress (@vishk23, ryanbr#1114).
  • HRV tuning moved out of the always-visible Strap card into Advanced — the in-app search still finds
    it — and a night whose R-R stream was over-counted now says its HRV is unverified rather than
    quietly reporting it.

Fixed — numbers that claimed more than they knew

  • Skin temperature read as a deviation it wasn't (ryanbr#622, reported by @bartmuskala). The column is
    bimodal: the live pipeline stores a signed deviation from your baseline, imports store an absolute
    wrist reading. Today's dashboard signed everything, so an imported night showed "+33.4°" — a
    deviation from baseline no body produces. It also ignored your °C/°F preference, alone among the
    screens. Both are now routed through the shared resolver the other screens already used.
  • Respiratory rate carried without limit (ryanbr#1312, @pipiche38 upstream; the same fix now on this
    fork's classic dashboard). One CSV import's last value could read as today's measurement for a
    fortnight. The carry is bounded to a week; past that the card says "—", which is the truthful
    answer when nobody measured. SpO₂ and skin temperature keep their unbounded carry on purpose —
    those are genuinely sparse, and last-known is the honest answer for them.
  • A workout's zone split ignored a manual maximum heart rate. It built its bands from age alone,
    so the same heart rate read as Zone 2 live and Zone 3 in the workout.
  • Three screens carried their own hardcoded zone ladder — the Health card, the haptic zone alert
    and the workout split — so a buzz could fire at a different boundary than the one displayed. All
    five zone consumers now read one resolver.
  • A band edge could fall outside its own zone. 0.55 × 200 is 110.000000000000014 in binary
    floating point, which put exactly 110 bpm below its own Zone 1 floor. Invisible on round tens,
    everyday with custom bands.
  • Apple Health received a mislabelled HRV number. HealthKit's HRV field is SDNN; the export wrote
    a whole-night standard deviation, which reads 2–3× high against Apple's own short-window samples.
    It now writes the stored 5-minute SDNN index, and never falls back to RMSSD under an SDNN label.

Verification

  • StrandAnalytics 1450 tests, WhoopStore 386, app target 2085 — all passing.
  • NOOPiOS (iOS) and Strand (macOS): both BUILD SUCCEEDED.
  • Tools/i18n_audit.py exits 0 with Polish at zero gaps, held to the same zero-tolerance tier as
    German, Spanish, French and Portuguese.
  • Nothing on the BLE or offload path changed in this release, so no strap behaviour was re-validated.

Thanks

The Oura decode work, the vitals-carry bound and a long run of protocol fixes are @pipiche38's.
@vishk23 connected Wave 0 scoring into Rest and readiness and rebuilt the stress timeline;
@Quaii did the sync indicator, quick actions and a great deal of layout; @AveMonti contributed
the Polish localization this release completes; @liaolo refined the iOS visual system;
@adrianlaureda, @evoveotech, @TAKEOFF69, @tigercraft4, @kavemang, @dnesdan and
@whisp0 contributed fixes, docs and hardening.

Reports drove much of the rest: @bartmuskala (ryanbr#622, the skin-temperature reading that started the
display fix), @flexagoon (ryanbr#1160, ryanbr#1161, light-mode cards), @h-nry (ryanbr#1311, sleep-stage nights),
@adamstefanik, @afonsojramos, @cybermicky0, @lukasito25, @Simple9,
@sudden-break, @UncreativeX and @digitalerdude — and everyone who filed the reports behind
these fixes.

Install

The unsigned IPA installs through AltStore, SideStore or Feather; the macOS build is a universal,
ad-hoc-signed app. Both are attached to this release, and the AltStore source updates itself when it
is published.