Future work: high-ROI backlog
Ranked by ROI (impact / effort), collected from AGENTS.md requirements not yet built, spec decision records, and review residuals. Effort is S/M/L relative to the send-dialogue milestone. AGENTS.md is normative; a spec and plan are prerequisites before implementation per the project’s workflow.
Tier 1: foundational, build next
1. Crypto providers: PGP and S/MIME via system tools (R10) - effort M-L
No sign/encrypt/decrypt on the send or read path yet. Zero crypto code in the client: gpg CLI with --status-fd parsing (aerc’s gpgbin pattern), S/MIME via openssl smime, gpg-agent + external pinentry with TUI suspend/resume (the only passphrase path; no loopback mode - Go cannot zero secrets).
- Sign/encrypt is a transform stage between go-message assembly and the send job (assemble -> sign/encrypt per dialogue flags -> fcc -> send).
- Decrypt/verify is an async job on the read path; the pager renders body and signature status.
- Key selection is a selector dialogue (R4 machinery) fed by
gpg --list-secret-keys --with-colons. - go-pgpmail builds on go-message for the transform stage (verified in the mail-library decision record).
Impact: the client becomes usable for signed/encrypted mail - table stakes for this user’s workflow. Pointers: AGENTS.md R10, references/neomutt/ncrypt/*, references/neomutt/smime/smime.c, references/aerc/lib/crypto/gpg/gpgbin.
Tier 2: strong ROI, schedule when a slot opens
2. Fix the redraw_test harness race, enable -race in CI - effort S
TestCursorMovePartialRepaint (src/tui/redraw_test.go) races the vendored renderer goroutine against the test goroutine under -race; verified pre-existing at the milestone base. The fix is a harness-side synchronization (join or poll the renderer), then -race becomes the CI standard without a skip list.
Impact: removes the one known red flag; CI runs race-clean like the rest of the suite. Pointers: src/tui/redraw_test.go (fake_screen_test.go - the renderer goroutine’s SetContent vs the test goroutine’s Get, re-verified 2026-08-19 under -race: TestLoopCursorMoveRepaints and TestFrameChromeSurvivesRefresh both race).
3. Staged-tag persistence (R14) - effort M
Staged tag ops and the undo buffer are session-local today; persistence is explicit future work in R14. A session record (applied ops per message id) would make undo survive restarts and make the apply path resumable.
Impact: undo becomes durable; mis-taps stop being permanent after a restart. Pointers: AGENTS.md R14, src/tui/model.go stage/apply/undo.
4. Send retry reopens the compose dialogue with the failed message (R4) - effort S-M
neomutt’s bg_send_retry seed: a failed send retains the Email and re-opens the compose dialog with the failed message. The PhaseFailed path exists (e retries in place); the missing piece is reopening with the failed state and its captured output shown.
Impact: send failures stop being lossy - the user edits and re-sends the actual failed message. Pointers: references/neomutt/send (async_send branch, bg_send_retry), src/app/send.go, src/compose/state.go PhaseFailed.
5. Address cache as a filter side effect (R2) - effort S-M
The reference pipeline’s remaining side effect: the address cache for query completion (notifications landed with the filter job’s completion event, src/app/notify_beeep.go). It subscribes to the same event.
Impact: query completion arrives with the filter pipeline. Pointers: AGENTS.md R2, references/muttrc/afew/config (the reference side effects).
Tier 3: later, smaller, or gated
- DBus dark/light sync (R12) - effort S-M, build-tag-gated (
dbus), godbus dependency only in that build. - Send-epoch stamping on SendResult - effort S. Closes the one accepted residual from the M2 snapshot fix: a channel-delivered failure racing a retry dispatch can re-apply the stale failure for one Update.
- UX nits accepted in the send milestone - effort S each. formIdx not clamped per tab; compose frame overflows below height 11;
openedset / busopenLastgrow per session. - Extractable TUI library (R5) - effort L, architectural. When the TUI stabilizes; the core has no UI code by design, so extraction is packaging.
- MIME cache compression knob - effort S, only after measuring (R13: “compress first” is explicitly a future knob, not a requirement).
Landed (removed from the ranks)
Implemented since this backlog was drafted; kept here as the audit trail.
- Filter engine with exclusive tag groups (R2) -
src/filter/(filter.go, mover.go), the [filter] job with DRY-RUN as a first-class mode, the [tag-groups] config, derived folder rules from account + preset data. The muttrc post-new hook and afew are reference shapes only. Algorithmic filters (bayes, DKIM) remain future plug-ins behind the same per-message contract. - MIME cache (R13) -
src/cache/: bbolt, keyed by (path, size, mtime) to attachment metadata, hit-only in steady state. - Fuzz targets on the mail-parsing boundary -
src/mail/fuzz_test.go. - Theme onedark port (R11) -
defaultTheme/defaultPalettein src/config/config.go (the muttrc onedark reference port); the base16 palette converter stays a future task (R11). - Lua bindings (R8) - the plugin layer (
src/app/lua_plugin.go, lua_action.go) and the build-tag-gated AI provider layer (src/app/ai/) shipped on the neovim model; TOML stays the config language. - Preview popup vs open-reads distinction - the p key opens a popup preview over the index (src/tui/preview.go); enter promotes it to a full open.
- Whole-fill dirty batch on refresh - the phase-2 emit loop runs inside one BeginMerge/EndMerge pair (src/app/refresh.go); the measured 17.7x trade is design-decisions record 15.
- cgo binding re-evaluation - resolved: the batched ThreadsWalk closed the gap (~1.6s vs the CLI’s 1.5s full walk) and cgo IS the runtime backend; the CLI survives behind
-tags clias the escape hatch (AGENTS.md R1, decision record 3). - Notifications as a filter side effect -
src/app/notify_beeep.go, wired to the filter job’s completion event (filterjob.go); the address cache half remains Tier 2 item 5.
Process notes
- Every Tier 1/2 item needs a spec (docs/superpowers/specs/) then a plan (docs/superpowers/plans/) before implementation, per the project workflow.
src/cache/*,src/app/cachejob.go, and (unless an exception is granted)src/core/view.gostay READ-ONLY for AI agents; items touching the cache need an explicit approval.- The benchmark harness from the lag investigation (real tea.Program, end-to- end per-press cost) should be kept as a reusable perf gate when the TUI gains features that touch the render path.