feat: port holistic node refinement contract
This commit is contained in:
+5
-5
@@ -12,7 +12,7 @@ RA-OS is a minimal knowledge graph UI with MCP server integration. It provides a
|
||||
|
||||
**Agent-agnostic** — No built-in AI chat. Instead, RA-OS exposes an MCP server that any AI agent (Claude Code, custom agents) can connect to.
|
||||
|
||||
**Simple & focused** — 2-panel UI for browsing and editing your knowledge graph. No bloat.
|
||||
**Simple & focused** — A compact multi-pane UI for browsing and editing your knowledge graph. No bloat.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
@@ -23,8 +23,8 @@ RA-OS is a minimal knowledge graph UI with MCP server integration. It provides a
|
||||
|
||||
## What's Included
|
||||
|
||||
- 2-panel UI (nodes list + focus panel)
|
||||
- Node/Edge/Dimension CRUD
|
||||
- Multi-pane UI for nodes, contexts, map, table, and focus work
|
||||
- Node/Edge CRUD with optional contexts
|
||||
- Full-text and semantic search
|
||||
- MCP server with graph and skill tools
|
||||
- Skills system (shared instructions for internal + external agents)
|
||||
@@ -49,7 +49,7 @@ RA-OS is a minimal knowledge graph UI with MCP server integration. It provides a
|
||||
│ │ │
|
||||
│ • Search │ • Node content │
|
||||
│ • Filters │ • Connections │
|
||||
│ • List │ • Dimensions │
|
||||
│ • List │ • Context + metadata │
|
||||
│ │ │
|
||||
└─────────────┴─────────────────────────┘
|
||||
```
|
||||
@@ -71,7 +71,7 @@ RA-OS is designed to be the knowledge backend for your AI workflows:
|
||||
|
||||
Add this to `~/.claude.json` and restart Claude. Works without RA-OS running.
|
||||
|
||||
Core tools include: `createNode`, `queryNodes`, `updateNode`, `getNodesById`, `createEdge`, `queryEdge`, `queryDimensions`, `createDimension`, `updateDimension`, `deleteDimension`, `listSkills`, `readSkill`
|
||||
Core tools include: `createNode`, `queryNodes`, `updateNode`, `getNodesById`, `createEdge`, `queryEdge`, `queryContexts`, `listSkills`, `readSkill`
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
+65
-342
@@ -1,367 +1,90 @@
|
||||
# Database Schema
|
||||
|
||||
This page describes the database as it exists on disk, including some legacy tables and columns that remain for compatibility and historical records. The current shipped product uses a single RA-H assistant; old delegation-era fields should not be read as active UX concepts.
|
||||
|
||||
## Entity Relationship Diagram
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
nodes ||--o{ node_dimensions : "has"
|
||||
nodes ||--o{ edges : "from"
|
||||
nodes ||--o{ edges : "to"
|
||||
nodes ||--o{ chunks : "contains"
|
||||
nodes ||--o{ chats : "focused_on"
|
||||
dimensions ||--o{ node_dimensions : "tagged_with"
|
||||
chats }o--|| agent_delegations : "belongs_to"
|
||||
|
||||
nodes {
|
||||
INTEGER id PK
|
||||
TEXT title
|
||||
TEXT source
|
||||
TEXT description
|
||||
TEXT event_date
|
||||
BLOB embedding
|
||||
}
|
||||
|
||||
edges {
|
||||
INTEGER id PK
|
||||
INTEGER from_node_id FK
|
||||
INTEGER to_node_id FK
|
||||
TEXT context
|
||||
TEXT explanation
|
||||
}
|
||||
|
||||
dimensions {
|
||||
TEXT name PK
|
||||
INTEGER is_priority
|
||||
TEXT icon
|
||||
}
|
||||
|
||||
node_dimensions {
|
||||
INTEGER node_id FK
|
||||
TEXT dimension FK
|
||||
}
|
||||
|
||||
chunks {
|
||||
INTEGER id PK
|
||||
INTEGER node_id FK
|
||||
TEXT text
|
||||
}
|
||||
|
||||
chats {
|
||||
INTEGER id PK
|
||||
INTEGER focused_node_id FK
|
||||
TEXT user_message
|
||||
TEXT assistant_message
|
||||
}
|
||||
|
||||
agent_delegations {
|
||||
INTEGER id PK
|
||||
TEXT task
|
||||
TEXT status
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Why SQLite?
|
||||
|
||||
RA-H uses **SQLite** for local-first data ownership. Your knowledge stays on your machine - no cloud dependencies. SQLite provides:
|
||||
- **Zero configuration** - single file database
|
||||
- **sqlite-vec extension** - fast vector similarity search
|
||||
- **Full-text search (FTS5)** - Google-like text search
|
||||
- **Relational integrity** - foreign keys, triggers, transactions
|
||||
- **Portability** - database file migrates with Mac app
|
||||
|
||||
**Database Location:** `~/Library/Application Support/RA-H/db/rah.sqlite`
|
||||
|
||||
## Two-Layer Embedding Architecture
|
||||
|
||||
RA-H uses **two types of embeddings** for different search needs:
|
||||
|
||||
### 1. Node-Level Embeddings
|
||||
- **Storage:** `nodes.embedding` column (BLOB)
|
||||
- **Purpose:** Semantic search for nodes (legacy memory pipeline used this too)
|
||||
- **Model:** `text-embedding-3-small` (1536 dimensions)
|
||||
- **Used by:** Search/agent tools (legacy memory pipeline has been removed)
|
||||
|
||||
### 2. Chunk-Level Embeddings
|
||||
- **Storage:** `chunks` table (text) → `vec_chunks` virtual table (embeddings)
|
||||
- **Purpose:** Detailed content search within long documents
|
||||
- **Model:** `text-embedding-3-small` (1536 dimensions)
|
||||
- **Used by:** `searchContentEmbeddings` tool
|
||||
# RA-H Schema
|
||||
|
||||
## Core Tables
|
||||
|
||||
### nodes
|
||||
Primary knowledge storage. Each row is a discrete knowledge item.
|
||||
### `nodes`
|
||||
- `id`
|
||||
- `title`
|
||||
- `description`
|
||||
- `source`
|
||||
- `link`
|
||||
- `metadata`
|
||||
- `chunk_status`
|
||||
- `event_date`
|
||||
- `context_id` nullable FK to `contexts.id`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
**Columns:**
|
||||
- `id` (INTEGER PK) - Unique identifier
|
||||
- `title` (TEXT) - Node title
|
||||
- `description` (TEXT) - WHAT this is + WHY it matters (primary identity field)
|
||||
- `source` (TEXT) - Canonical source content used for chunking and embedding
|
||||
- `link` (TEXT) - External source URL (only for source nodes, not derived ideas)
|
||||
- `event_date` (TEXT) - When the thing actually happened (vs `created_at` = when it entered the graph)
|
||||
- `metadata` (TEXT) - JSON metadata
|
||||
- `chunk_status` (TEXT) - Chunking status (not_chunked, chunked)
|
||||
- `embedding` (BLOB) - Node-level embedding vector
|
||||
- `embedding_text` (TEXT) - Text that was embedded
|
||||
- `embedding_updated_at` (TEXT) - Embedding timestamp
|
||||
- `created_at`, `updated_at` (TEXT) - Timestamps
|
||||
### `contexts`
|
||||
- `id`
|
||||
- `name`
|
||||
- `description`
|
||||
- `icon`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
**Temporal dimensions:** Each node has three timestamps:
|
||||
- `created_at` - When the node entered the graph (transaction time)
|
||||
- `updated_at` - When the node was last modified
|
||||
- `event_date` - When the thing actually happened (valid time)
|
||||
### `edges`
|
||||
- `id`
|
||||
- `from_node_id`
|
||||
- `to_node_id`
|
||||
- `explanation`
|
||||
- `context`
|
||||
- `source`
|
||||
- `created_at`
|
||||
|
||||
**FTS:**
|
||||
- `nodes_fts` - Full-text search on title + source + description
|
||||
### `chunks`
|
||||
- `id`
|
||||
- `node_id`
|
||||
- `chunk_idx`
|
||||
- `text`
|
||||
- `embedding_type`
|
||||
- `metadata`
|
||||
- `created_at`
|
||||
|
||||
### edges
|
||||
Directed relationships between nodes (knowledge graph).
|
||||
### `dimension_migration_snapshots`
|
||||
- Stores one-time snapshots of legacy dimension data before dropping the old tables.
|
||||
- Exists for auditability and migration verification only.
|
||||
|
||||
**Important behavior:**
|
||||
- **Storage is directed** (`from_node_id → to_node_id`)
|
||||
- **UI treats connections as bidirectional** (a node shows edges where it is either `from` or `to`)
|
||||
- **Every new edge requires an explanation** (enforced in service layer)
|
||||
- **Every new edge is classified** into a structured `EdgeContext` (stored as JSON)
|
||||
## Search / Retrieval
|
||||
|
||||
**Columns (SQLite):**
|
||||
- `id` (INTEGER PK)
|
||||
- `from_node_id` (INTEGER FK → nodes.id) — directed “from”
|
||||
- `to_node_id` (INTEGER FK → nodes.id) — directed “to”
|
||||
- `source` (TEXT) — creation source (`user`, `helper_name`, `ai_similarity`)
|
||||
- `created_at` (TEXT)
|
||||
- `context` (TEXT) — JSON blob (canonical; see `EdgeContext` below)
|
||||
- `explanation` (TEXT) — legacy column (currently not the canonical source of truth)
|
||||
- `nodes_fts` indexes title, description, and source for full-text lookup.
|
||||
- `chunks_fts` indexes chunk text.
|
||||
- Vector tables store node and chunk embeddings.
|
||||
|
||||
**Indexes:**
|
||||
- `idx_edges_from` — fast “outgoing edges” queries
|
||||
- `idx_edges_to` — fast “incoming edges” queries
|
||||
## Important Constraints
|
||||
|
||||
#### EdgeContext (canonical relationship metadata)
|
||||
Stored as JSON in `edges.context`. This is the “Idea Genealogy” layer.
|
||||
- `dimensions` and `node_dimensions` are no longer canonical tables.
|
||||
- New installs should never create them.
|
||||
- Existing installs migrate by snapshotting old dimension data, then dropping the legacy tables.
|
||||
- `contexts` are optional. `nodes.context_id` must allow `NULL`.
|
||||
|
||||
```typescript
|
||||
interface EdgeContext {
|
||||
// SYSTEM-INFERRED (AI + heuristics classify from explanation + node context)
|
||||
category: 'attribution' | 'intellectual';
|
||||
type:
|
||||
| 'created_by' // attribution: authorship/creation/founding
|
||||
| 'features' // attribution: appears in / host / guest / explicitly mentioned
|
||||
| 'part_of' // attribution: membership/container (episode→podcast, chapter→book, video→channel)
|
||||
| 'source_of' // intellectual: idea/insight came from source
|
||||
| 'extends' // intellectual: builds on
|
||||
| 'supports' // intellectual: evidence for
|
||||
| 'contradicts' // intellectual: in tension
|
||||
| 'related_to'; // intellectual: fallback
|
||||
confidence: number; // 0–1
|
||||
inferred_at: string; // ISO timestamp
|
||||
## Common Queries
|
||||
|
||||
// PROVIDED BY USER/AGENT
|
||||
explanation: string; // required; free-form text (user can edit)
|
||||
|
||||
// SYSTEM-MANAGED
|
||||
created_via: 'ui' | 'agent' | 'mcp' | 'workflow' | 'quicklink';
|
||||
}
|
||||
```
|
||||
|
||||
#### Direction rule (how to write explanations)
|
||||
Explanations must read correctly **FROM → TO**:
|
||||
- `created_by`: **FROM** was created/authored/founded by **TO**
|
||||
- `features`: **FROM** features/mentions **TO**
|
||||
- `part_of`: **FROM** is part of **TO**
|
||||
- `source_of`: **FROM** came from / was inspired by **TO**
|
||||
|
||||
#### Inference + guardrails
|
||||
On edge create and on explanation edits, RA-H:
|
||||
- runs lightweight **heuristics** for common phrases (e.g., “Created by …”, “Part of …”, “Came from …”, “Features …”)
|
||||
- otherwise runs an AI classification step to populate `category/type/confidence`
|
||||
|
||||
The UI also provides 4 quick chips to reduce user cognitive load:
|
||||
- **Made by** → “Created by …”
|
||||
- **Part of** → “Part of …”
|
||||
- **Came from** → “Came from …”
|
||||
- **Related** → “Related to …”
|
||||
|
||||
#### Where edges get created/updated
|
||||
All edge creation funnels through the service layer enforcement:
|
||||
- UI (`FocusPanel`) — requires explanation; allows editing explanation (re-infers)
|
||||
- REST API `POST /api/edges` — requires `explanation`
|
||||
- Tooling (`createEdge` tool) — requires `explanation`
|
||||
- MCP (`rah_create_edge`) — requires `explanation`
|
||||
- Workflows (e.g. `connect`, `integrate`) — call `createEdge` with `explanation`
|
||||
|
||||
### chunks
|
||||
Long-form content split into searchable pieces.
|
||||
|
||||
**Columns:**
|
||||
- `id` (INTEGER PK)
|
||||
- `node_id` (INTEGER FK → nodes.id)
|
||||
- `chunk_idx` (INTEGER) - Sequence number
|
||||
- `text` (TEXT) - Chunk content
|
||||
- `embedding_type` (TEXT) - Model used
|
||||
- `metadata` (TEXT) - JSON metadata
|
||||
- `created_at` (TEXT)
|
||||
|
||||
**Indexes:**
|
||||
- `idx_chunks_by_node` - Fast node→chunks lookup
|
||||
- `idx_chunks_by_node_idx` - Ordered retrieval
|
||||
|
||||
**FTS:**
|
||||
- `chunks_fts` - Full-text search within chunks
|
||||
|
||||
### dimensions
|
||||
Master list of categorization tags.
|
||||
|
||||
**Columns:**
|
||||
- `name` (TEXT PK) - Dimension name
|
||||
- `is_priority` (INTEGER) - Legacy compatibility field retained in schema
|
||||
- `icon` (TEXT) - Icon identifier (persisted in database)
|
||||
- `updated_at` (TEXT)
|
||||
|
||||
### node_dimensions
|
||||
Many-to-many junction table (nodes ↔ dimensions).
|
||||
|
||||
**Columns:**
|
||||
- `node_id` (INTEGER FK → nodes.id)
|
||||
- `dimension` (TEXT FK → dimensions.name)
|
||||
- Primary key: `(node_id, dimension)`
|
||||
|
||||
**Indexes:**
|
||||
- `idx_dim_by_dimension` - Fast "all nodes in dimension X"
|
||||
- `idx_dim_by_node` - Fast "all dimensions for node X"
|
||||
|
||||
### chats
|
||||
Conversation history with token/cost tracking.
|
||||
|
||||
The chat schema still carries some legacy multi-agent fields. Current product framing is simpler: one RA-H assistant, with these columns mainly retained for older records, analytics, and backwards compatibility.
|
||||
|
||||
**Columns:**
|
||||
- `id` (INTEGER PK)
|
||||
- `chat_type` (TEXT) - Conversation type
|
||||
- `helper_name` (TEXT) - Legacy runtime label; current app sessions use `ra-h`
|
||||
- `agent_type` (TEXT) - Legacy role field retained for historical rows/analytics
|
||||
- `delegation_id` (INTEGER FK) - Legacy link to delegation records
|
||||
- `user_message` (TEXT)
|
||||
- `assistant_message` (TEXT)
|
||||
- `thread_id` (TEXT) - Conversation thread
|
||||
- `focused_node_id` (INTEGER FK → nodes.id)
|
||||
- `metadata` (TEXT) - JSON with token counts, costs, traces
|
||||
- `created_at` (TEXT)
|
||||
|
||||
**Indexes:**
|
||||
- `idx_chats_thread` - Fast thread retrieval
|
||||
|
||||
### agent_delegations
|
||||
Legacy delegation queue from the older multi-agent runtime. Retained so old rows and analytics remain readable; not an active user-facing feature in the current product.
|
||||
|
||||
**Columns:**
|
||||
- `id` (INTEGER PK)
|
||||
- `session_id` (TEXT UNIQUE) - Delegation identifier
|
||||
- `agent_type` (TEXT) - Delegate type (default: 'mini')
|
||||
- `task` (TEXT) - Task description
|
||||
- `context` (TEXT) - Execution context
|
||||
- `expected_outcome` (TEXT)
|
||||
- `status` (TEXT) - queued, in_progress, completed, failed
|
||||
- `summary` (TEXT) - Result summary
|
||||
- `created_at`, `updated_at` (TEXT)
|
||||
|
||||
### logs
|
||||
Activity audit trail (auto-pruned to last 10k).
|
||||
|
||||
**Columns:**
|
||||
- `id` (INTEGER PK)
|
||||
- `ts` (TEXT) - Timestamp
|
||||
- `table_name` (TEXT) - Affected table
|
||||
- `action` (TEXT) - INSERT, UPDATE, DELETE
|
||||
- `row_id` (INTEGER) - Affected row
|
||||
- `summary` (TEXT) - Human-readable summary
|
||||
- `snapshot_json` (TEXT) - Row snapshot
|
||||
- `enriched_summary` (TEXT) - Enriched log entry
|
||||
|
||||
**Indexes:**
|
||||
- `idx_logs_ts` - Chronological queries
|
||||
- `idx_logs_table_ts` - Per-table chronological
|
||||
- `idx_logs_table_row` - Per-row history
|
||||
- `idx_logs_enriched` - Enriched-only filtering
|
||||
|
||||
## Vector Tables (Auto-Created)
|
||||
|
||||
### vec_nodes
|
||||
Virtual table for node-level vector search (sqlite-vec).
|
||||
Nodes in a context:
|
||||
|
||||
```sql
|
||||
VIRTUAL TABLE USING vec0(
|
||||
node_id INTEGER PRIMARY KEY,
|
||||
embedding FLOAT[1536]
|
||||
)
|
||||
SELECT *
|
||||
FROM nodes
|
||||
WHERE context_id = ?
|
||||
ORDER BY updated_at DESC;
|
||||
```
|
||||
|
||||
**Supporting tables (auto-generated):**
|
||||
- `vec_nodes_info`, `vec_nodes_chunks`, `vec_nodes_rowids`, `vec_nodes_vector_chunks00`
|
||||
|
||||
### vec_chunks
|
||||
Virtual table for chunk-level vector search.
|
||||
Most connected nodes:
|
||||
|
||||
```sql
|
||||
VIRTUAL TABLE USING vec0(
|
||||
chunk_id INTEGER PRIMARY KEY,
|
||||
embedding FLOAT[1536]
|
||||
)
|
||||
```
|
||||
|
||||
**Supporting tables (auto-generated):**
|
||||
- `vec_chunks_info`, `vec_chunks_chunks`, `vec_chunks_rowids`, `vec_chunks_vector_chunks00`
|
||||
|
||||
**Note:** Vec tables are NOT pre-seeded in distribution. They auto-create on first app startup via `ensureVectorTables()` in `sqlite-client.ts:45`.
|
||||
|
||||
## Views
|
||||
|
||||
### nodes_v
|
||||
Nodes with dimensions aggregated as JSON array.
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
n.id, n.title, n.description, n.source, n.link, n.metadata,
|
||||
n.event_date, n.created_at, n.updated_at,
|
||||
COALESCE(JSON_GROUP_ARRAY(d.dimension), '[]') AS dimensions_json
|
||||
SELECT n.id, n.title, COUNT(DISTINCT e.id) AS edge_count
|
||||
FROM nodes n
|
||||
LEFT JOIN node_dimensions d ON d.node_id = n.id
|
||||
LEFT JOIN edges e ON (e.from_node_id = n.id OR e.to_node_id = n.id)
|
||||
GROUP BY n.id
|
||||
ORDER BY edge_count DESC, n.updated_at DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
### logs_v
|
||||
Enriched logs with related data (node titles, edge titles, chat previews).
|
||||
|
||||
## Triggers
|
||||
|
||||
**Logging triggers:**
|
||||
- `trg_nodes_ai` / `trg_nodes_au` - Log node inserts/updates
|
||||
- `trg_edges_ai` / `trg_edges_au` - Log edge inserts/updates
|
||||
- `trg_chats_ai` - Log chat inserts (with token/cost/trace metadata)
|
||||
|
||||
**Maintenance triggers:**
|
||||
- `trg_edges_update_nodes_on_insert` - Touch node timestamps on edge creation
|
||||
- `trg_logs_prune` - Keep last 10,000 log rows
|
||||
|
||||
## Schema Version
|
||||
|
||||
**schema_version table:**
|
||||
- Tracks database migrations
|
||||
- Current: v1.0 (frozen for Mac app release)
|
||||
Recently updated nodes:
|
||||
|
||||
```sql
|
||||
CREATE TABLE schema_version (
|
||||
version INTEGER PRIMARY KEY,
|
||||
applied_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
||||
description TEXT
|
||||
);
|
||||
SELECT id, title, updated_at
|
||||
FROM nodes
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT 25;
|
||||
```
|
||||
|
||||
## Seed Database
|
||||
|
||||
**Location:** `/dist/resources/rah_seed.sqlite`
|
||||
**Purpose:** Ships with Mac app for new users
|
||||
**Contents:** Clean schema, no data, no vec tables (auto-created on first run)
|
||||
**Size:** ~128KB
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> MCP tools for graph operations and skills for procedural guidance.
|
||||
|
||||
**How it works:** External agents call MCP tools to read and write your graph. For complex tasks, they read skills (`listSkills`/`readSkill`) to follow your preferred operating patterns.
|
||||
**How it works:** External agents call MCP tools to read and write your graph. Contexts are optional soft organization only; node quality should come from clear nodes and explicit edges.
|
||||
|
||||
---
|
||||
|
||||
@@ -14,18 +14,15 @@ RA-OS exposes these core standalone MCP tools:
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `getContext` | Graph overview: stats, contexts, hub nodes, dimensions, recent activity, skills |
|
||||
| `queryNodes` | Search nodes by keyword/dimensions/date |
|
||||
| `getContext` | Graph overview: stats, contexts, hub nodes, recent activity, skills |
|
||||
| `queryNodes` | Search nodes by keyword/date/context |
|
||||
| `getNodesById` | Fetch full nodes by ID |
|
||||
| `createNode` | Create a node |
|
||||
| `updateNode` | Update a node |
|
||||
| `createEdge` | Create an edge between nodes |
|
||||
| `queryEdge` | Query edges |
|
||||
| `updateEdge` | Update edge explanation |
|
||||
| `queryDimensions` | List dimensions |
|
||||
| `createDimension` | Create a dimension |
|
||||
| `updateDimension` | Update/rename a dimension |
|
||||
| `deleteDimension` | Delete a dimension |
|
||||
| `queryContexts` | List contexts and optional attached nodes |
|
||||
|
||||
### Skills + Search
|
||||
|
||||
|
||||
+17
-212
@@ -1,218 +1,23 @@
|
||||
# User Interface
|
||||
# UI Surfaces
|
||||
|
||||
> How to navigate and use RA-OS's interface.
|
||||
## Main Views
|
||||
|
||||
**How it works:** RA-OS uses a collapsible left navigation rail plus a flexible workspace that can show one or two panes at once. Nodes, dimensions, map, table, skills, and settings all live inside the same workspace.
|
||||
- `Feed` for recent and sortable node browsing
|
||||
- `Contexts` for optional context browsing
|
||||
- `Map` for graph structure
|
||||
- `Table` for dense inspection
|
||||
- `Skills` for editable agent instructions
|
||||
- `Chat` for agent-driven graph work
|
||||
|
||||
---
|
||||
## UI Contract After The Migration
|
||||
|
||||
## Workspace Layout
|
||||
- The app no longer exposes a dimensions pane.
|
||||
- Feed and table filtering are context-aware and no longer dimension-based.
|
||||
- Persisted pane layout should only hydrate valid pane types: `views`, `node`, `contexts`, `map`, `table`, `skills`.
|
||||
- Contexts are shown as a secondary organizational aid, not as a hard requirement for capture.
|
||||
|
||||
```
|
||||
┌────────┬──────────────────────┬──────────────────────┐
|
||||
│ NAV │ PANE A │ PANE B │
|
||||
│ │ │ │
|
||||
│ Search │ Nodes / Focus │ Optional second pane │
|
||||
│ Add │ Dimensions / Map │ for compare/browse │
|
||||
│ Views │ Table / Skills │ │
|
||||
└────────┴──────────────────────┴──────────────────────┘
|
||||
```
|
||||
## Focus And Capture
|
||||
|
||||
---
|
||||
|
||||
## Left Navigation
|
||||
|
||||
The left rail can stay compact or expand into a labeled navigation column.
|
||||
|
||||
### Features
|
||||
|
||||
- **Search** — Cmd+K opens global search
|
||||
- **Add Stuff** — open the quick-add flow
|
||||
- **Refresh** — reload pane data
|
||||
- **Workspace views** — Nodes, Skills, Map, Dimensions, and Table
|
||||
- **Settings** — open settings and MCP/config panels
|
||||
|
||||
---
|
||||
|
||||
## Nodes Pane
|
||||
|
||||
Browse and manage your knowledge base in the main feed.
|
||||
|
||||
### Features
|
||||
|
||||
- **Search bar** — filter nodes by text
|
||||
- **Dimension filters** — filter the feed with one or more dimensions
|
||||
- **Pending quick-add items** — processing placeholders appear in the feed
|
||||
- **Open in other pane** — send a node to the second pane for comparison
|
||||
|
||||
### Node Display
|
||||
|
||||
Each node shows:
|
||||
- Title and preview
|
||||
- Dimension tags
|
||||
- Last updated timestamp
|
||||
- Node ID badge
|
||||
|
||||
---
|
||||
|
||||
## Dimensions Pane
|
||||
|
||||
The dimensions pane is now a dedicated browser instead of a modal-only overlay.
|
||||
|
||||
### Features
|
||||
|
||||
- Browse dimension cards with counts and lock state
|
||||
- Create new dimensions from the pane header
|
||||
- Select a dimension to push that filter into the Nodes pane
|
||||
- Manage dimension metadata and node grouping from one place
|
||||
|
||||
---
|
||||
|
||||
## Focus Pane
|
||||
|
||||
Active workspace for the node(s) you're working with.
|
||||
|
||||
### Tabbed Interface
|
||||
|
||||
- **Primary tab** — Main focused node
|
||||
- **Additional tabs** — Related nodes opened from links
|
||||
- **Tab controls** — Close (×), reorder, switch
|
||||
|
||||
### Node Detail View
|
||||
|
||||
| Section | Content |
|
||||
|---------|---------|
|
||||
| **Header** | Title, node ID, trash icon |
|
||||
| **Content** | Full markdown notes with node tokens and links |
|
||||
| **Metadata** | Created, updated, type, link |
|
||||
| **Dimensions** | Editable dimension tags |
|
||||
| **Connections** | Incoming/outgoing edges |
|
||||
|
||||
### Content Rendering
|
||||
|
||||
- Markdown support
|
||||
- `[NODE:id:"title"]` renders as clickable links
|
||||
- Syntax highlighting for code blocks
|
||||
- YouTube embeds (if link is YouTube URL)
|
||||
|
||||
---
|
||||
|
||||
## Search (Cmd+K)
|
||||
|
||||
Global search modal with 4-tier relevance:
|
||||
|
||||
1. **Exact title match** — Highest priority
|
||||
2. **Title substring** — High priority
|
||||
3. **FTS content match** — Medium priority
|
||||
4. **Semantic embedding** — Conceptual matches
|
||||
|
||||
**Features:**
|
||||
- Type-ahead instant results
|
||||
- Keyboard navigation (↑↓, Enter)
|
||||
- Click or Enter to open in Focus panel
|
||||
|
||||
---
|
||||
|
||||
## Settings Panel
|
||||
|
||||
**Access:** Settings item in the left navigation
|
||||
|
||||
### Tabs
|
||||
|
||||
| Tab | Purpose |
|
||||
|-----|---------|
|
||||
| **API Keys** | Configure OpenAI/Tavily keys |
|
||||
| **Skills** | View, edit, create skills |
|
||||
| **Tools** | View available tools |
|
||||
| **Database** | Full node table with filters/sorting |
|
||||
| **Logs** | Activity feed (last 100 entries) |
|
||||
| **Context** | Context/system information viewer |
|
||||
| **Agents** | External agent (MCP) configuration |
|
||||
|
||||
---
|
||||
|
||||
## Map View
|
||||
|
||||
Visual graph of your knowledge network.
|
||||
|
||||
**Features:**
|
||||
- Dimension View and Hub View modes
|
||||
- Saved node positions per view mode
|
||||
- Pan/zoom with fit controls and minimap
|
||||
- Node size proportional to edge count
|
||||
- Top nodes labeled by title and dimension color
|
||||
- Click node to highlight connections
|
||||
- Selection shows connected nodes in green
|
||||
|
||||
---
|
||||
|
||||
## Database View
|
||||
|
||||
Full table view of all nodes.
|
||||
|
||||
**Columns:**
|
||||
- Node (title + ID)
|
||||
- Dimensions (folder badges)
|
||||
- Edges (count)
|
||||
- Updated (timestamp)
|
||||
|
||||
**Features:**
|
||||
- Search by title/content
|
||||
- Filter by dimensions
|
||||
- Sort by updated/edges/created
|
||||
- Pagination
|
||||
- Toolbar lives in the pane header for faster switching
|
||||
|
||||
---
|
||||
|
||||
## Dimension Icons
|
||||
|
||||
Each dimension can have a custom Lucide icon.
|
||||
|
||||
**To set:**
|
||||
1. Open Folder View → hover over dimension
|
||||
2. Click edit (pencil) icon
|
||||
3. Choose icon from curated options
|
||||
4. Icons persist in localStorage
|
||||
|
||||
---
|
||||
|
||||
## Node References
|
||||
|
||||
**Format:** `[NODE:id:"title"]`
|
||||
|
||||
**Rendering:**
|
||||
- Clickable labels in node content
|
||||
- Hover shows preview tooltip
|
||||
- Click opens in Focus panel
|
||||
|
||||
---
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Cmd+K` | Open search |
|
||||
| `Cmd+Shift+R` | Refresh all panes |
|
||||
| `Escape` | Close modals/overlays |
|
||||
|
||||
---
|
||||
|
||||
## Design System
|
||||
|
||||
### Colors
|
||||
|
||||
- **Background:** `#0a0a0a` (near black)
|
||||
- **Accent:** Green (`#22c55e`) for actions, selections
|
||||
- **Text:** White (primary), neutral-400 (secondary)
|
||||
|
||||
### Typography
|
||||
|
||||
- **Font:** Geist (monospace feel)
|
||||
- **Sizes:** 11-14px for UI, larger for content
|
||||
|
||||
### Buttons
|
||||
|
||||
- **Primary:** White bg, black text
|
||||
- **Secondary:** Transparent, border, white text
|
||||
- **Toggle:** 28×28px, subtle border, icon only
|
||||
- Capture must succeed when both context and dimensions are omitted.
|
||||
- Focus surfaces should emphasize title, description, source, metadata, and edges.
|
||||
- Node cards may show context when present, but should not depend on it for meaning.
|
||||
|
||||
+30
-156
@@ -1,164 +1,38 @@
|
||||
# MCP Server
|
||||
# MCP Surface
|
||||
|
||||
> Connect Claude Code and other AI assistants to your knowledge base.
|
||||
RA-H exposes MCP tools for direct graph work against the local database or app API.
|
||||
|
||||
**How it works:** RA-OS includes an MCP (Model Context Protocol) server. This lets any MCP-compatible assistant — like Claude Code — search your knowledge graph, add new knowledge, and manage your graph. Everything stays local.
|
||||
## Core MCP Contract
|
||||
|
||||
---
|
||||
- `getContext` returns graph orientation: stats, contexts, hubs, and skills.
|
||||
- `createNode` and `updateNode` accept optional `context_id` but do not require context.
|
||||
- `queryNodes` searches title, description, and source, with optional context filters.
|
||||
- `dimensions` are removed from the MCP contract.
|
||||
|
||||
## Quick Start (Recommended)
|
||||
## Main Tools
|
||||
|
||||
The easiest way is using the npm package:
|
||||
Read:
|
||||
- `getContext`
|
||||
- `queryNodes`
|
||||
- `queryContexts`
|
||||
- `getNodesById`
|
||||
- `queryEdge`
|
||||
- `listSkills`
|
||||
- `readSkill`
|
||||
- `searchContentEmbeddings`
|
||||
- `sqliteQuery`
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"ra-h": {
|
||||
"command": "npx",
|
||||
"args": ["ra-h-mcp-server"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Write:
|
||||
- `createNode`
|
||||
- `updateNode`
|
||||
- `createEdge`
|
||||
- `updateEdge`
|
||||
- `writeSkill`
|
||||
- `deleteSkill`
|
||||
|
||||
Add this to your `~/.claude.json` (Claude Code) or Claude Desktop settings.
|
||||
## Tool Behavior
|
||||
|
||||
**Requirements:**
|
||||
- Node.js 18+ installed
|
||||
|
||||
**That's it.** The database is created automatically on first connection. No need to keep RA-OS running.
|
||||
|
||||
---
|
||||
|
||||
## Alternative: Local Development
|
||||
|
||||
If you're developing RA-OS and want to use the local server:
|
||||
|
||||
### Standalone (No Web App Required)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"ra-h": {
|
||||
"command": "node",
|
||||
"args": ["/path/to/ra-h_os/apps/mcp-server-standalone/index.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
First install dependencies:
|
||||
```bash
|
||||
cd apps/mcp-server-standalone
|
||||
npm install
|
||||
```
|
||||
|
||||
### HTTP Transport (Web App Required)
|
||||
|
||||
If you want real-time UI updates when nodes are created:
|
||||
|
||||
1. Start RA-OS: `npm run dev`
|
||||
2. Configure:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"ra-h": {
|
||||
"url": "http://127.0.0.1:44145/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Available Tools
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `getContext` | Get graph overview — stats, contexts, hub nodes, dimensions, recent activity. Called first automatically. |
|
||||
| `queryContexts` | List contexts, inspect a context, or search contexts by name/description. |
|
||||
| `createNode` | Create a new node (title/source/dimensions) |
|
||||
| `queryNodes` | Search existing nodes by keyword |
|
||||
| `updateNode` | Update an existing node |
|
||||
| `getNodesById` | Get nodes by ID |
|
||||
| `createEdge` | Create relationship between nodes |
|
||||
| `updateEdge` | Update an edge explanation |
|
||||
| `queryEdge` | Query existing edges |
|
||||
| `queryDimensions` | List all dimensions |
|
||||
| `createDimension` | Create a new dimension |
|
||||
| `updateDimension` | Update/rename dimension |
|
||||
| `deleteDimension` | Delete a dimension |
|
||||
| `listSkills` | List available skills |
|
||||
| `readSkill` | Read a skill by name |
|
||||
| `writeSkill` | Create or update a custom skill |
|
||||
| `deleteSkill` | Delete a custom skill |
|
||||
| `searchContentEmbeddings` | Search extracted source content |
|
||||
| `sqliteQuery` | Run read-only SQL queries |
|
||||
|
||||
---
|
||||
|
||||
## What to Expect
|
||||
|
||||
Once connected, the MCP server instructs Claude to:
|
||||
|
||||
1. **Call `getContext` first** to orient itself (contexts, hub nodes, dimensions, stats, available skills)
|
||||
2. **Proactively capture knowledge** — when a new insight, decision, person, or reference surfaces, it proposes a specific node (title, dimensions, description) so you can approve with minimal friction
|
||||
3. **Read skills for complex tasks** — skills provide reusable procedural instructions for graph operations and workflows
|
||||
4. **Search before creating** to avoid duplicates
|
||||
|
||||
You don't need to ask Claude to use your knowledge base — it will offer when it spots something worth saving.
|
||||
|
||||
---
|
||||
|
||||
## Example Usage
|
||||
|
||||
Once connected, you can ask your AI assistant:
|
||||
|
||||
```
|
||||
"What's in my knowledge graph?"
|
||||
"Search RA-H for what I wrote about product strategy"
|
||||
"Add this conversation summary to RA-H as a new node"
|
||||
"Find all nodes with the 'research' dimension"
|
||||
"Create an edge between node 123 and node 456"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `apps/mcp-server-standalone/` | **Standalone server (direct SQLite, recommended)** |
|
||||
| `apps/mcp-server/server.js` | HTTP MCP server |
|
||||
| `apps/mcp-server/stdio-server.js` | STDIO bridge to HTTP server |
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
- The MCP server only binds to `127.0.0.1` — localhost only
|
||||
- No authentication required (local access only)
|
||||
- All data persisted to `~/Library/Application Support/RA-H/db/rah.sqlite`
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Database not found"
|
||||
|
||||
The MCP server auto-creates the database on first connection (v1.1.0+). If you're on an older version, run RA-OS once to create it:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### "Tools not showing" (npm package)
|
||||
|
||||
1. Make sure Node.js 18+ is installed: `node --version`
|
||||
2. Try running manually: `npx ra-h-mcp-server`
|
||||
3. Restart Claude Code
|
||||
|
||||
### "Connection refused" (HTTP method)
|
||||
|
||||
1. Make sure RA-OS is running: `npm run dev`
|
||||
2. Check the port: `lsof -i :44145`
|
||||
- Always search before creating.
|
||||
- Prefer explicit context assignment when the primary scope is clear.
|
||||
- Do not expect automatic context assignment.
|
||||
- Judge graph quality by node quality and edges, not taxonomy completeness.
|
||||
|
||||
+16
-33
@@ -1,40 +1,23 @@
|
||||
# RA-OS
|
||||
# Open Source Surface
|
||||
|
||||
This is **RA-OS** — a minimal, local-first knowledge graph UI with MCP server integration.
|
||||
The open-source RA-H surface should match the main app contract:
|
||||
|
||||
## What is RA-OS?
|
||||
- no runtime `dimensions` model,
|
||||
- optional soft `contexts`,
|
||||
- no automatic context assignment on write,
|
||||
- node quality driven by title, description, source, metadata, and edges.
|
||||
|
||||
RA-OS is a stripped-down version of [RA-H](https://ra-h.app) focused on:
|
||||
## Important App Routes
|
||||
|
||||
- **2-panel UI** for browsing and editing your knowledge graph
|
||||
- **MCP server** so external AI agents (like Claude Code) can access your notes
|
||||
- **Local SQLite** database with vector search
|
||||
- **BYO API keys** — no cloud dependencies
|
||||
- `app/api/nodes/`
|
||||
- `app/api/contexts/`
|
||||
- `app/api/edges/`
|
||||
- `app/api/rah/chat/`
|
||||
- extraction routes
|
||||
- eval / verification helpers
|
||||
|
||||
## What's NOT Included
|
||||
## Porting Rule
|
||||
|
||||
RA-OS intentionally excludes:
|
||||
Main `ra-h` ships first.
|
||||
|
||||
- Chat interface (use external agents via MCP)
|
||||
- Voice features
|
||||
- Built-in AI agents
|
||||
- Auth/subscription system
|
||||
- Desktop packaging (Tauri)
|
||||
|
||||
## Relationship to RA-H
|
||||
|
||||
This repo (`ra-h_os`) is derived from the private `ra-h` repository. Shared features (database, UI components, MCP server) are synced from private to public.
|
||||
|
||||
## Getting Started
|
||||
|
||||
See [README.md](../README.md) for installation.
|
||||
|
||||
## Contributing
|
||||
|
||||
- **Bug reports** — Open an issue
|
||||
- **Feature requests** — Open an issue
|
||||
- **Pull requests** — Welcome for bug fixes and improvements
|
||||
|
||||
## License
|
||||
|
||||
MIT — See [LICENSE](../LICENSE)
|
||||
`ra-h_os` is a required follow-up port of the same contract, not a place to preserve older taxonomy behavior.
|
||||
|
||||
Reference in New Issue
Block a user