From 4ec0a366eb7b72380c5dd8ad2fa9edc3693cc6ff Mon Sep 17 00:00:00 2001 From: Till Wegmueller Date: Sun, 12 Apr 2026 01:00:55 +0200 Subject: [PATCH] Add Anima system design spec Comprehensive design covering service architecture (anima-server, anima-mail, anima-agent, anima-ai, anima-desktop), domain model, gRPC API, Slint desktop client, mail integration via Stalwart/JMAP, agent VM lifecycle, embedded MCP server, RBAC, and crate structure. --- .../specs/2026-04-12-anima-system-design.md | 508 ++++++++++++++++++ 1 file changed, 508 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-12-anima-system-design.md diff --git a/docs/superpowers/specs/2026-04-12-anima-system-design.md b/docs/superpowers/specs/2026-04-12-anima-system-design.md new file mode 100644 index 0000000..2c23dd0 --- /dev/null +++ b/docs/superpowers/specs/2026-04-12-anima-system-design.md @@ -0,0 +1,508 @@ +# Anima System Design + +**Date**: 2026-04-12 +**Status**: Draft +**Author**: Till Wegmueller + Claude + +## Overview + +Anima is a strategic work coordination platform for developers who manage projects, AI agents, and collaborative workflows. It is not an IDE — it is the command post layer above, where you assign work, track AI progress, manage discussions (including email threads), and surface documentation. + +The system is server-authoritative. The desktop client is a terminal into the command post — it caches for responsiveness but does not own data. + +## Service Architecture + +### Services + +| Service | Role | Runtime | +|---------|------|---------| +| **anima-server** | Core API + embedded MCP server. Projects, work items, plans, workflows, teams, settings, RBAC. gRPC for desktop client. Forge integration. Seshat's Library client. | Rust binary, always running | +| **anima-mail** | Polls Stalwart via JMAP, routes inbound mail to work item threads, sends outbound mail on behalf of work items. Creates/manages mailboxes via Stalwart admin API. | Rust binary, async worker | +| **anima-agent** | v1: Single-agent manager. Provisions VM/container, deploys skills, manages agent lifecycle. Interface designed for future multi-provider orchestration. | Rust binary, on-demand | +| **anima-ai** | Light AI inference — summaries, gap analysis triggers, thread updates, description generation, mail classification. Stateless, horizontally scalable. | Rust binary, scalable | +| **anima-desktop** | Slint desktop client. gRPC to anima-server. Caches for responsiveness, doesn't own data. | Slint/Rust app | + +### External Dependencies + +| Dependency | Purpose | +|------------|---------| +| **PostgreSQL** | Primary relational store | +| **Stalwart** | Mail server (JMAP + admin API + plus-addressing) | +| **Seshat's Library** | Document library, vector search (pgvector), blob storage for files/patches/attachments | +| **Forge APIs** | GitHub/Gitea/GitLab — PR metadata, issue migration, read-only | + +### Data Flow + +``` +Desktop ──gRPC──► anima-server ──SQL──► PostgreSQL + │ ╰── MCP (embedded) + ├──► Seshat's Library (docs, vectors, blobs) + ├──► anima-mail ──JMAP──► Stalwart + ├──► anima-ai (light inference, N instances) + ├──► anima-agent ──► VM/Container + └──► Forge APIs (read-only) + +AI in VM ──MCP──► anima-server (scoped token, work item context only) +``` + +## Domain Model + +### Entities + +**Project** +- Name, description, status (active/archived) +- Has many Plans, Work Items, Repositories, Mailboxes +- Links to team members with roles via RBAC + +**Plan** +- Belongs to a Project +- Title, description, progress (derived from child work items) +- Has many Work Items +- Phases derived from its Workflow + +**Work Item** +- Belongs to a Project, optionally to a Plan +- Title, description (versioned — every update creates a new revision, revertable), status, priority +- Follows a Workflow (determines phases and required AI skills) +- Has a Discussion Thread (messages, email attachments, AI/Akh contributions) +- Has Patches/PRs (attachments, linked to forge PRs) +- Has Documents (stored in Seshat's Library) +- Has many Agent Sessions (long-running, parallel or sequential) +- Has Capabilities (derived from what the work needs — repo access, API keys, network zones). Agent sessions inherit these. +- Phase tracking within its workflow + +**Workflow** +- Template defining phases (e.g., Analysis → Implementation → Review & Audit) +- Each phase declares required AI Skills +- Ships with defaults, user-customizable +- Future: marketplace for sharing + +**Discussion Thread** +- Belongs to a Work Item +- Ordered messages from: humans, AI (via Akh), email (inbound/outbound) +- AI contributions are promotable to update work item description (creates new revision) +- Email messages carry headers linking back to work item via plus-addressing + +**Agent Session** +- Belongs to a Work Item (many sessions per work item) +- Represents heavy work running in a VM/container +- Status (provisioning, running, paused, completed, failed) +- Has Tasks (sub-units of work within the session) +- Skills deployed, capabilities inherited from work item +- Akh identity configured (persona for thread contributions) +- Long-running once started, persists while work item is open +- Admins can login (SSH) to inspect/debug — audit logged + +**Akh** +- AI persona/identity from the Akh domain +- Agents assume an Akh when writing in discussion threads +- Gives AI contributions a consistent voice and attribution + +**Repository** +- Belongs to a Project +- Forge type (GitHub/Gitea/GitLab), remote URL +- Has Worktrees (checked-out branches, managed by agents in VMs) +- PRs/patches linked to Work Items + +**Document** +- Stored in Seshat's Library (blob + vector embedding) +- Linked to Project and/or Work Item +- Types: markdown, text, patches, attachments +- Searchable by AI via vector queries + +**Team Member** +- User identity, role bindings per project (via RBAC) +- Settings, notification preferences + +**Mailbox** +- Belongs to one or more Projects (no global unattached box) +- A "gather" mailbox is one linked to multiple projects +- Managed via Stalwart admin API +- Plus-address routing rules + +### Relationships + +``` +Project ─┬─► Plans ──► Work Items ─┬─► Discussion Thread (messages, emails, Akh-authored) + │ ├─► Patches/PRs + ├─► Repositories ├─► Agent Sessions (many, long-running, loginable) + ├─► Team Members │ └─► Tasks + └──►┐ ├─► Documents (→ Seshat's Library) + Mailboxes (shared across ├─► Capabilities (derived, inherited by sessions) + multiple projects) ├─► Description Revisions (versioned, revertable) + └─► Workflow (phases, skills) + +Akh ──► identity assumed by AI in discussions +``` + +## gRPC API Design + +### Public Services (desktop client, embedded MCP) + +**ProjectService** +- `ListProjects`, `GetProject`, `CreateProject`, `UpdateProject`, `ArchiveProject` +- `ListProjectMembers`, `AddProjectMember`, `RemoveProjectMember` + +**PlanService** +- `ListPlans`, `GetPlan`, `CreatePlan`, `UpdatePlan`, `DeletePlan` + +**WorkItemService** +- `ListWorkItems`, `GetWorkItem`, `CreateWorkItem`, `UpdateWorkItem`, `DeleteWorkItem` +- `GetDescriptionRevisions`, `RevertDescription` — versioned description management +- `ListCapabilities`, `UpdateCapabilities` — derived capabilities attached to work items + +**WorkflowService** +- `ListWorkflows`, `GetWorkflow`, `CreateWorkflow`, `UpdateWorkflow`, `DeleteWorkflow` +- Ships with built-in defaults, user workflows stored alongside + +**ThreadService** +- `GetThread`, `PostMessage`, `PromoteMessage` — promote AI message to update work item description (creates new revision) +- `StreamThread` — server-streaming RPC for live thread updates + +**AgentSessionService** +- `ListSessions`, `GetSession`, `StartSession`, `StopSession` +- `LoginSession` — returns connection info for admin SSH/shell access +- `ListTasks`, `GetTask`, `UpdateTaskStatus` +- `StreamSessionStatus` — server-streaming for live status + +**RepositoryService** +- `ListRepositories`, `AddRepository`, `RemoveRepository` +- `ListPatches`, `AttachPatch` — link forge PRs to work items + +**MailboxService** +- `ListMailboxes`, `CreateMailbox`, `DeleteMailbox` +- `LinkProjects`, `UnlinkProjects` — manage which projects a mailbox serves + +**DocumentService** +- `ListDocuments`, `GetDocument`, `UploadDocument`, `DeleteDocument` +- Delegates storage to Seshat's Library + +**AkhService** +- `ListAkhs`, `GetAkh`, `CreateAkh`, `UpdateAkh`, `DeleteAkh` + +**TeamService** +- `ListUsers`, `GetUser`, `CreateUser`, `UpdateUser`, `DeleteUser` +- Roles and permissions per project via RBAC + +**DashboardService** +- `GetDashboard` — aggregated view: pending decisions, active sessions, work item status across projects +- `StreamDashboardUpdates` — live updates + +### Internal Services (not exposed to desktop) + +**AnimaAiService** (anima-server → anima-ai) +- `Summarize`, `AnalyzeGap`, `GenerateDescription`, `ClassifyMail` + +**AgentProviderService** (anima-server → anima-agent) +- `ProvisionVM`, `DestroyVM`, `DeploySkills`, `GetVMStatus`, `GetLoginCredentials` + +### API Patterns + +- **Streaming** for anything real-time: threads, agent sessions, dashboard +- **Pagination** via cursor-based tokens on all List RPCs +- **Field masks** on Update RPCs for partial updates +- **Standard error model** with domain-specific error codes + +## Desktop Client (anima-desktop) + +### Technology + +- **Slint** for UI rendering (native, cross-platform: macOS, Wayland, X11, Windows) +- **Rust** for all client logic +- **tonic** gRPC client for server communication +- Local **SQLite** cache for responsiveness (read cache, server is source of truth) + +### Screen Map + +| Screen | Purpose | Key Data | +|--------|---------|----------| +| **Dashboard** | Morning command view. Pending human decisions, active agent sessions, work item status summaries. | DashboardService | +| **Project List** | Grid/list of all projects with status, stats, AI activity indicators. | ProjectService | +| **Project Detail** | Plans-centric view. Plans with progress bars, nested work items, phase indicators, repositories, skills. | PlanService, WorkItemService, RepositoryService | +| **Work Item Detail** | Full work item view. Versioned description, thread (messages + emails + Akh contributions), patches, phases, capabilities, agent sessions. | WorkItemService, ThreadService, AgentSessionService | +| **Work Item Email Mode** | Same work item focused on email thread. Inbound/outbound mail, share buttons. | ThreadService, MailboxService | +| **Library** | Document browser. Search, read, manage documents across projects. | DocumentService (→ Seshat's Library) | +| **Workflows** | Browse/create/edit workflow templates. Phase editor, skill assignment. | WorkflowService | +| **Settings** | Server connection, user preferences, notification settings. | TeamService | +| **Team/People** | Team member management, roles per project. | TeamService | + +### Client Architecture + +``` +┌─────────────────────────────┐ +│ Slint UI Layer │ +│ (.slint files, components) │ +├─────────────────────────────┤ +│ View Models (Rust) │ +│ Translate domain → UI state │ +├─────────────────────────────┤ +│ gRPC Client Layer │ +│ tonic, streaming listeners │ +├─────────────────────────────┤ +│ Local Cache (SQLite) │ +│ Read cache, invalidated by │ +│ streaming updates from server│ +└─────────────────────────────┘ +``` + +### Caching Strategy + +- On startup: fetch current state, populate SQLite cache +- gRPC streams (threads, dashboard, sessions) push updates → invalidate/update cache → UI reacts +- Stale cache is acceptable for offline viewing but all writes go to server +- Cache is disposable — can be wiped and rebuilt from server + +### Design System + +- Headings: **Inter** +- Body: **Geist** +- Captions: **Funnel Sans** +- Color palette: **Violet Void** (dark theme) +- Roundness: Basic +- Elevation: Sharp depth +- Decorative: Neon streak overlays + +## Mail Integration (anima-mail) + +### Inbound Flow + +``` +External sender + → sends to workitem+WI-123@project.anima.example + → Stalwart receives, stores in project mailbox + → anima-mail polls via JMAP + → parses plus-address to extract work item ID + → calls ThreadService.PostMessage on anima-server (as email-type message) + → work item thread updated, desktop streams update +``` + +### Outbound Flow + +``` +User clicks "Send" on work item thread (email mode) + → desktop calls ThreadService.PostMessage (outbound email) + → anima-server notifies anima-mail + → anima-mail composes email with: + - Reply-To: workitem+WI-123@project.anima.example + - Custom headers: X-Anima-WorkItem, X-Anima-Project + → sends via JMAP submission to Stalwart + → recipient replies → inbound flow catches it +``` + +### Mailbox Management + +- anima-mail uses Stalwart's admin API to create/delete mailboxes +- One or more mailboxes per project, linked via MailboxService +- "Gather" mailboxes link to multiple projects — routing uses plus-address to disambiguate +- Compromised addresses get rotated, old mailbox dropped + +### Spam Handling + +- Simple screener on inbound: reject unknown senders on work-item-specific addresses +- Gather mailboxes are more open but can have basic filtering rules +- Compromised addresses get rotated, old mailbox dropped + +### Mail Classification + +- anima-mail calls anima-ai `ClassifyMail` to route ambiguous inbound mail when plus-addressing isn't present +- **Classification always runs on the smallest/cheapest AI model available** — it is a simple routing task, not a reasoning task. anima-ai supports model tiers and mail classification always uses the minimal tier. + +## Agent System (anima-agent) + +### v1 Scope + +Single-agent interaction. One provider (configurable — local Docker, bare-metal hypervisor, or cloud VM). The interface is designed for future multi-provider orchestration but v1 runs one provider. + +### Lifecycle + +``` +Work Item needs heavy work + → anima-server calls AgentProviderService.ProvisionVM + → anima-agent provisions VM/container with: + - Capabilities from work item (repo access, API keys, network rules) + - AI skills deployed for current workflow phase + - Akh identity configured (persona for thread contributions) + → Agent starts working, reports progress via tasks + → Agent writes to discussion thread as its Akh + → Session is long-running, persists while work item is open + → Admin can LoginSession to SSH in and inspect/debug (audit logged) + → When work completes or is stopped: VM can be kept or destroyed +``` + +### Capabilities + +- Defined on the Work Item, derived from what the work needs +- Examples: access to specific repos, GCP service accounts, k8s API, database credentials, network zones +- anima-agent translates capabilities into VM provisioning config (mounted secrets, firewall rules, IAM bindings) +- No allowlisting needed — the VM only has what the work item declares + +### Skills Deployment + +- Workflow phases declare required AI skills +- anima-agent deploys skills into the VM before the agent starts +- Skills are versioned and stored (future: pulled from marketplace) + +### Admin Access + +- `LoginSession` returns SSH connection details +- For when AI gets stuck and a human needs to inspect VM state +- Audit logged + +### MCP Server (embedded in anima-server) + +The MCP server exists to give **agents running inside VMs** access to Anima data relevant to their work item. It is not a general integration point for external tools. + +- **Scoped tokens**: Each agent session gets a token that identifies it. Permissions and scope are stored server-side in the database — looked up on each request. +- **No external tool access**: The desktop UI is the interface for humans. The MCP is the interface for Anima's own agents only. +- **Read-heavy**: Agents read work item descriptions, thread history, documents, workflow phase requirements +- **Limited writes**: Post to thread (as Akh), update task status, flag for human review +- **Token lifecycle**: Token provisioned when agent session starts, scope stored in DB, revoked on session end + +``` +anima-agent provisions VM + → generates MCP token (identifies agent session) + → scope stored in DB (work item context, allowed permissions) + → deploys token into VM alongside skills + → AI agent inside VM uses MCP to read context and report back + → token revoked on session end +``` + +### Future: Multi-Provider Orchestration + +The v1 `AgentProviderService` interface supports future expansion: +- An **Agent Orchestrator** sits in front of multiple providers +- Providers register capabilities (GCP provider, bare-metal provider, corporate-net provider, Docker provider) +- Orchestrator matches work item capabilities to provider capabilities and dispatches +- Each provider manages its own VM pool +- Scheduler places work on providers based on access requirements (GCP for GCP deployments, corporate-net machine for firewalled k8s API, etc.) + +## anima-ai Service + +### Model Tiers + +anima-ai supports multiple model tiers. Callers specify the tier, not the model — the service maps tiers to configured models. + +| Tier | Use Cases | Model Characteristics | +|------|-----------|----------------------| +| **Minimal** | Mail classification, spam screening, routing | Smallest/cheapest available | +| **Standard** | Summaries, description generation, thread digests | Mid-range, good at text | +| **Reasoning** | Gap analysis triggers, code review decisions, capability derivation | Stronger reasoning, higher cost | + +### API (internal gRPC, called by anima-server) + +- `ClassifyMail(mail) → work_item_id, confidence` — minimal tier +- `Summarize(thread/document) → summary` — standard tier +- `GenerateDescription(context) → description` — standard tier +- `AnalyzeGap(plan, implementation_state) → gap_report` — reasoning tier +- `ShouldReview(work_item, changes) → review_decision` — reasoning tier +- `DeriveCapabilities(work_item) → capabilities` — reasoning tier + +### Design Principles + +- **Stateless**: no persistent state, reads context from anima-server per request +- **Horizontally scalable**: run N instances behind a load balancer +- **Model-agnostic**: tier mapping is configuration, swap models without code changes +- **Cost-conscious**: always use the cheapest model that can do the job + +## Authentication & Authorization + +### Authentication + +- **Users (humans)**: Session-based auth against anima-server. Login via credentials (v1), future: OIDC/SSO. +- **Desktop client**: Authenticates on launch, receives a session token, attaches to all gRPC calls. +- **Inter-service**: anima-mail, anima-ai, anima-agent authenticate to anima-server with service tokens (pre-shared, rotatable). +- **Agent MCP tokens**: Tokens identify the agent session only. Scope and permissions are stored server-side in the database, looked up on each request. Revocation is instant. + +### RBAC System + +Full role-based access control: + +- **Permissions**: granular actions (e.g., `workitem.create`, `workitem.read`, `thread.post`, `plan.update`, `agent.login`, `mailbox.manage`) +- **Roles**: named collections of permissions, stored in database (e.g., Owner, Admin, Member, Viewer) +- **Role bindings**: user + project + role, stored in database +- Custom roles are a configuration change, not a code change. v1 ships with sensible defaults. + +| Concept | Storage | Example | +|---------|---------|---------| +| Permission | Code-defined enum, referenced in DB | `workitem.update`, `agent.login` | +| Role | DB row, has many permissions | "Admin" → [workitem.*, plan.*, agent.login, ...] | +| Role Binding | DB row: user + project + role | Till → Project Anima → Owner | +| MCP Token | DB row: token ID → agent session ID | Token abc123 → Session S-42 | +| MCP Scope | DB row: session → work item → allowed permissions | S-42 → WI-17 → [thread.post, workitem.read] | + +### v1 Simplifications + +- No OIDC/SSO, just username/password +- Service tokens are static config, rotated manually + +## Crate & Repository Structure + +### Workspace Layout + +``` +anima/ +├── proto/ # Protobuf definitions +│ └── anima/v1/ # Versioned API +│ ├── project.proto +│ ├── plan.proto +│ ├── workitem.proto +│ ├── workflow.proto +│ ├── thread.proto +│ ├── agent.proto +│ ├── repository.proto +│ ├── mailbox.proto +│ ├── document.proto +│ ├── akh.proto +│ ├── team.proto +│ ├── dashboard.proto +│ └── ai.proto # Internal: anima-server → anima-ai +│ +├── crates/ +│ ├── anima-core/ # Domain types, RBAC, shared logic +│ ├── anima-db/ # PostgreSQL migrations, queries (sqlx) +│ ├── anima-proto/ # Generated protobuf code (tonic-build) +│ ├── anima-server/ # Main server binary + embedded MCP +│ ├── anima-mail/ # Mail worker binary +│ ├── anima-agent/ # Agent manager binary +│ ├── anima-ai/ # AI inference service binary +│ └── anima-desktop/ # Slint desktop client +│ +├── docs/ +│ └── superpowers/specs/ # Design specs +│ +├── main.pen # Penpot design file +├── projectbrief.txt # Project brief +├── Cargo.toml # Workspace root +└── README.md +``` + +### Crate Dependencies + +| Crate | Type | Depends On | +|-------|------|------------| +| **anima-core** | lib | — | +| **anima-proto** | lib | anima-core | +| **anima-db** | lib | anima-core | +| **anima-server** | bin | anima-core, anima-proto, anima-db | +| **anima-mail** | bin | anima-proto, anima-core | +| **anima-agent** | bin | anima-proto, anima-core | +| **anima-ai** | bin | anima-proto, anima-core | +| **anima-desktop** | bin | anima-proto, anima-core | + +### Key Rust Dependencies + +- **tonic** / **prost** — gRPC server & client, protobuf +- **sqlx** — async PostgreSQL with compile-time query checking +- **slint** — desktop UI +- **tokio** — async runtime +- **jmap-client** or custom — JMAP protocol for Stalwart + +## Forge Integration + +- **Read-only** forge API integration for GitHub, Gitea, GitLab +- Pull PR/merge request metadata, link to work items +- Issue migration path: import existing issues as work items +- **Anima owns work items** — no dual issue tracking on forges +- Git operations (clone, commit, push) only happen inside agent VMs (heavy work) +- Patches and documents are attachments stored in Seshat's Library for AI ingestion +- AI reads forge data via MCP when needed during agent sessions