From 854c850972b949b8124744c9af83d812ab98b208 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 14 Aug 2026 18:28:57 +0200 Subject: 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 --- .../plans/2026-08-03-post-0.1.0-usability.md | 83 +++++----------------- 1 file changed, 19 insertions(+), 64 deletions(-) (limited to 'docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md') 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 -- cgit v1.2.3