From fb74b686e3abe414f50d9dd29457cfd07eb40819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 25 Jul 2026 06:13:07 +0200 Subject: [PATCH] =?UTF-8?q?chore(release):=20v1.32.29=20=E2=80=94=20a=20re?= =?UTF-8?q?-scored=20Fitbit=20night=20stops=20double=20counting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stable per-segment sleep keys plus the replace-by-window sweep, a one-shot repair over the past year, Retry-After handling, and the unchanged-value write skip. Migration 0270 records which connections the repair has been through. --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ docs/api/openapi.yaml | 2 +- package.json | 2 +- public/sw.js | 2 +- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bfa5c7be..1b50f4df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,35 @@ ## [Unreleased] +## [1.32.29] — 2026-07-25 + +Fitbit re-scores a night hours after you wake up: blocks get split, merged or +relabelled. HealthLog identified each block by its position in the list, so a +re-score that renumbered the blocks looked like a set of brand new ones. The +previous version stayed on file, nothing removed it, and from then on the night +counted twice. It was quiet: the sync kept reporting success, because the sync +was in fact working. + +- **A re-scored night no longer double counts.** Each sleep block is now + identified by the moment it starts, which does not move when Fitbit rescores + the night. A block that changes from light to deep updates in place instead + of leaving the old copy behind, and anything the new scoring dropped is + cleared from that night's window before the new blocks are written. +- **Nights already affected repair themselves.** A one off pass runs once per + connection after the update and rereads the past year of sleep, so the + duplicates collapse without you doing anything. It covers 365 days, the same + horizon the Fitbit history import uses. Nights older than that keep whatever + they already hold; they cannot gain new duplicates, since Fitbit does not + rescore year old nights. Migration `0270_fitbit_sleep_repair_marker` records + which connections have been through the pass. +- **Rate limits are handled instead of ignored.** When Fitbit asks for a short + wait, the request now waits and tries again once. A long wait is refused + outright and left to the next scheduled run, so one throttled account cannot + hold up everybody else's. +- **Fewer pointless writes.** Fitbit rereads the last 24 hours every hour. Rows + that came back unchanged were rewritten anyway, which showed up as needless + traffic for the iOS app. Unchanged rows are now left alone. + ## [1.32.28] — 2026-07-25 Oura used to look back exactly one week and no further. If the sync had been diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index ddff6a25d..0e84cb9ff 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: HealthLog API - version: 1.32.28 + version: 1.32.29 description: >- Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest. diff --git a/package.json b/package.json index e19716cb8..ece582df5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "healthlog", - "version": "1.32.28", + "version": "1.32.29", "description": "Self-hosted personal-health-tracking PWA with Withings integration, AI insights, and doctor-report PDF export.", "license": "PolyForm-Noncommercial-1.0.0", "homepage": "https://healthlog.dev", diff --git a/public/sw.js b/public/sw.js index 207db6e90..ca9eabcfc 100644 --- a/public/sw.js +++ b/public/sw.js @@ -36,7 +36,7 @@ try { // v1.4.38.4 → v1.4.42. Do not hand-edit; bump `package.json` and rebuild. const CACHE_VERSION = (typeof self !== "undefined" && self.__APP_VERSION__) || - /* @sw-version-fallback */ "v1.32.28"; + /* @sw-version-fallback */ "v1.32.29"; const STATIC_CACHE = `healthlog-static-${CACHE_VERSION}`; const PAGE_CACHE = `healthlog-pages-${CACHE_VERSION}`; // v1.18.6 — read-only data cache for a curated allowlist of safe GET `/api/*`