summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-20 12:38:00 +0200
committerDanilo M. <danix@danix.xyz>2026-08-20 12:38:00 +0200
commitdca7818517b4444cac5a7c27feb9ff8791e96e8f (patch)
tree836fdb9f2b72f84ce144497a22e9ca97891af00a /docs
parentfd3bd06580f6bde5d57a68b82cac46eefd89f412 (diff)
downloadqtmaildir-dca7818517b4444cac5a7c27feb9ff8791e96e8f.tar.gz
qtmaildir-dca7818517b4444cac5a7c27feb9ff8791e96e8f.zip
docs: choose warning surfaces by consequence, item 123
Two corrections from the user, both of which the spec had wrong. A failed sent-copy write was put in the main window's status bar, on the reasoning that the composer closes so the message needs somewhere persistent. Wrong instinct: the fix for "the window is gone" is a dialog, not a quieter surface. It is the one failure here that produces a silent divergence between what the recipient received and what the local archive holds, and nobody discovers that from a line that showed for a few seconds. It gets a modal. A failed autosave stays in the composer but as a persistent banner rather than a status-area line, since the quit path already escalates that state to a dialog and depends on it surviving. Stated as a rule at the head of the section, because the user's point was general: modal for silent divergence, banner for mid-task, status bar only for what is already obvious. Second correction: the composer's busy indicator is not built inline. A second instance of MainWindow's progress-bar-plus-label pairing is where a widget class earns itself, and "this codebase builds small UI inline" describes what the code does rather than justifying repeating it. Item 134 extracts it and converts MainWindow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YDq53rMd3AQp7QmcZzpuBM
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md1
-rw-r--r--docs/superpowers/specs/2026-08-20-compose-and-send-design.md50
2 files changed, 40 insertions, 11 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 f01c94e..a35d9fa 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
@@ -203,6 +203,7 @@ taking that too literally.
| 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 |
| 133 | The composer shows no markdown syntax highlighting | v2 | S | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** A `QSyntaxHighlighter` over the composer's editor, so `**bold**` reads as bold while the buffer stays plain markdown. Standard Qt, no dependency. Deliberately after 123's formatting toolbar: agreeing with the grammar about nesting and about code spans suppressing what is inside them is the expensive part, and the toolbar is what makes the feature usable |
+| 134 | The busy indicator is built inline and is about to be built twice | maintenance | S | open, 2026-08-20, raised by the user during the item 123 brainstorm. An indeterminate `QProgressBar` beside a status label, built inline in `MainWindow` as `m_syncProgress`, and item 123's composer needs the same pairing. Extract a widget class and convert `MainWindow` to it. **Not blocked on 123**, and better done first: if 123 lands first it creates the class itself and this row closes with it. The user's position is general, build once and reuse, so the inline habit `CLAUDE.md` records is a description of the code rather than a rule to follow |
Sizes are rough: XS under an hour, S a sitting, M a session.
diff --git a/docs/superpowers/specs/2026-08-20-compose-and-send-design.md b/docs/superpowers/specs/2026-08-20-compose-and-send-design.md
index afca9be..af13c2f 100644
--- a/docs/superpowers/specs/2026-08-20-compose-and-send-design.md
+++ b/docs/superpowers/specs/2026-08-20-compose-and-send-design.md
@@ -277,13 +277,18 @@ Filing sent copy... DraftStore writing to the account's sent folder
Removing draft... the draft revision is unlinked
```
-The indicator is an **indeterminate `QProgressBar`** (`setRange(0, 0)`), built
-inline in the composer, which is exactly what `MainWindow` already does for the
-sync indicator (`m_syncProgress`) and for the same reason: neither operation has
-measurable progress. It is deliberately not factored into a shared widget class.
-This codebase builds small UI inline (the query row and the message-pane header
-are both built that way and `CLAUDE.md` records that they are not classes), and
-two `QProgressBar`s in two windows do not justify a third name.
+The indicator is an **indeterminate `QProgressBar`** (`setRange(0, 0)`) beside a
+status label, which is what `MainWindow` already does for the sync indicator
+(`m_syncProgress`) and for the same reason: neither operation has measurable
+progress.
+
+**This is the second instance of that pairing, so it becomes a widget class**
+rather than a second inline build. Item 134 covers extracting it and converting
+`MainWindow` to use it. Building the same thing twice is where a class earns
+itself, and "this codebase builds small UI inline" describes what the code does
+rather than justifying repeating it. Whether 134 lands before or after this
+work, the composer uses the shared widget: if it has not happened yet, this work
+creates the class and converts `MainWindow` as part of the same change.
Exit 0 closes the window. Non-zero re-enables it with everything intact and
shows the command's stderr.
@@ -506,6 +511,19 @@ markdown dialect.
## Error handling
+**The surface is chosen by consequence, not by convenience.** A warning the user
+does not see is the same defect as an indicator that lies, and the status bar
+does not catch the eye. The rule for this design:
+
+| Consequence | Surface |
+|---|---|
+| Silent divergence the user would not otherwise discover | modal dialog |
+| Something needing attention while they are mid-task | persistent banner, does not fade |
+| Routine, self-correcting, or already visible | status bar, or nothing |
+
+The status bar is for what is already obvious. Nothing whose failure the user
+would learn about months later belongs there.
+
**Send failed** (non-zero exit). Composer re-enabled intact, stderr shown in a
pane below the body, in the shape `MailSync`'s log pane already has. The draft
stays. No retry loop.
@@ -519,8 +537,11 @@ paths are not later "harmonised".
**Command missing or unrunnable** (`QProcess::FailedToStart`). Reported as a
failure naming the command, since a typo'd path is the likely cause.
-**Draft write failed.** A warning in the composer's status area, not a modal. It
-must not interrupt typing and must not silently succeed.
+**Draft write failed.** A **persistent banner** in the composer, not a modal and
+not a status-bar line that fades. A modal mid-sentence is hostile while the user
+is typing, but the warning must survive until it is dealt with, because the quit
+path's honesty depends on it: case 3 below escalates exactly this state to a
+dialog on the way out.
**Sent copy write failed after a successful send.** A warning saying exactly
that. Never a send failure, never an offer to resend.
@@ -529,8 +550,15 @@ The staged progress display makes this visible rather than confusing: the
failure arrives while the status bar reads "Filing sent copy...", so the user
can see the send stage already passed. The composer still **closes**, because
the message went and holding a composer open for a message already sent invites
-sending it twice. The warning goes to the main window's status bar, which
-outlives the composer.
+sending it twice.
+
+**It is reported with a modal dialog, not a status-bar line.** This is the one
+failure in the whole design that produces a silent divergence between what the
+recipient received and what the local archive shows, and a status bar does not
+catch the eye. Nobody discovers a missing sent copy by noticing a line that
+appeared for a few seconds; they discover it months later by looking for a
+message that is not there. The dialog names the account and the folder it could
+not write to.
**An attachment vanished between attaching and sending.** Send is refused before
the command runs, naming the file. Checked at build time, not at attach time.