import { afterEach, describe, expect, it } from 'bun:test' import { existsSync, mkdtempSync, rmSync } from 'fs' import { tmpdir } from 'os' import { join } from 'path' import { DebugKnowledgeStore } from '../../src/knowledge/DebugKnowledgeStore.js' import { LearnedMemoryStore } from '../../src/knowledge/LearnedMemoryStore.js' describe('C1: Knowledge Store schema alignment', () => { const created: string[] = [] afterEach(() => { for (const dir of created.splice(0)) rmSync(dir, { recursive: true, force: true }) }) it('DebugKnowledgeStore stores and queries records from .air/local', () => { const root = mkdtempSync(join(tmpdir(), 'air-debug-store-')) created.push(root) const store = new DebugKnowledgeStore(root) store.open() const now = new Date().toISOString() store.insert({ id: 'debug_1', failure_signature: 'compiler:error:missing-header', task_id: 'task_1', root_cause: 'missing include path', fix_ref: 'fix://1', summary: 'Add include path before rebuilding', evidence_json: JSON.stringify(['evi_1']), verification_json: JSON.stringify(['build passed']), created_at: now, updated_at: now, metadata_json: JSON.stringify({ source: 'test' }), }) expect(existsSync(join(root, '.air', 'local', 'debug-records.db'))).toBe(true) expect(existsSync(join(root, '.air', 'shared', 'debug-records.db'))).toBe(false) expect(store.lookup_by_signature('compiler:error:missing-header')).toHaveLength(1) expect(store.lookup_by_task('task_1')[0]).toMatchObject({ id: 'debug_1', failure_signature: 'compiler:error:missing-header', task_id: 'task_1', root_cause: 'missing include path', fix_ref: 'fix://1', summary: 'Add include path before rebuilding', }) store.update('debug_1', { summary: 'Updated summary', updated_at: now }) expect(store.lookup_by_signature('compiler:error:missing-header')[0].summary).toBe('Updated summary') }) it('LearnedMemoryStore stores candidates/promoted memories from .air/local', () => { const root = mkdtempSync(join(tmpdir(), 'air-memory-store-')) created.push(root) const store = new LearnedMemoryStore(root) store.open() const now = new Date().toISOString() store.insert({ id: 'mem_1', memory_type: 'project_rule', summary: 'Use Bun for package scripts', content: 'Project commands should use Bun unless explicitly overridden.', source_entity_type: 'task', source_entity_id: 'task_1', status: 'candidate', created_at: now, updated_at: now, metadata_json: JSON.stringify({ confidence: 0.8 }), }) expect(existsSync(join(root, '.air', 'local', 'learned-memory.db'))).toBe(true) expect(existsSync(join(root, '.air', 'shared', 'learned-memory.db'))).toBe(false) expect(store.lookup_by_type('project_rule')).toHaveLength(1) expect(store.lookup_by_type('project_rule')[0]).toMatchObject({ id: 'mem_1', memory_type: 'project_rule', status: 'candidate', source_entity_type: 'task', source_entity_id: 'task_1', }) store.update_status('mem_1', 'promoted') expect(store.lookup_by_type('project_rule')[0].status).toBe('promoted') store.update_status('mem_1', 'archived') expect(store.lookup_by_type('project_rule')).toHaveLength(0) }) })