Repository navigation
fix(whoopstore): re-home legacy 'my-whoop' alias rows onto the registry device id - #2753
pranav6226 wants to merge 5 commits into
Conversation
…ry device id Rows written under the session-scoped 'my-whoop' alias split a strap's data across two device ids, so per-day single-owner scoring never saw HR+RR together: sleep staging returned staged-none and HRV never computed. Migration v48 plus a guarded per-launch re-check in bootstrapStore re-homes the alias rows onto the registry serial id; stored data self-heals on first launch. Adds LegacyWhoopAliasRehomeTests.
|
Approved the workflow runs. Swift Packages CI is green, so the v48 migration and all seven 1. The Kotlin twin is a claim the ledger cannot resolveThat is the line reading 2. The parity authority is stale
3. The Android schema oracle asserts something Android does not do
Worth saying separatelyThe split you describe is not Apple-only. Android seeds the same For what it is worth, the diagnosis reads correct to me and the guard set is the right shape: requiring exactly two WHOOP rows, refusing a seed that adopted a different peripheral, and requiring the seed to actually hold rows are each the guard I would want before a merge of this kind touches anybody's history. |
The doc comment's 'Kotlin twin:' line parsed as an attached twin claim for a function that does not exist, failing the repository acceptance suite with dead-twin-reference. Reword it to plain prose and add platform_specific dispositions for rehomeLegacyWhoopAlias, rehomeLegacyWhoopAliasIfNeeded and legacyWhoopId. The Room re-home is a follow-up, called out in the PR.
The Android oracle declared v48-legacy-whoop-alias-rehome, a migration Android does not perform; nothing on that side catches the gap. The entry travels with the future Room re-home instead of ahead of it. The WhoopStore (Apple) oracle entry stays.
What this PR does
An install that started on the legacy single-device flow and later paired the
same strap in the multi-device registry holds one strap's rows under two
device ids: the v15 seed id
my-whoop(the write id is session-scoped, sosessions launched while the seed row was active banked under it) and the
registry's
whoop-…serial id. Scoring resolves one owner per day, so asplit day only ever sees one side:
Neither side alone can score a night, so an affected install shows live HR
only, indefinitely, with healthy sync throughout.
The fix heals the store in place:
v48-legacy-whoop-alias-rehome, data-only, no schemachange) runs
DeviceRegistryStore.rehomeLegacyWhoopAliasat upgrade time.BLEManagerbootstrap path), so a split created after the upgrade also self-heals.
adoptSerialIdentity's semantics: the active registry idwins primary-key clashes, the
-noopcomputed sibling travels with it, andthe seed rows are dropped after the move.
Guards make it a no-op unless the two ids provably denote the same single
strap: the seed row exists; the active device is a registry WHOOP id other
than the seed; there are exactly two WHOOP rows in total; the seed never
adopted a different peripheral than the active device; and the seed actually
holds banked rows.
Refs #814 — that PR's read spine UNIONs the two ids at read time; this change
removes the split at the data level so the union stops finding two owners.
Maintainers decide if/when the report that led here is resolved; no closing
keyword intended.
Type of change
How it was tested
New
LegacyWhoopAliasRehomeTests(7 tests) covering the merge and everyguard: split store merges onto the active serial id; no-op when the seed is
the active device; no-op when another device is active; refusal when the seed
adopted a different peripheral; refusal with a third WHOOP row; no-op when
the seed holds no rows; and the v48 migration healing a split install
end-to-end.
Package suite (Linux, per docs/BUILD.md snapshot-SQLite recipe):
cd Packages/WhoopStore && swift test— 628 tests executed, 1 skipped,0 failures, including the 7 above. (macOS CI
swift-packages.ymlis theauthority; the Linux run is a convenience check. The run used the pinned
GRDB 6.29.3 sources supplied from a local path — the sandbox's git fetch
of the dependency does not complete — with every GRDB file hash-verified
against the upstream v6.29.3 tree before use.)
On hardware: WHOOP MG, firmware 50.42.1.0, iOS build carrying this fix. The
test install had a real split store — two nights unscored (NO-NIGHT), HRV
never computed, sync healthy. On first launch post-upgrade the rows merged
and the same nights scored: sleep detected, HRV present, and later nights
score normally. The bootstrap call site is in the BLE-adjacent launch path
and was exercised on the device, not just in the package suite.
Cross-platform parity (called out per AGENTS.md)
The Kotlin twin —
DeviceRegistryStore.rehomeLegacyWhoopAliasas RoomMIGRATION_41_42 plus the same bootstrap call — is required for full parity
and is not in this PR; the Swift function doc says so in terms. The
split originates in the legacy seed-id install flow; whether Room installs
can reach the same state is a maintainer call. Both
schema_oracle.jsoncopies gain
v48-legacy-whoop-alias-rehomeso the shared canonicalmigration list stays in step. Happy to add the Room twin to this PR or as a
follow-up, whichever the maintainers prefer.
Checklist
swift testinPackages/<name>)android/(only the shared schema-oracle fixture underandroid/app/src/test/resources/— no Kotlin changed)StrandDesigntokens — no hardcoded colors, fonts, or spacing (no UI changed)docs/CONTRIBUTING.mdStrand.xcodeproj/) or any secrets/keystoresRelated issues
Refs #814