From 871c5760ef964faec87187d9909fb9d145688c7b Mon Sep 17 00:00:00 2001 From: ryanbr Date: Wed, 8 Jul 2026 17:46:00 +1200 Subject: [PATCH] =?UTF-8?q?Strap=20log:=20soften=20stale-RTC=20diag=20word?= =?UTF-8?q?ing=20=E2=80=94=20"no=20clock=20correlation=20at=20decode",=20n?= =?UTF-8?q?ot=20"never"=20(#67=20follow-up)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The identity-fallback diagnostic line (#69) asserted "(GET_CLOCK never correlated)", but sessionUsedIdentityRef is captured on the FIRST chunk. In the normal flow the correlation lands before chunk 1, and in the reset-RTC case it never lands — both fine. But on a slow link GET_CLOCK can reply late: chunk 1 decodes on the identity fallback, later chunks on the real ref, so "never" is false. First-chunk capture is still the right choice (it flags that the early rows landed misdated), only the absolute word overreached — reword to "(no clock correlation at decode)", true regardless of any later reply. Doc comment + test assertion updated to match. --- Strand/Collect/Backfiller.swift | 5 +++-- StrandTests/BackfillerSessionTallyTests.swift | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Strand/Collect/Backfiller.swift b/Strand/Collect/Backfiller.swift index f46daf977..5ab9c5f84 100644 --- a/Strand/Collect/Backfiller.swift +++ b/Strand/Collect/Backfiller.swift @@ -109,7 +109,8 @@ final class Backfiller { /// #67 diag: the clock reference the offload ACTUALLY decoded with, captured on the first chunk of the /// session. Surfaces whether the stale-RTC timestamp correction (FIX #72's `correctedWall`) could even - /// engage. `sessionUsedIdentityRef` = GET_CLOCK never correlated, so decode fell back to an identity + /// engage. `sessionUsedIdentityRef` = no clock correlation had landed when the first chunk decoded, so + /// that decode fell back to an identity /// ref (device==wall==now) → clock offset 0 → correction OFF. On a strap whose RTC has reset, that /// silently stores the strap's stale (years-old) timestamps verbatim, so the night lands off the recent /// timeline and reads as "missed sleep". Paired with the persisted-nights DATE RANGE below, one strap @@ -306,7 +307,7 @@ final class Backfiller { let offset = wall - device let days = offset / 86_400 if usedIdentityRef { - line += " · clock ref: IDENTITY fallback (GET_CLOCK never correlated) - stale-record correction OFF" + line += " · clock ref: IDENTITY fallback (no clock correlation at decode) - stale-record correction OFF" } else if abs(offset) > 86_400 { line += " · strap clock \(days >= 0 ? "\(days)d behind" : "\(-days)d ahead") wall - correction engaged" } else { diff --git a/StrandTests/BackfillerSessionTallyTests.swift b/StrandTests/BackfillerSessionTallyTests.swift index 3b04dc1f8..1023fb016 100644 --- a/StrandTests/BackfillerSessionTallyTests.swift +++ b/StrandTests/BackfillerSessionTallyTests.swift @@ -64,7 +64,7 @@ final class BackfillerSessionTallyTests: XCTestCase { let line = Backfiller.sessionClockDiagLine(nightKeys: [marchDay], device: 1_783_486_611, wall: 1_783_486_611, usedIdentityRef: true) - XCTAssertEqual(line, "Backfill: rows landed on 2024-03-24 · clock ref: IDENTITY fallback (GET_CLOCK never correlated) - stale-record correction OFF") + XCTAssertEqual(line, "Backfill: rows landed on 2024-03-24 · clock ref: IDENTITY fallback (no clock correlation at decode) - stale-record correction OFF") } // A genuinely stale-but-correlated ref: the correction IS engaged and the behind-by days are named.