# Architecture

## Plugin Architecture

QuidClaw is a Claude Code Plugin with 5 component types:

```
┌──────────────────────────────────────────────┐
│  Claude Code / Claude Coworker               │
├──────────────────────────────────────────────┤
│  Plugin Layer                                │
│  ├── Skills (7)    — AI workflows            │
│  ├── Agents (2)    — Specialized subagents   │
│  ├── Hooks  (1)    — SessionStart inbox check│
│  └── MCP Server    — 16 tools, 2 resources   │
├──────────────────────────────────────────────┤
│  core/             (pure business logic)     │
│  ├── ledger.py     — Beancount read/write    │
│  ├── accounts.py   — Account CRUD            │
│  ├── transactions.py — Transaction recording │
│  ├── balance.py    — Balance queries         │
│  ├── reports.py    — BQL & reports           │
│  ├── prices.py     — Price directives        │
│  ├── init.py       — Ledger initialization   │
│  ├── inbox.py      — Inbox file management   │
│  ├── notes.py      — Financial knowledge base│
│  └── anomaly.py    — Anomaly detection       │
├──────────────────────────────────────────────┤
│  Beancount V3 + beanquery + beanprice        │
├──────────────────────────────────────────────┤
│  <project-dir>/  (user data directory)         │
│  ├── ledger/   — Clean .bean files           │
│  ├── inbox/    — User drops files here       │
│  ├── documents/— Organized archive           │
│  ├── notes/    — Financial knowledge base    │
│  └── reports/  — Generated reports           │
└──────────────────────────────────────────────┘
```

## Key Principle

`core/` has zero MCP dependency. Every financial operation is a plain Python function. The `mcp_server/` layer is a thin adapter. Skills and Agents orchestrate these tools via AI.

## Component Collaboration

```
User drops files into inbox/
       |
[Hook: SessionStart] detects new files, notifies user
       |
[Skill: import-bills] initiates import workflow
       |
[Agent: bill-parser] parses file contents, extracts transactions
       |
[MCP Tool: add_transaction] writes to ledger (with dedup)
[Skill: organize-documents] organizes source file
       |
[Skill: financial-memory] captures key info into notes/
```

## Data Flow

```
User: "Lunch was ¥45, paid with WeChat"
  → AI understands: Expenses:Food 45 CNY from Assets:WeChat
  → AI calls MCP tool: add_transaction(...)
  → tools.py: converts params, calls TransactionManager.add_transaction()
  → transactions.py: writes to <project-dir>/ledger/2026/2026-03.bean
  → Beancount validates on next load()
```

## Data Directory Structure

```
<project-dir>/
├── ledger/                # Beancount ledger (clean, structured)
│   ├── main.bean          #   option + include directives only
│   ├── accounts.bean      #   Open/Close directives
│   ├── prices.bean        #   Price directives
│   └── YYYY/YYYY-MM.bean  #   Transactions by month
├── inbox/                 # Drop zone (user puts files here)
├── documents/             # Organized archive (AI-managed)
│   └── YYYY/MM/           #   Named: {Source}-{Type}-{YYYY-MM}.{ext}
├── notes/                 # Financial knowledge base (AI-managed)
│   ├── profile.md         #   User profile (living)
│   ├── calendar.md        #   Payment calendar (living)
│   ├── assets/            #   Property, vehicles, investments (living)
│   ├── liabilities/       #   Loans, debts (living)
│   ├── insurance/         #   Policy details (living)
│   ├── accounts/          #   Bank/card details (living)
│   ├── subscriptions/     #   Recurring charges (living)
│   ├── income/            #   Income sources (living)
│   ├── decisions/         #   Decision log (append-only)
│   └── journal/           #   Conversation captures (append-only)
└── reports/               # Generated reports (AI-managed)
```

## Testing Architecture

Three layers:

| Layer | What | How | Speed |
|-------|------|-----|-------|
| **Core** | Python business logic | `pytest tests/core/` | Fast, free |
| **MCP** | Tool interface | `pytest tests/mcp_server/` | Fast, free |
| **E2E** | Full AI workflow | `pytest tests/e2e/ -m e2e` | Slow, uses API |

E2E tests run `claude -p` with the plugin, then verify resulting data state (ledger entries, file locations, balances) — not AI text output.
