mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-09-14 14:01:28 +08:00
126c23a0fc
Scaffolds plugins/ruflo-graph-intelligence/ — the RuFlo Graph Intelligence Engine. Built on sublinear-time-solver@^1.7.0. Three-layer architecture: Neural / Graph Intelligence / Complexity. Phase 1 deliverables: - package.json @ 0.1.0-alpha.1 - domain/types.ts — SparseMatrix, ComplexityClass (12 tiers + fitsBudget + isEdgeSafe), CoherenceReport, PageRankQuery/Result, SolveQuery/Result, SolveOnChangeQuery, structured GraphIntelError taxonomy - domain/adapter.ts — SublinearAdapter interface, AdapterRegistry (singleton) - infrastructure/solver-bridge.ts — coherenceScore, singleEntryPageRank (forward-push), conjugateGradient, neumann, solveOnChange, hashResult, observedComplexity, runPageRank/runSolve/runSolveOnChange entry points - mcp-tools/index.ts — 6 MCP tools under sublinear/*: page-rank-entry / solve / solve-on-change / analyze / feasibility / jl-embed All threaded with maxComplexityClass + coherenceThreshold budget gates. - tests: 37/37 passing — solver-bridge (coherence, PR, CG, Neumann, solve-on-change, hash determinism), adapter-registry (CRUD + singleton), mcp-tools (happy path, graph-not-found, coherence-rejected, complexity-budget-exceeded) CI guard (#2044 follow-up): - .github/workflows/v3-ci.yml — adds plugins/ruflo-graph-intelligence/** to both push and pull_request path filters - New job: ruflo-graph-intelligence build + test smoke. Installs (npm ci with --legacy-peer-deps because the plugin is outside the v3 pnpm workspace), typechecks, builds, runs vitest. Cross-platform via Node 22. Co-Authored-By: RuFlo <ruv@ruv.net>
70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
/**
|
|
* ruflo-graph-intelligence — Adapter Registry Tests (ADR-123 Phase 1)
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach } from 'vitest';
|
|
import { AdapterRegistry, getRegistry, resetRegistry } from '../src/domain/adapter.js';
|
|
import type { SublinearAdapter } from '../src/domain/adapter.js';
|
|
import type { SparseMatrix } from '../src/domain/types.js';
|
|
|
|
function fakeAdapter(graphId: string): SublinearAdapter {
|
|
return {
|
|
graphId,
|
|
ownerPlugin: 'test',
|
|
async exportAsSparseMatrix(): Promise<SparseMatrix> {
|
|
return {
|
|
graphId,
|
|
size: 1,
|
|
entries: [{ row: 0, col: 0, value: 1 }],
|
|
nodeIndex: { only: 0 },
|
|
indexNode: ['only'],
|
|
capturedAt: 't',
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
describe('AdapterRegistry', () => {
|
|
beforeEach(() => resetRegistry());
|
|
|
|
it('registers + retrieves an adapter', () => {
|
|
const r = new AdapterRegistry();
|
|
const a = fakeAdapter('test:graph');
|
|
r.register(a);
|
|
expect(r.get('test:graph')).toBe(a);
|
|
});
|
|
|
|
it('throws on duplicate registration', () => {
|
|
const r = new AdapterRegistry();
|
|
r.register(fakeAdapter('test:graph'));
|
|
expect(() => r.register(fakeAdapter('test:graph'))).toThrow(/already registered/);
|
|
});
|
|
|
|
it('unregister removes the adapter', () => {
|
|
const r = new AdapterRegistry();
|
|
r.register(fakeAdapter('test:graph'));
|
|
expect(r.unregister('test:graph')).toBe(true);
|
|
expect(r.get('test:graph')).toBeUndefined();
|
|
});
|
|
|
|
it('list returns all adapters', () => {
|
|
const r = new AdapterRegistry();
|
|
r.register(fakeAdapter('a'));
|
|
r.register(fakeAdapter('b'));
|
|
expect(r.list()).toHaveLength(2);
|
|
});
|
|
|
|
it('getRegistry returns a singleton', () => {
|
|
const r1 = getRegistry();
|
|
const r2 = getRegistry();
|
|
expect(r1).toBe(r2);
|
|
});
|
|
|
|
it('resetRegistry forces a new instance', () => {
|
|
const r1 = getRegistry();
|
|
resetRegistry();
|
|
const r2 = getRegistry();
|
|
expect(r1).not.toBe(r2);
|
|
});
|
|
});
|