Oura: log WHY a UTC anchor was rejected — iOS + Android (#91)#123
Merged
Conversation
Diagnostic observability for #91 (Oura anchor never lands -> history samples stay unanchored -> no sleep/daily). Reimplements the intent of #96 correctly. Each driver exposes a pure, read-only isPlausibleAnchorEpoch(epoch) predicate (the same 2020-2035 window setAnchorIfPlausible / the .timeSync/.rtcBeacon ingest already gate on). OuraLiveSource uses it, on receiving a 0x42/0x85 event, to log the precise rejection: - 0x42 time-sync with an implausible epoch -> log the offending epoch. - 0x85 RTC beacon with an implausible epoch -> log it. A beacon merely blocked because a primary anchor already exists is NORMAL and deliberately NOT logged. Also fixes a latent bug: the "UTC time anchor acquired" line fired on the FIRST time-sync unconditionally, even when that sync was rejected as implausible; it now announces "acquired" only when the sync actually anchored. Why not #96's approach: it added a Boolean return to setAnchorIfPlausible but never used it (dead code + unused-variable warnings), de-privatised the method for no caller, and keyed the logs off a d.hasAnchor property that DOESN'T EXIST -> it did not compile. And its messages were wrong (0x85 'primary already set' can never fire via !hasAnchor; the 0x42 epoch was divided by 1000). This version reads the driver's own plausibility predicate, so it compiles, uses the real signal, and logs the right reason with the right value. Adds a pinned-boundary unit test on both platforms (Swift + Kotlin twins). Verified: Android :app:compileFullDebugKotlin + OuraDriverTest pass; iOS OuraProtocol package builds + all 33 OuraDriverTests pass (both on WSL). The OuraLiveSource.swift log wiring rides the next iOS build (app target can't compile on WSL).
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.
Cross-platform diagnostic observability for #91 (Oura anchor never lands → history samples stay unanchored → no sleep/daily data). Reimplements the intent of #96 correctly, and supersedes it.
Approach
Each driver exposes a pure, read-only
isPlausibleAnchorEpoch(epoch)— the same 2020–2035 window the.timeSync/.rtcBeaconingest already gates on.OuraLiveSource, on receiving a 0x42/0x85 event, uses it to log the precise rejection:It also fixes a latent bug: the "UTC time anchor acquired" line fired on the first time-sync unconditionally — even when that sync was rejected as implausible. It now announces "acquired" only when the sync actually anchored.
Why not #96's implementation
#96 does not compile — it logs off a
d.hasAnchorproperty that doesn't exist anywhere in the tree (its own PR body claims to add it, but the commit doesn't). Beyond that: it added aBooleanreturn tosetAnchorIfPlausiblethat's never used (dead code + unused-variable warnings), de-privatised the method for no caller, and its messages were wrong (the 0x85 "primary already set" branch can never fire via!hasAnchor; the 0x42 epoch was divided by 1000). Reading the driver's own predicate compiles, uses the real signal, and logs the right reason with the right value.Files & verification
Drivers (
OuraDriver.swift/OuraDriver.kt): the predicate. Sources (OuraLiveSource.swift/.kt): the logging. Plus a pinned-boundary unit test on both platforms (Swift + Kotlin twins).:app:compileFullDebugKotlin+OuraDriverTestpass locally.OuraProtocolpackage builds + all 33OuraDriverTestspass on WSL (pure Swift, no SQLite wall), so the driver predicate + test are verified. TheOuraLiveSource.swiftlog wiring is self-reviewed and rides the next iOS build (app target can't compile on WSL).