mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-09-14 14:01:28 +08:00
7eb505d22f
Wire @ruvector/ruvllm as intelligence coordinator (SonaCoordinator, ContrastiveTrainer, TrainingPipeline) and @ruvector/graph-node as native graph database for agent relationships and causal edges. - Fix ESM/CJS import: use createRequire pattern for CJS packages - Eager loading of all backends during initialization - Wire into neural status, hooks_intelligence, ruvllm_status CLI/MCP - Auto-trigger background learning on trajectory-end - Auto-save LoRA checkpoints after neural train - Graph-node records agents on spawn, causal edges, swarm teams - Fix community issues #1511, #1509, #1507, #1506, #1505 - Real Product Quantization with k-means trained codebooks - SONA native routing with 5-tier fallback - Embedding fallback transparency warnings - Plugin peer dep fixes (semver ranges, removed phantom deps) 32 test files, 1762 tests passing, 0 regressions. Co-Authored-By: claude-flow <ruv@ruv.net>
93 lines
4.1 KiB
TypeScript
93 lines
4.1 KiB
TypeScript
/**
|
|
* ADR-087: @ruvector/graph-node native graph database backend tests
|
|
*
|
|
* Tests the wrapper module's exports and CJS import pattern.
|
|
* The actual graph-node integration is verified by the e2e node script.
|
|
*/
|
|
import { describe, it, expect } from 'vitest';
|
|
|
|
describe('ADR-087: graph-node backend', () => {
|
|
describe('module exports', () => {
|
|
it('exports all expected functions', async () => {
|
|
const mod = await import('../src/ruvector/graph-backend.js');
|
|
expect(typeof mod.isGraphBackendAvailable).toBe('function');
|
|
expect(typeof mod.addNode).toBe('function');
|
|
expect(typeof mod.addEdge).toBe('function');
|
|
expect(typeof mod.addHyperedge).toBe('function');
|
|
expect(typeof mod.getNeighbors).toBe('function');
|
|
expect(typeof mod.getGraphStats).toBe('function');
|
|
expect(typeof mod.recordCausalEdge).toBe('function');
|
|
expect(typeof mod.recordCollaboration).toBe('function');
|
|
expect(typeof mod.recordSwarmTeam).toBe('function');
|
|
});
|
|
});
|
|
|
|
describe('graceful degradation', () => {
|
|
it('getGraphStats returns unavailable when graph-node not loaded', async () => {
|
|
// In test environment, graph-node may or may not be available
|
|
const { getGraphStats } = await import('../src/ruvector/graph-backend.js');
|
|
const stats = await getGraphStats();
|
|
expect(stats).toHaveProperty('totalNodes');
|
|
expect(stats).toHaveProperty('totalEdges');
|
|
expect(stats).toHaveProperty('avgDegree');
|
|
expect(stats).toHaveProperty('backend');
|
|
expect(['graph-node', 'unavailable']).toContain(stats.backend);
|
|
});
|
|
|
|
it('addNode returns string or null', async () => {
|
|
const { addNode } = await import('../src/ruvector/graph-backend.js');
|
|
const result = await addNode({ id: 'test-1', type: 'test' });
|
|
// Either a node ID string or null if backend unavailable
|
|
expect(result === null || typeof result === 'string').toBe(true);
|
|
});
|
|
|
|
it('getNeighbors returns array', async () => {
|
|
const { getNeighbors } = await import('../src/ruvector/graph-backend.js');
|
|
const result = await getNeighbors('nonexistent', 2);
|
|
expect(Array.isArray(result)).toBe(true);
|
|
});
|
|
|
|
it('recordCausalEdge returns result with backend', async () => {
|
|
const { recordCausalEdge } = await import('../src/ruvector/graph-backend.js');
|
|
const result = await recordCausalEdge('a', 'b', 'caused');
|
|
expect(result).toHaveProperty('success');
|
|
expect(result).toHaveProperty('backend');
|
|
});
|
|
|
|
it('recordSwarmTeam returns result', async () => {
|
|
const { recordSwarmTeam } = await import('../src/ruvector/graph-backend.js');
|
|
const result = await recordSwarmTeam(['a', 'b'], 'mesh');
|
|
expect(result).toHaveProperty('success');
|
|
});
|
|
});
|
|
|
|
describe('CJS import pattern', () => {
|
|
it('source uses createRequire for @ruvector/graph-node', async () => {
|
|
const { readFileSync } = await import('fs');
|
|
const { join } = await import('path');
|
|
const content = readFileSync(join(import.meta.dirname, '..', 'src', 'ruvector', 'graph-backend.ts'), 'utf8');
|
|
expect(content).toContain('createRequire');
|
|
expect(content).toContain("'@ruvector/graph-node'");
|
|
// Should NOT use ESM dynamic import for graph-node
|
|
expect(content).not.toMatch(/await import\(['"]@ruvector\/graph-node['"]\)/);
|
|
});
|
|
});
|
|
|
|
describe('type exports', () => {
|
|
it('exports GraphNodeData interface shape', async () => {
|
|
const { addNode } = await import('../src/ruvector/graph-backend.js');
|
|
// TypeScript ensures this matches GraphNodeData
|
|
const data = { id: 'x', type: 'agent', name: 'test', properties: { foo: 'bar' } };
|
|
const result = await addNode(data);
|
|
expect(result === null || typeof result === 'string').toBe(true);
|
|
});
|
|
|
|
it('exports GraphEdgeData interface shape', async () => {
|
|
const { addEdge } = await import('../src/ruvector/graph-backend.js');
|
|
const data = { from: 'a', to: 'b', label: 'test', description: 'desc', weight: 0.5, properties: {} };
|
|
const result = await addEdge(data);
|
|
expect(result === null || typeof result === 'string').toBe(true);
|
|
});
|
|
});
|
|
});
|