fix(evidence): X11 sensor polls so tab/title changes are tracked

The X11 source only re-read the active window on _NET_ACTIVE_WINDOW
changes, so switching a browser tab — which changes the window title
but not the active window — was invisible. All the time on the new tab
was credited to the stale title (e.g. reading a Consume article showed
up as time on the Keel tab).

Mirror the Windows sensor: poll the active window every 750ms and emit
only when the window or its title changes. A shared, display-free
pollLoop carries the change-dedup and is unit-tested for the exact
regression (a title-only change must emit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-05 20:32:24 -04:00
parent 6d296bf743
commit 682eb603fa
4 changed files with 157 additions and 39 deletions
+3 -2
View File
@@ -24,8 +24,9 @@ type WindowSnapshot struct {
}
// Source is the activity port. Watch runs until ctx is cancelled, invoking
// onChange on every active-window change, and once immediately with the
// current window.
// onChange once immediately with the current window and then on every change of
// the active window or its title (a tab switch changes the title but not the
// active window).
type Source interface {
Watch(ctx context.Context, onChange func(WindowSnapshot))
}