Repository navigation
Conversation
Labelling live WHOOP 4 beats is the point of the change, so the ingress test moves to the new shape rather than losing the assertion: a standard-BLE beat is `whoop4Standard` now where it was left unlabelled, and that NULL is exactly what let a partial type-47 offload hide live intervals. Only a beat with no family stays nil. The test's own name reads truer for it. `extractStreams` gained `family` on both platforms in the same change, which changed the arity on both sides at once and unpaired them in the ledger even though they moved together. Declared twin references pair them again, and the derived authority is refreshed for it: the baseline holds at 292 known findings and no disposition is touched. The Kotlin query now says why it is not `AS MATERIALIZED` like the Swift twin. That hint wants SQLite 3.35 and `minSdk` is 26, so it is a syntax error on most supported devices; the cost is the per-row re-evaluation the Swift comment names, and the note exists so nobody closes the gap by adding the keyword. Worth stating because the PR description says otherwise: the merged policy is provenance order, not the fuller stream. History, then type-40 realtime, then standard BLE, then legacy rows, chosen per UTC hour. Commits one to three selected by count; commit four replaced that with `MIN(rank)` and rewrote the tests to pin it. Keeping it: type-47 carries the strap's own device timestamps where standard BLE is stamped on receipt, which is where #1008's cross-second over-count came from, so the better-timestamped stream winning is the safer read. The residual is that an hour holding sparse history still prefers it over dense live beats. Refs #2496, #1118, #2335
8 of 12 tasks
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.
Merges @rodrigosa7's #2496 for #1118 / #2335, rebased onto current main with one change on top.
What it fixes
A WHOOP 4 scoring read chose type-47 history for its whole multi-night interval the moment any historical row existed, so a partial offload left the remaining hours reading nothing and nights without the coverage to score HRV. The decision is per UTC hour now, so hours history never covered fall back to the live stream.
testWhoop4PartialHistoryKeepsUnlabelledRowsFromOtherHourspins that, and it is the actual defect.Underneath it, WHOOP 4 R-R gains three labelled transports where live traffic was previously all NULL: type-47 history (8), type-40 realtime (9) and standard BLE (10). That is the direct follow-on from #2478, which found history and live BLE both carrying
srcChannelNULL was what made them indistinguishable. Legacy NULL rows still participate, at the lowest rank, so existing installs benefit rather than only future data. Both platforms bump their read cache keys (v4tov5,s3tos4), which is easy to forget and would otherwise have served stale memoised reads straight past the change.The policy, stated because the description says otherwise
The merged behaviour is provenance order, not the fuller stream: history, then realtime, then standard BLE, then legacy, chosen per hour. Commits one to three selected by count with history breaking ties, which is what the PR description and commit one's title describe. Commit four replaced that with
MIN(rank)and rewrote the tests to pin it, so the code and tests agree and it is the prose that is stale.Keeping provenance order. Type-47 carries the strap's own device timestamps where standard BLE is stamped on receipt, and receipt stamping is where #1008's cross-second over-count came from, so letting the better-timestamped stream win is the safer read even when it is sparser. The residual is worth naming: an hour holding sparse history still prefers it over dense live beats, which is the reported failure mode surviving at hour granularity rather than interval granularity. If coverage should win instead, that is a scoring decision rather than a review note.
The change on top
The ingress test still pinned the old NULL for a live WHOOP 4 standard-BLE beat, so
build (Strand, macOS)was red. Labelling that beat is the point of the change, so the assertion moves to[.whoop5Standard, .whoop4Standard, nil]rather than losing coverage. Only a beat with no family stays nil, and the test's name,RrFamilyIsCapturedAtIngress, reads truer than before.extractStreamsgainedfamilyon both platforms at once, which changed the arity on both sides together and unpaired them in the ledger even though they moved as one. Declared twin references pair them again, and the derived authority is refreshed: baseline holds at 292 known findings, no disposition touched.The Kotlin query now records why it is not
AS MATERIALIZEDlike its Swift twin: the hint wants SQLite 3.35 andminSdkis 26, so it is a syntax error on most supported devices. The cost is the per-row re-evaluation the Swift comment names, and the note exists so the gap is not closed by adding the keyword.Verification
parity_ledger.pyandparity_ratchet.py: clean, errors=0, twin references 1018 to 1020.WhoopProtocol: 804 tests, 0 failures. Kotlin:Whoop5RRSqliteTest24,FramingTest39,Whoop5RRTest5,HrFingerprintTest4, all 0 failures under--no-build-cache --rerun-taskswith result XML checked fresh against the clock.Tools/doc_comment_lint.pyclean, baseline unchanged at 24.WhoopStoretests cannot link on Linux (GRDB needssqlite3_snapshot_*) andStrandTestsruns only on the macOS leg, so both of those, including the repinned test, are CI's to confirm.Because this carries
Tools/parity_twin_map.json,parity-governanceruns on it. Worth noting the original branch could not have caught the parity break: the changed files sit inside the parity globs while the workflow triggers only onTools/parity_*.Refs #2496, #1118, #2335