Files
cortex/docs/milestones/09-multi-graph.md
omigamedev d484f61b29 Add development plan with 13 milestone specifications
- docs/plan.md: Master roadmap with phases and priorities
- docs/milestones/01-13: Detailed specs for each feature
- Updated CLAUDE.md with plan references and build commands

Milestones cover:
- Phase 1: Temporal versioning, auto-capture, context injection, codebase indexing
- Phase 2: Daily journal, content ingestion, graph visualization, import/export
- Phase 3: Multi-graph, smart retrieval, TUI dashboard, browser extension, shell completions
2026-02-03 09:36:08 +01:00

295 lines
6.4 KiB
Markdown

# Milestone 9: Multi-Graph Support
## Overview
Support multiple separate knowledge graphs, one per project or context. Switch between them seamlessly.
## Motivation
- Different projects have different knowledge domains
- Prevents cross-contamination of contexts
- Enables project-specific memory without noise
- Clean separation of concerns
## Features
### 9.1 Graph Management
```bash
# List all graphs
cortex graphs
# Create new graph
cortex graphs create work
cortex graphs create personal
# Switch active graph
cortex use work
cortex use personal
# Delete graph
cortex graphs delete old-project
```
### 9.2 Automatic Project Detection
```bash
# Auto-detect based on .cortex file or git remote
cd ~/projects/myapp
cortex query "auth" # Automatically uses 'myapp' graph
# Explicit override
cortex query "auth" --graph personal
```
### 9.3 Cross-Graph Search
```bash
# Search across all graphs
cortex query "auth" --all-graphs
# Search specific graphs
cortex query "auth" --graphs work,personal
```
### 9.4 Graph Linking
```bash
# Link nodes across graphs
cortex link abc123 --to def456 --graph work
# Reference external graph nodes
cortex show work:abc123 # graph:nodeId syntax
```
### 9.5 Graph Configuration
```bash
# Set default graph
cortex config set default-graph work
# Project-specific graph mapping
# In .cortex.json or .cortex file:
{
"graph": "myapp"
}
```
## Implementation
### Storage Structure
```
~/.cortex/
├── graphs/
│ ├── default/
│ │ └── cortex.db
│ ├── work/
│ │ └── cortex.db
│ └── personal/
│ └── cortex.db
├── config.json
└── graph-links.db # Cross-graph references
```
### Graph Manager
```typescript
// src/core/graphs.ts
export interface GraphInfo {
name: string;
path: string;
nodeCount: number;
lastAccessed: number;
createdAt: number;
}
export function listGraphs(): GraphInfo[] {
const graphsDir = path.join(getConfigDir(), 'graphs');
const dirs = fs.readdirSync(graphsDir);
return dirs.map(name => ({
name,
path: path.join(graphsDir, name),
...getGraphStats(path.join(graphsDir, name, 'cortex.db')),
}));
}
export function createGraph(name: string): void {
const graphPath = path.join(getConfigDir(), 'graphs', name);
fs.mkdirSync(graphPath, { recursive: true });
initializeDatabase(path.join(graphPath, 'cortex.db'));
}
export function useGraph(name: string): void {
const graphPath = path.join(getConfigDir(), 'graphs', name);
if (!fs.existsSync(graphPath)) {
throw new Error(`Graph '${name}' does not exist`);
}
setActiveGraph(name);
}
export function getActiveGraph(): string {
// Check project-local .cortex file
const localConfig = findLocalConfig();
if (localConfig?.graph) return localConfig.graph;
// Check git remote for auto-detection
const gitRemote = getGitRemote();
if (gitRemote) {
const projectName = extractProjectName(gitRemote);
if (graphExists(projectName)) return projectName;
}
// Fall back to default
return getConfig().defaultGraph || 'default';
}
```
### Database Connection Manager
```typescript
// src/core/db.ts
let activeDb: Database | null = null;
let activeGraph: string = 'default';
export function getDb(): Database {
const currentGraph = getActiveGraph();
if (activeDb && activeGraph === currentGraph) {
return activeDb;
}
// Close previous connection
if (activeDb) {
activeDb.close();
}
// Open new connection
const dbPath = path.join(getConfigDir(), 'graphs', currentGraph, 'cortex.db');
activeDb = new Database(dbPath);
activeGraph = currentGraph;
return activeDb;
}
```
### Project Detection
```typescript
// src/core/graphs.ts
function findLocalConfig(): LocalConfig | null {
// Walk up directory tree looking for .cortex or .cortex.json
let dir = process.cwd();
while (dir !== path.dirname(dir)) {
const configPath = path.join(dir, '.cortex');
if (fs.existsSync(configPath)) {
return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
}
const jsonPath = path.join(dir, '.cortex.json');
if (fs.existsSync(jsonPath)) {
return JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
}
dir = path.dirname(dir);
}
return null;
}
```
### Cross-Graph References
```typescript
// Parse graph:nodeId syntax
function parseNodeRef(ref: string): { graph?: string; nodeId: string } {
if (ref.includes(':')) {
const [graph, nodeId] = ref.split(':');
return { graph, nodeId };
}
return { nodeId: ref };
}
// Get node from any graph
async function getNodeFromAnyGraph(ref: string): Promise<Node | null> {
const { graph, nodeId } = parseNodeRef(ref);
if (graph) {
const originalGraph = getActiveGraph();
useGraph(graph);
const node = await getNode(nodeId);
useGraph(originalGraph);
return node;
}
return getNode(nodeId);
}
```
## CLI Commands
| Command | Description |
|---------|-------------|
| `cortex graphs` | List all graphs |
| `cortex graphs create <name>` | Create new graph |
| `cortex graphs delete <name>` | Delete graph |
| `cortex use <name>` | Switch active graph |
| `cortex <cmd> --graph <name>` | Run command on specific graph |
| `cortex query --all-graphs` | Search all graphs |
## MCP Tools
```typescript
memory_graphs // List available graphs
memory_use_graph // Switch active graph
memory_query // Add optional 'graph' parameter
```
## Project Config File
```json
// .cortex or .cortex.json in project root
{
"graph": "myproject",
"autoCapture": true,
"contextInjection": {
"maxTokens": 4000,
"includeTasks": true
}
}
```
## Testing
- [ ] Create/list/delete graphs
- [ ] Switch between graphs
- [ ] Auto-detect from .cortex file
- [ ] Auto-detect from git remote
- [ ] Cross-graph search works
- [ ] Cross-graph references resolve
- [ ] Concurrent access handles graph switching
## Acceptance Criteria
- [ ] Each project can have isolated graph
- [ ] Auto-detection based on directory
- [ ] Cross-graph search available
- [ ] Graph switching is fast (<100ms)
- [ ] No data leakage between graphs
- [ ] MCP tools respect active graph
## Estimated Effort
- Storage structure: 2 hours
- Graph manager: 4 hours
- DB connection manager: 2 hours
- Project detection: 3 hours
- Cross-graph search: 3 hours
- CLI commands: 2 hours
- Testing: 3 hours
- **Total: ~19 hours**
## Dependencies
- None (can implement independently)
## References
- [Git worktrees](https://git-scm.com/docs/git-worktree) for multi-project inspiration