Skip to content

Fix #665: give every rule condition its own checkbox - #666

Merged
kellylford merged 2 commits into
mainfrom
claude/issue-665-release-223be0
Sep 6, 2026
Merged

Fix #665: give every rule condition its own checkbox#666
kellylford merged 2 commits into
mainfrom
claude/issue-665-release-223be0

Conversation

@kellylford

Copy link
Copy Markdown
Owner

Fixes #665.

The problem

The rule editor reached by Ctrl+Shift+T (Create Rule from Message) prefilled the message's
From and Subject and offered no way to say which of them the rule was meant to use, so it used
both. "Rule for someone@example.com" therefore matched that sender only when the subject was the
exact line it was made from — in practice, the one conversation it was created from.

The reported editor is ServerRuleEditorWindow, the one the unified Rules Manager opens for a
profile with a Microsoft 365 account. The client-only RulesManagerWindow has had condition
checkboxes since #333; this window never got them.

The change

Each free-text condition now has a checkbox in front of it — From addresses and Subject
contains
, plus Sender contains, Sent to addresses, Subject or body contains and
Body contains under Advanced. Clearing one leaves the text in its box (read-only and out of
the tab order, the same shape the client Rules Manager already uses), so a prefilled value stays
one keystroke from being used rather than something to retype.

The switches are authoritative everywhere, not only in the UI: ToModel, ToClientRule,
ServerOnlyFeaturesUsed and HasAdvancedContent all read private Effective* accessors, so a
switched-off condition is invisible to saving, to the client-rule mapping and to the
server/client classification. A consumer that reads the raw text property instead is the
regression the tests are aimed at.

They default on, matching the client Rules Manager, so a hand-made rule behaves exactly as
before — an empty field was, and still is, no condition. Loading an existing rule clears the
switch on every empty field, so the editor reads back what the rule actually does.

One behaviour change worth calling out: CreateRuleFromMessage now builds its template with
UseSubjectCondition = false. The subject still comes across, so it is sitting in the box ready
to switch on — but the rule you get by default is the one its name claims: everything from that
sender. This is the half of #665 that the checkbox alone would not have fixed.

Keyboard walkthrough (Ctrl+Shift+T, Microsoft 365 account)

  1. Press Ctrl+Shift+T on a message. The rule editor opens with focus in Rule name, holding
    "Rule for someone@example.com".
  2. Tab. Rule enabled checkbox, checked.
  3. Tab. From addresses (comma-separated) checkbox, checked.
  4. Tab. The From box, editable, holding the sender's address.
  5. Tab. Subject contains checkbox, not checked.
  6. Tab. Skips the subject box — it is not a tab stop while its condition is off. Focus lands on
    Move to folder. To use the subject after all, Shift+Tab back to its checkbox, press Space
    (announced as checked), then Tab into the box, which now holds the message's subject and is
    editable.
  7. Choose an action, then Save.

Infrastructure changes

  • No new commands, no F6 ring changes, no new AccessibilityHelper.Announce calls. Toggling a
    checkbox is reported by the platform; nothing here announces on top of it.
  • Six new VM properties (UseFromAddresses, UseSubjectContains, UseSenderContains,
    UseSentToAddresses, UseBodyOrSubjectContains, UseBodyContains).
  • The new checkboxes carry no AutomationProperties.Name: their Content is the field's
    label, and restating it in different words is how a label/name mismatch gets in.
  • Nothing new is persisted. A switched-off condition simply is not written, so there is no
    migration and no config change.

Out of scope

  • The client-only RulesManagerWindow is unchanged apart from receiving the same template — it
    already had checkboxes.
  • The already-boolean conditions (Sent to me, Sent only to me, Has attachments) and the
    Importance combo, whose "Not set" entry is its own off state.
  • Ctrl+Shift+T is registered by both mail.createRuleFromMessage and view.focusTabs. Not
    touched here, but noted.

Tests

  • RuleConditionSwitchTests — 13 tests over the prefill, the round trip, ToClientRule, and the
    classifier (a switched-off server-only condition must stop blocking the client mapping).
  • RuleEditorConditionWiringTests — a Sites-style table of the six condition fields, asserting
    each has a CheckBox bound to its switch and binds both IsReadOnly and IsTabStop to it.
    Adding a seventh condition field without a checkbox fails it.
  • Full suite: 3546 passed, 0 failed, 3 skipped (the opt-in synthesized-input tests).

Not run: scripts/ui-probe.ps1. Its rules surface captures the Rules Manager list window, not
this editor, so the plan does not cover the changed window either way. The new checkboxes use the
EditorCheckBox style already used six times in the same window.

🤖 Generated with Claude Code

The rule editor reached by Ctrl+Shift+T prefilled the message's From and
Subject and offered no way to say which of them the rule was meant to use,
so it used both. "Rule for someone@example.com" therefore matched that
sender only when the subject was the exact line it was made from — the one
conversation it was created from.

Each free-text condition in ServerRuleEditorWindow now has a checkbox in
front of it: From addresses and Subject contains, plus Sender contains,
Sent to addresses, Subject or body contains and Body contains under
Advanced. Clearing one leaves the text in its box (read-only and out of the
tab order, as in the client Rules Manager), so a prefilled value stays one
keystroke from being used rather than something to retype.

The switches are authoritative everywhere, not just in the UI: the VM routes
saving, the client-rule mapping and the server/client classification through
private Effective* accessors, so a switched-off condition is invisible to
all three. They default on, matching the client Rules Manager, so a
hand-made rule behaves exactly as before — an empty field was, and still is,
no condition. Loading an existing rule clears the switch on every empty
field so the editor reads back what the rule actually does.

CreateRuleFromMessage now builds its template with UseSubjectCondition
false: the subject comes across so it is there to switch on, but the rule
you get by default is the one its name claims.

RuleEditorConditionWiringTests is the regression guard — a Sites-style table
of the six condition fields, asserting each has a CheckBox bound to its
switch and binds both IsReadOnly and IsTabStop to it. Adding a seventh
condition field without a checkbox fails it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kellylford
kellylford deployed to azure-signing September 5, 2026 23:49 — with GitHub Actions Active
… guard

Three findings from the independent review.

ToClientRule dropped the text of a switched-off condition, so saving a
QuickMail rule from the unified editor lost what the editor had promised was
one keystroke away — while the standalone Rules Manager, editing the same
rule, has always kept it. The text is now carried with the flag left clear,
which is MailRule's own meaning (engine, row summary and validation all
require the flag AND text), so the same rule no longer means two different
things depending on which window saved it. Carrying only ever fills a slot
the switched-on conditions left empty, so a populated-but-off Sender cannot
displace the From address that is actually in use.

HasAdvancedContent asked whether an advanced field was switched on, which
broke its own invariant that editing never hides a populated field: a client
rule with Body switched off but populated opened with Advanced collapsed and
the text invisible. It asks about text again.

RuleEditorConditionWiringTests checked only the binding path of IsReadOnly,
so binding it straight to the switch without InverseBoolConverter — the
inversion that makes a box editable exactly when its condition is off —
passed. It now asserts the converter, and that the checkbox is the element
immediately in front of its field rather than merely somewhere in the window.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kellylford
kellylford deployed to azure-signing September 6, 2026 00:03 — with GitHub Actions Active
@kellylford
kellylford merged commit 586b78f into main Sep 6, 2026
5 checks passed
@kellylford
kellylford deleted the claude/issue-665-release-223be0 branch September 6, 2026 00:14
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.

Basic Rule Creation Should Use Check Boxesfor Conditions

1 participant