docs: Phase 8 documentation - Gitea, Obsidian, Outline, Vikunja, map (AUD-74)

- README: architecture Mermaid, Phase 8 status, Phase 7 endpoints, Documentation index
- docs/outline/: AI-context collection (index, system, config, code map, runbook)
- docs/email-agent-architecture.mmd + rendered PNG + Archify map (showcase pass)
- docs/vikunja-tasks.json (Vikunja project 17, tasks 179-185)
- docs/phase8-documentation.md evidence
This commit is contained in:
Documenter
2026-10-13 10:46:21 +11:00
parent 77febe6470
commit c5760db43d
12 changed files with 14575 additions and 26 deletions

108
README.md
View File

@@ -7,34 +7,59 @@ replies, and answers the Hub.
The build spec is [`AGENTS.md`](AGENTS.md). `ORIGINAL_NOTES.md` is archived
pre-planning material and is not authoritative.
## Architecture
```mermaid
flowchart LR
SAM["Sam<br/>phone or desktop browser"] --> CADDY["Caddy on .35<br/>mail.lab.audasmedia.com.au"]
CADDY --> UI["HTMX dashboard<br/>login, inbox, rules, reports"]
UI --> DB[("SQLite<br/>email_agent_data")]
UI --> GMAIL["Gmail<br/>IMAP :993 / SMTP :587 (IPv4)"]
UI --> JEV["JEV / TypeSafe<br/>classify"]
UI --> OMNI["OmniRoute :20129<br/>draft reply"]
UI --> APPRISE["Apprise :8210<br/>summary email"]
HUB["Central AI Hub :8788"] --> API["Hub API<br/>/capabilities /ask /notify"]
API --> DB
N8N["n8n schedule"] --> JOBS["CLI jobs<br/>-fetch -classify -summary-send"]
JOBS --> DB
```
Sources: [`docs/email-agent-architecture.mmd`](docs/email-agent-architecture.mmd)
and [`docs/email-agent-map.html`](docs/email-agent-map.html). Interactive map:
<https://maps.lab.audasmedia.com.au/email_agent/docs/>.
## Status
**Phase 7 — Summary and Hub; retention.** The Go skeleton, session login,
and HTMX dashboard (Phase 1), real mail over **IMAP with an app password,
forced to IPv4** (Phase 2), **JEV classification** (Phase 3), **bulk triage
actions** (Phase 4), **reply drafts** (Phase 5), and now **unsubscribe
detection and the rules editor** (Phase 6). Open a message to read it, draft a
reply with the LLM through **OmniRoute** from a template, edit it, and send it
over Gmail SMTP (IPv4 + STARTTLS). A reply is sent **as the address the mail
arrived at** (`X-Pm-Original-To`, FR-15) and returns to the original sender; the
reply sets `In-Reply-To`/`References` so Gmail keeps the thread, and the
original is filed under its `Replied-to/<address>` label. Sending is a
deliberate UI action with a confirmation — there is no auto-send (§10). The
**rules editor** (`/rules`) saves and versions the plain-text rules that JEV and
the reply model read. **Unsubscribe detection** (`/unsubscribe`) finds RFC
2369/8058 links and body links, keeps a domain ignore list, and records what Sam
marks — it **never follows a link**. Every action, including drafts, sends,
rules edits, and unsubscribe marks, is appended to `actions_log` (FR-13).
**Phase 7** adds the daily **summary** (`-summary`, `-summary-send`; delivered
by email through Apprise) and the read-only **Hub API** (`/capabilities`,
`/ask`, `/notify`). **Retention** (AGENTS.md §7) is enforced by the bounded
`-retain` job: it clears message bodies older than one month, keeps metadata,
and caps the append-only `actions_log`; see
[`docs/retention.md`](docs/retention.md). See
[`docs/phase7-summary-hub.md`](docs/phase7-summary-hub.md) for Phase 7,
[`docs/phase6-unsubscribe.md`](docs/phase6-unsubscribe.md) for the phase evidence,
[`docs/phase5-replies.md`](docs/phase5-replies.md) for Phase 5, and
[`docs/phase4-triage.md`](docs/phase4-triage.md) for Phase 4.
**Complete and deployed.** All eight AGENTS.md §11 phases are done. The Go
skeleton, session login, and HTMX dashboard (Phase 1), real mail over **IMAP with
an app password, forced to IPv4** (Phase 2), **JEV classification** (Phase 3),
**bulk triage actions** (Phase 4), **reply drafts** (Phase 5), **unsubscribe
detection and the rules editor** (Phase 6), and the **daily summary by email plus
the read-only Hub API** (Phase 7) run on `.13` behind Caddy. Phase 8 documents
the project across Gitea, Obsidian, Outline, Vikunja, and the architecture map.
Open a message to read it, draft a reply with the LLM through **OmniRoute** from
a template, edit it, and send it over Gmail SMTP (IPv4 + STARTTLS). A reply is
sent **as the address the mail arrived at** (`X-Pm-Original-To`, FR-15) and
returns to the original sender; the reply sets `In-Reply-To`/`References` so
Gmail keeps the thread, and the original is filed under its
`Replied-to/<address>` label. Sending is a deliberate UI action with a
confirmation — there is no auto-send (§10). The **rules editor** (`/rules`)
saves and versions the plain-text rules that JEV and the reply model read.
**Unsubscribe detection** (`/unsubscribe`) finds RFC 2369/8058 links and body
links, keeps a domain ignore list, and records what Sam marks — it **never
follows a link**. Every action, including drafts, sends, rules edits, and
unsubscribe marks, is appended to `actions_log` (FR-13). **Phase 7** adds the
daily **summary** (`-summary`, `-summary-send`; delivered by email through
Apprise) and the read-only **Hub API** (`/capabilities`, `/ask`, `/notify`).
**Retention** (AGENTS.md §7) is enforced by the bounded `-retain` job: it clears
message bodies older than one month, keeps metadata, and caps the append-only
`actions_log`; see [`docs/retention.md`](docs/retention.md). Phase evidence:
[`docs/phase7-summary-hub.md`](docs/phase7-summary-hub.md),
[`docs/phase6-unsubscribe.md`](docs/phase6-unsubscribe.md),
[`docs/phase5-replies.md`](docs/phase5-replies.md),
[`docs/phase4-triage.md`](docs/phase4-triage.md), and
[`docs/phase8-documentation.md`](docs/phase8-documentation.md).
## Layout
@@ -52,6 +77,10 @@ internal/unsubscribe/ RFC 2369/8058 + body unsubscribe-link detection (no netw
internal/version/ build metadata (set via -ldflags)
web/static/ embedded design tokens, Inter fonts, htmx, app.css
web/templates/ embedded server-rendered HTML
docs/ phase evidence, retention, AI context, map, diagrams
docs/outline/ AI-context documents (system, config, code, runbook)
docs/archify/ Archify JSON spec for the architecture map
docs/diagrams/ rendered Mermaid PNG
Dockerfile multi-stage, CGO-free build
docker-compose.yml this project's own container and image
```
@@ -280,6 +309,12 @@ Caddy on `.35` proxies `mail.lab.audasmedia.com.au` to this port.
| `POST` | `/unsubscribe/ignore` | session + CSRF | Adds a domain to the ignore list |
| `POST` | `/unsubscribe/unignore` | session + CSRF | Removes a domain record |
| `POST` | `/unsubscribe/mark` | session + CSRF + confirm | Records a domain for unsubscribe; never contacts the link |
| `GET` | `/reports` | session | Reports screen: build, send, and delete a daily summary (FR-10) |
| `POST` | `/reports/generate` | session + CSRF | Builds and stores today's summary; sends nothing |
| `POST` | `/reports/send` | session + CSRF + confirm | Delivers today's summary by email via Apprise |
| `POST` | `/reports/delete` | session + CSRF | Deletes a stored summary |
| `GET` | `/capabilities` | Hub bearer | Hub capability list (FR-12) |
| `POST` | `/ask` | Hub bearer | Read-only short answer (FR-12); never writes |
| `GET` | `/static/…` | public | Embedded `tokens.css`, `app.css`, Inter fonts, `htmx.min.js` |
Unauthenticated requests to `/` and `/partials/…` redirect to `/login?next=…`.
@@ -300,3 +335,24 @@ folders; migration v5 adds `messages.message_id_header` (reply threading) and
`drafts.sent_at`; migration v6 adds `messages.list_unsubscribe` and
`messages.list_unsubscribe_post` and extends `unsubscribe` with `url` and
`updated_at`.
## Documentation
Phase 8 recorded the project in five places.
| Surface | Location |
|---|---|
| Gitea | This README, `docs/phaseN-*.md`, `docs/outline/`, `docs/email-agent-architecture.mmd`, `docs/email-agent-map.html` |
| Obsidian | Note `Email Agent — Family Inbox Triage` in `010 inbox` on `.27` (the sorter files it) |
| Outline | Collection `Email Agent` (`00-index`, system overview, config, code map, runbook) |
| Vikunja | Project `Email Agent` (human milestones) |
| Map | `central_ai_llm_master/docs/hub-architecture-map.html` and this repo's map, published to <https://maps.lab.audasmedia.com.au/email_agent/docs/> |
Rebuild the map:
```sh
mmdc -i docs/email-agent-architecture.mmd -o docs/diagrams/email-agent-architecture.png --scale 2 -b white
~/.agents/skills/project-docs/scripts/publish-maps.sh /home/sam/paseo/projects/email_agent
```
See [`docs/phase8-documentation.md`](docs/phase8-documentation.md) for the evidence.