Inbox Sweep
A rule-based bulk email triage console at /workshop/pages/sweep/. The goal is
narrow and measurable:
Inbox zero in under a minute a day β approve a rule once, never see that sender again; residue is only mail that needs a human.
Status: shipped 2026-07-21.
vita.email.*namespace (9 capabilities) overscripts/email_sweep/. Verified live including a net-zero write test.
Why the previous attempts died
bio-zack's work inbox hit 23,800 messages, 68% of it one class of server alerts. He bulk-archives in his head but never in Gmail.
The classifier was never the problem. Vita had built an email client (Mercury) before, and the autopsy named four specific reasons it went cold:
| Failure | What it meant |
|---|---|
| It was a destination client | competing with Gmail, which always wins |
| Trust-gated archives | archiving was staged/simulated, i.e. fake β so he still had to go do it for real |
| Stale queue counts | the number on screen wasn't the number in Gmail |
| No bulk one-tap, no undo | so the risky action was never worth taking |
Inbox Sweep is built as the inverse of each: a console, not a client; real
batchModify archives; live counts straight from Gmail; one tap with a real
undo.
How it works
discovery (sampled, cached <1h)
β newest inbox mail per account
βΌ
candidate rules ββ sender / subject β archive
β + "needs you" human residue (matches no rule)
βΌ
rules store data/email/triage_rules.json
β status: proposed β approved β (dismissed)
βΌ
preview ββ live match count + samples, read-only
β
βΌ
sweep ββ real Gmail batchModify, removes INBOX label
β β€10k per rule, `-is:starred` ALWAYS excluded
βΌ
ledger data/email/sweeps.jsonl (append-only)
β
βΌ
undo ββ re-add INBOX to exactly those message ids
(refuses a double-undo β the ledger is append-only)
Design decisions that carry the trust
Counts are never cached. vita.email.overview calls the Gmail labels.get
API for exact messagesTotal / messagesUnread per account β it never reads
email.json or any vita-side cache. A console whose numbers disagree with
Gmail is worthless.
Only approved rules can sweep. New rules default to status=proposed.
vita.email.sweep refuses proposed/dismissed/unknown rules with
invalid_input listing the offenders β and archives nothing in that case,
rather than partially applying.
Starred is always excluded. -is:starred is appended unconditionally, not
as a user option.
Every sweep is undoable. Each run's message ids are ledgered, so undo
re-adds the INBOX label to exactly those messages. The raw ids are never
returned through the capability surface β only a human rule_summary, the
archived count, and whether it was undone.
The capability surface
| Capability | Kind | What it does |
|---|---|---|
vita.email.overview |
read | live per-account inbox totals from Gmail |
vita.email.discover |
read | sample newest mail β propose rules + "needs you" residue |
vita.email.rules |
read | full rules list (proposed / approved / dismissed) |
vita.email.rule_preview |
read | live match count + samples for a rule |
vita.email.rule_upsert |
write | create/update a rule |
vita.email.rule_delete |
write | delete a rule |
vita.email.sweep |
write | bulk-archive matches of approved rules |
vita.email.sweeps |
read | recent ledger entries, with cross-session undo |
vita.email.undo_sweep |
write | restore exactly what a sweep archived |
Because it's built on the capability layer, the same nine operations are available to the workshop page, to any agent, and to the CLI without a second implementation.
Seeding
32 rules were seeded from a recon pass over the real inbox, matching roughly
24,000 messages β all in proposed state. Each shows a live preview count and
sample messages before bio-zack approves anything.
Per-rule auto is opt-in: when set, the rule sweeps on page visit.
Signals
Working: he approves the seeds and the first sweep clears ~80%; repeat
visits every day-or-two keep inbox_total near the human-residue floor; new
candidate rules get approved or dismissed rather than ignored; undo exists
but goes unused (trust earned).
Failing: counts climb back and the page goes cold, like Mercury did.
Not built
Deliberately deferred until daily use earns them: scheduled server-side
auto-sweep of auto rules, a telegram nudge ("N archivable β sweep?"), and a
needs-you β task hook.
Related
- Vita Workshop β the page surface
- Capability Layer β the
vita.email.*namespace - External & Agent Email β the inbound agent-email path