v3.0.74 — Bridge-capability program (Phases 0–7)
Bridge-capability program — a subsystem-by-subsystem TDD redesign with a per-function multi-agent ultra-review to a 9.5 quality bar (8 phases, docs/quality-audit.md). Adds the gated empty_trash and mark_answered/mark_forwarded capabilities and fixes a fail-open folder-delete protection hole, an attachment-download OOM bypass, two search under-return bugs, the $Forwarded write/read asymmetry, the SMTP TLS divergence + IPv6 ::1 handling, and the multi-account keychain credential shadow.
Added
mark_answered/mark_forwardedtools — set/clear the IMAP\Answeredflag and the$Forwardedkeyword (the marker the forward tool writes and the readers now honour). Both threadsourceFolderand wrap the existingsetFlag.empty_trashtool — the one sanctioned permanent-delete path. PERMANENTLY EXPUNGEs the Trash mailbox (resolved by server\Trashspecial-use, so localised names likePapelerawork) and only Trash — it can never be pointed at live mail. Gated by{ confirmed: true }like the other destructive tools; short-circuits an already-empty Trash. Everywhere else, delete still means move-to-Trash. Scored 10/10 on the ultra-review.
Fixed
get_foldersexposesspecialUse+folderTypeso agents identify Trash/Sent/Archive by special-use (localised-account-safe) instead of English names, and avoid the\Allunion.- Fail-open folder protection closed (security):
delete_folder/rename_foldercould destroy a localised system mailbox if folder discovery threw; the protection check now fails closed. getFoldersrobustness: one folder'sSTATUSfailure no longer nukes the whole listing (Promise.allSettled); a cold-cache + disconnect throws instead of returning[].getEmailspagination: an out-of-rangeoffsetreturns an empty page instead of a clamped message #1.- Forwarded flag: reads
$Forwarded/\Forwarded(the setter's flag) instead of the non-existent\Forward, which always read back as not-forwarded. download_attachmentmemory safety: the oversize guard now checks the actual resolved byte length (the stale-metadata path could OOM); re-maps by filename if the re-fetch attachment order drifts.bulk_copyfailure messages now carry the source folder, matchingbulk_move.search_emailsno longer returns[]on a connection failure (IMAP-012) — it throws, so a connection drop is distinguishable from "no matches".search_emailshasAttachmentno longer under-returns below the requested limit — the local attachment filter now runs before the limit (with a bounded over-fetch) instead of after; per-folder failures and folder-cap truncation are logged instead of silent;searchSingleFoldervalidates its folder defensively.fts_searchsinceEpochis applied in SQL beforeLIMIT(was a post-LIMITfilter that could return far fewer than the limit).- Bridge
SEARCH BODY/TEXTdocs reconciled —body/textsearch criteria are wired and exposed (the limitation note was pre-Phase-0 stale). - SMTP now uses the shared
buildBridgeTlsConfig(no more 4th inline TLS copy that could diverge from the IMAP path's pinned-cert/insecure-fallback contract), which also fixes SMTP + the IMAP IDLE socket not recognizing IPv6 loopback::1as localhost. forward_emailkeeps the message in its thread — it now carries the originalIn-Reply-To/References(parity withreply_to_email), CRLF-strips the embedded original From/To in the quoted header, and logs (instead of silently swallowing) a$Forwarded/\Answeredflag-set failure. Also fixed a latent crash:referencesis normalized to an array (mailparser returns a bare string for a single-reference message, which would have thrown on the send path).- Multi-account credential staleness fixed: the per-account keychain entry is now authoritative on startup, so a stale legacy keychain entry can no longer shadow the fresh per-account password a Settings save wrote (and account #2 can't inherit account #1's password). Single-account / config-plaintext installs are unaffected.
- Background IDLE now runs for every account, not just the active one, so a non-active account still receives push cache invalidations instead of degrading to manual syncs.