summaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-24 21:37:13 +0200
committerDanilo M. <danix@danix.xyz>2026-08-24 21:37:13 +0200
commitf6ceeacad8e1fe15c30db66dcfde8efa9dfb4758 (patch)
treeffbe76068c56d03373f82e90a9a94c0f8eaf27d2 /docs/superpowers/plans
parent16bbd9a164ae4c4afc8914199c37386ed6914582 (diff)
downloadqtmaildir-f6ceeacad8e1fe15c30db66dcfde8efa9dfb4758.tar.gz
qtmaildir-f6ceeacad8e1fe15c30db66dcfde8efa9dfb4758.zip
docs(backlog): close item 152, signatures
Diffstat (limited to 'docs/superpowers/plans')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md75
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md73
2 files changed, 76 insertions, 72 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 7314700..94a02d2 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
@@ -7349,6 +7349,81 @@ importing the other.
---
+## 152. Signatures are not managed at all
+
+**Observed (user, 2026-08-24, from the notes):** listed under "some basic
+functionalities not brainstormed which didn't enter the first Send
+implementation", as:
+
+> signatures:
+> - not tied to an account, with a switch in the editor bar UI.
+
+**Specified 2026-08-24.** The design is in
+`docs/superpowers/specs/2026-08-24-signatures-design.md`. Read that rather
+than this section, which records only what the brainstorm settled and why.
+
+**The constraint is the shape of the item, and it survived a second key.**
+Not tied to an account rules out `[account.*] signature` as the whole answer.
+The user then asked for that key anyway, as a convenience, and it does not
+reopen the constraint: the account supplies a STARTING value, the editor-bar
+switch keeps every signature reachable under any account, and changing From:
+stops re-seeding the moment the user touches the switch. Seeding is not
+binding.
+
+**One choice must serve both forms, and that costs nothing.**
+`MessageBuilder` already derives `text/plain` from `markdownBody` verbatim and
+`text/html` from `MarkdownRenderer::toHtml()` over the same string
+(`messagebuilder.cpp:321-324`). A markdown signature in the buffer therefore
+gets both, correctly, with no change to `MessageBuilder` and no second code
+path. The user's "transparent to the user" requirement is a property the
+pipeline already has.
+
+A two-file variant (`work.md` plus an optional `work.html` overriding the
+rendered form) was chosen and then dropped by the user the same session: it
+buys designed HTML signatures at the cost of the signature no longer being
+visible in the editor, since the two parts diverge and the buffer can hold
+only one of them.
+
+**The switch is stateless, by using the delimiter rather than tracking a
+range.** `seedBody()` deliberately refuses to track "my text" and "the quote"
+as separate pieces (`composewindow.cpp:640-644`), and a signature switch is a
+toggle by definition, so it cannot duck that question the way the quote did.
+It answers it without state: the signature is the last `-- ` block not
+followed by quoted lines, found by scanning. Nothing to desync from the undo
+stack, and it survives editing above it.
+
+**`signature_position` covers both placements over one scan.** The user's own
+habit is `end`, which is the default; `above_quote` exists because other
+clients offer it. The scan needed the quote-aware clause for `above_quote`
+anyway, so the key is roughly ten lines rather than one, and a naive tail rule
+would have eaten the quote under the other placement.
+
+**A delimiter alone must not authorise a deletion.** The block after `-- ` is
+replaced only when its text matches one of the signatures on disk; otherwise
+the new one is inserted and nothing is removed. `-- ` can reach the buffer
+pasted in with quoted text from another client, and the unguarded scan would
+have silently deleted everything after it. The failure is now directional: a
+wrong guess adds a visible duplicate rather than losing the user's writing.
+Raised by the user against the first draft of this design.
+
+Two markers were considered for the same problem and refused. A zero-width
+character SHIPS in the sent message, fingerprinting the client in outgoing
+mail, and must survive the draft round trip through GMime, quoted-printable
+and `MimeParser`, which is exactly what normalises such characters away. A
+doubled delimiter (`--` plus two spaces) is not the RFC 3676 separator, so no
+receiving client would fold or strip the signature, and trailing whitespace is
+unreliable through the same pipeline.
+
+**Two things the design refuses.** No signature editor: the directory is
+edited with the user's own editor, and a text editor inside a mail client is
+not this project's to build. And a resumed draft seeds nothing, because the
+saved body already carries whatever signature it was written with, and
+seeding again would put a second one on a message written once.
+
+**Closed 2026-08-24** (unreleased). See the status table row for the outcome.
+
+---
+
## 153. A draft cannot be opened for editing, so it is write-only
**Observed (user, 2026-08-24).** Found the moment item 138 gave drafts a
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 c2c82ea..b86740e 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
@@ -221,7 +221,7 @@ taking that too literally.
| 149 | A reply's cursor lands on the attribution line, not on blank space | defect | XS | **done** 2026-08-24, unreleased, in TWO passes. The first fixed the cursor within each branch (`End` under Above, `Start` under Below) and the user still saw the old layout, because the branches were already right and the DEFAULT was wrong: `above` shipped, and the layout asked for is what `below` produces. Default flipped, and the composer now focuses the body whenever To: is already filled, which a Reply and a Forward always are. Both halves were invisible to the existing `theQuotePositionDecidesWhereTheQuoteLands`, which asserts the quote's position and never the cursor's |
| 150 | The receive-only ribbon stays up after the message that raised it is gone | defect | S | **done** 2026-08-24, unreleased. One line in `MessageView::clear()`, beside the blocked-content bar, the stale notice and the attachment bar it already reset by hand. Only `setReceiveOnlyAccount()` hid the ribbon, which every SELECTION change reaches, so a row-to-row move was never the reproducer: it survived the FOUR routes that blank the pane without one (`clear_pane`, `clear_selection`, a new query, a multi-row selection). The first test written for it passed against the defect for exactly that reason |
| 151 | The message-pane bars blend into the UI and carry no severity | presentation | S | **done** 2026-08-24, unreleased. Two severities as the user asked: yellow for a warning that only explains (the receive-only ribbon), blue for one offering an action (remote content blocked, stale thread), each with its own light and dark set read off `QPalette::Base` as `HtmlBuilder` does. The blocked row had to become a WIDGET first: it was a bare `QHBoxLayout`, which has nothing to paint a ground on, and its six `hide()` sites then had to move to the wrapper or a painted empty strip would show. Both action bars put the button right of a stretch |
-| 152 | Signatures are not managed at all | v2 | S | **specified** 2026-08-24, unbuilt. Design in `specs/2026-08-24-signatures-design.md`; read that, not this row. Sized `?` until the brainstorm; it is an S. One markdown file per signature under `~/.config/qtmaildir/signatures/`, spliced into the composer buffer, so `MessageBuilder` needs NO change at all: it already derives both parts from one string, which is the transparency the user asked for. The constraint holds, and the per-account key the user then asked for does not break it: an account SEEDS the choice, the editor-bar switch keeps every signature reachable |
+| 152 | Signatures are not managed at all | v2 | S | **done** 2026-08-24, unreleased. One markdown file per signature under `~/.config/qtmaildir/signatures/`, spliced into the composer buffer by the `Signatures` namespace and chosen from a `QToolButton` switch on the editor bar. `[compose] signature` seeds a new message, `[account.<key>] signature` overrides per account, `[compose] signature_position` picks end or above_quote. `MessageBuilder` is untouched: it already derives both parts from one string, the transparency the user asked for, and the per-account key does not break "not tied to an account", since an account SEEDS the choice while the switch keeps every signature reachable. A hand test caught one guard defect (a trailing newline defeated the replace guard); fixed and regression-tested |
| 153 | A draft cannot be opened for editing, so it is write-only | defect | M | **done** 2026-08-24, unreleased. `ComposeContextBuilder::forDraft()` reads a draft back into a context; a new `Kind::Draft` seeds the fields verbatim, takes the body with no quote framing, and carries `draftPath` so the autosave REPLACES the file instead of leaving a second copy. `MimeParser` gained `bcc`, which nothing read before: `MessageBuilder` writes Bcc into the draft deliberately, so a resumed draft that ignored it would silently drop every blind recipient. Reachable by double-click and by an `edit_draft` action, gated on the file being in a configured drafts folder because opening ordinary mail this way would make the first autosave DELETE a received message. Found a live defect on the way, see the section |
| 154 | No read confirmation | v2 | ? | open, 2026-08-24, from the notes. `Disposition-Notification-To`, which is a header `MessageBuilder` would add and a request the message pane would have to honour or ignore on the receiving side. Unspecified: whether this is send-side only, and what the reader is asked |
| 155 | No urgency switch on an outgoing message | v2 | S | open, 2026-08-24, from the notes: low, regular, high. `X-Priority` and `Importance`, headers `MessageBuilder` adds; regular writes neither. A control in the composer, and the same question item 144 answered for the HTML toggle applies to where it sits |
@@ -1334,77 +1334,6 @@ than a slow one.
---
-## 152. Signatures are not managed at all
-
-**Observed (user, 2026-08-24, from the notes):** listed under "some basic
-functionalities not brainstormed which didn't enter the first Send
-implementation", as:
-
-> signatures:
-> - not tied to an account, with a switch in the editor bar UI.
-
-**Specified 2026-08-24.** The design is in
-`docs/superpowers/specs/2026-08-24-signatures-design.md`. Read that rather
-than this section, which records only what the brainstorm settled and why.
-
-**The constraint is the shape of the item, and it survived a second key.**
-Not tied to an account rules out `[account.*] signature` as the whole answer.
-The user then asked for that key anyway, as a convenience, and it does not
-reopen the constraint: the account supplies a STARTING value, the editor-bar
-switch keeps every signature reachable under any account, and changing From:
-stops re-seeding the moment the user touches the switch. Seeding is not
-binding.
-
-**One choice must serve both forms, and that costs nothing.**
-`MessageBuilder` already derives `text/plain` from `markdownBody` verbatim and
-`text/html` from `MarkdownRenderer::toHtml()` over the same string
-(`messagebuilder.cpp:321-324`). A markdown signature in the buffer therefore
-gets both, correctly, with no change to `MessageBuilder` and no second code
-path. The user's "transparent to the user" requirement is a property the
-pipeline already has.
-
-A two-file variant (`work.md` plus an optional `work.html` overriding the
-rendered form) was chosen and then dropped by the user the same session: it
-buys designed HTML signatures at the cost of the signature no longer being
-visible in the editor, since the two parts diverge and the buffer can hold
-only one of them.
-
-**The switch is stateless, by using the delimiter rather than tracking a
-range.** `seedBody()` deliberately refuses to track "my text" and "the quote"
-as separate pieces (`composewindow.cpp:640-644`), and a signature switch is a
-toggle by definition, so it cannot duck that question the way the quote did.
-It answers it without state: the signature is the last `-- ` block not
-followed by quoted lines, found by scanning. Nothing to desync from the undo
-stack, and it survives editing above it.
-
-**`signature_position` covers both placements over one scan.** The user's own
-habit is `end`, which is the default; `above_quote` exists because other
-clients offer it. The scan needed the quote-aware clause for `above_quote`
-anyway, so the key is roughly ten lines rather than one, and a naive tail rule
-would have eaten the quote under the other placement.
-
-**A delimiter alone must not authorise a deletion.** The block after `-- ` is
-replaced only when its text matches one of the signatures on disk; otherwise
-the new one is inserted and nothing is removed. `-- ` can reach the buffer
-pasted in with quoted text from another client, and the unguarded scan would
-have silently deleted everything after it. The failure is now directional: a
-wrong guess adds a visible duplicate rather than losing the user's writing.
-Raised by the user against the first draft of this design.
-
-Two markers were considered for the same problem and refused. A zero-width
-character SHIPS in the sent message, fingerprinting the client in outgoing
-mail, and must survive the draft round trip through GMime, quoted-printable
-and `MimeParser`, which is exactly what normalises such characters away. A
-doubled delimiter (`--` plus two spaces) is not the RFC 3676 separator, so no
-receiving client would fold or strip the signature, and trailing whitespace is
-unreliable through the same pipeline.
-
-**Two things the design refuses.** No signature editor: the directory is
-edited with the user's own editor, and a text editor inside a mail client is
-not this project's to build. And a resumed draft seeds nothing, because the
-saved body already carries whatever signature it was written with, and
-seeding again would put a second one on a message written once.
-
## 158. A freshly saved draft is invisible until a sync indexes it
**Observed (user, 2026-08-24, by hand).** Composing a new message or resuming