aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md97
1 files changed, 97 insertions, 0 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 bcb6431..945aacd 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
@@ -10278,3 +10278,100 @@ when it was written with `tr()`, and a comma joins a list the same way in
Italian; a translatable separator is a string for a translator to get wrong for
no gain.
+## 184. New mail waits up to ten minutes, because sync is a fixed cron tick
+
+**Done 2026-09-13, outside this repository.** Built as `mail-watcher`, its own
+project at `~/Programming/GIT/mail-watcher`, designed in that repository's
+`docs/superpowers/specs/2026-09-13-mail-watcher-design.md` and confirmed running
+on this machine as `~/bin/mail-watcher.sh --config ~/.config/mail-watcher/config.ini`.
+Nothing in `src/` changed, which is the outcome this entry argued for: qtmaildir
+is as ignorant of IMAP as it was, and the no-network-protocol rule is intact.
+
+**The three decisions this entry said could not be made by reading the repository
+were made against the live servers.** A watcher of ours rather than a third-party
+daemon, so there is no new SlackBuild to maintain; both hosts were probed and
+advertise IDLE; and the connection count was the real constraint, since watching
+all 50 synced folders would have sat one folder under the mail host's cap. The
+answer was default-watch with an explicit exclude list, so the failure mode is
+watching too much rather than silently missing mail, which matters because
+server-side rules file mail directly into folders without touching INBOX.
+
+**Both constraints held.** The cron tick stays as a backstop, so a watcher that
+dies silently degrades to the old ten minute wait rather than stopping mail; and
+`/tmp/mbsync.lock` is still the shared mutex, so a triggered sync, a cron sync
+and a click in qtmaildir serialise as before.
+
+**Item 174 was the blocker and was the right one.** `mailsync.sh` already writes
+`~/.local/state/qtmaildir/syncstatus.json`, so the watcher had a tested reporting
+channel to trigger into rather than making the application's guesswork about
+external runs worse.
+
+The original entry follows.
+
+### The entry as it stood while open
+
+**Observed (user, 2026-08-29):** "the 10 minutes fixed tick has always bothered
+me, I want the changes to my mail to be immediate, the 10 minutes mark is a
+compromise, it had started at 30 min and was awful."
+
+**Split the want in two, because only half of it is open.**
+
+- **Outgoing is already immediate.** An edit arms `auto_sync_delay_ms`, 2
+ seconds by default (item 71), so marking a message read reaches the server
+ without waiting for the tick.
+- **Incoming is the gap.** Mail that arrives is invisible until the next cron
+ run of `mailsync.sh`, so the wait is uniform on [0, 10] minutes with a mean
+ of five.
+
+**Why a faster tick is not the fix.** Polling every minute is ten times the
+connections and the server load for a mean wait of thirty seconds, and it is
+still a poll: the wait is bounded by the interval however small it gets. The
+answer to "tell me when something arrives" is IMAP IDLE, where the server holds
+the connection and speaks first.
+
+**Where IDLE may live, and where it must not.** `AGENTS.md` states this
+application does NO network protocol work at all: fetching and sending are
+external commands, which is what keeps a mail client out of TLS, authentication
+and an IMAP state machine. IDLE inside qtmaildir would break that rule outright
+and is not on the table.
+
+It does not need to be inside. mbsync has no IDLE mode, being a batch syncer
+that runs and exits; the tools that hold a connection and TRIGGER a sync are
+separate programs (`goimapnotify` and the older `imapnotify` are the usual
+ones). That shape fits the architecture exactly: the watcher replaces the cron
+line, runs `mailsync.sh <channel>` on activity, and qtmaildir stays as ignorant
+of IMAP as it is today. The script's flock still serialises a triggered sync
+against a manual one.
+
+**Blocked on item 174**, and not merely sequenced after it. A watcher makes
+syncs arrive at unpredictable times rather than on a known tick, which makes
+the application's current guesswork about external runs worse. Item 174's
+status file is the reporting channel this needs, and building it first means
+the watcher has a tested one to write into.
+
+**Decisions needed before any code, none of which can be made by reading this
+repository.**
+
+- **Which watcher**, or a small one of ours. A third-party daemon means a
+ SlackBuild in the `my-slackbuilds` repo and a package to maintain.
+- **What the mail server supports.** IDLE is optional in IMAP, and a server
+ without it leaves polling as the only mechanism.
+- **How many connections.** One per account per watched folder, held open
+ indefinitely; some servers cap concurrent connections.
+
+**Constraints.**
+
+- **Keep a slow cron tick as a backstop.** A held connection drops on network
+ sleep, a server restart or a laptop suspend, and a watcher that dies silently
+ stops mail altogether, which is worse than a ten minute wait. Belt and
+ braces: the watcher for latency, a slow tick so a dead watcher is survivable.
+- **The lock is the shared mutex** and stays so. A triggered sync, a cron sync
+ and a click in qtmaildir must continue to serialise through
+ `/tmp/mbsync.lock`, or two mbsync runs corrupt Maildir UID state.
+- **This is not a qtmaildir daemon.** A long-running qtmaildir service was
+ considered and rejected in the same conversation: it answers none of items
+ 174 or 125 better than a file does, and it adds a process that can wedge and
+ take mail delivery with it. What the user wants is a watcher, which is a
+ different thing in a different place.
+
+