aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers/plans')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md91
1 files changed, 35 insertions, 56 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 49f4000..ebcbea9 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
@@ -189,7 +189,7 @@ taking that too literally.
| 121 | The thread list shows nothing while a query is running | feedback | S | open, 2026-08-20, from the notes. Follows item 74, which fixed the status-bar half and left the list itself blank |
| 122 | The README documents a version of the app that no longer exists | documentation | M | open, 2026-08-20, from the notes. Delete-to-trash is entirely undocumented, including a config key a user must now set |
-| 123 | Sending mail is not designed | v2 | ? | open, 2026-08-20, from the notes. Brainstorm only, explicitly `#plan-only`; the user places most open UX behind it |
+| 123 | Sending mail is not designed | v2 | L | **specified** 2026-08-20, on branch `compose-and-send`. Design in `docs/superpowers/specs/2026-08-20-compose-and-send-design.md`; read that, not this row. Send is a per-account `send_command` on stdin, so the no-network-protocol rule stands. Composer is a separate window, body is markdown via cmark-gfm, drafts autosave to the account's drafts folder. No code written |
| 124 | The worker reads the index directory as the mail root | defect | S | **done** 2026-08-20, unreleased. `mailRootOf()` over `NOTMUCH_CONFIG_MAIL_ROOT`, correct under both layouts. Verified by migrating the developer's own index to NVMe the same day: cold start 38.6 s to 0.67 s |
@@ -197,6 +197,11 @@ taking that too literally.
| 126 | A link with `target="_blank"` does nothing when clicked | defect | S | **done** 2026-08-20, unreleased. `createWindow()` returns a relay page that receives the navigation, hands the URL to the browser and refuses. The URL cannot be read in `createWindow()` itself, which is why a relay rather than a lookup |
| 127 | A link's context menu offers four browser actions that cannot work | defect | XS | **done** 2026-08-20, unreleased. Three Open-in actions removed, `CopyLinkToClipboard` kept. Item 126 made them more dangerous rather than less: with a real `createWindow()` they would have started working |
+| 128 | No outbox: a send with no network fails instead of queueing | v2 | M | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** The seam is designed in (`MessageSender` is the one funnel), so this wraps it rather than reworking it. Needs its own indicator story first: items 18, 19, 28 and 54 are all an indicator lying, and 125 is one still open |
+| 129 | No inline images in a composed message | v2 | M | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** Wanted by the user. `cid:` from the HTML part with `multipart/related` nested inside the alternative, the most nesting-heavy part of MIME assembly, and markdown offers no syntax for it |
+| 130 | A message cannot be attached to another message directly | v2 | S | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** A `message/rfc822` part, which GMime builds natively. The manual route exists from 123's first commit: `save_message` writes the `.eml` and it is attached as a file |
+| 131 | The markdown dialect and extensions are fixed | v2 | S | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** Configurable in the shape Hugo's config uses. Deliberately fixed initially: CommonMark plus autolink, strikethrough and tasklist |
+| 132 | Every action must have a shortcut, and that no longer serves | policy | S | open, 2026-08-20, raised by the user during the item 123 brainstorm. `everyActionHasAShortcut` was written when the action list was short; item 123 adds six more, and each new action consumes a chord whether or not anyone would press it. Replacement is the shape `everyActionIsReachableFromAMenu()` already has: menu reachability required, shortcuts a chosen subset. **Not** done inside 123, which would confuse two changes |
Sizes are rough: XS under an hour, S a sitting, M a session.
@@ -998,61 +1003,35 @@ likely to have drifted, since both enumerate things that have been added to.
## 123. Sending mail is not designed
-**Observed (user, from the notes):** "we should start brainstorming sending
-emails. Most of the open issues are UX. #v2 #plan-only #new-branch".
-
-**Not a defect and not implementation work.** The note tags it `#plan-only`, and
-this repo's own scope statement agrees: `CLAUDE.md` records that v1 is
-read-and-organize only and that compose and send are v2. Recorded here so the
-backlog stops being silent about the largest thing the user has written down.
-
-**What it blocks.** Item 72 (khard/khal) is explicitly placed after send by the
-user's own note, and cannot be specified before it. The completion machinery
-that would serve recipient completion already exists as `QueryCompleter`, and
-the `QLineEdit::setCompleter` trap in `CLAUDE.md` applies directly to any
-multi-recipient field, so there is prior art to reuse rather than a blank page.
-
-**What it does NOT change.** The architecture note that this application does
-**no network protocol work at all** is load-bearing: fetching is `mbsync` via
-`assets/mailsync.sh`, and sending should be an external script on the same
-model, not an SMTP client written here. A design that puts a socket in this
-process is out of scope regardless of how the UI turns out.
-
-**What exists on this machine, measured 2026-08-20, because the sentence above
-assumes something that is not there.** "Sending should be an external script on
-the same model" is easy to write and there is no such model to copy: the fetch
-side has `mbsync`, and the send side has NOTHING.
-
-- No MTA is installed at all. `msmtp` and `sendmail` are both absent.
-- neomutt sends over its OWN built-in SMTP, configured per account
- (`smtp_url` and `smtp_pass` in `~/.config/neomutt/accounts/*.rc`), so the
- working setup this application mirrors has no external send path either.
-- All five accounts already configure a `drafts` folder, so the draft half has
- somewhere to live before anything is decided.
-
-That is the first question for the user, and it is not a UX one: sending needs
-either an MTA they choose to install and configure (msmtp being the obvious
-one, and the only shape that keeps the no-network-protocol rule intact), or a
-decision to relax that rule. Do not assume the first just because it is
-tidier; installing and configuring an MTA is work they have not asked for, and
-the credentials already exist in neomutt's files.
-
-**Approach.** Brainstorm first, on its own branch, producing a spec under
-`docs/superpowers/specs/` before any code. The open questions are all UX, as the
-note says: where a composer lives, how a draft is stored so `notmuch` can see
-it, what reply and forward do to the thread the user is looking at, and how a
-queued message reaches the sending script.
-
-**Constraints.**
-
-- **Ask the user before designing.** They have not said what they pictured, and
- this is the item where guessing costs the most.
-- Drafts are already visible to the app: item 67 counts them in the placeholder
- pane, so a draft folder is configured and indexed.
-- `#new-branch` is the user's own tag on it.
-
-**Size: `?`** until the brainstorm has happened. It is the largest open item by
-some distance.
+**Specified 2026-08-20.** Read
+`docs/superpowers/specs/2026-08-20-compose-and-send-design.md` instead of this
+section. Brainstormed with the user on branch `compose-and-send`; no code
+written, which is what the note's `#plan-only` asked for.
+
+**The three constraints a reader needs before opening the spec.**
+
+- **There is no MTA on this machine**, measured 2026-08-20. `msmtp` and
+ `sendmail` are both absent, and neomutt sends over its own built-in SMTP. So
+ "an external script on the same model as `mailsync.sh`" had no model to copy.
+ The design keeps the no-network-protocol rule by making send a **per-account
+ `send_command`** taking the message on stdin, exactly as `[sync] command`
+ works. What the user installs behind it is their choice.
+- **An account with no `send_command` is receive-only by construction**, which
+ is how one of the five accounts is meant to work. Reply, reply-all and forward
+ are disabled on its mail, with a ribbon in the message pane saying why.
+- **The body is markdown**, parsed by cmark-gfm (autolink, strikethrough,
+ tasklist; tables off), sent as `multipart/alternative` or plain text per a
+ per-message toggle. A hand-written parser for a limited set was rejected
+ because it would be deleted wholesale the moment the set widened.
+
+**What it blocks and what it opened.** Item 72 (khard/khal) is placed after send
+by the user's own note. The brainstorm opened items 128 to 132: an outbox,
+inline images, attaching a message to a message, a configurable markdown
+dialect, and a review of the every-action-has-a-shortcut rule.
+
+**Size: L.** Four new units, six new actions, and a new dependency
+(`cmark-gfm`, already installed here, and a `REQUIRES` entry for the
+SlackBuild).
## 125. A skipped sync leaves the spinner running for ever