diff options
Diffstat (limited to 'docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md')
| -rw-r--r-- | docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md index 1704a28..d5f58dd 100644 --- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md +++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md @@ -5290,3 +5290,51 @@ defect when `QT_TRANSLATE_NOOP` is reverted to `QT_TR_NOOP`. **Not done:** no language-selection UI, and no second language. `QLocale()` reading the environment is how a Linux desktop already chooses; add a selector when there is something to choose between. + +## 96. A query returning the thread already on display opens onto the placeholder + +**Observed (user, 2026-08-15, with two screenshots):** an `id:` query produces +exactly one card, the status bar reports "1 thread selected (1 message)", the +card paints as selected, and the message pane stays on the placeholder. Two +different messages from two different providers, with and without an account +selected. + +**Filed originally as the unverified half of item 66** and assumed to be the +same empty-`MessageIdRole` failure. It is not, and that assumption is what kept +it open: 66's fix was correct and this reproduced against it. + +**Cause (verified in code and by instrumented run):** `runQuery()` blanks the +message pane but leaves `m_currentThreadId`, `m_currentMessageId` and +`m_currentMessageThreadId` naming the thread that was showing. Both selection +handlers compare a newly selected row against those to decide whether it is +already displayed, so a result containing that same thread is recognised as +"already showing" and `onThreadSelected()` is never called. An instrumented run +printed `currentThreadId after runQuery: "0000000000000001"` against an +identical row thread id with the pane on the placeholder. + +**Why an `id:` query and nothing else.** The id is copied out of the details +dialog of the message being read, so that thread is current at the exact moment +the query replaces the view. Any query returning a different thread hides the +fault completely, which is why it survived from 2026-08-04 to 2026-08-15 and +why the first version of the regression test passed against it. + +**Four hypotheses eliminated by measurement before the cause was found**, each +of which looked likely from reading: + +- `MessageIdRole` empty on a fresh single-message row. The row carries the id. +- Account scoping mangling the query. `path:"acct/**" and (id:...)` returns the + row, and the user reproduced it with no account selected. +- `MimeParser` failing on the real file. A probe against it reported `ok true`, + 9614 bytes of plain text and 40701 of HTML. +- The id needing quoting. Both real ids resolve bare and quoted, one of them + carrying a `=` before the `@`. + +**Fix.** Clear the three ids where the pane is blanked, in `runQuery()`. They +describe what the pane is showing, so they cannot outlive it. + +**The regression test's first query must open the SAME thread the second one +returns.** With two different threads it passes against the defect, which is +how the first version of it was green. It asserts the ids are cleared, because +that is the fix's contract, and then that the pane leaves the placeholder, +which is what the user sees. Mutation check: reverting the fix fails it with +"runQuery blanked the pane but still names a current thread". |
