Repository navigation
Conversation
query_bucket returns events newest-first, but the merge walks both lists in ascending order. Unsorted input emitted overlapping events: a 40-minute span with full coverage in both lists summed to 70 minutes. period_union and filter_period_intersect already sort their inputs. Counterpart of ActivityWatch/aw-server-rust#838. Git-Session-Id: f67bd883-b10a-49dd-99de-2938d082f464
[Medium impact] This PR appears safe to merge. Summary
Reviews (1) · Last reviewed commit: "fix(transform): sort union_no_overlap in..." · Reviewed by Greptile |
|
CI-green and mergeable — waiting only on a maintainer click. This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted. |
🤖 AI code reviewThe PR changes Safe to merge — no P0/P1 findingsConfidence 5/5 ✅ No findings. The diff looks correct to me on this pass. Files changed (2) — the diff as I read it
Reviewed Maintainer commands
|
union_no_overlapwalks both lists in ascending timestamp order, butquery_bucketreturns events newest-first, and the query function passes its arguments through unsorted. The result then contains overlapping events and durations are double-counted.Repro against a v0.14.1 aw-server-rust
--testingserver (this module ports the same algorithm): window and AFK buckets that each fully cover the same 40 minutes.union_no_overlap(query_bucket("w"), query_bucket("afk")) -> sum_durations 4200.0 union_no_overlap(sort_by_timestamp(query_bucket("w")), sort_by_timestamp(query_bucket("afk"))) -> sum_durations 2400.0aw-webui hits this path with raw bucket output:
canonicalEvents:stopwatch_events = query_bucket(...)thenunion_no_overlap(stopwatch_events, events)activityQuery:not_afk_curr = filter_keyvals(query_bucket(...), ...)thenunion_no_overlap(not_afk, not_afk_curr), once per AFK bucket. With two or more devices the total is inflated.The fix sorts both inputs inside the transform, as
period_unionandfilter_period_intersectalready do. Inputs that are already sorted produce the same output as before.Test:
test_newest_first_inputs_are_sorted_before_mergingfeeds reversed lists. It fails without the sort and passes with it. The fullpytest testssuite passes (359 passed, 5 skipped) andruff checkis clean.Counterpart of ActivityWatch/aw-server-rust#838. The Python server is what aw-qt autostarts in the v0.14.1 Qt bundle, so this is the path most desktop users hit.
Also reproduced live on the released Python
aw-serverv0.14.1 (--testing, isolated home), using the same buckets: unsorted4200.0, sorted2400.0. A chainedactivityQuery-style union (a = []; a = union_no_overlap(a, afk); a = union_no_overlap(a, window)) returns3600.0where the correct coverage is2400.0.