Files
Profa 2253d05618 feat: flatten project structure — archive v2, promote v3 to root
Remove the nested v3/ subdirectory by moving all active source code,
tests, configs, and assets directly to the project root. Archive v2/
(dead code, 847MB) to v2-archive.tar.gz.

Key changes:
- Move v3/src/ → src/, v3/tests/ → tests/, v3/packages/ → packages/
- Move v3/tsconfig.json, v3/vitest.config.ts to root
- Merge v3/package.json into root package.json (ESM, scripts, deps, exports)
- Merge v3/scripts/ into scripts/, v3/implementation/ into docs/implementation/
- Update all CI workflows to remove "cd v3 &&" and v3/ path prefixes
- Fix all init installer path resolution (3-level-up → 2-level-up)
- Fix hooks to use "node ./dist/cli/bundle.js" instead of bare "aqe"
- Update settings.json ADR/DDD directories to docs/implementation/
- Fix helper scripts (statusline, adr-compliance, ddd-tracker, guidance-hooks)
- Update 58 agent definitions: aqe/v3/ → aqe/ memory namespaces
- Update 15 guidance shards: v3/src/ → src/ path references
- Fix sync interfaces: remove v3/ and v2/ path references
- Fix test path calculations (process.cwd() + '..' no longer needed)
- Fix flaky perf test threshold (500ms → 1000ms for CI environments)
- Fix complexity-analyzer test to match ADR-051 keyword-based eligibility

Build passes, 17,901 tests pass, CLI and MCP bundles verified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:35:41 +00:00

817 lines
26 KiB
TypeScript

