diff options
Diffstat (limited to 'docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md')
| -rw-r--r-- | docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md | 41 |
1 files changed, 10 insertions, 31 deletions
diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md index 15377ea..087ce95 100644 --- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md +++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md @@ -150,7 +150,7 @@ taking that too literally. | 83 | A rule named with spaces is written to the file and dropped by every reader | defect | S | **done** 2026-08-14, unreleased. The name is sanitised into an id, save validates, a bad id loads for repair | | 84 | A config problem blocks `test_mainwindow` on a modal nobody can dismiss | testing | S | open; measured 2026-08-14, `showWarnings()` calls `QMessageBox::warning` from the constructor | | 85 | Nothing on screen can be searched for by right-clicking it | workflow | M | **done** 2026-08-14, unreleased; see `specs/2026-08-14-search-from-message-design.md`. Split from 78; rebuilt the details dialog as rows | -| 86 | A right-click search can replace or narrow, but never exclude | workflow | S | open; follows 85. The `extend` bool has no room for a third choice, so this widens a signature rather than adding a menu entry | +| 86 | A right-click search can replace or narrow, but never exclude | workflow | S | open, specced 2026-08-14; see `specs/2026-08-14-exclude-from-search-design.md`. Follows 85. The `extend` bool has no room for a third choice, so this widens a signature rather than adding a menu entry | Sizes are rough: XS under an hour, S a sitting, M a session. @@ -597,36 +597,15 @@ bool: `extend ? SearchTerm::extend(m_queryEdit->text(), query) : query`. missing menu entry over an existing capability; there is no third state for a menu entry to select, and the signature cannot express one. -**Approach.** Three changes, in this order, and the first is the only design -decision. - -- **Widen the signal past a bool.** A third operation makes `bool extend` wrong - at four call sites. An enum (replace, narrow, exclude) carried through - `MessageView`, `MessageDetailsDialog` and `MainWindow` is the honest shape. - Note that it crosses no thread boundary, so the `Q_ENUM` metatype trap in - `CLAUDE.md` does not apply here; these are direct connections. -- **Add `SearchTerm::exclude(existing, addition)`**, parenthesising both sides - exactly as `extend()` does, as `(existing) AND NOT (addition)`. The - parenthesising is load-bearing for the same reason it is in `extend()`: the - query bar can hold a hand-written disjunction, and an unparenthesised - `NOT a or b` binds so that the exclusion covers only the first term. This is - the whole of the testable surface and it needs no widget. -- **A third menu entry per offer**, wrapped in `tr()`. - -**Constraints.** - -- **Excluding from an empty query is not a search.** `extend()` returns the - addition alone when `existing` is empty; the same rule here would produce - `NOT (x)`, meaning "all mail except", which is a plausible thing to ask for - and an implausible thing to have meant by right-clicking a sender. Decide - deliberately: either suppress the entry when the query bar is empty, or let it - through. Do not let it fall out of the code by accident. -- **notmuch reports nothing for a malformed query**, so correctness is asserted - against the constructed string, never against a provoked failure or a result - count. `SearchTerm`'s own header records this. -- The details dialog must keep calling `accept()` BEFORE emitting, per item 85's - trap. A new action added to that menu inherits the same requirement, and its - mutation check hangs rather than fails. +**Specced 2026-08-14: read +`specs/2026-08-14-exclude-from-search-design.md` rather than planning from +here.** Three constraints decide whether it can be picked up. The `bool extend` +becomes a `SearchMode` enum across four signatures, which is the bulk of the +work and touches three files. Excluding from an EMPTY query would mean the whole +Maildir minus one value, so the entry is greyed when the query bar is empty and +the grammar returns empty as a second layer. And correctness is asserted against +the constructed string, never a result count, because notmuch parses `from:((((` +cleanly and matches zero. **Size: S.** The grammar is one function beside an existing one with existing tests; the spread is the signature change across three files. |
