v0.10.0 — Mail complete
v0.10.0 — Mail complete
The whole mail arc since 0.9.0: every planned Mail capability shipped, hardened on
device, and the #119/#140 release gate closed. 75 commits.
Mail — new capabilities
- Recoverable destructive plane (#159):
move_mail,trash_mail,create_mailbox,
update_mail_status— every destructive batch backs up message bytes + source mailbox
first and returns areceipt;mail_undoreplays it. Soft delete is the only delete
(Mail scripting cannot permanently erase — documented, not worked around). - Outbound lifecycle (#157):
send_mail(new message or approved-draft send),
reply_all,forward_mail— all dry-run-by-default, gated behind
MACOS_APPS_ALLOW_SEND; drafts plane (create_draft,mail_reply,drafts,
delete_draft). - Reads that answer completely (#155/#156, breaking): every read returns the
addressing triple (id + folder + account); ids resolve on their own months later. - Bulk + body reads:
mail_bodies(batch),mail_thread(snippets=), body FTS via
mail_index_bodies—.partial.emlxbodies included (#119: a partial is missing
attachments, not text; 99.47% of bodies are local). - Attachments (#81):
mail_attachments,save_mail_attachment— hostile-name-safe,
size-capped, never overwrites. - Stats & hygiene:
mail_overview,mail_stats,mail_duplicatesreport;
export_mail(.eml, lossless-or-labeled); cross-account dedupe CLI gated on body
identity, not byte size (#153). - Triage:
mail_needs_response/mail_awaiting_reply— real In-Reply-To/References
threading; scans now get their declared 120s budget (#188).
Runtime & operations
- Wedged-vs-busy classification on the Mail timeout path (#183) — a permanent event-
queue wedge is distinguished from a benign resync, with the right remediation named. doctor().build(#143): build stamp baked bybuild_app.sh; a same-version
rebuild is now provable. Deploy proof =doctor().version+doctor().build.- Shim↔daemon transport contract (#170): no read deadline on the UDS hop — a bulk
Mail pass may run hours; a dead stream answers loudly instead of hanging. - The daemon registers the outbound tier from argv role detection (#166) —
allow-sendworks under launchd.
Fixed
- #188 triage scans died at the 30s host cap while their scripts budget 120s
- #170 the shim silently killed any destructive Mail call over ~5s
- #174
_MOVEre-checks before accusing; #171local://source refused at the boundary - #146 any mailbox reachable, not just inbox; #144 one mailbox vocabulary
- AppleScript
missing valueblanked across all adapters
Declined / closed by evidence (device-verified, documented in
docs/mail-applescript-facts.md)
- #84 Send Later: no scripting surface exists — not shippable under that name
- #167 nothing scriptable converts a
.partial.emlx; #119's premise was wrong - #164 dropped deletes are a sick-Mail symptom; restart, don't retry-loop
Known degradation
mail_awaiting_replycan exceed its (raised) 600s budget on large stores — the
unified All-Sent scan is high-variance O(store) (#192, open). It fails loud,
classified, and bounded; the fix direction is moving the scan onto the Envelope
Index.mail_needs_responseis unaffected (~34s). The send tools' id-resolve is
fast with a concretefoldertoken; a canonical name ("inbox") can hit the same
slow path on large stores.
Dependencies
- cryptography 50.0.0 + mcp 1.29.0 (clears both high security alerts), fastmcp 3.4.7,
full lock refresh; CI actions off deprecated Node 20 runners (#112).