From 41acc805d17a311c15ea5c13853c92c97c69acc2 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sun, 22 Feb 2026 12:08:12 +0100 Subject: [PATCH] Replace ASCII diagrams with SVG images - Create Mermaid source files for all diagrams - Generate SVGs using mermaid-cli - Replace all ASCII art with embedded SVG images - Diagrams: architecture, sandbox-config, session-lifecycle, crash-recovery, client-interactions, mailbox-flow, automation-workflow, events - Fixes alignment issues with ASCII box drawing characters --- EVENTS.md | 15 +-- README.md | 172 ++------------------------ docs/diagrams/architecture.mmd | 30 +++++ docs/diagrams/architecture.svg | 1 + docs/diagrams/automation-workflow.mmd | 17 +++ docs/diagrams/automation-workflow.svg | 1 + docs/diagrams/client-interactions.mmd | 9 ++ docs/diagrams/client-interactions.svg | 1 + docs/diagrams/crash-recovery.mmd | 10 ++ docs/diagrams/crash-recovery.svg | 1 + docs/diagrams/events.mmd | 9 ++ docs/diagrams/events.svg | 1 + docs/diagrams/mailbox-flow.mmd | 17 +++ docs/diagrams/mailbox-flow.svg | 1 + docs/diagrams/sandbox-config.mmd | 11 ++ docs/diagrams/sandbox-config.svg | 1 + docs/diagrams/session-lifecycle.mmd | 16 +++ docs/diagrams/session-lifecycle.svg | 1 + 18 files changed, 135 insertions(+), 179 deletions(-) create mode 100644 docs/diagrams/architecture.mmd create mode 100644 docs/diagrams/architecture.svg create mode 100644 docs/diagrams/automation-workflow.mmd create mode 100644 docs/diagrams/automation-workflow.svg create mode 100644 docs/diagrams/client-interactions.mmd create mode 100644 docs/diagrams/client-interactions.svg create mode 100644 docs/diagrams/crash-recovery.mmd create mode 100644 docs/diagrams/crash-recovery.svg create mode 100644 docs/diagrams/events.mmd create mode 100644 docs/diagrams/events.svg create mode 100644 docs/diagrams/mailbox-flow.mmd create mode 100644 docs/diagrams/mailbox-flow.svg create mode 100644 docs/diagrams/sandbox-config.mmd create mode 100644 docs/diagrams/sandbox-config.svg create mode 100644 docs/diagrams/session-lifecycle.mmd create mode 100644 docs/diagrams/session-lifecycle.svg diff --git a/EVENTS.md b/EVENTS.md index 4233205..c878d8f 100644 --- a/EVENTS.md +++ b/EVENTS.md @@ -4,20 +4,7 @@ The events system provides a real-time text stream of all AnviLLM activity using ## Architecture -``` - ┌─────────────────┐ - │ agent/events │ - │ (event stream) │ - └────────┬────────┘ - │ - ┌──────────────┼──────────────┐ - │ │ │ - ▼ ▼ ▼ - ┌──────────────┐ ┌──────────┐ ┌────────────┐ - │ Notification │ │ Logger │ │ etc. │ - │ │ │ (audit) │ │ │ - └──────────────┘ └──────────┘ └────────────┘ -``` +![Events System](diagrams/events.svg) Multiple clients can read from `agent/events` simultaneously, each consuming the same event stream for different purposes: notifications (desktop, SMS, WhatsApp), logging/auditing, custom integrations, etc. diff --git a/README.md b/README.md index f488dad..a73c6f4 100644 --- a/README.md +++ b/README.md @@ -4,38 +4,7 @@ LLM orchestrator using 9P — scriptable, multi-backend, crash-resilient ## Architecture -``` -┌─────────────────────────────────────────────────────────────┐ -│ Clients │ -│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ -│ │ Assist │ │ TUI │ │ Emacs │ │ Web │ │ -│ │ (Acme) │ │ │ │ │ │ │ │ -│ └───┬────┘ └───┬────┘ └───┬────┘ └───┬────┘ │ -└──────┼───────────┼───────────┼───────────┼────────────────┘ - │ │ │ │ - └───────────┴───────────┴───────────┘ - │ 9P - ┌───────────────┴───────────────┐ - │ │ -┌──────▼──────────────────────────────────────────────────────┐ -│ Core Services │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ anvilsrv │ │ anvilmcp │ │anvilwebgw│ │ -│ │(9P daemon) │(MCP server) │(API proxy)│ │ -│ └─────┬────┘ └──────────┘ └──────────┘ │ -└────────┼───────────────────────────────────────────────────┘ - │ - ┌────┴────┬────────┐ - │ │ │ -┌───▼───┐ ┌──▼────┐ ┌─▼─────┐ -│ Claude│ │ Kiro │ │ ollie │ -└───────┘ └───────┘ └───┬───┘ - │ - ┌───▼────┐ - │ Ollama │ - └────────┘ - Backends -``` +![Architecture](docs/diagrams/architecture.svg) **Core:** anvilsrv (9P daemon), anvilmcp (MCP server), anvilwebgw (API proxy) **Clients:** Assist (Acme), anvillm.el (Emacs), anvillm (TUI), anvilweb (web) @@ -151,26 +120,7 @@ Templates use `{VARNAME}` syntax. Any environment variable can be referenced. **Config** (`~/.config/anvillm/`): Layered YAML files, most permissive wins: -``` -┌─────────────────┐ -│ global.yaml │ Base configuration -└────────┬────────┘ - │ (override) -┌────────▼────────┐ -│ backends/*.yaml │ Backend-specific -└────────┬────────┘ - │ (override) -┌────────▼────────┐ -│ roles/*.yaml │ Role-specific (default: roles/default.yaml) -└────────┬────────┘ - │ (override) -┌────────▼────────┐ -│ tasks/*.yaml │ Task-specific -└────────┬────────┘ - │ - ▼ - Final Config (most permissive wins) -``` +![Sandbox Config Layering](docs/diagrams/sandbox-config.svg) - Default role: `roles/default.yaml` @@ -186,43 +136,13 @@ Set `best_effort: true` for unsandboxed fallback (⚠️ if no Landlock support) **Session lifecycle:** -``` - ┌─────────────────────────┐ - │ │ - │ ┌──────────┐ │ - │ │ starting │ │ - │ └─────┬────┘ │ - │ │ │ - │ ▼ │ - │ ┌─────────┐ │ - └────►│ idle │◄────┐ │ - └────┬────┘ │ │ - │ │ │ - │ userPromptSubmit hook - │ (user sends prompt) - │ │ │ - ▼ │ │ - ┌─────────┐ │ │ - │ running │ │ │ - └────┬────┘ │ │ - │ │ │ - │ stop hook│ │ - │ (agent finishes) - │ │ │ - └──────────┘ │ - │ │ - │ crash │ - ▼ │ - ┌───────┐ restart │ - │ error │───────────┘ - └───────┘ -``` +![Session Lifecycle](docs/diagrams/session-lifecycle.svg) State transitions: `idle` ↔ `running` cycle via CLI hooks (`userPromptSubmit` when user sends prompt, `stop` when agent finishes). Crash → `error` → auto-restart → `starting`. Note: any state can transition to `stopped` or `killed` (not shown); `stopped` can restart → `starting`. **Self-healing:** Auto-restarts crashes every 5s (preserves context/alias/cwd), skips intentional stops -``` +![Crash Recovery](docs/diagrams/crash-recovery.svg) ┌─────────┐ crash ┌─────────┐ 5s wait ┌─────────┐ │ running │─────────►│ error │──────────►│ running │ └─────────┘ └─────────┘ └─────────┘ @@ -308,21 +228,7 @@ agent/ **Client Interactions:** -``` -┌─────────┐ ┌─────────┐ ┌─────────┐ -│ Assist │ │ TUI │ │ Script │ -└────┬────┘ └────┬────┘ └────┬────┘ - │ │ │ - │ 9p read │ 9p write │ 9p read - │ agent/list │ agent/ctl │ agent/events - │ │ │ - └───────────────────┴───────────────────┘ - │ - ┌────▼────┐ - │ agent/ │ - │ (9P fs) │ - └─────────┘ -``` +![Client Interactions](docs/diagrams/client-interactions.svg) Different clients interact with different parts of the filesystem: frontends read state, control files manage sessions, scripts consume events. @@ -345,43 +251,7 @@ Config: `~/.beads/` (override: `ANVILLM_BEADS_PATH`) — Shared across namespace **Mailbox Flow:** -``` -User writes to Agent A: - echo '{"to":"agent-a",...}' | 9p write user/mail - │ - ▼ - [mailbox system] - │ - ▼ - agent-a/inbox (Agent A reads) - -Agent A writes to Agent B: - echo '{"to":"agent-b",...}' | 9p write agent/agent-a/mail - │ - ▼ - [mailbox system] - │ - ▼ - agent-b/inbox (Agent B reads) - -Agent B replies to Agent A: - echo '{"to":"agent-a",...}' | 9p write agent/agent-b/mail - │ - ▼ - [mailbox system] - │ - ▼ - agent-a/inbox (Agent A reads) - -Agent B replies to User: - echo '{"to":"user",...}' | 9p write agent/agent-b/mail - │ - ▼ - [mailbox system] - │ - ▼ - user/inbox (User reads) -``` +![Mailbox Flow](docs/diagrams/mailbox-flow.svg) Cross-backend communication: messages route between any participants (user, Claude agents, Kiro agents, Ollama agents) via the mailbox system. @@ -443,35 +313,7 @@ Templates set up context, roles, and initial configuration. Interact via any cli Automate workflows with Taskmaster and Conductor bots. Input project plan → Taskmaster creates tasks with dependencies → Conductor orchestrates parallel execution. -``` -┌──────────────┐ -│ Project Plan │ -└──────┬───────┘ - │ - ▼ -┌──────────────┐ ┌─────────────────────────────┐ -│ Taskmaster │────►│ Beads (dependency graph) │ -└──────────────┘ │ ┌─────────────────────┐ │ - │ │ Top-level bead ID │ │ - │ │ (represents project)│ │ - │ └──────────┬──────────┘ │ - └─────────────┼────────────────┘ - │ - ▼ - ┌──────────────────┐ - │ Conductor │ - │ (coordinates │ - │ dependencies) │ - └────────┬─────────┘ - │ - ┌───────────────┼───────────────┐ - │ │ │ - ▼ ▼ ▼ - ┌──────────┐ ┌──────────┐ ┌──────────┐ - │ Agent 1 │ │ Agent 2 │ │ Agent 3 │ - │ │ │ │ │ │ - └──────────┘ └──────────┘ └──────────┘ -``` +![Automation Workflow](docs/diagrams/automation-workflow.svg) Conductor receives the top-level bead ID, analyzes dependencies, and spawns agents to work in parallel. Agents notify Conductor when blocked; Conductor signals them to resume when dependencies resolve. diff --git a/docs/diagrams/architecture.mmd b/docs/diagrams/architecture.mmd new file mode 100644 index 0000000..ca4f090 --- /dev/null +++ b/docs/diagrams/architecture.mmd @@ -0,0 +1,30 @@ +graph TB + subgraph Clients + Assist["Assist
(Acme)"] + TUI["TUI"] + Emacs["Emacs"] + Web["Web"] + end + + subgraph Core["Core Services"] + anvilsrv["anvilsrv
(9P daemon)"] + anvilmcp["anvilmcp
(MCP server)"] + anvilwebgw["anvilwebgw
(API proxy)"] + end + + subgraph Backends + Claude["Claude"] + Kiro["Kiro"] + ollie["ollie"] + Ollama["Ollama"] + end + + Assist -->|9P| anvilsrv + TUI -->|9P| anvilsrv + Emacs -->|9P| anvilsrv + Web -->|9P| anvilsrv + + anvilsrv --> Claude + anvilsrv --> Kiro + anvilsrv --> ollie + ollie --> Ollama diff --git a/docs/diagrams/architecture.svg b/docs/diagrams/architecture.svg new file mode 100644 index 0000000..0265572 --- /dev/null +++ b/docs/diagrams/architecture.svg @@ -0,0 +1 @@ +

