screen-locker/screen_locker
Krzysztof kuhy Rudnicki cdee896d43 Apply sync tombstones across the device union, not per device log
The previous commit dropped tombstoned records while reading each device
log, which was not enough: _merge_device_records unions across devices
keeping the highest HLC, so a record tombstoned on one device and still
live on another was simply absent from one dict and won the merge from
the other -- ingested exactly as before.

Collect tombstoned ids across every device log, then suppress by id
after the union. crdt-sync makes deletion monotonic inside its own merge
for this reason; this reader rolls its own merge, so it has to honour
the same rule itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018M5gKyYzxWG6QkCaj1wWfk
2026-08-21 13:38:52 +02:00
..
tests Apply sync tombstones across the device union, not per device log 2026-08-21 13:38:52 +02:00
__init__.py Fix test discovery and coverage for python_pkg modules 2025-12-02 22:33:34 +01:00
_adb_transport.py Split _shutdown, _phone_verification and _status_data 2026-08-15 20:11:28 +02:00
_auto_upgrade.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_cli.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_compliance_predicates.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_compliance_state.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_compliance_trace.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_constants.py Queue behind stronger lockers, single-instance guard, fix budget-crash in fit check 2026-08-21 13:04:54 +02:00
_decision_log.py Re-arm the locker, and make a disarmed enforcer impossible to miss 2026-08-17 16:47:25 +02:00
_device.py Push under a persisted per-install uuid, not a fixed role id 2026-08-09 17:31:15 +02:00
_early_bird.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_extra_benefits.py Support multiple workouts per day; fix the dead sync; ban silent failures 2026-07-17 09:22:31 +02:00
_heat_skip.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_http_workout_fetch.py Split _shutdown, _phone_verification and _status_data 2026-08-15 20:11:28 +02:00
_instance.py Queue behind stronger lockers, single-instance guard, fix budget-crash in fit check 2026-08-21 13:04:54 +02:00
_log_io.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_log_mixin.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_manual_push.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_manual_sync.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_manual_workout_dialog.py Split _manual_workout_dialog.py and _manual_workout.py 2026-08-15 20:16:33 +02:00
_manual_workout_sport_fields.py Split _manual_workout_dialog.py and _manual_workout.py 2026-08-15 20:16:33 +02:00
_manual_workout_types.py Split _manual_workout_dialog.py and _manual_workout.py 2026-08-15 20:16:33 +02:00
_manual_workout_widgets.py Split _manual_workout_dialog.py and _manual_workout.py 2026-08-15 20:16:33 +02:00
_manual_workout.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_mcp.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_phone_verification.py Split _shutdown, _phone_verification and _status_data 2026-08-15 20:11:28 +02:00
_runnerup_backfill.py Split _runnerup_verification, _ui_widgets and _sick_dialog 2026-08-15 20:37:15 +02:00
_runnerup_db.py Retry RunnerUp verification every 15 min, and stop hiding why it fails 2026-08-12 19:17:29 +02:00
_runnerup_tcx.py Split _runnerup_verification, _ui_widgets and _sick_dialog 2026-08-15 20:37:15 +02:00
_runnerup_verification.py Finish the RunnerUp sport-allowlist removal; isolate the instance lock in tests 2026-08-21 13:17:26 +02:00
_shutdown_base.py Support multiple workouts per day; fix the dead sync; ban silent failures 2026-07-17 09:22:31 +02:00
_shutdown_sick_state.py Split _shutdown, _phone_verification and _status_data 2026-08-15 20:11:28 +02:00
_shutdown.py Split _shutdown, _phone_verification and _status_data 2026-08-15 20:11:28 +02:00
_sick_budget.py Split _workout_sync.py and _sick_tracker.py 2026-08-15 20:30:42 +02:00
_sick_commitment.py Split _runnerup_verification, _ui_widgets and _sick_dialog 2026-08-15 20:37:15 +02:00
_sick_dialog.py Split _runnerup_verification, _ui_widgets and _sick_dialog 2026-08-15 20:37:15 +02:00
_sick_tracker.py Split _workout_sync.py and _sick_tracker.py 2026-08-15 20:30:42 +02:00
_startup_checks.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_status_data.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_status_projection.py Split _shutdown, _phone_verification and _status_data 2026-08-15 20:11:28 +02:00
_status_sections.py Split _compliance_state.py and status_view.py 2026-08-15 20:01:12 +02:00
_status_types.py Split _shutdown, _phone_verification and _status_data 2026-08-15 20:11:28 +02:00
_status_view_verify.py Make Check Phone week-aware; add RunnerUp GPS tolerance; fix CLI weekly count 2026-07-18 06:55:55 +02:00
_status.py Re-arm the locker, and make a disarmed enforcer impossible to miss 2026-08-17 16:47:25 +02:00
_surface_group.py Type the surface groups properly and exempt the test helpers by name 2026-07-25 16:56:59 +02:00
_sync_client.py Split _workout_sync.py and _sick_tracker.py 2026-08-15 20:30:42 +02:00
_sync_mixin.py Split screen_lock.py under the 250-line cap 2026-08-15 19:01:18 +02:00
_sync_records.py Apply sync tombstones across the device union, not per device log 2026-08-21 13:38:52 +02:00
_sync_retry.py Let the PC see phone workouts again, and stop losing progression on reinstall 2026-08-10 14:39:02 +02:00
_sync_status.py Show which sync backend the PC uses in the status window 2026-08-09 21:20:02 +02:00
_temperature_status_mixin.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_temperature.py Add phone-workout GitHub sync via shared crdt_sync (Workstream C) 2026-07-11 00:06:59 +02:00
_time_check.py Support multiple workouts per day; fix the dead sync; ban silent failures 2026-07-17 09:22:31 +02:00
_ui_flows_lockout.py Split _ui_flows.py into sick-day and lockout flow mixins 2026-08-15 19:56:16 +02:00
_ui_flows_relaxed.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_ui_flows_sick.py Split _ui_flows.py into sick-day and lockout flow mixins 2026-08-15 19:56:16 +02:00
_ui_flows.py Split _ui_flows.py into sick-day and lockout flow mixins 2026-08-15 19:56:16 +02:00
_ui_form_fields.py Split _runnerup_verification, _ui_widgets and _sick_dialog 2026-08-15 20:37:15 +02:00
_ui_widgets.py Split _runnerup_verification, _ui_widgets and _sick_dialog 2026-08-15 20:37:15 +02:00
_unlock_view.py Stop the lock screen scrolling itself, and make every screen fit 768px 2026-08-03 15:57:48 +02:00
_wake_alarm.py Split _shutdown, _phone_verification and _status_data 2026-08-15 20:11:28 +02:00
_wake_state.py Migrate to the shared gatelock backend 2026-06-21 20:11:16 +02:00
_weekly_check.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_window_setup.py Queue behind stronger lockers, single-instance guard, fix budget-crash in fit check 2026-08-21 13:04:54 +02:00
_workout_credit.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00
_workout_sync.py Apply sync tombstones across the device union, not per device log 2026-08-21 13:38:52 +02:00
adjust_shutdown_schedule.sh fix: resolve shutdown-schedule canonical path via guardctl dynamically 2026-07-04 11:48:39 +02:00
screen_lock.py Opt in to preempting a weaker gatelock holder 2026-08-21 13:31:57 +02:00
status_view.py Stop the relaxed-day popup from re-firing every 30 minutes after Skip 2026-08-18 21:55:59 +02:00