docs: add VitePress documentation site

- 22 content pages across Guide, Concepts, and Reference sections
- Custom indigo/cyan theme with Lucide icons and Mermaid diagrams
- GitHub Actions workflow for GitHub Pages deployment
- Live preview: https://mempalace-docs.netlify.app/
This commit is contained in:
Igor Lins e Silva
2026-04-09 19:11:23 -03:00
parent 2981433535
commit dfb22f5345
37 changed files with 3673 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
# AAAK Dialect
AAAK is an experimental lossy abbreviation system designed to pack repeated entities and relationships into fewer tokens at scale. It is readable by any LLM — Claude, GPT, Gemini, Llama, Mistral — without a decoder.
::: warning Experimental
AAAK is a separate compression layer, **not the storage default**. The 96.6% benchmark score comes from raw verbatim mode. AAAK mode currently scores 84.2% R@5 — a 12.4 point regression. We're iterating.
:::
## What AAAK Is
- **Lossy, not lossless.** Uses regex-based abbreviation, not reversible compression.
- **A structured summary format.** Extracts entities, topics, key sentences, emotions, and flags from plain text.
- **Readable by any LLM.** No decoder needed — models read it naturally.
- **Designed for scale.** Saves tokens when the same entities appear hundreds of times.
## What AAAK Is Not
- **Not lossless compression.** The original text cannot be reconstructed.
- **Not efficient at small scale.** Short text already tokenizes efficiently — AAAK overhead costs more than it saves.
- **Not the default storage format.** MemPalace stores raw verbatim text in ChromaDB.
## Format
```
Header: FILE_NUM|PRIMARY_ENTITY|DATE|TITLE
Zettel: ZID:ENTITIES|topic_keywords|"key_quote"|WEIGHT|EMOTIONS|FLAGS
Tunnel: T:ZID<->ZID|label
Arc: ARC:emotion->emotion->emotion
```
### Entity Codes
Three-letter uppercase codes: `ALC=Alice`, `KAI=Kai`, `MAX=Max`.
### Emotion Codes
| Code | Meaning | Code | Meaning |
|------|---------|------|---------|
| `vul` | vulnerability | `joy` | joy |
| `fear` | fear | `trust` | trust |
| `grief` | grief | `wonder` | wonder |
| `rage` | rage | `love` | love |
| `hope` | hope | `despair` | despair |
| `peace` | peace | `humor` | humor |
| `tender` | tenderness | `raw` | raw honesty |
| `doubt` | self-doubt | `relief` | relief |
| `anx` | anxiety | `exhaust` | exhaustion |
### Flags
| Flag | Meaning |
|------|---------|
| `ORIGIN` | Origin moment (birth of something) |
| `CORE` | Core belief or identity pillar |
| `SENSITIVE` | Handle with absolute care |
| `PIVOT` | Emotional turning point |
| `GENESIS` | Led directly to something existing |
| `DECISION` | Explicit decision or choice |
| `TECHNICAL` | Technical architecture detail |
## Example
**Input:**
```
We decided to use GraphQL instead of REST because the frontend team needs
flexible queries. Kai recommended it after researching both options. The team
was excited about the schema-first approach.
```
**AAAK output:**
```
0:KAI|graphql_rest_decided|"decided to use GraphQL instead of REST"|determ+excite|DECISION+TECHNICAL
```
## Usage
### Compress drawers
```bash
# Preview compression
mempalace compress --wing myapp --dry-run
# Compress and store
mempalace compress --wing myapp
```
### With entity config
```bash
mempalace compress --wing myapp --config entities.json
```
Entity config format:
```json
{
"entities": {"Alice": "ALC", "Bob": "BOB"},
"skip_names": ["Gandalf", "Sherlock"]
}
```
### Python API
```python
from mempalace.dialect import Dialect
# Basic compression
dialect = Dialect()
compressed = dialect.compress("We decided to use GraphQL...")
# With entity mappings
dialect = Dialect(entities={"Alice": "ALC", "Kai": "KAI"})
compressed = dialect.compress(text, metadata={"wing": "myapp", "room": "arch"})
# From config file
dialect = Dialect.from_config("entities.json")
```
## When to Use AAAK
AAAK is most useful when:
- You have **many repeated entities** across thousands of sessions
- You need to **compress context** for local models with small windows
- You want **structured summaries** pointing back to verbatim drawers
For most users, raw verbatim mode is the better default.
+61
View File
@@ -0,0 +1,61 @@
# Specialist Agents
MemPalace currently supports **agent diaries** through MCP tools. The practical model is simple: give an agent a stable name, and write/read diary entries under that agent's wing.
::: warning Current Scope
This page documents the diary workflow that exists today. MemPalace does **not** currently ship an agent registry, `~/.mempalace/agents/*.json`, or a `mempalace_list_agents` tool.
:::
## What Agents Do
Each agent:
- **Has a focus** — what it pays attention to
- **Keeps a diary** — entries persist across sessions
- **Can read recent history** — useful for patterns, continuity, and follow-up work
## Agent Diary
The diary is a lightweight memory stream for one named agent: observations, findings, decisions, and recurring patterns.
### Writing Entries
```text
MCP tool: mempalace_diary_write
arguments: {
"agent_name": "reviewer",
"entry": "PR#42|auth.bypass.found|missing.middleware.check|pattern:3rd.time.this.quarter|★★★★"
}
```
### Reading History
```text
MCP tool: mempalace_diary_read
arguments: { "agent_name": "reviewer", "last_n": 10 }
→ returns last 10 findings, compressed in AAAK
```
### MCP Tools
| Tool | Description |
|------|-------------|
| `mempalace_diary_write` | Write an AAAK diary entry |
| `mempalace_diary_read` | Read recent diary entries |
## How It Works
Each named agent maps to its own wing in the palace:
- `wing_reviewer` — the reviewer's diary, findings, patterns
- `wing_architect` — the architect's decisions, tradeoffs
- `wing_ops` — the ops agent's incidents, deploys
All entries go into a `diary` room within the wing, tagged with topic, timestamp, and agent name.
## Specialization
Separate diary streams let you keep different working contexts apart. A reviewer can keep bug patterns, an architect can keep decisions, and an ops agent can keep incident notes without mixing them into one shared log.
::: tip
If you use multiple specialist prompts or toolchains, keep the agent names stable so each one writes back to the same diary wing over time.
:::
@@ -0,0 +1,33 @@
# Contradiction Detection
::: warning Experimental
Contradiction detection is a planned capability, not a shipped end-to-end feature in the current MCP workflow. The examples below show the intended behavior rather than a fully integrated command path.
:::
## What It Does
Checks assertions against entity facts in the knowledge graph. When enabled, it catches contradictions like:
```
Input: "Soren finished the auth migration"
Output: 🔴 AUTH-MIGRATION: attribution conflict — Maya was assigned, not Soren
Input: "Kai has been here 2 years"
Output: 🟡 KAI: wrong_tenure — records show 3 years (started 2023-04)
Input: "The sprint ends Friday"
Output: 🟡 SPRINT: stale_date — current sprint ends Thursday (updated 2 days ago)
```
## How It Works
Facts are checked against the knowledge graph:
- **Attribution conflicts** — the wrong person credited for a task
- **Temporal errors** — wrong dates, tenures, or durations
- **Stale information** — facts that have been superseded
Ages, dates, and tenures are calculated dynamically from the entity's recorded facts — not hardcoded.
## Status
The current codebase includes the temporal knowledge graph primitives needed for this direction, but not a complete contradiction-checking tool exposed through the CLI or MCP server.
+91
View File
@@ -0,0 +1,91 @@
# Knowledge Graph
MemPalace includes a temporal entity-relationship graph — like Zep's Graphiti, but SQLite instead of Neo4j. Local and free.
## What It Stores
Entity-relationship triples with temporal validity:
```
Subject → Predicate → Object [valid_from → valid_to]
```
Facts have time windows. When something stops being true, you invalidate it — and historical queries still find it.
## Usage
### Python API
```python
from mempalace.knowledge_graph import KnowledgeGraph
kg = KnowledgeGraph()
# Add facts
kg.add_triple("Kai", "works_on", "Orion", valid_from="2025-06-01")
kg.add_triple("Maya", "assigned_to", "auth-migration", valid_from="2026-01-15")
kg.add_triple("Maya", "completed", "auth-migration", valid_from="2026-02-01")
# Query: everything about Kai
kg.query_entity("Kai")
# → [Kai → works_on → Orion (current), Kai → recommended → Clerk (2026-01)]
# Query: what was true in January?
kg.query_entity("Maya", as_of="2026-01-20")
# → [Maya → assigned_to → auth-migration (active)]
# Timeline
kg.timeline("Orion")
# → chronological story of the project
```
### Invalidating Facts
When something stops being true:
```python
kg.invalidate("Kai", "works_on", "Orion", ended="2026-03-01")
```
Now queries for Kai's current work won't return Orion. Historical queries still will.
### MCP Tools
Through the MCP server, the knowledge graph is available as tools:
| Tool | Description |
|------|-------------|
| `mempalace_kg_query` | Query entity relationships with time filtering |
| `mempalace_kg_add` | Add facts |
| `mempalace_kg_invalidate` | Mark facts as ended |
| `mempalace_kg_timeline` | Chronological entity story |
| `mempalace_kg_stats` | Graph overview |
## Storage
The knowledge graph uses SQLite with two tables:
**`entities`** — people, projects, tools, concepts:
- `id` — lowercase normalized name
- `name` — display name
- `type` — person, project, tool, concept, etc.
- `properties` — JSON blob for extra metadata
**`triples`** — relationships between entities:
- `subject``predicate``object`
- `valid_from` — when this became true
- `valid_to` — when it stopped being true (NULL = still current)
- `confidence` — 0.0 to 1.0
- `source_closet` — link back to the verbatim memory
Database location: `~/.mempalace/knowledge_graph.sqlite3`
## Comparison
| Feature | MemPalace | Zep (Graphiti) |
|---------|-----------|----------------|
| Storage | SQLite (local) | Neo4j (cloud) |
| Cost | Free | $25/mo+ |
| Temporal validity | Yes | Yes |
| Self-hosted | Always | Enterprise only |
| Privacy | Everything local | SOC 2, HIPAA |
+104
View File
@@ -0,0 +1,104 @@
# Memory Stack
MemPalace uses a 4-layer memory stack. Each layer loads progressively more data only when needed.
## The Layers
| Layer | What | Size | When |
|-------|------|------|------|
| **L0** | Identity — who is this AI? | ~50-100 tokens | Always loaded |
| **L1** | Essential Story — top moments | ~500-800 tokens | Always loaded |
| **L2** | Room Recall — filtered retrieval | ~200500 each | When topic comes up |
| **L3** | Deep Search — full semantic query | Variable | When explicitly asked |
In the current implementation, a typical wake-up is roughly **~600-900 tokens** for L0 + L1. Searches only fire when needed.
## Layer 0: Identity
A plain text file at `~/.mempalace/identity.txt`. Always loaded as the AI's self-concept.
```text
I am Atlas, a personal AI assistant for Alice.
Traits: warm, direct, remembers everything.
People: Alice (creator), Bob (Alice's partner).
Project: A journaling app that helps people process emotions.
```
~50 tokens. Tells the AI who it is and who it works with.
## Layer 1: Essential Story
Auto-generated from the highest-importance drawers in the palace. Groups by room, picks the top moments, and keeps the output bounded.
The generation process:
1. Reads all drawers from ChromaDB
2. Scores each by importance/emotional weight
3. Takes the top 15 moments
4. Groups by room for readability
5. Truncates to fit within 3,200 characters
```
## L1 — ESSENTIAL STORY
[auth-migration]
- Team decided to migrate from Auth0 to Clerk — pricing + DX (session_2026-01-15.md)
- Kai debugged the OAuth token refresh issue (session_2026-01-20.md)
[deploy-process]
- Switched to blue-green deploys after the January outage (session_2026-02-01.md)
```
## Layer 2: On-Demand Recall
Loaded when a specific topic or wing comes up in conversation. Retrieves drawers filtered by wing and/or room — typically ~200500 tokens.
```python
stack = MemoryStack()
stack.recall(wing="driftwood", room="auth")
# → returns recent drawers about auth in the driftwood project
```
## Layer 3: Deep Search
Full semantic search against the entire palace. This is what fires when you or the AI explicitly asks a question.
```python
stack.search("why did we switch to GraphQL")
# → returns top-5 matching drawers with similarity scores
```
## Wake-Up Budget
The point of the stack is bounded startup context, not a fixed universal token count. The exact size depends on your identity file and what Layer 1 selects, but the implementation keeps wake-up meaningfully smaller than loading the full corpus into the prompt.
## Using the Stack
### CLI
```bash
# Wake-up context (L0 + L1)
mempalace wake-up
# Project-specific wake-up
mempalace wake-up --wing driftwood
```
### Python API
```python
from mempalace.layers import MemoryStack
stack = MemoryStack()
# L0 + L1: wake-up (~600-900 tokens in typical use)
print(stack.wake_up())
# L2: on-demand recall
print(stack.recall(wing="myapp"))
# L3: deep search
print(stack.search("pricing change"))
# Status
print(stack.status())
```
+110
View File
@@ -0,0 +1,110 @@
# The Palace
Ancient Greek orators memorized entire speeches by placing ideas in rooms of an imaginary building. Walk through the building, find the idea. MemPalace applies the same principle to AI memory.
## Structure
Your conversations are organized into a navigable hierarchy:
```mermaid
graph TD
subgraph wing_person["WING: Person"]
direction TB
RA["Room A"] -- hall --> RB["Room B"]
RA --> CA["Closet"]
CA --> DA["Drawer (verbatim)"]
end
subgraph wing_project["WING: Project"]
direction TB
RA2["Room A"] -- hall --> RC["Room C"]
RA2 --> CA2["Closet"]
CA2 --> DA2["Drawer (verbatim)"]
end
RA -.->|tunnel| RA2
style wing_person fill:#1e1b4b,stroke:#4f46e5,color:#e0e7ff
style wing_project fill:#164e63,stroke:#06b6d4,color:#cffafe
style RA fill:#312e81,stroke:#6366f1,color:#e0e7ff
style RB fill:#312e81,stroke:#6366f1,color:#e0e7ff
style CA fill:#3b0764,stroke:#8b5cf6,color:#f3e8ff
style DA fill:#0f766e,stroke:#14b8a6,color:#ccfbf1
style RA2 fill:#155e75,stroke:#22d3ee,color:#cffafe
style RC fill:#155e75,stroke:#22d3ee,color:#cffafe
style CA2 fill:#3b0764,stroke:#8b5cf6,color:#f3e8ff
style DA2 fill:#0f766e,stroke:#14b8a6,color:#ccfbf1
```
## Components
### Wings
A person or project. As many as you need.
Every project, person, or topic gets its own wing in the palace. Wings are the top-level organizational unit.
### Rooms
Specific topics within a wing. Examples: `auth-migration`, `graphql-switch`, `ci-pipeline`.
Rooms are named ideas. They're auto-detected from your folder structure during `mempalace init`, and you can create additional rooms manually.
### Halls
Halls are the conceptual categories that describe how related memories connect *within* a wing:
- `hall_facts` — decisions made, choices locked in
- `hall_events` — sessions, milestones, debugging
- `hall_discoveries` — breakthroughs, new insights
- `hall_preferences` — habits, likes, opinions
- `hall_advice` — recommendations and solutions
### Tunnels
Connections *between* wings. When the same room appears in different wings, the graph layer can treat that as a cross-wing connection.
```
wing_kai / hall_events / auth-migration → "Kai debugged the OAuth token refresh"
wing_driftwood / hall_facts / auth-migration → "team decided to migrate auth to Clerk"
wing_priya / hall_advice / auth-migration → "Priya approved Clerk over Auth0"
```
Same room. Three wings. The graph can use that shared room name as a bridge.
### Closets
Closets are the summary layer in the broader MemPalace vocabulary: compact notes that point back to the original content. In the current implementation, the main persisted storage path is still the underlying drawer text plus metadata.
### Drawers
The original stored text chunks. This is the primary retrieval layer used by the current search and benchmark flows.
## Why Structure Matters
Tested on 22,000+ real conversation memories:
| Search scope | R@10 | Improvement |
|-------------|------|-------------|
| All closets | 60.9% | baseline |
| Within wing | 73.1% | +12% |
| Wing + hall | 84.8% | +24% |
| Wing + room | 94.8% | +34% |
The practical point is that structure improves retrieval. In the project benchmarks, narrowing the search scope by wing and room outperformed searching the entire corpus at once.
## Navigation
The palace supports graph traversal across wings:
```text
MCP tool: mempalace_traverse
arguments: { "start_room": "auth-migration" }
→ discovers rooms in wing_kai, wing_driftwood, wing_priya
MCP tool: mempalace_find_tunnels
arguments: { "wing_a": "wing_code", "wing_b": "wing_team" }
→ auth-migration, deploy-process, ci-pipeline
```
This is the navigation story: shared room structure gives the model more than one way to reach relevant context.