Add first-class edge files in graph/edges/ with bidirectional frontmatter refs, hybrid Ollama/OpenAI embedding providers with fallback chain, and native MCP server (18 tools) for direct Claude Code integration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
422 lines
12 KiB
Markdown
422 lines
12 KiB
Markdown
# Cognitive Memory Schema
|
||
|
||
## Memory File Format
|
||
|
||
Each memory is a markdown file with YAML frontmatter. Filename format: `{slugified-title}-{6char-uuid}.md`
|
||
|
||
Example: `graph/solutions/fixed-redis-connection-timeouts-a1b2c3.md`
|
||
|
||
```markdown
|
||
---
|
||
id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
||
type: solution
|
||
title: "Fixed Redis connection timeouts"
|
||
tags: [redis, timeout, production, homelab]
|
||
importance: 0.8
|
||
confidence: 0.8
|
||
created: 2025-12-06T16:25:58+00:00
|
||
updated: 2025-12-06T16:25:58+00:00
|
||
relations:
|
||
- target: def789ab-...
|
||
type: SOLVES
|
||
direction: outgoing
|
||
strength: 0.8
|
||
context: "Keepalive prevents idle disconnections"
|
||
---
|
||
|
||
Added socket_keepalive=True and socket_timeout=300 to Redis connection configuration.
|
||
```
|
||
|
||
### Frontmatter Fields
|
||
|
||
| Field | Type | Required | Description |
|
||
|-------|------|----------|-------------|
|
||
| `id` | string (UUID) | Yes | Unique identifier |
|
||
| `type` | string | Yes | Memory type (see below) |
|
||
| `title` | string (quoted) | Yes | Descriptive title |
|
||
| `tags` | list[string] | No | Categorization tags (inline YAML list) |
|
||
| `importance` | float 0.0-1.0 | Yes | Importance score |
|
||
| `confidence` | float 0.0-1.0 | No | Confidence score (default 0.8) |
|
||
| `steps` | list[string] | No | Ordered steps (procedure type only) |
|
||
| `preconditions` | list[string] | No | Required preconditions (procedure type only) |
|
||
| `postconditions` | list[string] | No | Expected postconditions (procedure type only) |
|
||
| `created` | string (ISO 8601) | Yes | Creation timestamp |
|
||
| `updated` | string (ISO 8601) | Yes | Last update timestamp |
|
||
| `relations` | list[Relation] | No | Relationships to other memories |
|
||
|
||
### Memory Types
|
||
|
||
| Type | Directory | Description |
|
||
|------|-----------|-------------|
|
||
| `solution` | `graph/solutions/` | Fix or resolution to a problem |
|
||
| `fix` | `graph/fixes/` | Code-level fix or patch |
|
||
| `decision` | `graph/decisions/` | Architecture or design choice |
|
||
| `configuration` | `graph/configurations/` | Working configuration |
|
||
| `problem` | `graph/problems/` | Issue or challenge |
|
||
| `workflow` | `graph/workflows/` | Process or sequence |
|
||
| `code_pattern` | `graph/code-patterns/` | Reusable code pattern |
|
||
| `error` | `graph/errors/` | Specific error condition |
|
||
| `general` | `graph/general/` | General learning |
|
||
| `procedure` | `graph/procedures/` | Structured workflow with steps/preconditions/postconditions |
|
||
| `insight` | `graph/insights/` | Cross-cutting pattern from reflection cycles |
|
||
|
||
### Relation Fields
|
||
|
||
| Field | Type | Required | Description |
|
||
|-------|------|----------|-------------|
|
||
| `target` | string (UUID) | Yes | Target memory ID |
|
||
| `type` | string | Yes | Relationship type |
|
||
| `direction` | string | Yes | `outgoing` or `incoming` |
|
||
| `strength` | float 0.0-1.0 | No | Relationship strength |
|
||
| `context` | string (quoted) | No | Context description |
|
||
| `edge_id` | string (UUID) | No | Link to edge file for rich description |
|
||
|
||
### Relationship Types
|
||
|
||
`SOLVES`, `CAUSES`, `BUILDS_ON`, `ALTERNATIVE_TO`, `REQUIRES`, `FOLLOWS`, `RELATED_TO`
|
||
|
||
### Edge File Format
|
||
|
||
Edge files live in `graph/edges/` with full descriptions. Filename: `{from-slug}--{TYPE}--{to-slug}-{6char}.md`
|
||
|
||
```markdown
|
||
---
|
||
id: <uuid>
|
||
type: SOLVES
|
||
from_id: <uuid>
|
||
from_title: "Fixed Redis connection timeouts"
|
||
to_id: <uuid>
|
||
to_title: "Redis connection drops under load"
|
||
strength: 0.8
|
||
created: <iso>
|
||
updated: <iso>
|
||
---
|
||
|
||
The keepalive fix directly resolves the idle disconnection problem because...
|
||
```
|
||
|
||
Edge frontmatter fields: id, type, from_id, from_title, to_id, to_title, strength, created, updated.
|
||
|
||
---
|
||
|
||
## _index.json
|
||
|
||
Computed index for fast lookups. Rebuilt by `reindex` command. **Source of truth: markdown files.**
|
||
|
||
```json
|
||
{
|
||
"version": 2,
|
||
"updated": "2025-12-13T10:30:00+00:00",
|
||
"count": 313,
|
||
"edges": {
|
||
"<edge-uuid>": {
|
||
"type": "SOLVES",
|
||
"from_id": "<uuid>",
|
||
"to_id": "<uuid>",
|
||
"strength": 0.8,
|
||
"path": "graph/edges/fixed-redis--SOLVES--redis-drops-a1b2c3.md"
|
||
}
|
||
},
|
||
"entries": {
|
||
"a1b2c3d4-e5f6-7890-abcd-ef1234567890": {
|
||
"title": "Fixed Redis connection timeouts",
|
||
"type": "solution",
|
||
"tags": ["redis", "timeout", "production", "homelab"],
|
||
"importance": 0.8,
|
||
"confidence": 0.8,
|
||
"created": "2025-12-06T16:25:58+00:00",
|
||
"updated": "2025-12-06T16:25:58+00:00",
|
||
"path": "graph/solutions/fixed-redis-connection-timeouts-a1b2c3.md",
|
||
"relations": [
|
||
{
|
||
"target": "def789ab-...",
|
||
"type": "SOLVES",
|
||
"direction": "outgoing",
|
||
"strength": 0.8,
|
||
"context": "Keepalive prevents idle disconnections"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Notes:**
|
||
- `_index.json` is gitignored (derived data)
|
||
- Can be regenerated at any time with `python client.py reindex`
|
||
- Entries mirror frontmatter fields for fast search without opening files
|
||
|
||
---
|
||
|
||
## _state.json
|
||
|
||
Mutable runtime state tracking access patterns and decay scores. **Kept separate from frontmatter to avoid churning git history with access-count updates.**
|
||
|
||
```json
|
||
{
|
||
"version": 1,
|
||
"updated": "2025-12-13T10:30:00+00:00",
|
||
"entries": {
|
||
"a1b2c3d4-e5f6-7890-abcd-ef1234567890": {
|
||
"access_count": 5,
|
||
"last_accessed": "2025-12-13T10:15:00+00:00",
|
||
"decay_score": 0.75
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Notes:**
|
||
- `_state.json` is gitignored (mutable, session-specific data)
|
||
- Access count increments on `get` operations
|
||
- Decay scores recalculated by `python client.py decay`
|
||
|
||
---
|
||
|
||
## Episode File Format
|
||
|
||
Daily markdown files in `episodes/` directory. Append-only, one file per day.
|
||
|
||
Filename format: `YYYY-MM-DD.md`
|
||
|
||
```markdown
|
||
# 2025-12-13
|
||
|
||
## 10:30 - Fixed Discord bot reconnection
|
||
- **Type:** fix
|
||
- **Tags:** major-domo, discord, python
|
||
- **Memory:** [discord-bot-reconnection](../graph/fixes/discord-bot-reconnection-a1b2c3.md)
|
||
- **Summary:** Implemented exponential backoff for reconnections
|
||
|
||
## 11:15 - Chose websocket over polling
|
||
- **Type:** decision
|
||
- **Tags:** major-domo, architecture
|
||
- **Memory:** [websocket-over-polling](../graph/decisions/websocket-over-polling-d4e5f6.md)
|
||
- **Summary:** WebSocket provides lower latency for real-time game state updates
|
||
```
|
||
|
||
**Notes:**
|
||
- Episodes are chronological session logs
|
||
- Entries link back to graph memories when available
|
||
- Append-only (never edited, only appended)
|
||
- Useful for reflection and session review
|
||
|
||
---
|
||
|
||
## CORE.md Format
|
||
|
||
Auto-generated summary of highest-relevance memories. Loaded into system prompt at session start.
|
||
|
||
```markdown
|
||
# Memory Core (auto-generated)
|
||
> Last updated: 2025-12-13 | Active memories: 180/313 | Next refresh: daily (systemd timer)
|
||
|
||
## Critical Solutions
|
||
- [title](relative/path.md) (tag1, tag2)
|
||
|
||
## Active Decisions
|
||
- [title](relative/path.md) (tag1, tag2)
|
||
|
||
## Key Fixes
|
||
- [title](relative/path.md) (tag1, tag2)
|
||
|
||
## Configurations
|
||
- [title](relative/path.md) (tag1, tag2)
|
||
|
||
## Patterns & Workflows
|
||
- [title](relative/path.md) (tag1, tag2)
|
||
```
|
||
|
||
**Notes:**
|
||
- Budget: ~3K tokens (~12,000 chars)
|
||
- Regenerated by `python client.py core`
|
||
- Memories included based on decay_score (must be >= 0.2)
|
||
- Grouped by type category, sorted by decay score within each group
|
||
- Capped at 15 entries per section
|
||
|
||
---
|
||
|
||
## Decay Model
|
||
|
||
```
|
||
decay_score = importance × e^(-λ × days_since_access) × log2(access_count + 1) × type_weight
|
||
```
|
||
|
||
Where:
|
||
- `λ = 0.03` (half-life ~23 days)
|
||
- `days_since_access` = days since `_state.json` `last_accessed`
|
||
- `access_count` = from `_state.json`
|
||
- `type_weight` = per-type multiplier (see below)
|
||
- For `access_count == 0`, `usage_factor = 0.5` (new memories start at half strength)
|
||
|
||
### Type Weights
|
||
|
||
| Type | Weight |
|
||
|------|--------|
|
||
| `procedure` | 1.4 |
|
||
| `decision` | 1.3 |
|
||
| `insight` | 1.25 |
|
||
| `solution` | 1.2 |
|
||
| `code_pattern` | 1.1 |
|
||
| `configuration` | 1.1 |
|
||
| `fix` | 1.0 |
|
||
| `workflow` | 1.0 |
|
||
| `problem` | 0.9 |
|
||
| `error` | 0.8 |
|
||
| `general` | 0.8 |
|
||
|
||
### Thresholds
|
||
|
||
| Range | Status |
|
||
|-------|--------|
|
||
| 0.5+ | Active |
|
||
| 0.2-0.5 | Fading |
|
||
| 0.05-0.2 | Dormant |
|
||
| <0.05 | Archived |
|
||
|
||
### Vault
|
||
|
||
Pinned memories (in `vault/`) have a decay score of 999.0 (effectively infinite).
|
||
|
||
---
|
||
|
||
## REFLECTION.md Format
|
||
|
||
Auto-generated summary of memory themes, cross-project patterns, and access statistics. Generated by `python client.py reflection` or automatically during `reflect`.
|
||
|
||
```markdown
|
||
# Reflection Summary (auto-generated)
|
||
> Last updated: 2026-02-13 | Last reflection: 2026-02-13 | Total reflections: 2
|
||
|
||
## Themes
|
||
Top tag co-occurrences revealing recurring themes:
|
||
|
||
- **fix + python**: 52 memories ("Fix S3 upload...", "fix_cardpositions.py...")
|
||
|
||
## Cross-Project Patterns
|
||
Tags that span multiple projects:
|
||
|
||
- **fix**: appears in major-domo (38), vagabond-rpg (22), paper-dynasty (19)
|
||
|
||
## Most Accessed
|
||
Top 10 memories by access count:
|
||
|
||
1. [Title](graph/type/filename.md) - N accesses
|
||
|
||
## Recent Insights
|
||
Insight-type memories:
|
||
|
||
- [Title](graph/insights/filename.md) - content preview...
|
||
|
||
## Consolidation History
|
||
|
||
- Total merges performed: 0
|
||
```
|
||
|
||
**Sections:**
|
||
1. **Themes** - Top 8 tag co-occurrences with example memory titles (top 3)
|
||
2. **Cross-Project Patterns** - Tags spanning 2+ known projects with per-project counts
|
||
3. **Most Accessed** - Top 10 memories ranked by `_state.json` access_count
|
||
4. **Recent Insights** - Latest insight-type memories with 80-char content preview
|
||
5. **Consolidation History** - Merge count from episode files
|
||
|
||
**Known projects:** major-domo, paper-dynasty, homelab, vagabond-rpg, foundryvtt, strat-gameplay-webapp
|
||
|
||
---
|
||
|
||
## _embeddings.json
|
||
|
||
Ollama embedding vectors for semantic search. **Gitignored** (derived, regenerated by `python client.py embed`).
|
||
|
||
```json
|
||
{
|
||
"model": "nomic-embed-text",
|
||
"updated": "2026-02-13T12:00:00+00:00",
|
||
"entries": {
|
||
"a1b2c3d4-e5f6-7890-abcd-ef1234567890": [0.0123, -0.0456, ...],
|
||
...
|
||
}
|
||
}
|
||
```
|
||
|
||
**Notes:**
|
||
- Vectors generated from `"{title}. {content_preview}"` per memory
|
||
- Uses Ollama `nomic-embed-text` model at `http://localhost:11434`
|
||
- Batched in groups of 50, 300-second timeout for first-time model pull
|
||
- Falls back gracefully if Ollama is unavailable
|
||
- Must be refreshed after adding new memories (`python client.py embed`)
|
||
|
||
---
|
||
|
||
## Procedure Memory Format
|
||
|
||
Procedure-type memories have additional frontmatter fields for structured steps:
|
||
|
||
```markdown
|
||
---
|
||
id: a1b2c3d4-...
|
||
type: procedure
|
||
title: "Deploy Major Domo to production"
|
||
tags: [major-domo, deploy, docker]
|
||
importance: 0.8
|
||
confidence: 0.8
|
||
steps:
|
||
- "Run tests"
|
||
- "Build docker image"
|
||
- "Push to registry"
|
||
- "Deploy to LXC"
|
||
preconditions:
|
||
- "All tests pass"
|
||
- "On main branch"
|
||
postconditions:
|
||
- "Service healthy"
|
||
- "Discord bot online"
|
||
created: 2026-02-13T12:00:00+00:00
|
||
updated: 2026-02-13T12:00:00+00:00
|
||
---
|
||
|
||
Standard deploy workflow for the Major Domo Discord bot.
|
||
```
|
||
|
||
**Notes:**
|
||
- `steps`, `preconditions`, `postconditions` are optional lists
|
||
- Values are quoted YAML strings in the list
|
||
- Procedures have the highest decay weight (1.4) - they persist longest
|
||
|
||
---
|
||
|
||
## _config.json
|
||
|
||
Embedding provider configuration. **Gitignored** (may contain API key).
|
||
|
||
```json
|
||
{
|
||
"embedding_provider": "ollama",
|
||
"openai_api_key": null,
|
||
"ollama_model": "nomic-embed-text",
|
||
"openai_model": "text-embedding-3-small"
|
||
}
|
||
```
|
||
|
||
**Notes:**
|
||
- `embedding_provider`: `"ollama"` (default) or `"openai"`
|
||
- Provider changes trigger automatic re-embedding (dimension mismatch safety: ollama=768, openai=1536)
|
||
- Configure via: `claude-memory config --provider openai --openai-key "sk-..."`
|
||
|
||
---
|
||
|
||
## .gitignore
|
||
|
||
```
|
||
_state.json
|
||
_index.json
|
||
_embeddings.json
|
||
_config.json
|
||
```
|
||
|
||
Only markdown files (memories, CORE.md, REFLECTION.md, episodes) are git-tracked. Index, state, embeddings, and config are derived/mutable data that can be regenerated.
|
||
|
||
---
|
||
|
||
*Schema version: 3.0.0 | Created: 2026-02-13 | Updated: 2026-02-19*
|