ADR 0033: Live classify on connected mail
Status
Accepted
Context
Duckbill™ already classifies golden-set fixtures and persists versioned AIInference rows (ADR 0022). Sync enqueues CLASSIFY work and leaves mail visible as UNPROCESSED when that work has not run. Home counts stay empty because classify never ran on a connected mailbox. MAIL-217 remains the parked latency measurement. This decision is the worker, not that measurement.
Decision
POST /api/classify/liveclassifies one bounded page of stored messages for a mailbox the signed-in user owns. The page size is at most 10. The handler does not receive a provider adapter and does not call Graph, Gmail, or iCloud.- Labels come from stored subject and body through
classifyConnectedMail. That function does not look up golden-set ids. Prompt-injection text is recorded as low-confidence review, not executed. - Each new result is an insert-only inference with
classify.v1, schema1.0.0, and taxonomy1.0.0. A matching fingerprint keeps the current row. A changed message inserts another row. Current classification pointers stay correctable by the existing human-correction path. - The worker writes conversation attention from the classification (
RESPOND,WAITING,FYI,ARCHIVE, orNONE). Home counts read that attention plus current classifications. The empty state says the mailbox is not classified yet, or that classify ran and Needs Me, Respond, and Waiting are empty. - iCloud stays read-write. This route does not change provider capability flags and does not move mail.
Alternatives
- Close the story on the golden set — rejected; MAIL-233 says a connected mailbox has to show queues.
- Let the model call
listMessages— rejected; AI must not call adapters. - Measure live p95 here — rejected; that is MAIL-217.
Consequences
Home can change after one signed-in classify of stored mail. Adapter write count stays 0. Preview still needs the route deployed before a browser session can press Classify connected mail.
