Skip to content

fix(aw-transform): empty regex rules never match - #774

Merged
ErikBjare merged 2 commits into
ActivityWatch:masterfrom
TimeToBuildBob:fix/empty-regex-never-matches
Oct 2, 2026
Merged

ErikBjare merged 2 commits into
ActivityWatch:masterfrom
TimeToBuildBob:fix/empty-regex-never-matches

Conversation

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Summary

  • An empty regex pattern compiles to a match-all regex in fancy_regex, so RegexRule::new("") silently categorized/tagged every event.
  • aw-core's Python aw_transform.classify.Rule deliberately never matches on an empty regex ("would erroneously match everything"). aw-server-rust diverged from that behavior.
  • fix(categories): treat blank regex rules as matching nothing everywhere aw-webui#1026 hides this for the web UI by sending blank rules as {type: 'none'}, but other clients (aw-client categorize queries, scripts, the CLI) still see the divergence.
  • Adds a never_matches flag on RegexRule, set when the source pattern is empty, checked before any regex evaluation on both the select_keys and shared-values match paths.
  • New regression test test_empty_regex_never_matches (fails on master, passes after the fix).

Unrelated CI note

This branch also carries the clippy::block_scrutinee allow from #771/#772 (Rust 1.99+ clippy toolchain drift in the generated aw-query parser, unrelated to this change) so this PR's own CI passes independently of whether #771 has merged yet. Once #771 merges first, that one-line diff here will disappear on rebase.

Test plan

  • cargo test -p aw-transform — 79 passed, 0 failed
  • Confirmed the new test fails on master without the fix (reverted the one-line guard locally, reproduced the failure, restored it)
  • cargo clippy --workspace -- -D warnings clean
  • cargo fmt --check clean

RegexRule::new("") compiled to a match-all regex in fancy_regex, so a
blank category rule matched every event. aw-core's Python
aw_transform.classify.Rule deliberately never matches an empty regex
("would erroneously match everything") — aw-server-rust silently
diverged from it. ActivityWatch/aw-webui#1026 hides this for the web UI
by sending blank rules as {type: 'none'}, but other clients (aw-client
categorize queries, scripts, the CLI) still see the divergence.

Add a never_matches flag set when the pattern is empty, checked before
any regex evaluation, so an empty-regex rule behaves like Rule::None
instead of a wildcard. Covered by a new regression test that fails on
master.

Also carries the aw-query clippy::block_scrutinee allow from ActivityWatch#771/ActivityWatch#772
(unrelated Rust 1.99+ toolchain drift) so this branch's own CI/clippy
passes independently of that PR's merge.

Git-Session-Id: 1d99
@greptile-apps

greptile-apps Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Fixes regex rule matching logic for empty patterns.

The PR appears safe to merge; the previously reported empty-regex conversion path is fixed.

Summary

The PR makes empty regex rules never match, including when constructed through the public Rule::from(Regex) conversion.

  • Adds regression coverage for both construction paths.
  • Adds a Clippy allowance for the generated query parser.

Reviews (2) · Last reviewed commit: "fix(aw-transform): derive never_matches ..."

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

codecov Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 82.59%. Comparing base (656f3c9) to head (144d324).
⚠️ Report is 169 commits behind head on master.

Files with missing lines Patch % Lines
aw-transform/src/classify.rs 88.88% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master     #774       +/-   ##
===========================================
+ Coverage   70.81%   82.59%   +11.77%     
===========================================
  Files          51       81       +30     
  Lines        2916    10428     +7512     
===========================================
+ Hits         2065     8613     +6548     
- Misses        851     1815      +964     

☔ 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.

Greptile P1: Rule::from(Regex::new("").unwrap()) hard-coded
never_matches: false, so the public conversion path still let an empty
regex match every event — the exact bug this PR fixes, reachable past
the new guard. Derive the flag from the source pattern and cover the
From path in the regression test.

Git-Session-Id: 2b7710f0-a6ec-5fa0-b895-bf715c0f8ab4
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

@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.

@TimeToBuildBob

TimeToBuildBob commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 AI code review

This PR adds a never_matches flag to RegexRule in aw-transform/src/classify.rs, set when the source regex pattern is empty, and checks it before any regex evaluation in both value_matches and matches. It also adds a regression test test_empty_regex_never_matches and updates the clippy allow list in aw-query/src/lib.rs to include unknown_lints and clippy::block_scrutinee.

Safe to merge — no P0/P1 findings

Confidence 5/5

✅ No thread-worthy findings. Advisory notes follow; they are retained without opening review threads.

1 advisory finding (summary-only, not scored)

These P2 guard, heuristic, trade-off, or documentation claims are retained for judgment without opening review threads.

⚠️ P2 medium — aw-transform/src/classify.rs

This is a fix(...) PR but no test files are included in the diff. Erik's feedback: 'where is the repro & fixes they are supposed to catch' (gptme#3441), 'that measurement should come with a regression test' (gptme#3446). Add a test that would have caught this bug. (Advisory: Erik merged all such PRs but consistently requested tests.)

Add a test file that reproduces the bug before the fix and passes after it.

How this was verified: static preflight: fix-commit + touched-files scan (rule 7)

Files changed (2) — the diff as I read it
  • aw-query/src/lib.rs — Adds unknown_lints and clippy::block_scrutinee to the clippy allow list on the parser module.
  • aw-transform/src/classify.rs — Adds never_matches flag to RegexRule, sets it from empty pattern in new and From<Regex>, checks it in value_matches and matches, and adds a regression test.

Reviewed 144d324cc70e · openrouter/deepseek/deepseek-v4-flash-0731 · llm engine · 72s · about this reviewer

Maintainer commands

@TimeToBuildBob review (own line) — fresh review · @TimeToBuildBob fix — a worker acts on the findings. Once per comment; 👀 = received.

@ErikBjare
ErikBjare merged commit 9008520 into ActivityWatch:master Oct 2, 2026
8 checks passed
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