-
released this
2026-08-22 13:01:04 -05:00 | 9 commits to main since this releaseM6. Destroying mail is its own tool, its own grant, and its own decision.
delete_message(permanent=true)is gone;expunge_messagereplaces it. Gmail's write phase
(G2) is what forced the question — itsdelete_messagehad to be specified before it was
written — and the answer applies to the tenant that already shipped one.Breaking, and in the way that costs a minute: the mail connector's tool list changed, so
reconnect it — Claude caches tool descriptions per connector and does not refetch them
because a container restarted. Per-tool permission toggles are keyed to tool names, so
expunge_messagearrives at its default anddelete_message's existing toggle survives.
Same shape as 0.14.0's rename, and the same reason it ships on its own rather than riding
along with the next change.Changed
delete_messagemoves to trash and does nothing else. Nopermanent, no
expected_subject, one argument. It is the tool a model reaches for when a user says
"delete", and it can no longer do anything a user would not expect from that word.
Added
-
expunge_message, behindMAIL_EXPUNGE_ENABLED.\Deleted+UID EXPUNGEon one
message,expected_subjectrequired rather than conditionally required, and no
message_idin the response because there is nothing left to name.A boolean was the weakest available gate on the one operation with no undo — one token
in a JSON object, on the same tool as the safe operation, described in a paragraph
appended to a description whose opening sentence was about moving to trash. Splitting buys
three things a parameter cannot: a description where every sentence is about
irreversibility, a grant that can be given and withheld separately, and a decision visible
in the call rather than buried in an argument. -
The gate nests, and it is the only one here that does.
MAIL_EXPUNGE_ENABLEDlayers
overMAIL_WRITABLE_FOLDERSrather than sitting parallel to it: that list says which
folders may be changed, this says whether destroying is permitted at all, and an expunge
is both. Turning it on alone registers nothing. While it was a boolean, naming a folder
writable was already consent to destroy what was in it, with nothing in the boot log to
say so — the grants line now carriesexpunge=on|off.MAIL_FOLDER_ADMINdeliberately does not nest, and the two are not inconsistent:
managing a collection is a different kind of grant, while destroying is a stronger degree
of the same one.
Notes
-
CLAUDE.mdsaid not to do this, and now says when to. "Do not split a tool to dodge
a bad argument" —delete_eventkeepsthis/following/allin one parameter, and
that rule stands. The distinction is written down rather than left to whoever remembers
this release:delete_event's scope is one operation with three equally-undoable targets,
while delete-versus-expunge is two operations that differ in whether the mail still
exists. The test is not could this be one argument — it usually could — but does the
choice change what a wrong call costs, and would an operator grant one side without the
other. Two yeses is two tools. -
Named
expunge_message, notdelete_message_permanently. Two names differing only by
a suffix are the easiest pair to confuse, which defeats the split. Expunge is IMAP's own
verb, so nothing about "delete this email" reads as selecting it by accident. -
A test tried to assert the wrong property and the fake refused it. "A delete never
expunges" is false about a correct implementation: iCloud advertises noMOVE, so a move
is COPY, flag the original, expunge the original. The COPY is the whole difference —
one call leaves the message somewhere and the other does not — and that is what is pinned
instead. -
The trash-missing error no longer offers the irreversible path as the way out. It read
"or pass permanent=true to remove the message outright", which is a suggestion to
destroy mail because a configuration value is unset. It now namesTRASH_FOLDERand says
explicitly not to reach forexpunge_messageinstead. -
Not yet run live. M6's live pass is written up in
docs/operations.mdbeside M1–M5
and is owed before this is trusted on real mail — including the two absence checks, which
no unit test can confirm on the deployed service.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads