Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
895 commits
Select commit Hold shift + click to select a range
848b797
Sleep test mode: pin questionnaire kinds and live-readout ids against…
NoopApp Jun 26, 2026
a5933ab
Sleep test mode: pure live-readout source (HR density, gravity covera…
NoopApp Jun 26, 2026
d8d6e0f
Sleep test mode: bind HR density, gravity coverage and last-gate read…
NoopApp Jun 26, 2026
656682e
Sleep test mode: guided multi-night capture reusing ScheduledDebugExp…
NoopApp Jun 26, 2026
2de3e99
Sleep test mode (Android): gate-trace twin emitted from detectSleep (…
NoopApp Jun 26, 2026
dfcc686
Sleep test mode (Android): Rest sub-score line + analyzeDay forwardin…
NoopApp Jun 26, 2026
d9891e9
Sleep test mode (Android): guided capture accountant + Swift/Kotlin g…
NoopApp Jun 26, 2026
04e0aca
Test Centre: import WhoopProtocol in LiveState for the Sleep readout …
NoopApp Jun 26, 2026
432185b
Battery test mode: pure estimateTrace SoC-series + discharge-run + sl…
NoopApp Jun 26, 2026
f42618e
Battery test mode: gated per-sample (t, soc) emit on bankBatterySample
NoopApp Jun 26, 2026
16f5f9b
Battery test mode: emitBatteryTrace wires discharge-run + slope + gat…
NoopApp Jun 26, 2026
8eb5943
Battery test mode: questionnaire/readout contract test + batteryReado…
NoopApp Jun 26, 2026
4ddb408
Battery test mode: guided multi-day capture reuses ScheduledDebugExport
NoopApp Jun 26, 2026
5f50ead
Battery test mode (Android): estimateTrace twin, byte-aligned trace w…
NoopApp Jun 26, 2026
d80eb7c
Battery test mode (Android): gated (t, soc) emit on setBattery via pu…
NoopApp Jun 26, 2026
ab79e7d
Battery test mode (Android): guided multi-day status twin, byte-align…
NoopApp Jun 26, 2026
d19983e
Test Centre H1: byte-align Kotlin meta.json object separator with Swi…
NoopApp Jun 26, 2026
1862190
Test Centre H2: wire Android Sleep test-mode trace into the analyzeDa…
NoopApp Jun 26, 2026
9260064
Test Centre M1: emit the battery analysis trace, not just the per-rea…
NoopApp Jun 26, 2026
cffaebe
Test Centre M2: match the Settings 5/MG gate in the Test Centre
NoopApp Jun 26, 2026
b9abd5a
Test Centre M3: review gate previews every text file in the bundle
NoopApp Jun 26, 2026
9cba0ad
Test Centre M4a: re-host the Continuous-HRV toggle in the Android Tes…
NoopApp Jun 26, 2026
f5a86bc
Test Centre: drop two em-dashes from review-fix comments (house style)
NoopApp Jun 26, 2026
1828b0d
Test Centre M5: register the 7 Phase-2 test-mode profiles (Swift)
NoopApp Jun 26, 2026
e984f39
Test Centre M5: Kotlin twin of the 7 Phase-2 profiles + parity test
NoopApp Jun 26, 2026
4427f4b
Test Centre G: Charge term-breakdown + HRV cleaning traces (StrandAna…
NoopApp Jun 26, 2026
fdce327
Test Centre G: wire Recovery + HRV traces into iOS
NoopApp Jun 26, 2026
80ef2c4
Test Centre G: Recovery + HRV traces on Android (twins + wiring)
NoopApp Jun 26, 2026
090745c
Test Centre: update layout tests for the 9-entry Phase-2 registry (we…
NoopApp Jun 26, 2026
d8de355
Test Centre: Connection & Sync mode on iOS/macOS (emitters, readout, …
NoopApp Jun 26, 2026
471e96b
Test Centre: Connection & Sync mode on Android (twins + wiring)
NoopApp Jun 26, 2026
88f527d
Test Centre: import StrandAnalytics in Backfiller for the Connection …
NoopApp Jun 26, 2026
5dc3607
Test Centre: Steps mode on iOS/macOS (emitters, readout, panel)
NoopApp Jun 26, 2026
5af813f
Test Centre: Steps mode on Android (twins + wiring)
NoopApp Jun 26, 2026
a8542eb
Test Centre: Workouts & GPS mode on iOS/macOS (emitters, readout, panel)
NoopApp Jun 26, 2026
b99df02
Test Centre: Workouts & GPS mode on Android (twins + wiring)
NoopApp Jun 26, 2026
5af18b1
Test Centre: drop three em-dashes from Steps/Workouts comments (house…
NoopApp Jun 26, 2026
8e23343
Test Centre: Import & Data Ingest mode on iOS/macOS (emitters, readou…
NoopApp Jun 26, 2026
925f8ac
Test Centre: Import & Data Ingest mode on Android (twin + wiring)
NoopApp Jun 26, 2026
a1963e9
Test Centre: Display & Performance mode on iOS/macOS (monitor, screen…
NoopApp Jun 26, 2026
a7600eb
Test Centre: Display & Performance mode on Android (twins + wiring)
NoopApp Jun 26, 2026
87500b4
Test Centre: fix Display p95 to surface the tail frame + use an IEEE-…
NoopApp Jun 26, 2026
6ef5e9f
Test Centre Import: make Android diagnostic honest and Swift-parity (…
NoopApp Jun 27, 2026
406ef9e
Test Centre Import: stop advertising captures nothing emits (L1)
NoopApp Jun 27, 2026
e511ded
Test Centre Import: align Kotlin redactCell with Swift isNumber (L10)
NoopApp Jun 27, 2026
e0bc136
Test Centre Connection: failedConnect parity, integer error tokens, g…
NoopApp Jun 27, 2026
a705868
Test Centre export: count the screenshot PNG against the 20 MB bundle…
NoopApp Jun 27, 2026
c58b8cd
Test Centre Workouts: redact free-text sport in the trace + fix dedup…
NoopApp Jun 27, 2026
85960b2
Test Centre Workouts: stop the dead GPS accept-rate on Android (L4)
NoopApp Jun 27, 2026
46f90b5
Test Centre traces: steps scaledSteps=none when production is nil + r…
NoopApp Jun 27, 2026
42268e3
Test Centre Import: read the dataImport gate once on import completio…
NoopApp Jun 27, 2026
e8af781
v7.3.0: bump versions + What's New entry for the Test Centre (iOS 156…
NoopApp Jun 27, 2026
dc2f843
v7.3.0: AltStore source + Homebrew cask
NoopApp Jun 27, 2026
7e9c5ea
v7.3.1 fix wave 1: backfill caught-up log (#783), corrupt-RTC detect …
NoopApp Jun 27, 2026
5d98f59
v7.3.1 wave-1 seam fixes: public minSkinTempSamples (skin-temp funnel…
NoopApp Jun 27, 2026
b6dfa9e
v7.3.1 fix wave 2: Today charge-ring layout (#762), pinned Stress car…
NoopApp Jun 27, 2026
e44810c
v7.3.1 wave-2 seam fixes: registryWriter rename in ExperimentalDriver…
NoopApp Jun 27, 2026
5f6ac36
v7.3.1 #755 review hardening: fix DatabasePoolConcurrencyTests (missi…
NoopApp Jun 27, 2026
a55a762
v7.3.1: lockstep bump (iOS 157 / Mac CFBundle 188 / Android vc 245) +…
NoopApp Jun 27, 2026
01f7847
v7.3.1: refresh AltStore source (build 157)
NoopApp Jun 27, 2026
5758114
Backup & Sync: scheduled local folder backup (default OFF) + restore-…
NoopApp Jun 27, 2026
b4b8ada
Bug-fix wave: source-attribution spine + Test Centre capture upgrades
NoopApp Jun 28, 2026
2bd4539
Spine fix v2: union-read model (fixes 2 regressions caught in review)
NoopApp Jun 28, 2026
bf94648
Big update: Test Centre reporting hardening + quick-win fixes
NoopApp Jun 28, 2026
e19818f
v7.3.2: lockstep bump (iOS 158 / Mac CFBundle 189 / Android vc 246) +…
NoopApp Jun 28, 2026
2695353
v7.3.2: refresh AltStore source (build 158)
NoopApp Jun 28, 2026
30bb7ef
Adopt OpenStrap learnings (wave 1): Charge what-shaped-it breakdown, …
NoopApp Jun 28, 2026
dd1f643
Fix iOS Test Centre report button: open the prefilled issue in-app, c…
NoopApp Jun 28, 2026
8665931
Simplify the app + explain the Charge score, plus conservative on-dev…
NoopApp Jun 28, 2026
bf3c240
Simpler Today, explain Charge, wire the on-device algorithm pickups, …
NoopApp Jun 28, 2026
4fe7622
v7.4.0: lockstep bump (iOS 159 / Mac CFBundle 190 / Android vc 247) +…
NoopApp Jun 29, 2026
00d8593
v7.4.0: refresh AltStore source (build 159)
NoopApp Jun 29, 2026
1f2d8a1
v7.4.1: bug-fix release (steps freeze, sleep-export drop, connect-dro…
NoopApp Jun 29, 2026
8563792
v7.4.1: add the What's New entry (steps, sleep export, battery-saving…
NoopApp Jun 29, 2026
781a2b7
v7.4.1: refresh AltStore source (build 160)
NoopApp Jun 29, 2026
4897f26
Add local Oura ring support (Gen 3/4/5), on-device, beta
NoopApp Jun 29, 2026
45a2444
v7.5.0: lockstep bump (iOS 161 / Mac CFBundle 192 / Android vc 249) +…
NoopApp Jun 29, 2026
c0a65fd
v7.5.0: refresh AltStore source (build 161)
NoopApp Jun 29, 2026
07f5f9a
Board sweep: reimplement 8 community PRs + bug fixes + localization, …
NoopApp Jun 30, 2026
09dea64
v7.6.0 additions: new board bugs + an anonymity source guard
NoopApp Jun 30, 2026
b24cb35
v7.6.0: lockstep bump (iOS 162 / Mac CFBundle 193 / Android vc 250) +…
NoopApp Jun 30, 2026
55b78df
v7.6.0: refresh AltStore source (build 162)
NoopApp Jun 30, 2026
02a1db7
v7.6.1: Today lands on today on launch, even mid-calibration (#860 it…
NoopApp Jun 30, 2026
73bcb80
v7.6.1: refresh AltStore source (build 163)
NoopApp Jun 30, 2026
e7099d9
#862: harden Oura export parser against the real export schema (Swift…
NoopApp Jun 30, 2026
4dc54fb
#864: iOS Smart-alarm tells the truth on WHOOP 5/MG (parity with Andr…
NoopApp Jun 30, 2026
acf8f77
#833/#167: move Deep Timeline raw post-processing off the UI thread (…
NoopApp Jun 30, 2026
ed544ec
AI Coach: snapshot provider across refreshModels fetch (#873) + surfa…
NoopApp Jun 30, 2026
f06f13a
#833: fix the macOS freeze for real (on-open + Insights), both root c…
NoopApp Jun 30, 2026
8c4c783
Battery estimate: seed from DB on connect (iOS/mac parity) + don't le…
NoopApp Jun 30, 2026
a7b91d9
Android HC import: per-source de-overlap for steps + calories (#589 p…
NoopApp Jun 30, 2026
03ccfd0
Sleep edits reconcile on imported nights (#0) + imported resp-rate re…
NoopApp Jun 30, 2026
4f8b2bb
Smart alarm: iOS scheduled wake backup (#4/#6) + Android single-slot …
NoopApp Jun 30, 2026
3863e16
Backfiller: no-cursor gate sees this END's own rows (#1) + Android lo…
NoopApp Jun 30, 2026
b132433
Day-nav date labels read the logical day, not raw Date() (#14/#15/#16)
NoopApp Jun 30, 2026
57ed64c
#10: re-key the GPS route when a workout's sport/start is edited (Apple)
NoopApp Jun 30, 2026
fc93495
#18: disclose when an edited Avg HR diverges from the recorded graph/…
NoopApp Jun 30, 2026
043969f
Add a device: move Oura ring to the first Experimental option so it s…
NoopApp Jun 30, 2026
de25e37
BLE: make all LiveState writes atomic to fix a lost-update race (reim…
NoopApp Jun 30, 2026
de49f97
WHOOP 4.0: surface banked-but-sparse data instead of empty screens (#…
NoopApp Jun 30, 2026
9f0c375
Today: show a live "workout in progress" card that taps through to Li…
NoopApp Jun 30, 2026
3445a8b
Localization: fold ~1265 Italian strings into the String Catalog (fro…
NoopApp Jun 30, 2026
b1bd683
Charts: pinch-to-zoom + drag-to-pan on the iOS Today heart-rate chart…
NoopApp Jun 30, 2026
0c7db18
Oura: fix the live-HR enable stall (#900, was fully broken) + honest …
NoopApp Jun 30, 2026
f808deb
Repo hygiene: drop 7 old committed macOS release zips (~75MB) from th…
NoopApp Jun 30, 2026
6348f67
Analytics: re-arm a forced rescore dropped mid-pass (#899-A)
NoopApp Jun 30, 2026
464b794
Steps: persist + show the strap's activity class (still/walk/run) fro…
NoopApp Jun 30, 2026
df650ee
AI Coach: editable system prompt + stress in the context (clean-room …
NoopApp Jun 30, 2026
d42d511
Release v7.7.0: bump versions + What's New (all platforms)
NoopApp Jun 30, 2026
f00caee
Release v7.7.0: regenerate Info.plist build number (195) to match pro…
NoopApp Jun 30, 2026
e5b347f
AltStore source: point at v7.7.0 (build 164)
NoopApp Jun 30, 2026
ed46bb7
Battery: personalise days-left without a near-full charge anchor (#919)
NoopApp Jul 1, 2026
1f5fb43
BLE (Android): atomic command seq + volatile cross-thread connection …
NoopApp Jul 1, 2026
3189044
Devices (Android): make the Add-a-device wizard list scroll under lar…
NoopApp Jul 1, 2026
2da2987
Backup: list date-only .noopbak files in the restore picker (#852)
NoopApp Jul 1, 2026
9070414
Widget: anchor every surface on the logical day, not the last scored …
NoopApp Jul 1, 2026
8e278f8
Oura: auto-reconnect a dropped ring with WHOOP-style backoff (#912)
NoopApp Jul 1, 2026
491c24e
Today: give Key Metrics tiles a uniform height (#907)
NoopApp Jul 1, 2026
d79f0e5
Effort/HR: read the active-strap union so a re-added strap is not inv…
NoopApp Jul 1, 2026
1d29a3f
Release v7.7.1: bump versions + What's New (all platforms)
NoopApp Jul 1, 2026
42a05cc
AltStore source: point at v7.7.1 (build 165)
NoopApp Jul 1, 2026
5dd93e4
Freeze (WIP, gated): AppleHealthView repo cache to cut the cold-mount…
NoopApp Jul 1, 2026
20a3aff
Repository: single-flight ensureStore to stop a thundering-herd of DB…
NoopApp Jul 1, 2026
71da37a
Freeze (WIP, gated): move backup and device-delete off the main threa…
NoopApp Jul 1, 2026
b8c6caf
Freeze (WIP, gated): move CSV export + non-HR timeline transforms off…
NoopApp Jul 1, 2026
e66feb7
Today: repo-level day-scoped cache so re-mounts skip the heavy day re…
NoopApp Jul 1, 2026
a4ea8d4
Buzz: route every one-shot user buzz through the confirmed sequence, …
NoopApp Jul 1, 2026
7678aff
iOS widget: republish the snapshot when the dashboard actually change…
NoopApp Jul 1, 2026
b487b11
Design: chips never wrap, one line always (#934)
NoopApp Jul 1, 2026
d2743fe
macOS sidebar: search field to filter destinations (#915)
NoopApp Jul 1, 2026
5842628
Health copy: entitlement-missing text covers paid reseller certs too …
NoopApp Jul 1, 2026
6434ece
Workouts: Bowling preset, all platforms (D#850)
NoopApp Jul 1, 2026
2e1963d
Compare: downsample the overlay chart and index the hover path (D#770)
NoopApp Jul 1, 2026
a62504c
Protocol: decode-only fast path, field metadata now opt-in (D#742)
NoopApp Jul 1, 2026
b56ad52
Sleep: overlap-aware session dedup + store heal for shifted-timebase …
NoopApp Jul 1, 2026
2ec1250
Localization: adopt the Chinese catalog, Simplified + Traditional (PR…
NoopApp Jul 1, 2026
de32e9f
Today: center the hero ring labels + make chart zoom actually reachab…
NoopApp Jul 1, 2026
b034c84
Watch: budget-aware snapshot push gate + mid-session trigger
NoopApp Jul 1, 2026
27f10be
Continuous HRV: opt-in overnight-only window + future-clock backfill …
NoopApp Jul 1, 2026
e2eb1a0
Localization sweep (app core + watch + design): catalogue the non-aut…
NoopApp Jul 1, 2026
72a90aa
Localization: clear em-dashes from translation VALUES too
NoopApp Jul 1, 2026
1891cc0
Localization sweep (screens A-M): catalogue non-auto contexts + clear…
NoopApp Jul 1, 2026
b0c1d1a
Localization sweep (screens N-Z + onboarding): catalogue non-auto con…
NoopApp Jul 1, 2026
57bec82
Bump 7.8.0: the everything update (iOS build 166, macOS 197, Android …
NoopApp Jul 1, 2026
3bf72d6
Today: fix two macOS compile breaks from the gesture and cache lanes
NoopApp Jul 1, 2026
cabb215
Localization: complete Italian, Spanish and both Chinese variants (6,…
NoopApp Jul 2, 2026
dac1d77
Fix the final-verify findings: watch-gate lockout, locale-stable spor…
NoopApp Jul 2, 2026
2694d75
Changelog honesty: the language milestone is iPhone and Mac; Android …
NoopApp Jul 2, 2026
632fe90
Android copy parity: clear em-dashes and comma-space artifacts from u…
NoopApp Jul 2, 2026
c6af847
Bump: macOS CFBundleVersion 197 (xcodegen sync)
NoopApp Jul 2, 2026
8b86e1a
Android: declare xForStrict after xFor (local functions resolve in or…
NoopApp Jul 2, 2026
ffa7124
AltStore source: point at v7.8.0 (build 166)
NoopApp Jul 2, 2026
e939720
Health hero + explorer: real 1Hz live-HR sampling and history-gated r…
NoopApp Jul 2, 2026
eeedd0e
Week in Review: honest sparse comparisons and the Effort scale everyw…
NoopApp Jul 2, 2026
c44fc7a
BLE: Android scan keeps the live strap, bond give-up hardened, alarms…
NoopApp Jul 2, 2026
2b33cdf
Sleep: impossible edits can no longer blank the screen (#940)
NoopApp Jul 2, 2026
82a7f68
Watch: real localization and a semantic freshness flag
NoopApp Jul 2, 2026
fc4cf49
Lab Book: markers CSV import lands (date, marker, value, unit)
NoopApp Jul 2, 2026
8de015a
Test: VitalRangeGating expectations account for ALL never being gated
NoopApp Jul 2, 2026
32819ee
v7.9.0 features: Coupled view, workout redesign, journal numeric entries
NoopApp Jul 2, 2026
da52e32
v7.9.0: apply adversarial-review remediation (14 findings on the 7.8.…
NoopApp Jul 2, 2026
7f02d55
Journal (Android): fix Kotlin compile (unit ctor prop + no continue-i…
NoopApp Jul 2, 2026
3029f96
Test: WhoopStore journal migration test compiles (await out of the XC…
NoopApp Jul 2, 2026
95db1ed
v7.9.0 remediation remainder: Swift range-chip coercion non-destructi…
NoopApp Jul 2, 2026
ad4cc1f
Sleep: band sleep-state stream end-to-end (#175)
NoopApp Jul 2, 2026
31cc9de
Sleep: deleting a detected sleep suppresses re-detection, with undo (…
NoopApp Jul 2, 2026
67af849
v7.9.0: final adversarial-verify remediation (Coupled readiness ancho…
NoopApp Jul 2, 2026
49c7683
v7.9.0: bump versions (iOS 167, macOS 198, Android 255) + What's New …
NoopApp Jul 2, 2026
8199b75
AltStore source: point at v7.9.0 (build 167)
NoopApp Jul 2, 2026
1b225a8
macOS Info.plist: regenerate CFBundleVersion 198 (v7.9.0)
NoopApp Jul 2, 2026
5b2fe14
V8 foundation: liquid Today + shared finish + off-main history decode…
NoopApp Jul 3, 2026
1652ef5
lane1-skintemp: family-aware WHOOP 4.0 v24 skin-temp raw->C conversio…
NoopApp Jul 3, 2026
533d37d
lane2-sleep: honest per-mode Test Centre day/night capture accumulato…
NoopApp Jul 3, 2026
222cefa
lane3-workouts: dedup detected shadows + effort backfill + auto-detec…
NoopApp Jul 3, 2026
555e239
lane4-resprate: pin slow-breather resp rate to fundamental, guard aga…
NoopApp Jul 3, 2026
d5ec5d1
lane5-android-ble: serialise analyzeRecent, confine reconcileRealtime…
NoopApp Jul 3, 2026
79d644b
lane6-android-parity: Health Connect body-comp import (#951) + German…
NoopApp Jul 3, 2026
1ae3931
lane7-macos: menu-bar sync-line height slot (#962) + Charge-driver/co…
NoopApp Jul 3, 2026
b66852a
lane8-trendchart: add top headroom via data-space yDomain, not the ma…
NoopApp Jul 3, 2026
52b6e88
lane9-oura: GetEvents history fetch + ring-time UTC anchor + battery …
NoopApp Jul 3, 2026
86c4096
V8 build-verify: keep iOS-shaped liquid Today out of the macOS target…
NoopApp Jul 3, 2026
980131e
V8 foundation: make liquid primitives cross-platform (guard haptics f…
NoopApp Jul 3, 2026
cc822ee
liquid-trends: finish Trends in the liquid language (vessel accents o…
NoopApp Jul 3, 2026
60c5fb7
liquid-sleep: restyle Sleep tab to the canonical liquid language
NoopApp Jul 3, 2026
120bcc1
liquid-health: full liquid finish on Health Monitor (sky backdrop, ve…
NoopApp Jul 3, 2026
a06bd88
liquid-live: restyle LiveView to the liquid language (vessel HR gauge…
NoopApp Jul 3, 2026
0fe353b
liquid-devices: restyle device manager to the liquid language
NoopApp Jul 3, 2026
985a191
liquid-insights: sky backdrop + liquid gauges/tube + press style on I…
NoopApp Jul 3, 2026
b8b1910
liquid-workouts: sky backdrop + LiquidVessel effort gauges + liquid-p…
NoopApp Jul 3, 2026
2b448c2
liquid-stress: sky backdrop + LiquidVessel hero gauge + LiquidTube st…
NoopApp Jul 3, 2026
080021e
liquid-coach: sky backdrop, liquid forecast/day gauges, liquid-tube w…
NoopApp Jul 3, 2026
1785912
Android liquid foundation: port the liquid primitives to Compose (phy…
NoopApp Jul 3, 2026
f15033c
liquid-mind: restyle Hydration, Breathe & Mind to the liquid language
NoopApp Jul 3, 2026
cd7ac9d
liquid-explore: finish MetricExplorer in the liquid language
NoopApp Jul 3, 2026
93c254c
liquid-coupled: restyle coupled day-glance to the liquid language
NoopApp Jul 3, 2026
36c8b16
liquid-settings: day-of-sky backdrop + LiquidPressStyle on tappable rows
NoopApp Jul 3, 2026
af1af4d
liquid-analysis: restyle Compare, Lab Book & Rhythm to the liquid lan…
NoopApp Jul 3, 2026
445749d
liquid-android-today: restyle Today to the liquid design language (pi…
NoopApp Jul 3, 2026
068b3ad
macOS liquid Today: make LiquidTodayView cross-platform + host it in …
NoopApp Jul 3, 2026
f80463e
Android liquid screens: apply the liquid design language across the a…
NoopApp Jul 3, 2026
6e7e9dd
WhoopProtocol test: accept integer-form gravity_mag in the decoder or…
NoopApp Jul 3, 2026
f546cbb
StrandAnalytics test: call WorkoutsTrace.detectedBoutLine (the #975 t…
NoopApp Jul 3, 2026
f4d0545
oura-android: GetEvents history backfill + ring-time UTC anchor (#953…
NoopApp Jul 3, 2026
01b6fb5
em-dash sweep: iOS/mac user-facing strings (#171)
NoopApp Jul 3, 2026
40de6c5
em-dash sweep: Android user-facing strings (#171)
NoopApp Jul 3, 2026
b1db9f5
macOS liquid sky: fix the white headers (Color.liquidComponents used …
NoopApp Jul 3, 2026
16a450b
Donation card: drop the out-of-date downloads/donors count line (both…
NoopApp Jul 3, 2026
9aa7eea
liquid-android-today: rebuild the Today to match the iOS structure (h…
NoopApp Jul 3, 2026
20eea00
liquid-android-today: match iOS density + mini-vessel card icons + 3-…
NoopApp Jul 3, 2026
980644b
liquid-android-today: each metric/vital card opens its OWN detail, no…
NoopApp Jul 3, 2026
7f86cbd
V8 review pass: fix Today value bugs + gauge floor + calories detail …
NoopApp Jul 3, 2026
89f439b
Release v8.0.0 (Liquid Metal): version bump + release notes
NoopApp Jul 3, 2026
f9b911f
AltStore source: point at v8.0.0 (build 167)
NoopApp Jul 3, 2026
26dbd4e
README: Liquid Metal refresh (v8 hero banner + new liquid screenshots)
NoopApp Jul 3, 2026
0d51ba4
Today: carry last night's HRV/Resting HR/Respiratory independently of…
NoopApp Jul 3, 2026
08b272e
Today/Watch: don't show a stale Rest score as if it were today's (#97…
NoopApp Jul 3, 2026
85d7840
Decode: skip building the whole-frame rawHex on the live fast path (#…
NoopApp Jul 3, 2026
93cef5b
Haptic Clock: widen the gaps so the taps stop blending on the wrist (…
NoopApp Jul 3, 2026
8e2ac8f
iOS widget: refresh the snapshot when a background backfill completes…
NoopApp Jul 3, 2026
88c33ee
Android connect: bound the connect/subscribe/self-drop loop (#982)
NoopApp Jul 3, 2026
e1c8b7e
Today: one-tap full-day HR trend (#979) + charging on the battery (#972)
NoopApp Jul 3, 2026
6612fd6
Oura: fix impossible SpO2 % and reject corrupt ring timestamps (#968)
NoopApp Jul 4, 2026
e5e7013
Health Connect import: write sleep sessions so HC-only users see slee…
NoopApp Jul 4, 2026
afe15f1
Scoring: skip the per-day owner probe on a single-WHOOP install (#970)
NoopApp Jul 4, 2026
93e5f8d
Deep Timeline: drag back up to 3 days (#986, serves #979)
NoopApp Jul 4, 2026
2566dac
Release v8.0.1: version bump + release notes
NoopApp Jul 4, 2026
08ff67e
AltStore source: point at v8.0.1 (build 168)
NoopApp Jul 4, 2026
ce1f136
v8.0.1 release notes: fuller detail + issues-closed list + coming-nex…
NoopApp Jul 4, 2026
3a55428
v8.1.0: Live Sessions (beta) + fix wave (#991 #992 #1000)
NoopApp Jul 4, 2026
cc8974e
AltStore source: point at v8.1.0 (build 169)
NoopApp Jul 4, 2026
8046d29
v8.2.0: the community release (12-lane fix wave)
NoopApp Jul 5, 2026
7898090
AltStore source: point at v8.2.0 (build 170)
NoopApp Jul 5, 2026
fb94f93
v8.2.1: key WHOOP imports to the wake day + stop heal purging importe…
NoopApp Jul 5, 2026
5ba19a1
chore: AltStore source → 8.2.1 (build 171)
NoopApp Jul 5, 2026
4bcb7d6
Android: corrupt-DB handler quarantines aside + rebuilds, no startup …
NoopApp Jul 5, 2026
2d00830
Terms gate: itemised affirmative attestations (clickwrap) + consent r…
NoopApp Jul 5, 2026
55a94a4
Terms gate: itemised affirmative attestations (clickwrap) + consent r…
Yloft17 Jul 5, 2026
59d19a0
Strip app down to a personal WHOOP + Apple Watch companion
claude Aug 5, 2026
5e34830
Fix WhoopProtocol test type-checker timeout in DecoderOracleTests
claude Aug 5, 2026
d7e834e
Restore StandardHeartRate parser + its test — WHOOP-internal, not dev…
claude Aug 5, 2026
559e089
Restore SourceCoordinator's instance isWhoop(_ id:) helper
claude Aug 5, 2026
95aad25
Merge pull request #1 from Yloft17/claude/cleanup-standalone-app-hvijkh
Yloft17 Aug 6, 2026
9427405
Unify bundle identifier to com.bbdw.noop and app group to group.bbdw.…
claude Aug 6, 2026
245f9f8
Strip remaining traces of the previous public project/team
claude Aug 6, 2026
72b5cea
Strip remaining traces of the previous public project/team (functiona…
claude Aug 6, 2026
e4f8bd7
Merge remote-tracking branch 'refs/remotes/origin/claude/cleanup-stan…
Yloft17 Aug 6, 2026
bc5d67a
idk
Yloft17 Aug 7, 2026
0cb7675
Re-theme StrandPalette to black/white + pink/purple
claude Aug 7, 2026
be3de48
Merge remote-tracking branch 'origin/claude/cleanup-standalone-app-hv…
claude Aug 7, 2026
0dae91d
Replace every time-of-day background with a static full-screen mesh
claude Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
33 changes: 33 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## What this PR does

<!-- A short description of the change and why it's needed. -->

## Type of change

- [ ] Bug fix
- [ ] New feature
- [ ] Refactor / cleanup
- [ ] Documentation
- [ ] CI / tooling

## How it was tested

<!--
For anything on the BLE path, say what you tested on real hardware and which
strap (4.0 / 5.0 / MG). For protocol or analytics changes, point to the test
that covers it. "Builds and unit tests pass" alone is not enough for BLE work.
-->

## Checklist

- [ ] Swift package tests pass for any package I touched (`swift test` in `Packages/<name>`)
- [ ] Android unit tests pass if I touched `android/` (`./gradlew testFullDebugUnitTest`)
- [ ] No new build warnings introduced
- [ ] UI changes use only `StrandDesign` tokens — no hardcoded colors, fonts, or spacing
- [ ] No hardcoded hex frame bytes; protocol facts live in the schema / decoders
- [ ] Follows the conventions in [`docs/CONTRIBUTING.md`](../docs/CONTRIBUTING.md)
- [ ] I did not commit generated output (`Strand.xcodeproj/`) or any secrets/keystores

## Related issues

<!-- Closes #N -->
64 changes: 64 additions & 0 deletions .github/workflows/app-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Compile-only verification for the macOS and iOS app targets.
#
# Why this exists: the iOS app is a build-from-source community port (no App Store —
# NOOP stays anonymous), so it isn't exercised on a device by the maintainer. This job
# compiles both app targets on every relevant change so a shared-code change can't
# silently break iOS (or regress macOS). It is anonymity-safe: CODE_SIGNING_ALLOWED=NO,
# no secrets, no signing identity, no artifacts uploaded — it only checks that it builds.
# (The shipped macOS .app is still produced and anonymized by hand; this is a compile gate.)
name: App build (macOS + iOS)

on:
pull_request:
branches: [main]
paths:
- 'Strand/**'
- 'StrandiOS/**'
- 'StrandiOSShared/**'
- 'StrandiOSWidgets/**'
- 'Packages/**'
- 'project.yml'
- '.github/workflows/app-build.yml'
push:
branches: [main]
paths:
- 'Strand/**'
- 'StrandiOS/**'
- 'StrandiOSShared/**'
- 'StrandiOSWidgets/**'
- 'Packages/**'
- 'project.yml'
- '.github/workflows/app-build.yml'
workflow_dispatch:

concurrency:
group: app-build-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: macos-15
strategy:
fail-fast: false
matrix:
include:
- scheme: Strand
destination: 'platform=macOS'
- scheme: NOOPiOS
destination: 'generic/platform=iOS Simulator'
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install XcodeGen
run: brew install xcodegen

- name: Generate Xcode project
run: xcodegen generate

- name: Build ${{ matrix.scheme }}
run: >-
xcodebuild -scheme '${{ matrix.scheme }}' -configuration Debug
-destination '${{ matrix.destination }}'
CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO
build
50 changes: 50 additions & 0 deletions .github/workflows/swift-packages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Compile-and-test verification for the reusable Swift packages.
#
# This job intentionally does NOT touch the macOS app target: that build needs
# XcodeGen to generate Strand.xcodeproj and a wired-up test scheme, and the app
# release is produced and anonymized by hand. The packages, by contrast, build
# and test on their own with plain SwiftPM — no Xcode project, no signing, no
# secrets — which makes them a safe, self-contained CI check that leaks nothing.
name: Swift Packages CI

on:
pull_request:
branches: [main]
paths:
- 'Packages/**'
- '.github/workflows/swift-packages.yml'
push:
branches: [main]
paths:
- 'Packages/**'
- '.github/workflows/swift-packages.yml'
workflow_dispatch:

concurrency:
group: swift-packages-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: macos-15
strategy:
fail-fast: false
matrix:
package:
- WhoopProtocol
- WhoopStore
- StrandAnalytics
- StrandImport
- StrandDesign
- NoopLocalAccess
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Build ${{ matrix.package }}
run: swift build
working-directory: Packages/${{ matrix.package }}

- name: Test ${{ matrix.package }}
run: swift test
working-directory: Packages/${{ matrix.package }}
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ Icon?
*.xcodeproj/
*.xcworkspace/
!*.xcworkspace/contents.xcworkspacedata
# …EXCEPT the xcodeproj's SPM lockfile. The shipped app builds from this Package.resolved,
# so it MUST be tracked — otherwise a clean checkout resolves a floating, uncommitted lockfile
# that could drift to a newer (potentially compromised) upstream release. Supply-chain pin.
# Git won't descend into an excluded directory, so re-include each ancestor on the path, then
# re-exclude its contents with a wildcard so ONLY Package.resolved gets tracked (not the
# generated project.pbxproj / contents.xcworkspacedata / xcuserdata cruft).
!Strand.xcodeproj/
Strand.xcodeproj/*
!Strand.xcodeproj/project.xcworkspace/
Strand.xcodeproj/project.xcworkspace/*
!Strand.xcodeproj/project.xcworkspace/xcshareddata/
Strand.xcodeproj/project.xcworkspace/xcshareddata/*
!Strand.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/
Strand.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/*
!Strand.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
build/
DerivedData/
.build/
Expand Down Expand Up @@ -54,6 +69,10 @@ android/app/release/
# ── Misc / secrets (never commit) ───────────────────────────────
*.log
.env
# Deployment credentials (PAT / signing / endpoints) — never commit. `.env` above
# won't match `deploy.env`, so list it (and any `deploy.env.<stage>`) explicitly.
deploy.env
deploy.env.*
secrets.*
android/local.properties
android/keystore.properties
Expand All @@ -68,3 +87,11 @@ export.xml
export.zip
*whoop_export*.zip
*apple_health*.zip

# Python bytecode
__pycache__/
*.pyc

# Local release artifacts (zips/ipas built for upload; never tracked)
dist/
err.txt
15 changes: 8 additions & 7 deletions ATTRIBUTION.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
# Attribution

Strand is an independent, unofficial, local-first macOS app. It is not affiliated
NOOP is an independent, unofficial, local-first app for macOS and iOS. It is not affiliated
with, endorsed by, or connected to WHOOP, Inc. "WHOOP" is used nominatively only to
identify the hardware the app interoperates with.

Strand builds on prior open-source reverse-engineering and interoperability work:
NOOP builds on prior community reverse-engineering and interoperability work:

## WHOOP 4.0 protocol + Swift packages
- **`johnmiddleton12/my-whoop`** — the `WhoopProtocol` and `WhoopStore` Swift packages
(vendored under `Packages/`), the WHOOP 4.0 BLE framing/command/decode work, and the
iOS collection logic that Strand's `WhoopBLE`/`Collect` layers are adapted from.
See `DISCLAIMER.md` (carried over from that project).
iOS collection logic that NOOP's `WhoopBLE`/`Collect` layers are adapted from.

## WHOOP 5.0 / MG protocol
- **`b-nnett/goose`** — the WHOOP 5.0 BLE reverse-engineering (service UUID family
`fd4b0001-…`, CRC16-Modbus header, CLIENT_HELLO, and the "puffin" packet types)
that Strand's `DeviceFamily` Whoop-5 path and `whoop5_protocol.json` are ported from.
that NOOP's `DeviceFamily` Whoop-5 path and `whoop5_protocol.json` are ported from.

## Other
- **GRDB.swift** (`groue/GRDB.swift`) — SQLite persistence (via Swift Package Manager).
- **MarkdownUI** (`gonzalezreal/swift-markdown-ui`) — renders the AI Coach's Markdown
replies (via Swift Package Manager).

Strand contains no WHOOP proprietary code, binaries, firmware, logos, or assets, and
NOOP contains no WHOOP proprietary code, binaries, firmware, logos, or assets, and
performs no DRM circumvention. It operates only with the user's own device and data.
Strand is **not a medical device**; all metrics (HR, HRV, recovery, strain, sleep,
NOOP is **not a medical device**; all metrics (HR, HRV, recovery, strain, sleep,
SpO₂, temperature) are approximations and not clinically validated.
76 changes: 0 additions & 76 deletions DISCLAIMER.md

This file was deleted.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions NOOPWatch/Assets.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"images" : [
{
"filename" : "AppIcon1024.png",
"idiom" : "universal",
"platform" : "watchos",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
6 changes: 6 additions & 0 deletions NOOPWatch/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
34 changes: 34 additions & 0 deletions NOOPWatch/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AppGroupIdentifier</key>
<string>$(APP_GROUP_ID)</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>NOOP</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>NOOP</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHealthShareUsageDescription</key>
<string>NOOP reads your heart rate from the Watch sensor to show a live readout on your wrist. It stays on your device.</string>
<key>NSHealthUpdateUsageDescription</key>
<string>NOOP records a basic workout session on your Watch for a higher-fidelity heart rate. The session stays on your device.</string>
<key>WKApplication</key>
<true/>
<key>WKCompanionAppBundleIdentifier</key>
<string>com.bbdw.noop</string>
</dict>
</plist>
Loading