Architecture
Four layers, and one rule that shapes all of them: the domain core has no Tauri dependency, so the same operations layer serves the desktop app and the MCP hub.
One agent call, drawn
Section titled “One agent call, drawn”
The drawing follows one hub call from the agent’s terminal down to disk. It leaves two things out on purpose: the app’s own write path — the UI reaches the same core through Tauri IPC, not through the hub — and cross-workspace delivery, which is covered in Teams.
The layers
Section titled “The layers”The UI (React 19, TypeScript, i18n)
Section titled “The UI (React 19, TypeScript, i18n)”App-level views: Projects, Teams, Agent sessions, Templates, Settings.
Workspace-level views: Dashboard, Tasks, Collaboration, Inbox, Specs, Ledger, Search, Tools, Terminal, Project settings.
The folders under src/ are a layering rule rather than a filing preference, and a test enforces the machine-checkable part of it. CONTRIBUTING.md in the repository root has the table.
It talks to the layer below over Tauri IPC, which carries lightweight DTOs and state diffs only. Three event families come back the other way:
workspace://changed: reload state from diskledger://appended: read the new tail onlyterminal://output,terminal://exit,terminal://sessions
The delivery layer (src-tauri)
Section titled “The delivery layer (src-tauri)”Thin on purpose.
commands.rs: the IPC surface. Heavy I/O always goes throughspawn_blocking, so it never blocks the UI thread.watcher.rs: the file watcher behindworkspace://changed.terminal.rs: the embedded terminal, a real PTY process per agent CLI (portable-pty; ConPTY on Windows). Sessions belong to the app layer, so switching workspaces does not interrupt them.mcp_deploy.rs: resolves the bundled hub binary and writes the root.mcp.jsonpointer — also the “Repair connection” path.git.rs: optional git init for fresh workspaces — the wizard’s checkbox, shown only when git is available; best-effort, never fails creation.
The domain core (crates/aipos-core)
Section titled “The domain core (crates/aipos-core)”Zero Tauri dependencies, hexagonal.
agent.rs: hub tool authorisation, by tier and by the per-tool allowlist.security/: crypto (AES-GCM) and secrets (an encrypted local key-value store).workspace/: layout; atomic writes (temp + rename); the cross-process lock; tasks (files are the truth); the ledger (append-only JSONL); workflow (the harness state machine and its gates); templates; handoff (the checkpoint serialiser); sync (after every mutation, brings the takeover surfaces back up to date from one snapshot); bootstrap (writes the handoff layer); manifest; specs (folded on archive); modules; settings; doctor; assets (curriculum upgrade); registry; backup (portable zip); init; ops (the consistency layer); flywheel (post-mortem lessons under an evidence rule); ids (sequentialT-0001families, plus the UUIDs used for anything crossing workspaces); context; rules; teams; exchange;agent_catalog.index/: scanning, language-agnostic chunking, and an FTS5 full-text index. A derivative, so it can always be rebuilt.state.rs: thread-safe shared state.orchestrator/: dormant. AnLLMProviderport with adapters, a model registry and a cost router. Nothing in the app or the hub reaches it; groundwork only.mcp/: archived. An rmcp client, kept as groundwork for a future tool gateway.
The hub MCP server (crates/aipos-mcp)
Section titled “The hub MCP server (crates/aipos-mcp)”A stdio binary, spawned by the agent host through the workspace’s .mcp.json (the Claude CLI does this automatically; other hosts differ).
Its tool surface is one shape: authorise → core ops → ledger. Denied calls are recorded too.
Concurrency and live updates
Section titled “Concurrency and live updates”The app and the hub reach the same workspace files. An agent and the app can write concurrently and safely because every mutation takes the same cross-process lock, held for the duration of one mutation; read paths stay lock-free.
Seeing an agent’s change appear in your window is a separate mechanism: the file watcher emits workspace://changed, debounced by 400 ms, and the UI reloads from disk.
See also Disk contract for what all of this writes to disk.