/**
* Agentic QE v3 - SONA Pattern Persistence Unit Tests
*
* Tests for PersistentSONAEngine with SQLite persistence.
*/
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import * as fs from 'fs';
import {
PersistentSONAEngine,
createPersistentSONAEngine,
createPersistentSONAEngineSync,
DEFAULT_PERSISTENT_SONA_CONFIG,
type PersistentSONAConfig,
} from '../../../../src/integrations/ruvector/sona-persistence';
import type { QESONAPattern, QEPatternType } from '../../../../src/integrations/ruvector/sona-wrapper';
import type { RLState, RLAction, DomainName } from '../../../../src/integrations/rl-suite/interfaces';
import { resetUnifiedPersistence } from '../../../../src/kernel/unified-persistence';
import { resetUnifiedMemory } from '../../../../src/kernel/unified-memory';
// Test database path
const TEST_DB_DIR = '/tmp/agentic-qe-test-sona-persistence';
const TEST_DB_PATH = `${TEST_DB_DIR}/memory.db`;
// Ensure test directory exists
function setupTestDb(): void {
if (!fs.existsSync(TEST_DB_DIR)) {
fs.mkdirSync(TEST_DB_DIR, { recursive: true });
}
// Clean up any existing test database
if (fs.existsSync(TEST_DB_PATH)) {
fs.unlinkSync(TEST_DB_PATH);
}
if (fs.existsSync(`${TEST_DB_PATH}-wal`)) {
fs.unlinkSync(`${TEST_DB_PATH}-wal`);
}
if (fs.existsSync(`${TEST_DB_PATH}-shm`)) {
fs.unlinkSync(`${TEST_DB_PATH}-shm`);
}
}
// Test fixtures
function createTestState(overrides: Partial<RLState> = {}): RLState {
return {
id: `state-${Date.now()}-${Math.random().toString(36).slice(2)}`,
features: new Array(384).fill(0).map(() => Math.random()),
...overrides,
};
}
function createTestAction(overrides: Partial<RLAction> = {}): RLAction {
return {
type: 'test-action',
value: 'execute-test',
...overrides,
};
}
function createTestOutcome(overrides: Partial<QESONAPattern['outcome']> = {}): QESONAPattern['outcome'] {
return {
reward: 0.8,
success: true,
quality: 0.9,
...overrides,
};
}
function createTestConfig(overrides: Partial<PersistentSONAConfig> = {}): PersistentSONAConfig {
return {
domain: 'test-generation' as DomainName,
loadOnInit: true,
autoSaveInterval: 0, // Immediate saves for testing
...overrides,
};
}
describe('PersistentSONAEngine', () => {
beforeEach(async () => {
// Reset singletons before each test
resetUnifiedPersistence();
resetUnifiedMemory();
// Setup fresh test database
setupTestDb();
// Set environment to use test database
process.env.AQE_DB_PATH = TEST_DB_PATH;
});
afterEach(async () => {
resetUnifiedPersistence();
resetUnifiedMemory();
delete process.env.AQE_DB_PATH;
});
describe('Factory Functions', () => {
it('should create engine with async factory', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
expect(engine).toBeInstanceOf(PersistentSONAEngine);
expect(engine.isInitialized()).toBe(true);
expect(engine.getDomain()).toBe('test-generation');
await engine.close();
});
it('should create engine with sync factory (requires manual init)', () => {
const engine = createPersistentSONAEngineSync(createTestConfig());
expect(engine).toBeInstanceOf(PersistentSONAEngine);
expect(engine.isInitialized()).toBe(false);
});
});
describe('Initialization', () => {
it('should initialize successfully', async () => {
const config = createTestConfig();
const engine = new PersistentSONAEngine(config);
await engine.initialize();
expect(engine.isInitialized()).toBe(true);
expect(engine.getDomain()).toBe(config.domain);
await engine.close();
});
it('should be idempotent (multiple initialize calls)', async () => {
const engine = new PersistentSONAEngine(createTestConfig());
await engine.initialize();
await engine.initialize();
await engine.initialize();
expect(engine.isInitialized()).toBe(true);
await engine.close();
});
it('should throw if not initialized when storing', async () => {
const engine = new PersistentSONAEngine(createTestConfig());
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
expect(() => {
engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
}).toThrow('not initialized');
});
});
describe('Pattern Storage', () => {
let engine: PersistentSONAEngine;
beforeEach(async () => {
engine = await createPersistentSONAEngine(createTestConfig());
});
afterEach(async () => {
await engine?.close();
});
it('should create and store a pattern', () => {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
const pattern = engine.createPattern(
state,
action,
outcome,
'test-generation',
'test-generation',
{ testMetadata: true }
);
expect(pattern).toBeDefined();
expect(pattern.id).toBeDefined();
expect(pattern.type).toBe('test-generation');
expect(pattern.domain).toBe('test-generation');
expect(pattern.outcome.success).toBe(true);
expect(pattern.outcome.quality).toBe(0.9);
expect(pattern.metadata).toEqual({ testMetadata: true });
});
it('should store and retrieve patterns', () => {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
const pattern = engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
const allPatterns = engine.getAllPatterns();
expect(allPatterns.length).toBeGreaterThanOrEqual(1);
expect(allPatterns.some((p) => p.id === pattern.id)).toBe(true);
});
it('should store multiple patterns in batch', () => {
const patterns: QESONAPattern[] = [];
for (let i = 0; i < 5; i++) {
const state = createTestState();
const action = createTestAction({ type: `action-${i}` });
const outcome = createTestOutcome({ quality: 0.5 + i * 0.1 });
patterns.push({
id: `batch-pattern-${i}`,
type: 'test-generation' as QEPatternType,
domain: 'test-generation' as DomainName,
stateEmbedding: state.features,
action,
outcome,
confidence: 0.5,
usageCount: 0,
createdAt: new Date(),
});
}
engine.storePatternsBatch(patterns);
const allPatterns = engine.getAllPatterns();
expect(allPatterns.length).toBeGreaterThanOrEqual(5);
});
});
describe('Persistence', () => {
it('should persist patterns to SQLite', async () => {
const config = createTestConfig();
const engine1 = await createPersistentSONAEngine(config);
// Create a pattern
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
const pattern = engine1.createPattern(
state,
action,
outcome,
'test-generation',
'test-generation',
{ persistent: true }
);
// Get persisted stats
const stats1 = await engine1.getPersistedStats();
expect(stats1.totalPatterns).toBeGreaterThanOrEqual(1);
await engine1.close();
// Create new engine - should load persisted patterns
const engine2 = await createPersistentSONAEngine({ ...config, loadOnInit: true });
const patterns = engine2.getAllPatterns();
expect(patterns.length).toBeGreaterThanOrEqual(1);
const loadedPattern = patterns.find((p) => p.id === pattern.id);
expect(loadedPattern).toBeDefined();
expect(loadedPattern?.type).toBe('test-generation');
await engine2.close();
});
it('should load patterns on initialization', async () => {
const config = createTestConfig({ domain: 'test-generation' as DomainName });
// Session 1: Create patterns
const engine1 = await createPersistentSONAEngine(config);
for (let i = 0; i < 3; i++) {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine1.createPattern(
state,
action,
outcome,
'test-generation',
'test-generation'
);
}
const count1 = engine1.getAllPatterns().length;
await engine1.close();
// Session 2: Load patterns
const engine2 = await createPersistentSONAEngine(config);
const count2 = engine2.getAllPatterns().length;
expect(count2).toBeGreaterThanOrEqual(count1);
await engine2.close();
});
it('should export and import patterns', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
// Create patterns
for (let i = 0; i < 3; i++) {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
}
// Export patterns
const exported = engine.exportPatterns();
expect(exported.length).toBeGreaterThanOrEqual(3);
// Clear and reimport
engine.clearMemory();
expect(engine.getAllPatterns().length).toBe(0);
engine.importPatterns(exported);
expect(engine.getAllPatterns().length).toBeGreaterThanOrEqual(3);
await engine.close();
});
});
describe('Pattern Operations', () => {
let engine: PersistentSONAEngine;
beforeEach(async () => {
engine = await createPersistentSONAEngine(createTestConfig());
});
afterEach(async () => {
await engine?.close();
});
it('should get patterns by type', () => {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
engine.createPattern(state, action, outcome, 'defect-prediction', 'test-generation');
const testGenPatterns = engine.getPatternsByType('test-generation');
expect(testGenPatterns.length).toBeGreaterThanOrEqual(1);
expect(testGenPatterns.every((p) => p.type === 'test-generation')).toBe(true);
});
it('should get patterns by domain', () => {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
const domainPatterns = engine.getPatternsByDomain('test-generation');
expect(domainPatterns.length).toBeGreaterThanOrEqual(1);
expect(domainPatterns.every((p) => p.domain === 'test-generation')).toBe(true);
});
it('should update pattern with feedback', () => {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
const pattern = engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
const initialConfidence = pattern.confidence;
// Positive feedback should increase confidence
const updated = engine.updatePattern(pattern.id, true, 0.95);
expect(updated).toBe(true);
const updatedPattern = engine.getPattern(pattern.id);
expect(updatedPattern).toBeDefined();
// Confidence should change based on feedback
expect(updatedPattern?.confidence).toBeDefined();
});
it('should delete a pattern', () => {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
const pattern = engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
expect(engine.getPattern(pattern.id)).toBeDefined();
const deleted = engine.deletePattern(pattern.id);
expect(deleted).toBe(true);
});
});
describe('Cross-Agent Pattern Sharing', () => {
it('should access persisted patterns from different domains', async () => {
// Engine 1: test-generation domain
const engine1 = await createPersistentSONAEngine(
createTestConfig({ domain: 'test-generation' as DomainName })
);
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine1.createPattern(state, action, outcome, 'test-generation', 'test-generation');
await engine1.close();
// Engine 2: defect-prediction domain
const engine2 = await createPersistentSONAEngine(
createTestConfig({ domain: 'defect-prediction' as DomainName })
);
// Should be able to access patterns from other domains via persisted query
const testGenPatterns = await engine2.getPersistedPatternsByDomain('test-generation');
expect(testGenPatterns.length).toBeGreaterThanOrEqual(1);
expect(testGenPatterns[0].domain).toBe('test-generation');
await engine2.close();
});
it('should import patterns from another domain', async () => {
// Engine 1: test-generation domain creates patterns
const engine1 = await createPersistentSONAEngine(
createTestConfig({ domain: 'test-generation' as DomainName })
);
for (let i = 0; i < 3; i++) {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine1.createPattern(state, action, outcome, 'test-generation', 'test-generation');
}
await engine1.close();
// Engine 2: defect-prediction domain imports patterns
const engine2 = await createPersistentSONAEngine(
createTestConfig({ domain: 'defect-prediction' as DomainName })
);
const imported = await engine2.importPatternsFromDomain('test-generation');
expect(imported).toBeGreaterThanOrEqual(1);
// Imported patterns should now be in the defect-prediction domain
const domainPatterns = engine2.getPatternsByDomain('defect-prediction');
expect(domainPatterns.length).toBeGreaterThanOrEqual(imported);
await engine2.close();
});
it('should get all persisted patterns', async () => {
// Create patterns in different domains
const engine1 = await createPersistentSONAEngine(
createTestConfig({ domain: 'test-generation' as DomainName })
);
engine1.createPattern(
createTestState(),
createTestAction(),
createTestOutcome(),
'test-generation',
'test-generation'
);
await engine1.close();
const engine2 = await createPersistentSONAEngine(
createTestConfig({ domain: 'defect-prediction' as DomainName })
);
engine2.createPattern(
createTestState(),
createTestAction(),
createTestOutcome(),
'defect-prediction',
'defect-prediction'
);
// Get all persisted patterns
const allPatterns = await engine2.getAllPersistedPatterns();
expect(allPatterns.length).toBeGreaterThanOrEqual(2);
// Should have patterns from both domains
const domains = new Set(allPatterns.map((p) => p.domain));
expect(domains.size).toBeGreaterThanOrEqual(2);
await engine2.close();
});
});
describe('Learning Operations', () => {
let engine: PersistentSONAEngine;
beforeEach(async () => {
engine = await createPersistentSONAEngine(createTestConfig());
});
afterEach(async () => {
await engine?.close();
});
// Note: Micro-LoRA test skipped - requires specific dimension match from @ruvector/sona
// The persistence layer is independent of this low-level functionality
it.skip('should apply Micro-LoRA transformation', () => {
const input = new Array(256).fill(0).map(() => Math.random());
const output = engine.applyMicroLora(input);
expect(output).toBeDefined();
expect(output.length).toBe(input.length);
});
it('should run learning cycle', () => {
// Create some patterns first
for (let i = 0; i < 5; i++) {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
}
// Force learning cycle
const result = engine.forceLearn();
expect(result).toBeDefined();
});
it('should tick for background learning', () => {
// Tick should not throw
const result = engine.tick();
// Result is null if no learning was due
expect(result === null || typeof result === 'string').toBe(true);
});
});
describe('Pattern Adaptation', () => {
let engine: PersistentSONAEngine;
beforeEach(async () => {
engine = await createPersistentSONAEngine(createTestConfig());
});
afterEach(async () => {
await engine?.close();
});
it('should adapt pattern based on context', async () => {
// Store a pattern first
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
// Adapt using similar state
const result = await engine.adaptPattern(state, 'test-generation', 'test-generation');
expect(result).toBeDefined();
expect(result.adaptationTimeMs).toBeDefined();
expect(typeof result.adaptationTimeMs).toBe('number');
expect(result.reasoning).toBeDefined();
});
it('should recall pattern for context', () => {
const state = createTestState();
const action = createTestAction();
const outcome = createTestOutcome();
engine.createPattern(state, action, outcome, 'test-generation', 'test-generation');
// May return null if no good match found (which is valid)
const recalled = engine.recallPattern(state, 'test-generation', 'test-generation');
// Just verify it doesn't throw
expect(recalled === null || typeof recalled === 'object').toBe(true);
});
});
describe('Statistics', () => {
it('should return in-memory statistics', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
const stats = engine.getStats();
expect(stats).toHaveProperty('totalPatterns');
expect(stats).toHaveProperty('patternsByType');
expect(stats).toHaveProperty('avgAdaptationTimeMs');
await engine.close();
});
it('should return persisted statistics', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
// Create some patterns
for (let i = 0; i < 3; i++) {
engine.createPattern(
createTestState(),
createTestAction(),
createTestOutcome(),
'test-generation',
'test-generation'
);
}
const stats = await engine.getPersistedStats();
expect(stats).toHaveProperty('totalPatterns');
expect(stats).toHaveProperty('uniqueTypes');
expect(stats).toHaveProperty('uniqueDomains');
expect(stats).toHaveProperty('avgConfidence');
expect(stats).toHaveProperty('byType');
expect(stats).toHaveProperty('byDomain');
expect(stats.totalPatterns).toBeGreaterThanOrEqual(3);
await engine.close();
});
});
describe('Maintenance', () => {
it('should prune old patterns', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
// Create patterns
for (let i = 0; i < 3; i++) {
engine.createPattern(
createTestState(),
createTestAction(),
createTestOutcome(),
'test-generation',
'test-generation'
);
}
// Prune patterns older than 30 days (should not delete recent patterns)
const pruned = await engine.pruneOldPatterns(30);
expect(pruned).toBe(0); // Nothing should be pruned
await engine.close();
});
it('should sync in-memory to SQLite', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
// Create patterns
engine.createPattern(
createTestState(),
createTestAction(),
createTestOutcome(),
'test-generation',
'test-generation'
);
// Sync should not throw
await engine.sync();
// Verify persisted
const stats = await engine.getPersistedStats();
expect(stats.totalPatterns).toBeGreaterThanOrEqual(1);
await engine.close();
});
it('should reload patterns from SQLite', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
// Create and persist
engine.createPattern(
createTestState(),
createTestAction(),
createTestOutcome(),
'test-generation',
'test-generation'
);
// Clear in-memory
engine.clearMemory();
expect(engine.getAllPatterns().length).toBe(0);
// Reload
await engine.reload();
expect(engine.getAllPatterns().length).toBeGreaterThanOrEqual(1);
await engine.close();
});
it('should clear domain patterns', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
// Create patterns
engine.createPattern(
createTestState(),
createTestAction(),
createTestOutcome(),
'test-generation',
'test-generation'
);
expect(engine.getAllPatterns().length).toBeGreaterThanOrEqual(1);
// Clear domain patterns
engine.clearDomainPatterns();
expect(engine.getAllPatterns().length).toBe(0);
await engine.close();
});
});
describe('Configuration', () => {
it('should get configuration', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
const config = engine.getConfig();
expect(config).toHaveProperty('hiddenDim');
expect(config).toHaveProperty('embeddingDim');
await engine.close();
});
it('should enable/disable engine', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
expect(engine.isEnabled()).toBe(true);
engine.setEnabled(false);
expect(engine.isEnabled()).toBe(false);
engine.setEnabled(true);
expect(engine.isEnabled()).toBe(true);
await engine.close();
});
});
describe('Cleanup', () => {
it('should close cleanly', async () => {
const engine = await createPersistentSONAEngine(createTestConfig());
await engine.close();
expect(engine.isInitialized()).toBe(false);
});
it('should flush pending saves on close', async () => {
// Create engine with delayed saves
const engine = await createPersistentSONAEngine(
createTestConfig({ autoSaveInterval: 5000 }) // 5 second delay
);
// Create pattern (creates pending save)
engine.createPattern(
createTestState(),
createTestAction(),
createTestOutcome(),
'test-generation',
'test-generation'
);
// Close should flush pending saves
await engine.close();
// Verify by creating new engine
const engine2 = await createPersistentSONAEngine(createTestConfig());
// Pattern should be persisted
const stats = await engine2.getPersistedStats();
expect(stats.totalPatterns).toBeGreaterThanOrEqual(1);
await engine2.close();
});
});
describe('Integration', () => {
it('should work end-to-end across sessions', async () => {
const domain = 'test-generation' as DomainName;
const config = createTestConfig({ domain });
// Session 1: Create patterns
const engine1 = await createPersistentSONAEngine(config);
for (let i = 0; i < 5; i++) {
const state = createTestState();
const action = createTestAction({ type: `action-${i}` });
const outcome = createTestOutcome({ quality: 0.6 + i * 0.08 });
const pattern = engine1.createPattern(state, action, outcome, 'test-generation', domain);
// Update with feedback
engine1.updatePattern(pattern.id, true, 0.9);
}
const stats1 = await engine1.getPersistedStats();
expect(stats1.totalPatterns).toBeGreaterThanOrEqual(5);
await engine1.close();
// Session 2: Load and continue
const engine2 = await createPersistentSONAEngine(config);
// Patterns should be loaded
expect(engine2.getAllPatterns().length).toBeGreaterThanOrEqual(5);
// Create more patterns
for (let i = 5; i < 10; i++) {
const state = createTestState();
const action = createTestAction({ type: `action-${i}` });
const outcome = createTestOutcome({ quality: 0.9 });
engine2.createPattern(state, action, outcome, 'test-generation', domain);
}
const stats2 = await engine2.getPersistedStats();
expect(stats2.totalPatterns).toBeGreaterThanOrEqual(10);
// Adapt based on stored patterns
const result = await engine2.adaptPattern(
createTestState(),
'test-generation',
domain
);
expect(result.adaptationTimeMs).toBeDefined();
await engine2.close();
});
});
});