diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md | 84 | ||||
| -rw-r--r-- | docs/superpowers/specs/2026-08-17-delete-to-trash-design.md | 12 |
2 files changed, 73 insertions, 23 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 82860a3..6a5e64d 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 @@ -182,6 +182,7 @@ taking that too literally. | 115 | A copy from the message pane gives no confirmation | presentation | XS | open, 2026-08-17. Copy link address, Copy image address and Copy image all work, silently. `statusMessage` already exists and already expires | | 116 | Copy image copies markup instead of the image | defect | XS | **dropped** 2026-08-17, same day. NOT A DEFECT: `wl-paste --list-types` run immediately after a copy reports `image/png`, `application/x-qt-image` and 30 more image flavours. The clipboard is correct and Chromium is behaving. The earlier "text only" reading was taken minutes late off a clipboard that had been overwritten, and a whole cause was theorised on it | | 117 | The message pane offers no Select all | workflow | XS | open, found 2026-08-17. NOT caused by item 100: verified by hand against a build with that filter reverted, and the menu holds Copy and the search entries either way | +| 118 | No way to empty the trash from inside the app | workflow | S | open, 2026-08-17. **Blocked on 103**, which creates the trash in the first place. Deliberately left out of 103's spec at the user's request rather than squeezed in | Sizes are rough: XS under an hour, S a sitting, M a session. @@ -505,26 +506,35 @@ Maildir filename flags, and mbsync carries filename flags to the server. Whether 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. -**Approach.** Measure before designing anything: the notmuch config's -`maildir.synchronize_flags` and its tag-to-flag mapping, one real message tagged -and synced in a test account, and what the server shows afterwards. Then decide -whether the UI needs to say what it does, whether "Delete" is even the right -word for it, and whether a trash view is wanted. - -**Constraints.** - -- **This is the one place the no-confirmation rule should be re-examined rather - than assumed.** `CLAUDE.md` records that a human at a GUI gets undo instead of - confirmation dialogs, and that is right for tags. If the measurement shows the - next sync expunges mail from the server, then undo does not in fact cover this - action, and the premise the rule rests on does not hold for it. -- Do not test this against the user's real accounts. A message that is expunged - to prove that it is expunged is still gone. -- Any answer that involves a trash view is a much larger item and should be - split out rather than folded in here. - -**Size: S** for the investigation and whatever the UI needs to say. Unknown -beyond that, and deliberately not sized further until the measurement exists. +**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**. ## 104. Mail visible in Thunderbird never reaches qtmaildir @@ -845,6 +855,40 @@ entry is missing. **Size: XS.** +## 118. No way to empty the trash from inside the app + +**Observed (user, 2026-08-17):** raised while reviewing item 103's spec, as +something that had been forgotten rather than newly noticed: "we could add +'Empty Trash' to the backlog as a future item. I forgot it existed, but I don't +want to squeeze it in this spec." + +**Blocked on 103**, which creates the trash folder this would empty. Until that +ships there is nothing to empty: Delete writes a tag and moves no file, so no +account has a populated trash folder except through another client. + +**Deliberately excluded from 103's spec**, at the user's request and recorded in +its "Out of scope" section. Worth keeping separate for a reason beyond scope +control: emptying the trash is the first action in this application that would +destroy mail with no undo. Every mutation so far is a tag or, after 103, a move, +and both are reversible. A purge is not. + +**Approach, unspecified.** The shape depends on decisions not yet made, and the +spec for 103 answers none of them: + +- **Local or remote.** Deleting the files locally and letting `Expunge Both` + carry it to the server is one thing; asking the provider to empty its own + trash is another, and mbsync offers no verb for the latter. The first is + probably what "Empty Trash" should mean here. +- **Whether the no-confirmation rule survives it.** It does not, on the face of + it. `CLAUDE.md` grants undo in place of confirmation dialogs, and this is the + action where undo cannot exist. That makes it the second item, after 103, that + re-examines the rule rather than assuming it, and unlike 103 it will probably + have to break it. +- **Per-account or all-accounts**, which should follow whatever the Trash filter + does once 103 ships rather than being decided independently. + +**Size: S**, provisionally, and not worth sizing properly until 103 exists. + ## Deferred, unsized, or split out Items noted while triaging but not part of the original list. Same numbering diff --git a/docs/superpowers/specs/2026-08-17-delete-to-trash-design.md b/docs/superpowers/specs/2026-08-17-delete-to-trash-design.md index 87b8634..dae5122 100644 --- a/docs/superpowers/specs/2026-08-17-delete-to-trash-design.md +++ b/docs/superpowers/specs/2026-08-17-delete-to-trash-design.md @@ -1,6 +1,8 @@ # Delete moves mail to trash -Item 103. Design settled 2026-08-17 with the user. +**Resolves item 103.** Design settled 2026-08-17 with the user. Item 118 +(Empty Trash) is blocked on this and deliberately out of scope, see the last +section. ## The problem, measured @@ -211,5 +213,9 @@ folder is purged on a timer. ## Out of scope No purge, no empty-trash, no expiry inside the app. Mail leaves the trash folder -when the server does it or when the user restores it. Purging from inside -qtmaildir is a separate item if it is ever wanted. +when the server does it or when the user restores it. + +Emptying the trash is **item 118**, filed separately at the user's request +rather than folded in here. It is blocked on this item, and it is the first +action in the application that would destroy mail with no undo, so it needs the +no-confirmation rule re-examined in a way this item does not. |
