Skip to content

feat(classify): optional priority field for category rules - #663

Merged
ErikBjare merged 3 commits into
ActivityWatch:masterfrom
TimeToBuildBob:feat/classify-priority-597
Sep 3, 2026
Merged

feat(classify): optional priority field for category rules#663
ErikBjare merged 3 commits into
ActivityWatch:masterfrom
TimeToBuildBob:feat/classify-priority-597

Conversation

@TimeToBuildBob

@TimeToBuildBob TimeToBuildBob commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Optional integer priority (alias weight) on categorize rules, as discussed in #597.

  • Explicit integer on the rule dict: higher wins
  • Omitted: rank is depth * 10 (depth 1 → 10, depth 2 → 20), so values can slot between nesting levels
  • Unprioritized configs keep the current deepest-match-wins order
  • Query example: { "type": "regex", "regex": "vim", "priority": 25 }

In the reported tree (A matches at depth 1, B→B1 matches at depth 2) A wins if its priority is higher than B1's default of 20.

Does not change default configs. Python ranking is ActivityWatch/aw-core#153. WebUI editor field is still a follow-up — not closing #597 here.

@greptile-apps

greptile-apps Bot commented Aug 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds optional integer priorities, including the weight alias, to category rules while preserving depth-based ranking for existing configurations.

  • Introduces CategoryRule with optional explicit priority.
  • Parses and validates priority metadata at the query boundary.
  • Selects the highest-ranked matching category while retaining later-match tie behavior.
  • Preserves Uncategorized when category paths are empty.
  • Adds unit and query-level coverage for priority ranking and invalid values.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
aw-transform/src/classify.rs Adds priority-aware category selection and completely applies the prior empty-category fallback fix before matching or ranking.
aw-query/src/datatype.rs Converts category-rule query values into CategoryRule instances and validates optional integer priority metadata.
aw-query/src/functions.rs Updates the categorize built-in to pass typed CategoryRule values into the transform.
aw-query/tests/query.rs Adds end-to-end coverage for priority overrides, the weight alias, and invalid priority values.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Query category-rule list] --> B[Parse category, rule, and optional priority]
    B --> C{Category path empty?}
    C -->|Yes| D[Skip rule]
    C -->|No| E{Rule matches event?}
    E -->|No| F[Check next rule]
    E -->|Yes| G[Rank by explicit priority or depth times 10]
    G --> H{Rank at least current rank?}
    H -->|Yes| I[Replace selected category]
    H -->|No| F
    D --> F
    F --> J[Write selected category or Uncategorized]
Loading

Reviews (3): Last reviewed commit: "fix(classify): default ranking to depth ..." | Re-trigger Greptile

Comment thread aw-transform/src/classify.rs
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Empty-category fallback fixed in 676c090 (Greptile P1).

macOS test_push_does_not_reexport_synced_buckets failure is the known aw-sync tmp_db collision (duplicate column name: data) — same flake #655 targets. Unrelated to this change; ubuntu/windows/android/clippy/format are green.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.97590% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.45%. Comparing base (656f3c9) to head (1003817).
⚠️ Report is 98 commits behind head on master.

Files with missing lines Patch % Lines
aw-query/src/datatype.rs 88.88% 3 Missing ⚠️
aw-transform/src/classify.rs 92.59% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #663      +/-   ##
==========================================
+ Coverage   70.81%   79.45%   +8.63%     
==========================================
  Files          51       67      +16     
  Lines        2916     5835    +2919     
==========================================
+ Hits         2065     4636    +2571     
- Misses        851     1199     +348     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

CI-green and mergeable (Greptile 5/5) — 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.

@ErikBjare

Copy link
Copy Markdown
Member

@TimeToBuildBob Strictly integer? If so I think default should be depth * 10 not just depth, so that users can prioritize rules inter-level. I always had depth * 10 in mind, not sure if integer-only is the right design (probably).

@ErikBjare

Copy link
Copy Markdown
Member

@TimeToBuildBob Also need support in aw-core/aw-server-python

When multiple rules match, ranking uses an optional `priority` (alias
`weight`) on the rule dict. If omitted, depth-based ranking is unchanged.

This lets a shallow rule beat a deeper organizational match without
changing default behavior for existing configs.
An empty match must not replace Uncategorized. The old depth comparison
rejected len 0 against the fallback's len 1; keep that when ranking
starts from i64::MIN so negative priorities can still categorize.
Integer-only priority. Unset rules rank as depth * 10 so explicit
values can slot between nesting levels (depth 1 → 10, depth 2 → 20).
Relative order of unprioritized rules is unchanged.
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Integer-only, with default depth * 10 as you described.

  • Unset rules rank as depth × 10 (depth 1 → 10, depth 2 → 20), so 15 slots between levels while unprioritized configs keep the same order.
  • Explicit priority/weight stays a strict integer (floats rejected).
  • Pushed on this PR in 1003817.

Python ranking is ActivityWatch/aw-core#153 (aw-server uses that aw_transform.classify path; no separate copy). WebUI editor field is still a follow-up.

@ErikBjare
ErikBjare merged commit d2e7b80 into ActivityWatch:master Sep 3, 2026
8 checks passed
ErikBjare pushed a commit to ActivityWatch/aw-core that referenced this pull request Sep 3, 2026
* feat(classify): optional priority field for category rules

Match ActivityWatch/aw-server-rust#663: integer `priority`/`weight` on
rules, default rank is depth * 10 so values can slot between nesting
levels. Existing configs keep their current ordering.

* fix(classify): pick category without i64 fallback sentinel

Replace the signed-64-bit Uncategorized rank with Optional[int] so a
valid unbounded Python priority below -(2**63) still beats Uncategorized.

Git-Session-Id: bob-monitor-aw-core-153
ironcatan pushed a commit to ironcatan/aw-core-es that referenced this pull request Sep 5, 2026
* feat(classify): optional priority field for category rules

Match ActivityWatch/aw-server-rust#663: integer `priority`/`weight` on
rules, default rank is depth * 10 so values can slot between nesting
levels. Existing configs keep their current ordering.

* fix(classify): pick category without i64 fallback sentinel

Replace the signed-64-bit Uncategorized rank with Optional[int] so a
valid unbounded Python priority below -(2**63) still beats Uncategorized.

Git-Session-Id: bob-monitor-aw-core-153
Judemasic added a commit to Judemasic/aw-server-rust that referenced this pull request Sep 8, 2026
Brings in category-rule priority support (ActivityWatch#663) and the aw-webui bump
(ActivityWatch#668). The aw-webui submodule pointer is unchanged: beta had already
moved it to a2ca625, which upstream master now also points at.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants