Repository navigation
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
ryanbr/noop#2887: a WHOOP 5.0/MG restored after an iOS CoreBluetooth background relaunch can display a WHOOP 4.0's 108-hour battery-runtime fallback. Reconnects in the same process also lose the persisted discharge history until new samples accumulate.
Fixes ryanbr#2887
Root cause (base
2a1de7609843b095505274ad6fc811757210be80)Strand/BLE/LiveState.swift:221initializesbatteryRatedHoursto WHOOP 4.0 (108 h).Strand/BLE/BLEManager.swift:1659-1664updated it only inconnectCore, which the iOSwillRestoreStatecallback atBLEManager.swift:6506-6524bypasses.LiveState.swift:765clears battery samples on disconnect, whileBLEManager.swift:1554-1571seeded the 14-day store history only duringbootstrapStore, which runs once per process.Change
selectedModelin one observer, including after both manager initializers. This also handles restore and scan-model changes without a separateconnectCoreassignment.WhoopStore. Reuse its 14-day SoC read after eachdidConnect; drop a late read if the link has disconnected or the device identity changed. Retain existing timestamp deduplication and 400-sample live cap.Tests
NOT RUN — the fork has GitHub Actions disabled, and no workflow was dispatched. There is no exact-head CI receipt yet.
New
StrandTests/RestoredBatteryEstimateTests.swiftXCTest cases:WHOOP 5.0 / MGinitializes its fallback at 288 h, even withoutconnectCore.WhoopStorewith 100% att - 10 hand 90% attgives a 1%/h measured slope and 90 h = 3.75 days remaining; afterclearBiometrics, reseeding restores exactly two samples and the measured estimate. A disconnected-only attempt seeds nothing; duplicate seeds remain two rows.Hand-check of the user report:
0.91 × 108 = 98.28 h = 4.095 days(incorrect fallback), versus0.91 × 288 = 262.08 h = 10.92 days(5/MG fallback). The 10-hour synthetic discharge exceeds the existing 2-hour/2%-drop slope gates. These are hand-worked expectations, not executed test outcomes.Verify on a macOS 15+/Xcode host:
Exact upstream PR job names for these
Strand/**+StrandTests/**paths:check(i18n Coverage),doc-comments(Source Hygiene),linux-capture(Tools Python CI),build (Strand, …)andbuild (NOOPiOS, …)(App build). Nobuild-and-test, Swift packagetest (…), ortools (…)job is path-triggered.Hardware needed
Still required: WHOOP 5.0/MG + iPhone. Reproduce a genuine
Restore:CoreBluetooth relaunch (including already-connected restore), check that the 5/MG rated fallback remains ~12 days at 100%, reconnect within the same process and observe measured discharge restored from banked samples, and verify WHOOP 4.0 still uses 108 hours. Record model/firmware, redacted timestamps/SoC and estimate source without sharing personal health data.Upstream readiness
HOLD pending exact-head macOS XCTest, iOS compile, independent review, and real-strap restoration evidence. The code and synthetic regressions are source-backed; no physical strap or iOS restoration path was exercised. Store access can fail while iOS data protection is locked; existing bootstrap retry/unlock behavior is unchanged. No upstream issue/PR/comment/review/reaction was created.
Implemented by ChatGPT (mobile app, GitHub connector) for Kevin's NOOP factory.