Roadmap item 3, and the one with the most ways to get it wrong.
The shape, which is not negotiable
- Your key or your machine. Either an API key you supply, or a local model over Ollama. There is no MailOh-hosted inference in the desktop app and no key of ours baked into a build — that would make a GPL binary that phones home, which is exactly what this repository exists not to be.
- Proposed, never applied. A suggestion is rendered as a suggestion. Nothing is moved, filed, replied to or deleted because a model said so. The Screener already has the right interaction for this: the model fills in a suggested destination and the human presses the button.
- Sensitive mail is structurally excluded, not excluded by a prompt. The protected-OTP path in the fixtures is the model for this: a message classified as protected is redacted structurally, and the exclusion is a property of the data path rather than an instruction a model can be talked out of.
- Off by default, and visibly off. Settings must say which provider is in use, what leaves the machine, and what does not.
What it touches
SettingsView on both platforms: provider, endpoint, key storage (Keychain on macOS, DPAPI/libsecret elsewhere), and a model picker for Ollama.
- The Screener's suggested-destination field, which is a fixture today — see
ScreenerView on both clients. It renders already; it needs a real source.
- Compose: draft replies.
ComposeView has an honestly disabled Send; a drafted reply must land in the editor, not in the outbox.
- A capability probe, so a machine with no Ollama and no key never shows a spinner that cannot finish.
Depends on
The engine slice. There is no point classifying a fixture mailbox — the value is in a real one, and the exclusion rules need real message structure to work on.
Acceptance
Roadmap item 3, and the one with the most ways to get it wrong.
The shape, which is not negotiable
What it touches
SettingsViewon both platforms: provider, endpoint, key storage (Keychain on macOS, DPAPI/libsecret elsewhere), and a model picker for Ollama.ScreenerViewon both clients. It renders already; it needs a real source.ComposeViewhas an honestly disabled Send; a drafted reply must land in the editor, not in the outbox.Depends on
The engine slice. There is no point classifying a fixture mailbox — the value is in a real one, and the exclusion rules need real message structure to work on.
Acceptance