From 1328bece05f2a47ba2ad54e78788ffd0a1f5cc99 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sun, 9 Aug 2026 16:41:53 +0200 Subject: [PATCH] Use the platform sync device id for HLC stamps, not a hardcoded 'phone' sync_merge.dart declared its own `const _syncDeviceId = 'phone'`, which was unconditional -- so the desktop web build wrote records under `diet-guard-sync/devices/desktop/` while every HLC string inside them ended in `-phone`. The path segment came from the conditional-export constant, the HLC did not. Import `syncDeviceId` from github_client_factory.dart instead, so both halves come from the same source: 'phone' on Android, 'desktop' on web, matching the Python side's 'pc' in _constants.py. Preventive, not a repair: there is no devices/desktop/ in the live RTDB yet, so no already-written record has the mismatch. HLC tie-break is nodeId.compareTo, so desktop stamps now sort below phone's rather than tying; entryHlc is deterministic from entry.time and the bodies are identical for a given entry id, so this changes which identical copy wins, never what data survives. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01GZH89WEqAjuJT8WZdqc7AP --- app/lib/services/sync_merge.dart | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/lib/services/sync_merge.dart b/app/lib/services/sync_merge.dart index 5d0e8fc..224d4ef 100644 --- a/app/lib/services/sync_merge.dart +++ b/app/lib/services/sync_merge.dart @@ -36,10 +36,9 @@ import 'package:crypto/crypto.dart'; import 'package:diet_guard_app/models/food_bank_record.dart'; import 'package:diet_guard_app/models/food_entry.dart'; import 'package:diet_guard_app/services/budget_schedule.dart'; +import 'package:diet_guard_app/services/github_client_factory.dart'; import 'package:diet_guard_app/services/log_storage_service.dart'; -const _syncDeviceId = 'phone'; - /// Derives a deterministic [Hlc] for [entry] from its own `time` field. /// /// The same entry always yields the same Hlc regardless of when this runs @@ -51,7 +50,7 @@ const _syncDeviceId = 'phone'; /// survives a merge. Hlc entryHlc(FoodEntry entry) { final wallTimeMs = DateTime.tryParse(entry.time)?.millisecondsSinceEpoch ?? 0; - return Hlc.newTick(_syncDeviceId, wallTimeMsOverride: wallTimeMs); + return Hlc.newTick(syncDeviceId, wallTimeMsOverride: wallTimeMs); } /// Deterministic id for a pre-`id` legacy entry, from `(time, desc)`. @@ -207,7 +206,7 @@ Log foodBankToLog(Map bank) { 'body': ( mapEntry.value.toJson(), Hlc.newTick( - _syncDeviceId, + syncDeviceId, wallTimeMsOverride: mapEntry.value.count.toInt(), ), ), @@ -271,7 +270,7 @@ Log manualBankToLog(Map bank) { fields: { 'body': ( body, - Hlc.newTick(_syncDeviceId, wallTimeMsOverride: wallTimeMs), + Hlc.newTick(syncDeviceId, wallTimeMsOverride: wallTimeMs), ), }, ); @@ -338,7 +337,7 @@ Hlc budgetHlc(Map record) { record['t'] as String? ?? '', )?.toUtc().millisecondsSinceEpoch ?? 0; - return Hlc.newTick(_syncDeviceId, wallTimeMsOverride: wallTimeMs); + return Hlc.newTick(syncDeviceId, wallTimeMsOverride: wallTimeMs); } /// Field-name prefix for the effective-from budget history, one field per @@ -356,7 +355,7 @@ const budgetHistoryFieldPrefix = 'hist:'; Hlc historyHlc(BudgetEntry entry) { final wallTimeMs = DateTime.tryParse(entry.editedAt)?.toUtc().millisecondsSinceEpoch ?? 0; - return Hlc.newTick(_syncDeviceId, wallTimeMsOverride: wallTimeMs); + return Hlc.newTick(syncDeviceId, wallTimeMsOverride: wallTimeMs); } /// Converts a raw local budget record plus its history into a [Log].