Repository navigation
Conversation
…e_subwatcher_fields Wire browser url and $domain fields into the canonical window event stream before categorize() runs, so URL-based category rules fire on desktop. merge_subwatcher_fields (added to aw-server-rust in ActivityWatch#824) overlays the named fields from browser_events onto the matching window events by temporal overlap. The call is guarded by the browser-buckets condition, so queries against servers without the function are unaffected when no browser watcher is installed. Closes ActivityWatch/activitywatch#352. Git-Session-Id: 0db2fd2e-f72d-4387-898c-6c33d3138142
The supported server floor (v0.12.3b18, both aw-server and aw-server-rust) predates merge_subwatcher_fields, so emitting it unconditionally broke the activity query for every user with a browser watcher on an older server (VariableNotDefined, whole Activity view fails) and failed the pinned-version CI jobs. Probe the function once at startup with a no-op query and only emit the enrichment when the server resolves it. Views now mount after the probe, so the first activity query already sees the correct flag. Also strengthen the stopwatch-order test (it never supplied bid_stopwatch, so moving the merge before the union would still have passed) and let the server-backed regex suite exercise enrichment only when the running server supports it. Git-Session-Id: b38a584e-5f94-5837-baea-39b0d5af5c57
aw-server answers any query program without a RETURN statement with EmptyQuery (HTTP 400) whether or not the called function exists, so the probe reported 'unsupported' on every server and silently disabled the URL enrichment this PR adds. Share the probe query between the store and the server-backed test so the two cannot drift, and assert it returns a value. Git-Session-Id: 2cf884cf-c63a-5199-abce-89689529d224
[Medium impact] The change affects category matching in a bounded set of browser-aware activity views. The PR appears safe to merge, with a non-blocking startup feedback issue. Findings
SummaryAdds
BMMach explicitly acknowledges single-device coverage, stored fields on older servers, offering fields without browser buckets, and Timeline coloring as known limitations. BMMach also leaves merge order, incognito behavior, conflict policy, blank-field rules, and the external documentation update out of scope. Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Load settings] --> B[Fetch server info]
B --> C[Probe browser-field merge support]
C --> D[Render views]
D --> E[Offer supported rule fields]
D --> F[Build activity query]
F --> G{Supported and browser buckets supplied?}
G -->|Yes| H[Copy URL and domain onto window events]
G -->|No| I[Keep window events unchanged]
H --> J[Apply category rules]
I --> J
Reviews (1) · Last reviewed commit: "feat(categories): offer url and $domain ..." · Reviewed by Greptile |
| await serverStore.getInfo(); | ||
| this.loaded = true; |
There was a problem hiding this comment.
Waiting for getInfo() now hides the entire page, including navigation and the error boundary. If the server stalls after settings load, the info request and capability probe run sequentially and can each take the default 30-second timeout. Users see a blank page for up to another minute.
Keep views gated until the probe finishes, but show a loading message while they wait.
…e_wins Per review feedback: - Move merge_subwatcher_fields before the stopwatch union — stopwatch events explicitly recorded by the user should not be split and stamped with browser url/$domain. - Exclude incognito browser events so private-window URLs don't reach category rules via this path. - Switch conflict mode from sub_wins to base_wins — on macOS, aw-watcher-window already writes url natively, and base_wins preserves it. Update test to assert merge now runs BEFORE the stopwatch union. Git-Session-Id: 38379c75-dec8-5614-bf5f-4c972d785e04
1bfdadb to
816765e
Compare
Git-Session-Id: 31183379-9a70-5e62-bc65-142d2a63be63
Git-Session-Id: 77734be4-4d7d-52ca-8645-c3eea4ffe632
The beforeAll probe now distinguishes the expected VariableNotDefined response (old server without merge_subwatcher_fields) from unexpected failures (5xx, network errors). A transient HTTP 500 previously silently disabled enrichment, making all three URL/domain tests skip instead of fail. Now a probeError variable is set and the enrichment tests throw it rather than returning silently. Git-Session-Id: 7c6247ec-d763-5fa9-be60-11ec4e47d9c0
aw-server (Python) rejects the unknown merge_subwatcher_fields call with QueryInterpretException "Tried to call function ... which doesn't exist", not aw-server-rust's VariableNotDefined. The probe classified it as an unexpected error, failing the three enrichment tests on the Python leg. Git-Session-Id: 58312207-09b2-4529-81a4-643fa48042ee
Builds on ActivityWatch#1153, which merges browser url/$domain into the categorized window events when the server supports merge_subwatcher_fields. This offers those keys in the rule editor's match fields, so a rule can target the URL or domain alone instead of every string field. - Offer url/$domain only when the startup probe from ActivityWatch#1153 found merge_subwatcher_fields. Without it, $domain never reaches window events, and url only does where aw-watcher-window records it itself (macOS). - Keep showing a stored key even when it is not offered, without listing it twice. - Add server-backed cases: url- and $domain-scoped rules claim only focused browser time, not another app's window (even when its title would match), and match nothing on servers without the merge. Refs ActivityWatch/activitywatch#352 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
816765e to
0b32b32
Compare
Stacked on #1153, so it needs that merged first. Only the last commit (816765e) is new; I'll rebase the first four away once #1153 lands. Draft until then.
Problem
#1153 merges browser
url/$domaininto the window events thatcategorize()sees. But the rule editor's match fields still offer onlyappandtitle(CANONICAL_SELECT_KEYS). The only way to use the URL is a rule with blank match fields, and that matches every string field at once. There's no way to write a rule from the editor that matches only the URL or only the domain.Change
src/util/classes.ts: addBROWSER_SELECT_KEYS = ['url', '$domain'].src/components/CategoryEditModal.vue: offer those keys next toapp/titleonly when the startup probe from feat(queries): enrich window events with browser url/$domain via merge_subwatcher_fields #1153 foundmerge_subwatcher_fields.select_keysUI before the default categories use it. This extends that UI to the browser fields.urlitself for some browsers, so aurlrule could match there even on older servers. I didn't special-case that.$domainvalue is the hostname without a leadingwww., as computed bysplit_url_events.There are no query, server or i18n changes, so query performance is unchanged. Field names render as-is, like
app/titletoday.Known limitations
canonicalEvents()merges browser fields only when the caller passes browser buckets.url/$domainmatches nothing, excepturlon macOS, where aw-watcher-window records it.url/$domain(for example from an imported preset) still shows them on older servers, where they won't match.url(except on macOS), and raw web events have no$domain, so$domainrules don't color Timeline rows, andurlrules only match browser rows.Tests
CategoryEditModaltests check three things: url/$domain are offered only whensupportsMergeSubwatcherFields()is true, a storedurlstays visible when it isn't, and with the flag on a storedurlis listed once.browserRegexServer.test.node.tsuse a minute of Edge, then a minute ofCode.exewith the same tab still reported active, and aCode.exetitle that a blank-field rule would match. With the merge, aurl- or$domain-scoped rule claims only the Edge minute. Without it, everything stays Uncategorized.make lint,npm run check:locales,npm run typecheck:testandnpx jest(with a local server) pass after merging current master.Out of scope
src/features/categorization.rstin ActivityWatch/docs still says URLs can't be matched. That's a separate docs PR once this lands.Refs ActivityWatch/activitywatch#352
🤖 Generated with Claude Code