aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md84
-rw-r--r--docs/superpowers/specs/2026-08-17-delete-to-trash-design.md12
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.