Skip to content

Commit e74fcc9

Browse files
committed
docs(architecture): add crates/memory to architecture spec
- Add memory crate to Layer 2 table, ASCII diagram, CC mapping - Add section 6.15 with full module/type/feature documentation - Update session section to reflect memory extraction - Renumber cli (6.17), daemon (6.18), global state (6.19)
1 parent c5964fb commit e74fcc9

3 files changed

Lines changed: 59 additions & 2941 deletions

File tree

docs/architecture.md

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Crab Code Architecture
22

3-
> Version: v2.1
4-
> Updated: 2026-04-06
3+
> Version: v2.2
4+
> Updated: 2026-04-14
55
66
---
77

@@ -13,7 +13,7 @@
1313
|-------|-------|----------------|
1414
| **Layer 4** Entry Layer | `crates/cli` `crates/daemon` | CLI entry point (clap), background daemon |
1515
| **Layer 3** Engine Layer | `agent` `session` | Multi-Agent orchestration, session management, context compaction |
16-
| **Layer 2** Service Layer | `tools` `mcp` `api` `fs` `process` `plugin` `skill` `telemetry` `tui` | Tool system, MCP protocol stack, multi-model API client, file/process operations, skill system, TUI components |
16+
| **Layer 2** Service Layer | `tools` `mcp` `api` `fs` `process` `plugin` `skill` `memory` `telemetry` `tui` | Tool system, MCP protocol stack, multi-model API client, file/process operations, skill system, persistent memory, TUI components |
1717
| **Layer 1** Foundation Layer | `core` `common` `config` `auth` | Domain model, config hot reload, authentication |
1818

1919
> Dependency direction: upper layers depend on lower layers; reverse dependencies are prohibited. `core` defines the `Tool` trait to avoid circular dependencies between tools/agent.
@@ -45,12 +45,12 @@
4545
│ │in │ │ │ │ │ │ │ │ │ │
4646
│ └┬────┬─┘ └───────┘ └────┘ └──────────┘ └────────────┘ │
4747
│ │ │ │
48-
│ ┌▼──┐ ┌▼──────┐ ┌──────┐ ┌──────┐
49-
│ │fs │ │process │ │plugin│ │skill │
50-
│ │glob│ │sub- │ │hooks │ │regis-│
51-
│ │grep│ │process│ │WASM │ │try + │
52-
│ │ │ │signal │ │MCP↔ │ │built-│
53-
│ └───┘ └───────┘ └──────┘ └──────┘
48+
│ ┌▼──┐ ┌▼──────┐ ┌──────┐ ┌──────┐ ┌──────┐
49+
│ │fs │ │process │ │plugin│ │skill │ │memory│
50+
│ │glob│ │sub- │ │hooks │ │regis-│ │store │
51+
│ │grep│ │process│ │WASM │ │try + │ │rank │
52+
│ │ │ │signal │ │MCP↔ │ │built-│ │age
53+
│ └───┘ └───────┘ └──────┘ └──────┘ └──────┘
5454
├───────────────────────────────────────────────────────────────────┤
5555
│ Layer 1: Foundation Layer │
5656
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
@@ -70,14 +70,14 @@
7070
| **Entry Layer** entrypoints/ | `cli.tsx` `main.tsx` | `crates/cli` `crates/daemon` | CC uses React/Ink for rendering, Crab uses ratatui |
7171
| **Command Layer** commands/ | `query.ts` `QueryEngine.ts` | `agent` + `session` | CC's query loop maps to agent orchestration |
7272
| **Tool Layer** tools/ | 52 Tool directories | `tools` + `mcp` | CC mixes tools and MCP in services/; Crab separates them |
73-
| **Service Layer** services/ | `api/` `mcp/` `oauth/` `compact/` | `api` `mcp` `auth` `skill` `plugin` `telemetry` | CC's service layer is flat; Crab splits by responsibility |
73+
| **Service Layer** services/ | `api/` `mcp/` `oauth/` `compact/` `memdir/` | `api` `mcp` `auth` `skill` `plugin` `memory` `telemetry` | CC's service layer is flat; Crab splits by responsibility. CC's `memdir/` maps to `memory` |
7474
| **Foundation Layer** utils/ types/ | `Tool.ts` `context.ts` | `core` `common` `config` | CC scatters types across files; Crab centralizes them in core |
7575

7676
### Core Design Philosophy
7777

7878
1. **core has zero I/O** -- Pure data structures and trait definitions, reusable by any frontend (CLI/GUI/WASM)
7979
2. **Message loop driven** -- Everything revolves around the query loop: user input -> API call -> tool execution -> result return
80-
3. **Workspace isolation** -- 16 library crates with orthogonal responsibilities (~190 modules); incremental compilation only triggers on changed parts
80+
3. **Workspace isolation** -- 17 library crates with orthogonal responsibilities; incremental compilation only triggers on changed parts
8181
4. **Feature flags control dependencies** -- No Bedrock? AWS SDK is not compiled. No WASM? wasmtime is not compiled.
8282

