Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
18250b1
fix(today): bound the classic dashboard's vital carry + honor °C/°F o…
ryanbr Aug 16, 2026
f2b18ff
feat(oura): decode 0x7E/0x7F real_steps_features as Tier-B instrument…
pipiche38 Aug 16, 2026
25d09ba
Fix German Strap gender in Android onboarding (#1358)
ben-tsk Aug 16, 2026
e74a102
fix(diagnostics): a clipped log generation must say it lost its head …
pipiche38 Aug 16, 2026
6a2e426
fix(oura): #1339 follow-ups — contain the dup-gen diagnostic, and log…
pipiche38 Aug 16, 2026
1959c72
fix(ble): stop hardcoding device.name to "WHOOP 4.0" for every paired…
pipiche38 Aug 16, 2026
7752a65
fix(oura): correct the 0x6B motion_period decode to match the documen…
pipiche38 Aug 16, 2026
dc655f3
fix(oura): add zh timeline_metric_movement + document the OURA_MOTION…
pipiche38 Aug 16, 2026
b894a39
fix(ui): respiratory rate is an on-device estimate on BOTH gens, not …
ryanbr Aug 16, 2026
19f41fd
perf(explore): stop reading sixty histories before drawing one metric…
ryanbr Aug 16, 2026
b9fc44e
fix(i18n): catch translations that are still the English source (both…
ryanbr Aug 16, 2026
33b580b
fix(sleep): stop truncating today's sleep read at 18:00 (both platfor…
ryanbr Aug 16, 2026
dc95c68
fix(health): guard the HealthKit share set against read-only types (#…
ryanbr Aug 16, 2026
0ce3e46
feat(backup): save custom journal behaviours to the .noopbak (#1361)
ryanbr Aug 16, 2026
f734e57
feat(rhythm): a truthful empty state when a device can't support the …
ryanbr Aug 16, 2026
5471b98
fix(multi-whoop): read the active strap, not a hardcoded "my-whoop", …
ryanbr Aug 16, 2026
8bd8fa0
fix(data-sources): count WHOOP badge days/workouts/HR across the stra…
ryanbr Aug 16, 2026
7ac9ebe
Charge: parasympathetic-saturation guard on the low-HRV penalty (inst…
vishk23 Aug 16, 2026
211557b
fix(data-sources): correct + fold the phone HR-broadcast enabled warn…
ryanbr Aug 16, 2026
76f2a5a
diag(ble): dump the GET_HELLO_HARVARD (cmd 35) response to locate the…
ryanbr Aug 16, 2026
12c7468
feat(polar): PMD control-point command layer + model catalog (both pl…
ryanbr Aug 16, 2026
23226cf
feat(ble): order the discovered HR-strap list by proximity (strongest…
ryanbr Aug 16, 2026
a1a5c32
Let users hide cycle awareness entirely (a private choice, never age-…
ryanbr Aug 16, 2026
a8122fd
Add a Polar strap-identity diagnostic behind a paired-only debug togg…
ryanbr Aug 16, 2026
eebc732
fix(sleep): collapse a grazing pre-onset fragment; stop merging adjac…
ryanbr Aug 16, 2026
75f380e
fix(ci): restore green main — @testable WhoopStore tests + baseline #…
ryanbr Aug 16, 2026
4df11d8
feat(oura): decode 0x6A sleep_period_info and instrument the ring's b…
pipiche38 Aug 16, 2026
8d29596
docs(oura): correct 0x6A comments that still claim breath feeds respR…
ryanbr Aug 16, 2026
b3885a3
release(10.1.0): release notes + What's New
ryanbr Aug 16, 2026
d4b7cc8
Release 10.1.0: add to AltStore source
ryanbr Aug 16, 2026
534d20e
feat(today): add VO₂max as an opt-in dashboard card (#1391) (#1393)
ryanbr Aug 16, 2026
abc697e
fix(analyze): re-score gate must fingerprint HR across ALL devices, n…
ryanbr Aug 17, 2026
81c1a8a
perf(analyzeRecent): per-day in-memory reuse cache — fix #1005 re-sco…
ryanbr Aug 17, 2026
afa882e
perf(analyzeRecent): extend the per-day reuse cache to WHOOP 5.0 / MG…
ryanbr Aug 17, 2026
9261daa
fix(steps): honest "connect a phone step source" prompt when a 4.0 ha…
ryanbr Aug 17, 2026
70b5ad5
fix(storage): count ALL decoded raw streams in the footprint (was 8 o…
ryanbr Aug 17, 2026
cbc128d
feat(breathe): ANS/Presence protocol catalog with holds, session leng…
Duzafizzl Aug 17, 2026
39d964a
fix(altstore): declare healthkit.access, location, and motion permiss…
terry-zeng1134 Aug 17, 2026
7e146ae
diag(hrv): size the CROSS-second R-R over-count with a windowed shado…
ryanbr Aug 17, 2026
5894735
chore(staging): bump to 10.1.1 (versionCode 338, iOS build 220) for t…
ryanbr Aug 17, 2026
9da37e3
diag: capture the 4.0 GET_BATTERY_LEVEL frame in the strap log (#900)…
ryanbr Aug 17, 2026
311c896
Baseline-relative daytime stress (revives #463) — opt-in + full parit…
ryanbr Aug 17, 2026
2853884
perf(analyzeRecent): stop the #1005 cache churning on baseline drift …
ryanbr Aug 17, 2026
242f664
diag: add the computed '-noop' spine to the Recent-Nd data line (#1403)
ryanbr Aug 17, 2026
25fce28
fix(android): wire the VO2max card's trend tap-through (#1391) (#1404)
ryanbr Aug 17, 2026
4e85a35
chore(staging): re-cut the 10.1.1 testing build (versionCode 339, iOS…
ryanbr Aug 17, 2026
2e67f4a
fix(android): route vo2max_est to its series trend — completes #1404 …
ryanbr Aug 17, 2026
601842a
feat(fitness): offer a VO₂max without a waist via the Uth HR-ratio fa…
ryanbr Aug 17, 2026
de8e398
#1391: settings VO₂max sub-text — note it builds from ~4 nights of HR
ryanbr Aug 17, 2026
3a10397
#1405: separate the Charge synthesis word from the training-readiness…
ryanbr Aug 17, 2026
99eb23b
chore(staging): 10.1.1 testing build — versionCode 340 / iOS build 222
ryanbr Aug 17, 2026
26f9a14
fix(ble): read the reboot-ack result at the family's offset (5/MG @12)
ryanbr Aug 17, 2026
e92a38d
fix(live-session): guard the upsert so a late start-write can't erase…
ryanbr Aug 17, 2026
497adc8
fix(healthkit): commit the observer anchor only after ingestion, not …
ryanbr Aug 17, 2026
4d8c1c6
fix(watch): tick the workout clock off the live builder, not sample c…
ryanbr Aug 17, 2026
f2271cd
chore(staging): 10.1.1 testing build — versionCode 341 / iOS build 223
ryanbr Aug 17, 2026
f40897a
fix(ble): widen the 5/MG liveness fuse to the whole family (#1414)
ryanbr Aug 17, 2026
a65fa56
feat(widget): keep showing the last heart rate through a quiet patch
ryanbr Aug 17, 2026
5749d28
fix(hrv): hold the spot capture to a real 60-second window (#1417)
bhelm Aug 17, 2026
23a08f9
feat(oura): 0x49-onset keying for duplicate sleep sessions — default-…
ryanbr Aug 17, 2026
d235692
fix(ble): standing-connect reconnect regime for WHOOP — survive suspe…
ryanbr Aug 17, 2026
d9aae8c
feat(backup): record the app build in exports + on version change (#1…
ryanbr Aug 17, 2026
b8c7b15
feat(analytics): add CTL/ATL/TSB training-load model (Swift + Kotlin)…
ryanbr Aug 18, 2026
ab0f699
Decode the v20 optical record's eleven config fields, and CRC-gate it…
vishk23 Jul 27, 2026
6cb3666
feat(analytics): descriptive sleep-vs-wake HR contrast (Swift + Kotli…
ryanbr Aug 18, 2026
b9f774f
feat(trends): CTL/ATL/TSB training-load card (iOS/macOS + Android) (#…
ryanbr Aug 18, 2026
100ce3b
refactor(sleep): split SleepScreen UI into sibling files (#1426)
ryanbr Aug 18, 2026
9c33a6f
fix(ble): pair WHOOP4 clock correlation with its capture wall, not no…
ryanbr Aug 18, 2026
ae3b6a5
fix(settings): waist row label vanished behind ~300dp of dead space (…
ryanbr Aug 18, 2026
f259768
feat(apple): hourly step import — per-hour iPhone steps with 90-day b…
ryanbr Aug 18, 2026
83596b6
feat(power): "Low refresh" hourly sync, a sub-option of Power saving …
ryanbr Aug 18, 2026
73acce8
feat(power): move Power saving out of Settings into its own screen, a…
ryanbr Aug 18, 2026
d347cbf
chore(staging): testing build 10.1.1 (342 / iOS 224)
ryanbr Aug 18, 2026
5456325
diag(rr): pre-storage R-R census + same-second tolerance sweep (#1008…
ryanbr Aug 19, 2026
7d7fe41
fix(hrv): align rolling rMSSD semantics across platforms (#1433)
bhelm Aug 19, 2026
96db410
fix(stress): resolve stress day windows through the zone's rules, not…
bhelm Aug 19, 2026
117f769
fix(breath): clamp negative stage durations instead of throwing (#1436)
bhelm Aug 19, 2026
13d4134
fix(recovery): align charge trace half-tie rounding across platforms …
bhelm Aug 19, 2026
69646d9
fix(sleep): trim newlines when matching wake stage labels (#1438)
bhelm Aug 19, 2026
142e1b1
fix(sleep): align reclip segment validation with the Kotlin twin (#1439)
bhelm Aug 19, 2026
9e51ec7
fix(recovery): preserve the signed-zero bit in the forecast clamp (#1…
bhelm Aug 19, 2026
3c0adc0
fix(recovery): render the skin-temperature driver's zero and decimals…
bhelm Aug 19, 2026
8de1f5a
fix(recovery): align charge driver point half-ties across platforms (…
bhelm Aug 19, 2026
c0da6a2
fix(workouts): preserve stored per-session steps during detector back…
bhelm Aug 19, 2026
ca0567d
fix(workouts): carry per-session steps through every row rebuild (#1444)
ryanbr Aug 19, 2026
c593cba
fix(recovery): keep the charge trace's negative zero, and correct the…
ryanbr Aug 19, 2026
f7572b6
chore(workouts): require steps explicitly at every WorkoutRow constru…
ryanbr Aug 19, 2026
c2f2af2
feat(ios): automatic Apple Health write-back after offload, with a ba…
MikaSchultes Aug 19, 2026
374144a
fix(hrv): make the windowed rMSSD gap-aware, like the nightly one alr…
ryanbr Aug 19, 2026
c6864f7
chore(staging): testing build 10.1.1 (343 / iOS 225)
ryanbr Aug 19, 2026
799a961
diag(rr): log the record cadence and per-record fill the census could…
ryanbr Aug 19, 2026
b6b2f73
fix(oura): restore the ring's own breath rate as dailyMetric.respRate…
pipiche38 Aug 19, 2026
9b83b8f
fix(sleep): stop gravity memo keys aliasing postures that share an ax…
bhelm Aug 19, 2026
2fe84e3
refactor(sleep): one gravity fold, not three copies of it (#1453 foll…
ryanbr Aug 19, 2026
82bfd3d
fix(sleep): order V2 stager streams before the binary-search clip (#1…
bhelm Aug 19, 2026
140c8b3
chore(staging): testing build 10.1.1 (344 / iOS 226)
ryanbr Aug 19, 2026
6cd649c
diag(rr): print each sampled beat's ord, the last field that can loca…
ryanbr Aug 19, 2026
b42d3f2
fix(sleep): floor Kotlin Rest sleep-need at 0.1 h, matching Swift (#1…
bhelm Aug 19, 2026
7171b9b
fix(analytics): omit Rest for a wake-only session, matching Kotlin (#…
bhelm Aug 19, 2026
7a75136
chore(staging): testing build 10.1.1 (345 / iOS 227)
ryanbr Aug 19, 2026
b0d8a29
fix(coupled): carry through the shared selector on both platforms, so…
ryanbr Aug 19, 2026
8124da3
Add per-chunk historical clock + R-R packing diagnostic (#1008)
ryanbr Aug 20, 2026
8e16332
Fix doubled and ungrammatical "ago" suffixes in the synced-at text (#…
ryanbr Aug 20, 2026
aa0037a
Mark the orphaned 'now' catalogue key stale (#1472 follow-up)
ryanbr Aug 20, 2026
451b56f
Don't report a productive offload as an interrupted sync (#1466)
ryanbr Aug 20, 2026
c5ea975
fix(analytics): omit Rest trace when score is absent (#1463)
bhelm Aug 20, 2026
3e3bff8
fix(steps): count usable calibration samples (#1469)
bhelm Aug 20, 2026
46596d6
fix(steps): distinguish missing day rows (#1470)
bhelm Aug 20, 2026
27484c3
fix(android): escape backup JSON controls (#1471)
bhelm Aug 20, 2026
524c250
fix(connection): make duration rounding deterministic (#1473)
bhelm Aug 20, 2026
a7db4c1
fix(labs): normalize custom marker keys to NFC (#1474)
bhelm Aug 20, 2026
fc10368
Fix FIT coordinate half-tie rounding parity (#1475)
bhelm Aug 20, 2026
c821c40
fix: include activity steps in Swift summary (#1477)
bhelm Aug 20, 2026
eb4fe18
fix(oura): reject malformed UTF-8 decoder text (#1478)
bhelm Aug 20, 2026
8d3310a
fix(android): render Test Centre live readouts (#1468)
bhelm Aug 20, 2026
cec9c80
fix(oura): widen the skin-temp worn-gate timestamp match for devices …
pipiche38 Aug 20, 2026
7b70b9c
doc(oura): correct §6.5 SpO2 overshoot stats - measured on collision-…
pipiche38 Aug 20, 2026
7e61bf0
Staging build: versionCode 346, build 228 (base 10.1.1)
ryanbr Aug 20, 2026
02488d8
Stop rebuilding the whole strap log on every Test Centre readout tick
ryanbr Aug 20, 2026
fbbfcfb
Poll the strap battery every keep-alive tick while charging
ryanbr Aug 20, 2026
c61a933
test(protocol): extend the golden decoder oracle past frame decode — …
vishk23 Aug 20, 2026
59c9571
Assert the widened unix as a Long (#869 follow-up) (#1484)
ryanbr Aug 20, 2026
f1753b1
Report the strap model that actually advertised, or say unknown
ryanbr Aug 20, 2026
ae5d17b
Staging build: versionCode 347, build 229 (base 10.1.1)
ryanbr Aug 20, 2026
6ed5163
Count deliveries per stored second across a whole night (#1331/#1008)
ryanbr Aug 20, 2026
22d1ed7
Retire two superseded R-R shadow measurements (#1331/#1118)
ryanbr Aug 20, 2026
6a7f4eb
Release notes for v10.5.0, and ship the Polish What's New card
ryanbr Aug 20, 2026
7f6ab8b
Release 10.5.0: bump version (none) + build numbers + What's New
ryanbr Aug 20, 2026
70406ed
Release 10.5.0: add to AltStore source
ryanbr Aug 20, 2026
343df89
Merge upstream ryanbr/noop v10.5.0
DX23876 Aug 20, 2026
156f2ec
Audit commit attribution only on commits this fork authored
DX23876 Aug 20, 2026
95eba44
Improve coach memory retention and eviction
DX23876 Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions .github/workflows/source-hygiene.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,17 @@ jobs:
# .githooks/commit-msg blocks it before the commit exists, and this job is the net for whatever
# bypasses the hook (--no-verify, a fresh clone with no core.hooksPath, the GitHub web editor).
#
# Deliberately scoped to the commits this push/PR ADDS. History already carries such trailers —
# including three commits that came from upstream, where they are ryanbr's to keep — and a job that
# audits all of history would be permanently red and therefore ignored.
# Deliberately scoped to the commits this push/PR ADDS, and within those, to the ones written under
# THIS fork's identity. History already carries such trailers — including commits that came from
# upstream, where they are their own authors' to keep — and a job that audits all of history would be
# permanently red and therefore ignored.
#
# The author filter is what makes an upstream sync mergeable at all: `git merge upstream/main` ADDS
# every upstream commit to base..head, four of which carry these trailers, and the only way to clear
# them would be to rewrite other people's commits — which changes their shas, drops their signatures
# and destroys the ancestry the next sync has to merge against. It weakens nothing for the fork's own
# work: a commit authored as DX23876 is audited exactly as before, and one authored under some other
# identity was never this project's to publish under its name anyway.
commit-attribution:
runs-on: ubuntu-latest
steps:
Expand All @@ -91,13 +99,24 @@ jobs:
fi
echo "auditing: ${RANGE[*]}"

# The one identity this fork's own commits carry (docs/FORK_GUIDE.md § Commit and attribution
# conventions). Anything else in the range arrived from elsewhere — an upstream sync, a merged
# third-party PR — and is not ours to rewrite.
OURS="176692557+DX23876@users.noreply.github.com"

# -z NUL-terminates each commit so a multi-line body cannot be misattributed to its
# neighbour, and suppresses the newline git otherwise appends after every entry (which would
# arrive glued to the FRONT of the next sha). %x1f separates the sha from the message.
# arrive glued to the FRONT of the next sha). %x1f separates sha, author email and message.
bad=0
while IFS= read -r -d '' entry; do
sha=${entry%%$'\x1f'*}
msg=${entry#*$'\x1f'}
rest=${entry#*$'\x1f'}
email=${rest%%$'\x1f'*}
msg=${rest#*$'\x1f'}
if [ "$email" != "$OURS" ]; then
echo "skipping ${sha:0:9} — authored by <$email>, not this fork"
continue
fi
hit=""
grep -qiE '^[[:space:]]*(co-authored-by|signed-off-by)[[:space:]]*:.*(claude|anthropic|copilot|chatgpt|openai|gemini|cursor)' <<<"$msg" \
&& hit="AI co-author trailer"
Expand All @@ -109,7 +128,7 @@ jobs:
echo "::error::${sha:0:9} — $hit"
bad=1
fi
done < <(git log -z --format="%H%x1f%B" "${RANGE[@]}")
done < <(git log -z --format="%H%x1f%ae%x1f%B" "${RANGE[@]}")

if [ "$bad" -ne 0 ]; then
echo "::error::NOOP commits carry no AI authorship. Amend the message(s) and force-push."
Expand Down
Loading
Loading