Repository navigation
test(cbio): pin the GS1 surface to the timestamp-free reading it publishes - #193
Merged
Merged
Conversation
…ishes #146 recorded a +7h28m skew on screen: the hero read `Latest reading at 09:04` and the 12 h axis ended at `09:01` while the phone clock read `02:34`. The counter advances 60 s per stored record, so 448 stored records rendered as 7 h 28 m of apparent elapsed time. The rendering half of that fix lives in the app-live branch: the session publishes `recordedAt: null` for these records, the hero reports the protocol position (`Sensor raw value · index 10067`), and the chart's null path renders `m<minute>`. Nothing on the lane pins that, so this adds the guard: - the removed counter-to-clock formula is asserted to be the on-screen skew (448 x 60 s == 7 h 28 m), so the arithmetic cannot be re-derived as harmless; - a GS1 reading is asserted to carry no `recordedAt`, and the hero's only time formatter is asserted to refuse to invent one; - the real dashboard is rendered with those readings and asserted to show the protocol position with no `HH:mm` anywhere in the hero, and to hand the chart only timestamp-free readings. Mutation check: reinstating `recordedAt: DateTime.fromMillisecondsSinceEpoch(record.rawTime * 1000, isUtc: true)` in `CbioGlucoseSession._historyReadings` fails `cbio_glucose_session_test.dart` with `Expected: null / Actual: DateTime:<...>`. Tests: openhealth 483 passed; `flutter analyze` clean; `dart format` clean on the added file.
This was referenced Sep 18, 2026
Owner
Author
|
No rebase needed for this PR: the anchor branch (#197) keeps the guard green unchanged, because its fixture carries no anchor metadata. Verified on The hero's new clock line is a separate |
shroominic
added a commit
that referenced
this pull request
Sep 18, 2026
The GS1 surface published no time at all: the `08` counter is epoch-less, so #146/`#193` forbid rendering a wall clock from it. That left the hero with `Sensor raw value · index 10070` and nothing else, and any surface that did ask for a time showed a placeholder. The one reference the app establishes itself is the sensor clock it writes once per session. `CbioIndexTimeAnchor` turns that into absolute time honestly: - an anchor exists only when the session wrote the clock and the sensor's own newest record stamp agrees with the app's clock within `cbioAnchorTolerance` (3 min); - the anchored position carries its own stamp, and every older position steps 60 s per index, as the vendor layout reports the counter (`base + 60 * i`); - the range the anchor speaks for ends at the first hole or counter jump, so positions the archive cannot support keep no timestamp; - the anchor travels in the snapshot metadata (`anchorIndex`, `anchorEpochSeconds`, `anchorCoveredFrom`, `referenceEpochSeconds`) and the diagnostics name it, so provenance is readable without the radio. The counter is never the source: a sensor that did not take the written clock (the 7 h 28 m skew of #146) publishes no anchor, and the hero says `Sensor clock unsynced · ordered by sensor index, not by clock` instead of a placeholder or an invented minute. With an anchor the hero reads `Sensor clock set by this app · latest 10:05 (±1 min)`, localised by the device. Refs #146, #193. Tests: cgm_cbio 91 passed (2 skipped), openhealth 485 passed; `flutter analyze` clean in both, including `openhealth/integration_test`.
This was referenced Sep 18, 2026
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.
Refs #146. Answers the open G2 question: no rendered timestamp on the GS1 lane is wrong today.
Verdict
The skew is gone because the GS1 lane renders no clock derived from the record
counter at all. Three independent checks:
CbioGlucoseSession._historyReadingspublishesrecordedAt: nullfor every08record - pinned bycbio_glucose_session_test.dart(expect(latest.recordedAt, isNull)).Sensor raw value · index 10070, and the stored-range caption is in sensorminutes.
readingTimeTextreturns--for a timestamp-free reading._axisLabeland its tooltip both key offrecordedAt == null,so a GS1 point renders
m<minute>/Minute <n>, neverHH:mm.The arithmetic from #146 still holds as the shape of the trap: 448 stored
records x 60 s is exactly the
01:36 -> 09:04(+7 h 28 m) the screen showed fora 448-record fetch, while the phone clock did not move.
RED
Mutation check on this branch's base (
05785b0). Reinstating the removedprojection in
CbioGlucoseSession._historyReadings:The mutated source is restored; the only change on this branch is the new test
file.
GREEN
Tests added
openhealth/test/cbio_timestamp_guard_test.dart, three tests:the counter-to-clock formula #146 removed is the on-screen skew- pins448 * 60 == 7 h 28 mand that the removed formula produces exactly it.a GS1 reading has no wall clock for any surface to render-recordedAtisnull and
readingTimeText/clampedDisplayRecordedAtrefuse to invent one.the hero and the chart carry no counter-derived clock- renders the realdashboard, finds
Sensor raw value · index 10070, asserts noHH:mmand noLatest reading atin the hero, and asserts only timestamp-free readingsreach
CgmDashboardChart. The chart's null-label branch has no seam to assertdirectly (
_axisLabelis private and paints to a canvas), so this pins theinput contract on top of the source pin in (1).
Observed, not fixed here
openhealth/test/cbio_app_surface_test.dartbuilds its GS1 fixture withrecordedAt: DateTime.now().subtract(...), which is not what the sessionpublishes. It has not hidden the skew (no assertion there depends on it), but a
fixture that invents timestamps cannot detect a regression in this area. Left
alone to avoid colliding with #188, which edits the same file.
Verification
cd openhealth && flutter test- exit 0,+483: All tests passed!(was+480)flutter analyze-No issues found!dart format --output=none --set-exit-if-changed test/cbio_timestamp_guard_test.dart- clean