summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md43
1 files changed, 43 insertions, 0 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 85e6ce8..f10a301 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
@@ -95,6 +95,7 @@ taking that too literally.
| 45 | Two Sync buttons, and only one of them works properly | correctness | S | **done** |
| 46 | `uiStateSurvivesARestart` fails under the offscreen platform | testing | XS | **done** |
| 47 | The query bar looks unfinished, and cannot be cleared by mouse | presentation | XS | **done** |
+| 48 | Removing a tag suggests every tag, not the thread's own | workflow | XS | open |
Sizes are rough: XS under an hour, S a sitting, M a session.
@@ -2361,6 +2362,48 @@ user as acceptable; suppressible if it becomes annoying in daily use.
**Verification:** by hand. The tests do not click the ✕, which is a mouse path.
The user confirmed the icon renders correctly, is themed, and clears the field.
+## 48. Removing a tag suggests every tag, not the thread's own
+
+**Observed (user, 2026-08-06):** "when removing a tag from a thread using the
+input box, I get suggested all tags, not only those relevant to the message
+being edited."
+
+**Cause (verified in code):** both fields share one completer setup.
+`TagDialog`'s constructor loops over `{ m_addEdit, m_removeEdit }` and builds
+`new QCompleter(knownTags, edit)` for each (`src/tagdialog.cpp:163-164`), and
+`knownTags` is every tag in the database. That is right for Add, where the point
+is to reach any tag and even create one, and wrong for Remove, where the only
+tags that can be removed are the ones the selected threads already carry.
+
+**The data is already in the dialog.** The constructor takes `currentTags`, a
+`QHash<QString, int>` of tag to how many selected threads carry it
+(`src/tagdialog.h:66-67`), and uses it at `:212` to render the existing-tag
+display. It is simply never given to the remove field's completer, so this needs
+no new plumbing and no worker query.
+
+**Approach.** Build the two completers from different vocabularies rather than
+in one loop: `knownTags` for Add, `currentTags.keys()` for Remove.
+
+**Constraints.**
+
+- **Keep the setWidget/prefix machinery exactly as it is.** Both fields hold a
+ comma-separated list, and `QLineEdit::setCompleter` is the documented trap
+ this dialog already works around, hit twice in this codebase. Only the
+ candidate list changes; the wiring does not.
+- **Completion stays a suggestion, not a whitelist.** The dialog's own comment
+ records that a tag absent from the list is exactly what it exists to create.
+ For Remove that matters less, but typing a tag not in the list must still be
+ possible rather than blocked, so nothing may start validating input against
+ the candidates.
+- On a multi-thread selection `currentTags` is the union across the selection,
+ with counts. That is the right set to offer, since removing a tag two of three
+ threads carry is meaningful. Do not filter to tags every thread has.
+
+**Verification:** a test can construct the dialog with a known `currentTags` and
+assert the remove field's completer offers only those. The keys must be typed,
+not `setText()`, since `setText` does not drive a completer at all, which
+`CLAUDE.md` records.
+
## Deferred, unsized, or split out
Items noted while triaging but not part of the original list. Same numbering