Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions npm/packages/ruvector/bin/cli.js
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -8157,7 +8157,9 @@ mcpCmd.command('info')
console.log(chalk.dim(' rvf_delete - Delete vectors by ID'));
console.log(chalk.dim(' rvf_status - Get store status'));
console.log(chalk.dim(' rvf_compact - Compact store'));
console.log(chalk.dim(' rvf_derive - COW-branch to child store'));
console.log(chalk.dim(' rvf_derive - Lineage-only child (no COW)'));
console.log(chalk.dim(' rvf_branch - Full COW branch with Rust CowEngine'));
console.log(chalk.dim(' rvf_freeze - Freeze/snapshot store (read-only)'));
console.log(chalk.dim(' rvf_segments - List file segments'));
console.log(chalk.dim(' rvf_examples - List example .rvf files'));

Expand Down Expand Up @@ -8303,7 +8305,9 @@ mcpCmd.command('tools')
{ name: 'rvf_delete', desc: 'Delete vectors by ID' },
{ name: 'rvf_status', desc: 'Store status' },
{ name: 'rvf_compact', desc: 'Compact store' },
{ name: 'rvf_derive', desc: 'COW-branch child store' },
{ name: 'rvf_derive', desc: 'Lineage-only child (no COW)' },
{ name: 'rvf_branch', desc: 'Full COW branch with Rust CowEngine' },
{ name: 'rvf_freeze', desc: 'Freeze/snapshot store' },
{ name: 'rvf_segments', desc: 'List file segments' },
{ name: 'rvf_examples', desc: 'Example .rvf files' },
],
Expand Down
54 changes: 53 additions & 1 deletion npm/packages/ruvector/bin/mcp-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@ const TOOLS = [
},
{
name: 'rvf_derive',
description: 'Derive a child RVF store from a parent using copy-on-write branching',
description: 'Derive a child RVF store from a parent for lineage tracking (records parent hash and depth, no COW — child cannot see parent vectors). For full COW branching with parent inheritance, use rvf_branch.',
inputSchema: {
type: 'object',
properties: {
Expand All @@ -1363,6 +1363,30 @@ const TOOLS = [
required: ['parent_path', 'child_path']
}
},
{
name: 'rvf_branch',
description: 'Create a full COW (Copy-on-Write) branch from a parent RVF store using the Rust CowEngine. The child inherits all parent vectors and queries return parent ∪ child. Re-ingested vectors in the child override parent on id collision; deletes in the child hide inherited vectors. The branch stores only its own edits on disk. The parent should be frozen first via rvf_freeze for production data.',
inputSchema: {
type: 'object',
properties: {
parent_path: { type: 'string', description: 'Path to parent .rvf store to branch from' },
child_path: { type: 'string', description: 'Path for the new branch .rvf store' },
label: { type: 'string', description: 'Optional human-readable branch label' }
},
required: ['parent_path', 'child_path']
}
},
{
name: 'rvf_freeze',
description: 'Freeze (snapshot) an RVF store, preventing further writes. Required before branching production data to guarantee parent immutability. Sets read_only flag and freezes the CowEngine epoch.',
inputSchema: {
type: 'object',
properties: {
path: { type: 'string', description: 'Path to .rvf store to freeze' }
},
required: ['path']
}
},
{
name: 'rvf_segments',
description: 'List all segments in an RVF file (VEC, INDEX, KERNEL, EBPF, WITNESS, etc.)',
Expand Down Expand Up @@ -3369,6 +3393,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
}
}

case 'rvf_branch': {
try {
const safeParent = validateRvfPath(args.parent_path);
const safeChild = validateRvfPath(args.child_path);
const { openRvfStore, rvfBranch, rvfClose } = require('../dist/core/rvf-wrapper.js');
const store = await openRvfStore(safeParent);
const childStore = await rvfBranch(store, safeChild);
const childStatus = await childStore.status();
await rvfClose(childStore);
return { content: [{ type: 'text', text: JSON.stringify({ success: true, parent: safeParent, child: safeChild, childStatus }, null, 2) }] };
} catch (e) {
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
}
}

case 'rvf_freeze': {
try {
const safePath = validateRvfPath(args.path);
const { openRvfStore, rvfFreeze, rvfClose } = require('../dist/core/rvf-wrapper.js');
const store = await openRvfStore(safePath);
await rvfFreeze(store);
await rvfClose(store);
return { content: [{ type: 'text', text: JSON.stringify({ success: true, path: safePath, readOnly: true }, null, 2) }] };
} catch (e) {
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
}
}

case 'rvf_segments': {
try {
const safePath = validateRvfPath(args.path);
Expand Down
24 changes: 24 additions & 0 deletions npm/packages/ruvector/src/core/rvf-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,30 @@ export async function rvfDerive(
return store.derive(childPath);
}

/**
* Create a full COW (Copy-on-Write) branch from a parent store.
* The child inherits all parent vectors — queries return parent ∪ child.
* Child overrides parent on id collision; deletes in child hide inherited vectors.
* Uses the Rust CowEngine with cluster-based COW and dual-graph ANN query merge.
* The parent should be frozen before branching for production data.
*/
export async function rvfBranch(
store: RvfStore,
childPath: string,
): Promise<RvfStore> {
return store.branch(childPath);
}

/**
* Freeze (snapshot) a store, preventing further writes.
* Required before branching to guarantee parent immutability.
*/
export async function rvfFreeze(
store: RvfStore,
): Promise<void> {
return store.freeze();
}

/**
* Close the store, releasing the writer lock and flushing data.
*/
Expand Down