Skip to content

feat: RAG memory graph with interlinked traversal#13

Merged
ForLoopCodes merged 1 commit intomainfrom
rag
Mar 3, 2026
Merged

feat: RAG memory graph with interlinked traversal#13
ForLoopCodes merged 1 commit intomainfrom
rag

Conversation

@ForLoopCodes
Copy link
Copy Markdown
Owner

Adds RAG memory graph engine with Obsidian-style interlinked traversal, 6 new MCP tools (17 total), 24 tests, and landing page updates reflecting RAG capabilities.

Copilot AI review requested due to automatic review settings March 3, 2026 22:41
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
contextplus Ready Ready Preview, Comment Mar 3, 2026 10:41pm

@ForLoopCodes ForLoopCodes merged commit ccdf8b7 into main Mar 3, 2026
3 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “memory graph” subsystem to support RAG-style persistence and Obsidian-like interlinked traversal, exposing it via new MCP tools and updating docs/landing copy to reflect the new capabilities.

Changes:

  • Introduces a JSON-persisted memory graph core with node upsert, typed relations, similarity auto-linking, traversal, and pruning.
  • Adds MCP tool wrappers + registers 6 new MCP tools on the server.
  • Adds a comprehensive test suite and updates landing/docs messaging for RAG + memory graph features.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/core/memory-graph.ts Implements the persistent property graph, traversal, decay scoring, pruning, and interlinking.
src/tools/memory-tools.ts Adds MCP-friendly wrapper functions that format output for the new graph operations.
src/index.ts Registers the 6 new MCP tools (upsert_memory_node, create_relation, etc.) with Zod schemas.
test/main/memory-graph.test.mjs Adds tests for core graph behavior and MCP wrapper formatting.
landing/src/components/ToolDiagram.tsx Adds a “RAG Functions” panel/label to the landing tool diagram.
landing/src/components/IsometricDiagram.tsx Adds new memory/RAG capability cards and tweaks layout spacing.
landing/src/components/InstructionsSection.tsx Documents the new memory tools + updates tool count and guidance text.
landing/src/components/IdeSetup.tsx Updates displayed env config snippet (removes some env vars).
landing/src/app/page.tsx Updates hero copy to mention RAG.
landing/src/app/layout.tsx Updates metadata description to mention RAG.
landing/src/app/api/instructions/route.ts Updates the served instructions text to include memory graph + tools.
README.md Adds “Memory & RAG” tool section and updates architecture/tool counts.
INSTRUCTIONS.md Updates instruction content to include memory graph + tools and tool counts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread landing/src/app/page.tsx
>
Context+ is an MCP server designed for developers who demand 99%
accuracy. By combining Tree-sitter AST parsing & Spectral
accuracy. By combining RAG, Treesitter AST & Spectral
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling/branding inconsistency: this sentence uses “Treesitter”, but other docs (e.g. README) use “Tree-sitter”. Consider using “Tree-sitter” consistently.

Suggested change
accuracy. By combining RAG, Treesitter AST & Spectral
accuracy. By combining RAG, Tree-sitter AST & Spectral

Copilot uses AI. Check for mistakes.
y1="0"
x2="0"
y2="6"
stroke={isDark ? "#000000" : "#000000"}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ternary is redundant: stroke is set to #000000 for both dark and light modes, which likely wasn’t intended and makes the conditional misleading. Consider either removing the conditional or using different stroke colors for each theme.

Suggested change
stroke={isDark ? "#000000" : "#000000"}
stroke="#000000"

Copilot uses AI. Check for mistakes.
Comment thread src/core/memory-graph.ts
Comment on lines +106 to +115
function scheduleSave(rootDir: string): void {
const existing = saveTimeout.get(rootDir);
if (existing) clearTimeout(existing);
savePending.set(rootDir, true);
saveTimeout.set(rootDir, setTimeout(() => {
if (savePending.get(rootDir)) {
persistGraph(rootDir).catch(() => {}).finally(() => savePending.set(rootDir, false));
}
}, 500));
}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scheduleSave can drop updates: if a save is in-flight and scheduleSave(rootDir) is called again, the earlier persistGraph(...).finally(() => savePending.set(rootDir, false)) may flip savePending back to false and prevent the newly-scheduled timer from persisting the latest changes. Consider tracking an in-flight save promise / revision counter per rootDir, or only clearing the pending flag if no newer writes were scheduled after the save started.

