diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-14 18:28:57 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-14 18:28:57 +0200 |
| commit | 854c850972b949b8124744c9af83d812ab98b208 (patch) | |
| tree | 60c0415e2ba9854966f39510401e44484efee73e /docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md | |
| parent | 86074f40121466798cdd64e07a00db2542543c52 (diff) | |
| download | qtmaildir-854c850972b949b8124744c9af83d812ab98b208.tar.gz qtmaildir-854c850972b949b8124744c9af83d812ab98b208.zip | |
docs: close item 84, spec item 36
Item 84's section moves to the closed file, recording that the fix was
a split rather than a suppression, and that its mutation check
reproduces the original hang at exit 124 rather than merely failing.
Item 36 is specced and no longer "on demand": item 66 needs it. Two
findings while writing it. The deliverable is a RED reproduction of 66,
with the fix deliberately excluded, since that defect has never been
isolated and designing a fix beside a hypothesis is how a wrong one gets
locked in. And the item is smaller than it has read since 2026-08-04:
wireWorker() already builds the worker from a config key, so a test
writes a config pointing at the fixture and nothing in src/ changes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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 | 83 |
1 files changed, 19 insertions, 64 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 f578a3a..9240ad6 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 @@ -100,7 +100,7 @@ taking that too literally. | 33 | Status bar messages never expire | feedback | S | **done** | | 34 | No overview of the Maildir itself | information | M | **done** | | 35 | No refresh of the thread list after a sync | workflow | M | **done** 2026-08-10; the list now follows a sync on its own | -| 36 | `test_mainwindow` cannot reach the worker | testing | S | open, on demand | +| 36 | `test_mainwindow` cannot reach the worker | testing | S-M | open, specced 2026-08-14; see `specs/2026-08-14-mainwindow-worker-fixture-design.md`. No longer on demand: item 66 needs it. Smaller than it reads, `wireWorker()` already builds the worker from a config key | | 37 | The worker stalls on a tag edit made during a background sync | correctness | S | **done** | | 38 | `test_mainwindow` fails when a real sync holds the lock | testing | XS | **done** | | 39 | Thread list cannot be sorted by clicking a column header | workflow | S | **dropped** 2026-08-10; the card list has no column headers to click, and 0.13.0 shipped a sort dropdown instead | @@ -148,7 +148,7 @@ taking that too literally. | 81 | No way to turn a saved query into a tagging rule | workflow | S | **done** 2026-08-14, unreleased; see `specs/2026-08-14-query-to-rule-design.md` | | 82 | A saved query cannot be edited, unpinned or deleted from the UI | defect | S | **done** 2026-08-13, shipped in 0.18.0. Right-click offers Edit, Pin/Unpin and Delete | | 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 | +| 84 | A config problem blocks `test_mainwindow` on a modal nobody can dismiss | testing | S | **done** 2026-08-14, unreleased. `showWarnings()` split: the status label stays in the constructor, `main.cpp` raises the modal after `show()` | | 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 | **done** 2026-08-14, unreleased; see `specs/2026-08-14-exclude-from-search-design.md`. Follows 85. The `extend` bool became a `SearchMode` enum across four signatures | @@ -246,17 +246,26 @@ one did. Where a real message exposes a parser bug, hand-write a minimal `.eml` reproducing its **shape**, as `truncated.eml` and `hostile_filename.eml` already do. -**Approach.** Give `test_mainwindow` the fixture and point the window's worker at -it, so a test can select a thread and let a real `threadLoaded` arrive. +**Specced 2026-08-14: read +`specs/2026-08-14-mainwindow-worker-fixture-design.md` rather than planning from +here.** -**Do this when a defect needs it, not before** (user, 2026-08-04). Wiring it -with nothing to test proves nothing. The two defects above are already fixed; -this item is the note that the next one of its kind should be tested properly -rather than modelled. +**No longer on demand.** The entry said to do this when a defect needs it, not +before (user, 2026-08-04). Item 66 needs it now, so the deliverable is a RED +reproduction of that defect, not fixture wiring on its own. Fixing 66 is +deliberately excluded: it has never been isolated, and designing a fix beside a +hypothesis is how a wrong one gets locked in. + +**Smaller than this entry has read since 2026-08-04.** No hook has to be added +to `MainWindow`. `wireWorker()` (`src/mainwindow.cpp:1440`) already builds the +worker from `m_config.notmuchConfig()`, an ordinary config key, so a test that +writes a `qtmaildir.conf` pointing at the fixture gets a real worker through the +shipping path with nothing in `src/` changed. Mind the `[general]` prefix trap +when writing that file. **Constraint:** every existing `test_mainwindow` case constructs a bare -`MainWindow` and must keep working. The fixture is per-test, not a suite-wide -`initTestCase`, or every case pays for a `notmuch new`. +`MainWindow` and must keep working. The fixture is opt-in per test, not a +suite-wide `initTestCase`, or every case pays for a `notmuch new`. ## 40. No live filter over the current view @@ -524,60 +533,6 @@ in CLAUDE.md. **Size: S**, down from M now that item 85 has built the menus and item 81 the seeded dialog. -## 84. A config problem blocks `test_mainwindow` on a modal nobody can dismiss - -**Observed (2026-08-14):** a new test in `test_mainwindow` hung with no output -and was killed at the two-minute timeout. It had configured an account section -carrying only `sent=`, with no `maildir=`. - -**Cause (verified by attaching gdb to the hung process, not inferred).** - -``` -#7 QDialog::exec() -#9 MainWindow::showWarnings ... src/mainwindow.cpp:1670 -#10 MainWindow::MainWindow ... src/mainwindow.cpp:381 -``` - -`Config::load` handles the malformed account exactly as it should: it records -"Account 'one' has no maildir; ignoring it" and carries on -(`src/config.cpp:413-418`). `showWarnings()` then puts every collected problem -in a `QMessageBox::warning`, which is modal, and it is called from the -`MainWindow` CONSTRUCTOR. Under the offscreen platform nothing can dismiss it, -so the constructor never returns. - -**This is not a defect in the application.** The modal is deliberate and is -right for a person: a config problem should interrupt startup rather than -scroll past, and the code comment at `src/mainwindow.cpp:1661` explains which -problems qualify. A user sees the dialog and clicks OK. The defect is that a -TEST cannot, and the failure it produces is a silent hang rather than an error -naming the cause, which cost a debugging detour to identify. - -**Constraint on any fix: the modal must survive for real use.** Suppressing it -whenever `QTEST_MAIN` is linked would be the obvious move and is wrong, since -that is exactly the path `test_mainwindow` exercises and a suppressed dialog -means the startup warning ships untested. Two candidates, neither yet chosen: - -- A `MainWindow` flag, defaulting to showing the modal, that the tests set. It - makes the behaviour explicit and testable in both states. -- Collecting the problems and emitting them, with the modal raised by a caller - outside the constructor. Larger, and it separates "what is wrong" from "how - the user is told", which is the better shape if anything else ever needs the - list. - -**Related: every test that configures an account is one typo away from this.** -The suite has several, all of them currently well-formed. A malformed one does -not fail, it hangs, and a hang in CI reads as an infrastructure problem rather -than a test problem. - -**A second trap sits on top of the first and wasted as much time.** A hang -leaves the test binary running, and a later `ctest` then runs a STALE binary -while the source on disk has moved on, so the failure appears to persist after -it has been fixed and to vanish for reasons unconnected to the change. Kill any -surviving `test_mainwindow` and rebuild before concluding anything about a hang -here. - -**Size: S.** The diagnosis is the expensive part and it is already done. - ## Deferred, unsized, or split out Items noted while triaging but not part of the original list. Same numbering |
