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 | 87 |
1 files changed, 87 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 f46fec5..ef51b5c 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 @@ -6612,3 +6612,90 @@ Three lessons, in the order they were paid for: `image/png` that is demonstrably on the clipboard: a Wayland clipboard-manager interaction, or GIMP's own paste path. Neither is this repository's, and neither needs an item here until it is shown to be. + +## 103. What Delete does to mail on the server is undocumented and unverified + +**Observed (user, from the notes):** "verify how 'delete' works", with two +sub-questions of their own: "trash bin (?)" and "delete from server (?)". + +**This is a question first.** The user is not reporting a defect; they are saying +they do not know what the button does to their mail, which for a destructive +action is its own problem regardless of the answer. + +**What the code does (verified).** `src/mainwindow.cpp:825` adds and removes the +`deleted` tag, and nothing else. It is a toggle, it goes through the undo stack, +and it writes a notmuch tag. + +**What that means downstream is what needs verifying, and it is NOT in this +repo.** `maildir.synchronize_flags` is true, so notmuch maps certain tags to +Maildir filename flags, and mbsync carries filename flags to the server. Whether +`deleted` is one of those, whether the user's `~/.mbsyncrc` has `Expunge Both` +(it does, on every channel), and what each provider does with a message flagged +deleted, together decide whether this button is reversible. The undo stack makes +the TAG reversible; it says nothing about what a sync did with it in between. + +**Measured 2026-08-17, and the answer is that Delete does not delete.** notmuch's +tag-to-flag table has no row for `deleted` and no `T` flag, confirmed by a probe +on a throwaway database: `+deleted` left the filename untouched while the +control `+flagged` immediately produced `:2,F`. mbsync carries filename flags, so +`Expunge Both` never sees anything to expunge, and `assets/mailsync.sh` contains +no delete path. Both sub-questions answer no: no trash bin, no deletion from the +server, and the mail stays in the Maildir and the index forever. + +**Specified in +`specs/2026-08-17-delete-to-trash-design.md`. Read that before writing code.** +Delete becomes a real move into the account's trash folder, with a `Trash` +filter beside the other built-ins and a Restore action. Three constraints decide +whether the spec is worth opening: + +- It needs a **mandatory per-account `trash` key**, so an existing config warns + until five keys are added. User-visible: minor bump and an `### Upgrading` + note. +- The worker gains its **first non-tag mutation**, a rename plus a reindex, + deliberately shaped as `moveMessages(ids, destFolder)` so Send in v2 reuses it + for Drafts and Sent. +- **848 messages carry the old tag** while sitting in an inbox, and would be + invisibly half-deleted after the change. A repeatable menu entry queries them + into the list for review; it is not a startup migration. + +The no-confirmation rule survives, with its justification amended: the mail +lands in a browsable folder, but reversibility is now bounded by the provider +where the trash is purged on a timer. + +**Size: S** for the investigation, which is done. The build is **M**. + +**Built 2026-08-19, over eight commits on `delete-to-trash`.** Delete moves the +file into the account's `trash` folder and records where it came from in a +`deleted-from:<folder>` tag, because the file has moved and nothing else still +knows. A `Trash` filter sits beside the other four, `Restore from trash` +(`Ctrl+R`) is the inverse, and `Find stranded deleted mail` (`Ctrl+Alt+T`, a +menu entry only at the user's request) lists the 848 messages the old behaviour +left tagged but unmoved. It reports and moves nothing: acting on its own would +be a bulk delete with no selection behind it. + +**Ten defects were found by hand testing, not by the suite**, each reproduced +with a probe before being fixed. One had already damaged real mail: a folder +name containing a space was truncated by the origin tag, creating a bogus folder +beside the real one and stranding four messages of a thread. mbsync had adopted +it and written state files for it. That is the fact worth carrying out of this +item: **under `Create Both` a wrongly named origin folder propagates to the mail +server**, so any code composing a folder name is reaching the server whether it +means to or not. Tags are joined by a TAB across the thread boundary for the +same reason, since a notmuch tag may contain a space. + +**Two process gaps closed alongside it.** Adding an action is FIVE places and +this repository's CLAUDE.md said four; the missing one is a menu, and nothing +enforced it, so `restore` shipped reachable by a chord and by nothing a user +could see. `everyActionIsReachableFromAMenu()` now asserts it and found three +more of the same (`open_thread`, `clear_pane`, `clear_selection`). And a guard +in `deletingTwiceLeavesNoOriginTagBehind()` queried through the query bar in the +gap between the file rename and the tag writes, where a run returns zero rows +forever because `QTRY_VERIFY` re-reads `rowCount()` and never re-runs the query: +3 failures in 12 runs, each burning a full 15s timeout, 0 in 8 after asking the +database directly. + +**Emptying the trash is item 118 and remains deferred**, at the user's request. + +**Verified:** clean build with no warnings from any changed file, 24 of 24 +suites over three consecutive runs, 211 tests in `test_mainwindow`. Every one of +the spec's six testing bullets has a test, each mutation-checked. |
