fix(idle): exclude paused timers from the idle auto-stop sweep - #752
Merged
evilguy4000 merged 1 commit intoSep 8, 2026
Merged
Conversation
A paused timer stops heartbeating, so its last_heartbeat_at goes stale and check_idle_timers() treats it as idle: it sends a "Still working?" push, then after the grace period flags it needs-review and, once the optional safety cap elapses, auto-stops it. But a paused timer is intentionally accumulating no time, so notifying, flagging, or stopping it is wrong. Guard the idle query on TimeEntry.paused_at.is_(None). paused_at shipped with the pause/resume feature but was never wired into this query. Adds a regression test: a stale paused timer must be skipped, while a stale non-paused timer is still notified.
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.
Problem
check_idle_timers()selects every open time entry (end_time IS NULL) whose last heartbeat is older than the idle window, then idle-notifies it, flags itneeds_review, and — with the safety cap enabled — auto-stops it.A paused timer is also an open entry with a stale heartbeat: it is intentionally accumulating no time and sends no heartbeats while paused. So the sweep treats a deliberately-paused timer exactly like an abandoned running one — it fires the "Still working?" push, flags it for review, and can auto-stop a timer the user chose to pause.
Root cause
paused_atwas added with the pause/resume feature but never wired into the idle-sweep query. TheWHEREclause guards onlyend_timeand the heartbeat cutoff, so paused rows fall straight through.Fix
Add
TimeEntry.paused_at.is_(None)to the idle query so paused timers are excluded from notify / flag / auto-stop. Four added lines, no behavioral change for running timers.Tests
New
tests/test_idle_timer_skips_paused.py:test_idle_sweep_skips_paused_timer— a paused, stale timer is neither notified, flagged, nor stopped.test_idle_sweep_still_notifies_running_timer— control: a genuinely idle, non-paused timer is still swept, guarding against over-correction.Full timer test suite green locally.