feat(classify): add regex_fields whole-field AND rule type - #670
TimeToBuildBob wants to merge 1 commit into
Conversation
|
Introduce Rule::RegexFields(RegexFieldsRule) alongside the existing
Rule::Regex. The new variant matches events by testing each named field
against its own compiled regex, requiring ALL fields to match (logical
AND). Each pattern is anchored to the entire field value via \A(?:...)\z
so that partial-string matches are rejected without requiring the caller
to add explicit anchors.
Motivation: mstsc.exe and winbox.exe can display the same title string
when connected to the same host. Title-only regexes cannot distinguish
them. Cross-field matching (app AND title) is the minimal change that
lets a user create mutually exclusive RDP vs Winbox categories.
Contract (mirrors aw-core Python implementation):
- type: 'regex_fields', fields: {<field>: <pattern>, ...}, ignore_case: bool
- All named fields must exist as strings in event.data
- Each pattern must match the full field value (not a substring)
- 'regex' and 'select_keys' members are rejected at parse time to guard
against the identified rollout hazard (old Python reads a stray 'regex')
- Empty fields map is a validation error
DataType parser in aw-query/src/datatype.rs extended to deserialise the
new rule shape; 6 new unit tests added to aw-transform/src/classify.rs.
Git-Session-Id: 3f81
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #670 +/- ##
==========================================
+ Coverage 70.81% 79.02% +8.20%
==========================================
Files 51 67 +16
Lines 2916 5893 +2977
==========================================
+ Hits 2065 4657 +2592
- Misses 851 1236 +385 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
adeba0a to
479359f
Compare
|
@greptileai review |
|
Greptile is now 5/5 on the current head, every CI check passes, and the prior compression finding is resolved on its thread. No further code change or re-trigger is needed; this is waiting only for maintainer review/merge. |
|
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. |
🤖 AI code reviewSafe to merge — no P0/P1 findings on latest reviewUpdated after inline dispositions on finding threads — this is the current state; the verdict below is frozen at review time and is kept as the historical record of that pass. Finding disposition
Adds a new Needs a look — P2 onlyConfidence 4/5 1 finding ·
|
|
@TimeToBuildBob Does this have a parallel aw-core implementation? Is this a finalized design? Is it really needed/a good idea? We already added something like this ( |
|
Answers in order: Parallel aw-core implementation: yes — ActivityWatch/aw-core#155 is the Python twin with the same rule format ( select_keys is not equivalent: it only narrows which keys a single shared regex searches ( Needed / good idea?: it's the only way to express the RDP-vs-Winbox disambiguation in rules today without a rule-execution-order hack, and it's strictly opt-in ( |
explain?
yeah something like that? Just not fully convinced that this is the design we want to settle into, seems pretty marginal and adds a whole rule type. I was hoping that the existing type could somehow be leveraged to accomplish stuff like this. I feel like there's a lot of prior work and discussion here, not just that one issue you came from. It's maybe worth collating all of that prior information and discussion to actually see what needs we have or what gaps there are in the category rules system. |
|
"Without a rule-execution-order hack" — explained: today, two apps sharing a title ( Collation of prior work on the category rules system (what keeps recurring is "which field(s) does this pattern apply to"):
The gap Proposal, converging on your instinct: drop the separate {"type": "regex", "fields": {"app": "mstsc\\.exe", "title": "office\\.example\\.com"}}
If that shape works for you, I'll rework both PRs to it. |
@TimeToBuildBob But is not how the current regex rules work? What's the most intuitive "anchoring" or "fullmatch" or whatever you call it here? |
|
No — current For the per-field
So the most intuitive anchoring here is: no implicit anchoring — inherit the existing rule's search semantics, let users anchor explicitly with |
|
Collation done, as a durable doc rather than another wall of comment text:
Two corrections to my 10:20Z collation, caught while verifying against the API:
The doc recommends Option B — fold per-field matching into the existing type as an optional map, keeping the type's current unanchored {"type": "regex", "fields": {"app": "mstsc\\.exe", "title": "office\\.example\\.com"}}
|
Summary
Adds a new
regex_fieldsrule variant for category/tag classification that lets users constrain multiple fields simultaneously (logical AND) with whole-field matching semantics.This addresses the use-case from ActivityWatch/aw-webui#939: when two apps (e.g.
mstsc.exefor RDP,winbox.exefor Winbox) share the same window title, the existingregexrule cannot distinguish them because it OR-tests fields. Aregex_fieldsrule with bothappandtitlepatterns resolves this exactly.New rule format
{ "type": "regex_fields", "fields": { "app": "mstsc\\.exe", "title": "office\\.example\\.com" }, "ignore_case": false }All named fields must be present in the event data, be strings, and fully satisfy their pattern (
\A(?:PATTERN)\zwhole-field anchoring, unaffected by embedded newlines).Backward compatibility
regexrules with OR semantics are completely unchanged."type": "regex_fields").regexorselect_keysmember (old Python silently reads a staleregexmember on unknown types).ignore_caseuses(?i)prefix (as inRegexRule) sinceRegexBuilder::case_insensitiveis unsupported byfancy_regex.What changed
aw-transform/src/classify.rs: NewRegexFieldsRulestruct +RuleTraitimpl; newRule::RegexFieldsvariant.aw-query/src/datatype.rs:TryFrom<&DataType> for Rulenow dispatches ontype == "regex_fields"and builds the rule from aDataType::Dictof field→pattern pairs.Testing
cargo test --package aw-transform --package aw-query— 55 tests pass.Companion PR for aw-core (Python server): ActivityWatch/aw-core#154 (pending)
Closes ActivityWatch/aw-webui#939 (partial — webui editor wiring is a follow-up once capability is advertised)