Backends

Core Services

Clients

9P

9P

9P

9P

Assist
(Acme)

TUI

Emacs

Web

anvilsrv
(9P daemon)

anvilmcp
(MCP server)

anvilwebgw
(API proxy)

Claude

Kiro

ollie

Ollama

\ No newline at end of file diff --git a/docs/diagrams/automation-workflow.mmd b/docs/diagrams/automation-workflow.mmd new file mode 100644 index 0000000..824ff62 --- /dev/null +++ b/docs/diagrams/automation-workflow.mmd @@ -0,0 +1,17 @@ +graph TB + Plan["Project Plan"] + Taskmaster["Taskmaster"] + Beads["Beads
(dependency graph)"] + TopBead["Top-level bead ID
(represents project)"] + Conductor["Conductor
(coordinates dependencies)"] + Agent1["Agent 1"] + Agent2["Agent 2"] + Agent3["Agent 3"] + + Plan --> Taskmaster + Taskmaster --> Beads + Beads --> TopBead + TopBead --> Conductor + Conductor --> Agent1 + Conductor --> Agent2 + Conductor --> Agent3 diff --git a/docs/diagrams/automation-workflow.svg b/docs/diagrams/automation-workflow.svg new file mode 100644 index 0000000..fad9e67 --- /dev/null +++ b/docs/diagrams/automation-workflow.svg @@ -0,0 +1 @@ +

Project Plan

Taskmaster

Beads
(dependency graph)

Top-level bead ID
(represents project)

Conductor
(coordinates dependencies)

Agent 1

Agent 2

Agent 3

\ No newline at end of file diff --git a/docs/diagrams/client-interactions.mmd b/docs/diagrams/client-interactions.mmd new file mode 100644 index 0000000..0cff313 --- /dev/null +++ b/docs/diagrams/client-interactions.mmd @@ -0,0 +1,9 @@ +graph TB + Assist["Assist"] + TUI["TUI"] + Script["Script"] + FS["agent/
(9P filesystem)"] + + Assist -->|9p read
agent/list| FS + TUI -->|9p write
agent/ctl| FS + Script -->|9p read
agent/events| FS diff --git a/docs/diagrams/client-interactions.svg b/docs/diagrams/client-interactions.svg new file mode 100644 index 0000000..3acaa77 --- /dev/null +++ b/docs/diagrams/client-interactions.svg @@ -0,0 +1 @@ +

9p read
agent/list

9p write
agent/ctl

9p read
agent/events

Assist

TUI

Script

agent/
(9P filesystem)

\ No newline at end of file diff --git a/docs/diagrams/crash-recovery.mmd b/docs/diagrams/crash-recovery.mmd new file mode 100644 index 0000000..7e5fd3b --- /dev/null +++ b/docs/diagrams/crash-recovery.mmd @@ -0,0 +1,10 @@ +graph LR + running1[running] + error[error] + running2[running] + state[context
alias
cwd
conversation] + + running1 -->|crash| error + error -->|preserves| state + state -->|restored +
auto-resume| running2 + error -->|5s wait| running2 diff --git a/docs/diagrams/crash-recovery.svg b/docs/diagrams/crash-recovery.svg new file mode 100644 index 0000000..905a912 --- /dev/null +++ b/docs/diagrams/crash-recovery.svg @@ -0,0 +1 @@ +

crash

preserves

restored +
auto-resume

5s wait

running

error

running

context
alias
cwd
conversation

\ No newline at end of file diff --git a/docs/diagrams/events.mmd b/docs/diagrams/events.mmd new file mode 100644 index 0000000..cb8c975 --- /dev/null +++ b/docs/diagrams/events.mmd @@ -0,0 +1,9 @@ +graph TB + events["agent/events
(event stream)"] + notif["Notification"] + logger["Logger
(audit)"] + etc["etc."] + + events --> notif + events --> logger + events --> etc diff --git a/docs/diagrams/events.svg b/docs/diagrams/events.svg new file mode 100644 index 0000000..97c77db --- /dev/null +++ b/docs/diagrams/events.svg @@ -0,0 +1 @@ +

agent/events
(event stream)

Notification

Logger
(audit)

etc.

\ No newline at end of file diff --git a/docs/diagrams/mailbox-flow.mmd b/docs/diagrams/mailbox-flow.mmd new file mode 100644 index 0000000..c4e2140 --- /dev/null +++ b/docs/diagrams/mailbox-flow.mmd @@ -0,0 +1,17 @@ +sequenceDiagram + participant User + participant Mailbox as Mailbox System + participant AgentA as Agent A (Claude) + participant AgentB as Agent B (Kiro) + + User->>Mailbox: write user/mail
{"to":"agent-a",...} + Mailbox->>AgentA: agent-a/inbox + + AgentA->>Mailbox: write agent/agent-a/mail
{"to":"agent-b",...} + Mailbox->>AgentB: agent-b/inbox + + AgentB->>Mailbox: write agent/agent-b/mail
{"to":"agent-a",...} + Mailbox->>AgentA: agent-a/inbox + + AgentB->>Mailbox: write agent/agent-b/mail
{"to":"user",...} + Mailbox->>User: user/inbox diff --git a/docs/diagrams/mailbox-flow.svg b/docs/diagrams/mailbox-flow.svg new file mode 100644 index 0000000..b1561fa --- /dev/null +++ b/docs/diagrams/mailbox-flow.svg @@ -0,0 +1 @@ +Agent B (Kiro)Agent A (Claude)Mailbox SystemUserAgent B (Kiro)Agent A (Claude)Mailbox SystemUserwrite user/mail{"to":"agent-a",...}agent-a/inboxwrite agent/agent-a/mail{"to":"agent-b",...}agent-b/inboxwrite agent/agent-b/mail{"to":"agent-a",...}agent-a/inboxwrite agent/agent-b/mail{"to":"user",...}user/inbox \ No newline at end of file diff --git a/docs/diagrams/sandbox-config.mmd b/docs/diagrams/sandbox-config.mmd new file mode 100644 index 0000000..bc6a33d --- /dev/null +++ b/docs/diagrams/sandbox-config.mmd @@ -0,0 +1,11 @@ +graph TB + global["global.yaml
(Base configuration)"] + backends["backends/*.yaml
(Backend-specific)"] + roles["roles/*.yaml
(Role-specific)
default: roles/default.yaml"] + tasks["tasks/*.yaml
(Task-specific)"] + final["Final Config
(most permissive wins)"] + + global -->|override| backends + backends -->|override| roles + roles -->|override| tasks + tasks --> final diff --git a/docs/diagrams/sandbox-config.svg b/docs/diagrams/sandbox-config.svg new file mode 100644 index 0000000..77479e5 --- /dev/null +++ b/docs/diagrams/sandbox-config.svg @@ -0,0 +1 @@ +

override

override

override

global.yaml
(Base configuration)

backends/*.yaml
(Backend-specific)

roles/*.yaml
(Role-specific)
default: roles/default.yaml

tasks/*.yaml
(Task-specific)

Final Config
(most permissive wins)

\ No newline at end of file diff --git a/docs/diagrams/session-lifecycle.mmd b/docs/diagrams/session-lifecycle.mmd new file mode 100644 index 0000000..c541ed2 --- /dev/null +++ b/docs/diagrams/session-lifecycle.mmd @@ -0,0 +1,16 @@ +stateDiagram-v2 + [*] --> starting + starting --> idle + starting --> error + + idle --> running: userPromptSubmit hook
(user sends prompt) + running --> idle: stop hook
(agent finishes) + + running --> error: crash + error --> starting: restart + + note right of idle + Any state can transition to + stopped or killed (not shown) + stopped can restart → starting + end note diff --git a/docs/diagrams/session-lifecycle.svg b/docs/diagrams/session-lifecycle.svg new file mode 100644 index 0000000..177f61d --- /dev/null +++ b/docs/diagrams/session-lifecycle.svg @@ -0,0 +1 @@ +

userPromptSubmit hook
(user sends prompt)

stop hook
(agent finishes)

crash

restart

starting

idle

error

running

Any state can transition to
stopped or killed (not shown)
stopped can restart → starting

\ No newline at end of file