8383
---
@@ -2337,20 +2337,21 @@ impl ToolExecutor {
23372337

23382338
### 6.10 `crates/session/` -- Session Management
23392339

2340-
**Responsibility**: State management for multi-turn conversations (corresponds to CC `src/services/compact/` + `src/services/SessionMemory/` + `src/services/sessionTranscript/`)
2340+
**Responsibility**: State management for multi-turn conversations (corresponds to CC `src/services/compact/` + `src/services/SessionMemory/` + `src/services/sessionTranscript/`). Memory system extracted to `crates/memory/`; session re-exports core memory types.
23412341

23422342
**Directory Structure**
23432343

23442344
```
23452345
src/
23462346
├── lib.rs
2347-
├── conversation.rs // Conversation state machine, multi-turn management
2348-
├── context.rs // Context window management, auto-compaction trigger
2349-
├── compaction.rs // Message compaction strategies (5 levels: Snip/Microcompact/Summarize/Hybrid/Truncate)
2350-
├── history.rs // Session persistence, recovery, search, export, statistics
2351-
├── memory.rs // Memory system (file persistence)
2352-
├── cost.rs // Token counting, cost tracking
2353-
└── template.rs // Session template + quick recovery
2347+
├── conversation.rs // Conversation state machine, multi-turn management
2348+
├── context.rs // Context window management, auto-compaction trigger
2349+
├── compaction.rs // Message compaction strategies (5 levels: Snip/Microcompact/Summarize/Hybrid/Truncate)
2350+
├── history.rs // Session persistence, recovery, search, export, statistics
2351+
├── memory.rs // Re-exports from crab-memory (MemoryStore, MemoryFile, etc.)
2352+
├── memory_extract.rs // Conversation → memory extraction (heuristic, depends on crab-core::Message)
2353+
├── cost.rs // Token counting, cost tracking
2354+
└── template.rs // Session template + quick recovery
23542355
```
23552356

23562357
**Core Types**
@@ -3193,7 +3194,42 @@ wasm = ["wasmtime"]
31933194

31943195
---
31953196

3196-
### 6.15 `crates/telemetry/` -- Observability
3197+
### 6.15 `crates/memory/` -- Persistent Memory System
3198+
3199+
**Responsibility**: File-based cross-session memory storage — user preferences, feedback, project context, external references (corresponds to CC `src/memdir/`)
3200+
3201+
**Directory Structure**
3202+
3203+
```
3204+
src/
3205+
├── lib.rs // Public API re-exports
3206+
├── types.rs // MemoryType enum, MemoryMetadata, frontmatter parsing
3207+
├── store.rs // MemoryStore — file CRUD + mtime-sorted scan
3208+
├── index.rs // MEMORY.md index read/write + truncation (200 lines / 25KB)
3209+
├── relevance.rs // MemorySelector keyword scoring + MemoryRanker trait
3210+
├── age.rs // Exponential decay scoring (30-day half-life, SystemTime)
3211+
├── paths.rs // Per-project / global / team memory directory resolution
3212+
├── security.rs // Path traversal / symlink / null byte validation
3213+
├── prompt.rs // MemoryPromptBuilder — system prompt injection
3214+
├── team.rs // TeamMemoryStore — shared team memory with slugified filenames
3215+
└── ranker.rs // LlmMemoryRanker — Sonnet sidequery (feature = "mem-ranker")
3216+
```
3217+
3218+
**External Dependencies**: `crab-common`, `serde`, `serde_json`, `serde_yml`, `dunce`. Optional: `crab-api`, `crab-core`, `tokio` (with `mem-ranker` feature)
3219+
3220+
**Feature Flags**
3221+
3222+
```toml
3223+
[features]
3224+
default = []
3225+
mem-ranker = ["dep:crab-api", "dep:crab-core", "dep:tokio"] # LLM-driven memory selection
3226+
```
3227+
3228+
**Key Types**: `MemoryType` (User/Feedback/Project/Reference), `MemoryMetadata`, `MemoryFile`, `MemoryStore`, `MemorySelector`, `MemoryRanker` (trait), `LlmMemoryRanker` (impl, feature-gated), `MemoryPromptBuilder`, `TeamMemoryStore`
3229+
3230+
---
3231+
3232+
### 6.16 `crates/telemetry/` -- Observability
31973233

31983234
**Responsibility**: Distributed tracing and metrics collection (corresponds to CC `src/services/analytics/` + `src/services/diagnosticTracking.ts`)
31993235

@@ -3264,7 +3300,7 @@ otlp = [ # OpenTelemetry O
32643300
32653301
---
32663302

3267-
### 6.15 `crates/cli/` -- Terminal Entry Point
3303+
### 6.17 `crates/cli/` -- Terminal Entry Point
32683304

32693305
**Responsibility**: An extremely thin binary entry point that only does assembly with no business logic (corresponds to CC `src/entrypoints/cli.tsx`)
32703306

@@ -3402,7 +3438,7 @@ full = ["tui", "crab-plugin/wasm", "crab-api/bedrock", "crab-api/vertex"]
34023438

34033439
---
34043440

3405-
### 6.16 `crates/daemon/` -- Background Daemon
3441+
### 6.18 `crates/daemon/` -- Background Daemon
34063442

34073443
**Responsibility**: A persistently running background daemon that manages multiple sessions (corresponds to CC `src/daemon/`)
34083444

@@ -3528,7 +3564,7 @@ async fn main() -> anyhow::Result<()> {
35283564

35293565
---
35303566

3531-
### 6.17 Global State Split: AppConfig / AppRuntime
3567+
### 6.19 Global State Split: AppConfig / AppRuntime
35323568

35333569
Global state shared by CLI and Daemon is split into **immutable configuration** and **mutable runtime** halves,
35343570
avoiding a single `Arc<RwLock<AppState>>` where read paths get blocked by write locks.

0 commit comments

Comments
 (0)