Copilot uses AI. Check for mistakes.
Comment thread src/core/memory-graph.ts
Comment on lines +155 to +167
export async function createRelation(rootDir: string, sourceId: string, targetId: string, relation: RelationType, weight?: number, metadata?: Record<string, string>): Promise<MemoryEdge | null> {
const graph = await loadGraph(rootDir);
if (!graph.nodes[sourceId] || !graph.nodes[targetId]) return null;

const duplicate = Object.values(graph.edges).find(e =>
e.source === sourceId && e.target === targetId && e.relation === relation
);
if (duplicate) {
duplicate.weight = weight ?? duplicate.weight;
if (metadata) Object.assign(duplicate.metadata, metadata);
scheduleSave(rootDir);
return duplicate;
}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edge directionality is inconsistent: traversal (getEdgesForNode + getNeighborId) treats edges as undirected, but createRelation de-dupes only when source === sourceId && target === targetId. Calling createRelation(A,B,rel) and later createRelation(B,A,rel) will create two edges that traversal treats as equivalent. Either (a) enforce directionality in traversal, or (b) canonicalize/de-dupe relations regardless of direction for symmetric relations (especially similar_to).

Copilot uses AI. Check for mistakes.
Comment thread src/index.ts
source_id: z.string().describe("ID of the source memory node."),
target_id: z.string().describe("ID of the target memory node."),
relation: z.enum(["relates_to", "depends_on", "implements", "references", "similar_to", "contains"]).describe("Relationship type between nodes."),
weight: z.number().optional().describe("Edge weight 0-1. Higher = stronger relationship. Default: 1.0."),
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The weight input is documented as 0–1, but the Zod schema accepts any number. Passing negatives or very large values will skew decay/scoring and pruning behavior. Consider adding validation (e.g., .min(0).max(1)) or normalizing weights consistently with the other tools’ patterns.

Suggested change
weight: z.number().optional().describe("Edge weight 0-1. Higher = stronger relationship. Default: 1.0."),
weight: z.number().min(0).max(1).optional().describe("Edge weight 0-1. Higher = stronger relationship. Default: 1.0."),

Copilot uses AI. Check for mistakes.
await mkdir(join(FIXTURE, ".mcp_data"), { recursive: true });
});

after(async () => {
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fixture directory is removed in after(), but memory-graph persists via a 500ms setTimeout. A pending save triggered by the last test can run after this rm() and recreate test/_memory_graph_fixtures (because ensureMcpDataDir uses recursive mkdir). Consider waiting for pending saves to flush before cleanup (or exposing a test-only flush/close helper from the module).

Suggested change
after(async () => {
after(async () => {
// Wait for any pending debounced saves (memory-graph uses a 500ms timeout)
await new Promise((resolve) => setTimeout(resolve, 600));

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +28
import { describe, it, before, after, beforeEach } from "node:test";
import assert from "node:assert/strict";
import { mkdir, rm, readFile } from "fs/promises";
import { join, resolve } from "path";
import { Ollama } from "ollama";

const {
upsertNode,
createRelation,
searchGraph,
pruneStaleLinks,
addInterlinkedContext,
retrieveWithTraversal,
getGraphStats,
} = await import("../../build/core/memory-graph.js");

const {
toolUpsertMemoryNode,
toolCreateRelation,
toolSearchMemoryGraph,
toolPruneStaleLinks,
toolAddInterlinkedContext,
toolRetrieveWithTraversal,
} = await import("../../build/tools/memory-tools.js");

const FIXTURE = resolve("test/_memory_graph_fixtures");
let embedCounter = 0;

Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several unused imports/variables here (beforeEach, readFile, and embedCounter is incremented but never asserted). If this repo runs linting on tests, this will fail CI; otherwise it still adds noise. Consider removing unused imports/vars or asserting the counter to validate batching behavior.

Copilot uses AI. Check for mistakes.
title: "Context+ // Semantic Intelligence for Large-Scale Engineering",
description:
"MCP server designed for developers who demand 99% accuracy. Tree-sitter AST parsing, Spectral Clustering, and Obsidian-style linking.",
"MCP server designed for developers who demand 99% accuracy. RAG, Treesitter AST, Spectral Clustering, and Obsidian-style linking.",
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling/branding inconsistency: the project uses “Tree-sitter” elsewhere, but this copy uses “Treesitter”. Consider standardizing to “Tree-sitter” for consistency and searchability.

Suggested change
"MCP server designed for developers who demand 99% accuracy. RAG, Treesitter AST, Spectral Clustering, and Obsidian-style linking.",
"MCP server designed for developers who demand 99% accuracy. RAG, Tree-sitter AST, Spectral Clustering, and Obsidian-style linking.",

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants