Files
Maven/docs/plans/01-email-reader.md
T
kami 5fe8f228c1 feat(mavweb): /ecosystem page consuming Nexus/Praxis/Hexis + shell fixes
Add a read-only /ecosystem page that consumes the sibling services'
JSON APIs (Nexus entities, Praxis attention, Hexis capabilities),
fetched concurrently with honest per-panel error states. Siblings stay
headless — mavweb is their human surface (arch §16). Wired via mavweb
-nexus/-praxis/-hexis flags; mavweb joins the ecosystem compose network.

Fix mobile horizontal overflow across all pages: .content is a flex
child with default min-width:auto, so it refused to shrink below the
tables' intrinsic width. min-width:0 lets wide tables pan inside .scroll
instead of dragging the page sideways. Verified via CDP geometry check
(scrollWidth === clientWidth at 430px).

Also includes in-progress Ethos UI redesign, ecosystem deploy compose,
and planning docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 22:04:23 +04:00

30 lines
2.5 KiB
Markdown

# Plan: Background Email Reader
**Goal:** Maven periodically polls configured IMAP mailboxes, extracts structured items (tasks, reminders, calendar events, important facts) via LLM, and writes them into the store through `ipc.CoreAPI` — discarding spam, newsletters, and noise.
**Done when:**
- `internal/email/` package exists with IMAP idle+poll loop
- New `email` block in `config.Config` (mailboxes, poll interval, extraction model)
- Extracted items land as `WriteFact`/`CreateReminder`/`WriteNote` via `ipc.Client`
- Spam/promotions/social are silently dropped (Gmail `X-GM-LABELS` or IMAP keyword check)
- Integration test with a throwaway mailbox verifies the round-trip
**Scope:**
- New `internal/email/` package — IMAP client (stdlib `net/mail` + `github.com/emersion/go-imap` or raw `net/textproto`)
- Config extension: `config.Config.Email` block with `PollInterval`, `Accounts[]` (host, username, password/app-password, folders)
- LLM extraction prompt (shared `internal/llm.Client`) classifies each unseen message as `task|reminder|event|fact|junk` and fills slots — same GBNF-constrained pattern as `internal/router/llmrouter.go:routeGrammar`
- Extracted items written through `ipc.CoreAPI` interface (same seam `internal/voice/reactiveHandler` uses)
- Daemon lifecycle: wired in `cmd/mavend/main.go` alongside the tick loop, starts after unlock
- `deploy/mavend.json` gets the email block
**Steps:**
1. Add `EmailConfig` struct to `internal/config/config.go` (accounts, poll interval, folders to scan)
2. Create `internal/email/` with `Poller` — IMAP connect, `IDLE` for push, fallback to periodic `SELECT INBOX` + `SEARCH UNSEEN`
3. Implement message → plaintext conversion (`text/plain` body, strip HTML from `text/html` via `golang.org/x/net/html` or simple regex)
4. Add LLM extraction via `internal/llm.Client.Complete()` with a GBNF grammar that outputs `{"type":"task|reminder|event|fact","key":"...","value":"...","when":"..."}` — mirroring `internal/router/llmrouter.go:routeGrammar`
5. Map extracted items to `ipc.WriteFactReq` / `ipc.CreateReminder` / `ipc.WriteNote` calls
6. Wire `Poller` into `cmd/mavend/main.go` — start on unlock, stop on context cancel
7. Test with a throwaway mailbox (Gmail app password or a self-hosted Dovecot); verify extraction accuracy
8. Add `models/seeds/email_*.txt` seed examples for the extraction classifier
9. Log poll stats (seen, extracted, junk, errors) through `log.Printf` (consistent with existing pattern in `cmd/mavend/tick.go`)