UNPKG

agentic-qe

Version:

Agentic Quality Engineering Fleet System - AI-driven quality management platform

1,260 lines 55.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SwarmMemoryManager = void 0; const sqlite3_1 = __importDefault(require("sqlite3")); const path = __importStar(require("path")); const fs = __importStar(require("fs-extra")); const AccessControl_1 = require("./AccessControl"); /** * SwarmMemoryManager - Manages persistent memory for agent swarm coordination * * Features: * - SQLite-based persistent storage with 12-table schema * - Partitioned key-value store * - TTL-based expiration with different policies per table * - Hint/blackboard pattern support * - Pattern-based retrieval * - 5-level access control (private, team, swarm, public, system) * - Agent-based permissions (read, write, delete, share) * - Event stream tracking (30-day TTL) * - Workflow checkpointing (never expires) * - Consensus gating (7-day TTL) * - Artifact manifests (never expires) * - GOAP planning support * - OODA loop tracking * - Session resumability * - Agent lifecycle management */ class SwarmMemoryManager { constructor(dbPath = ':memory:') { this.db = null; this.initialized = false; // TTL policy constants (in seconds) this.TTL_POLICY = { artifacts: 0, // Never expire shared: 1800, // 30 minutes patterns: 604800, // 7 days events: 2592000, // 30 days workflow_state: 0, // Never expire consensus: 604800 // 7 days }; this.dbPath = dbPath; this.accessControl = new AccessControl_1.AccessControl(); this.aclCache = new Map(); } run(sql, params = []) { return new Promise((resolve, reject) => { this.db.run(sql, params, (err) => { if (err) reject(err); else resolve(); }); }); } get(sql, params = []) { return new Promise((resolve, reject) => { this.db.get(sql, params, (err, row) => { if (err) reject(err); else resolve(row); }); }); } all(sql, params = []) { return new Promise((resolve, reject) => { this.db.all(sql, params, (err, rows) => { if (err) reject(err); else resolve((rows || [])); }); }); } async initialize() { if (this.initialized) { return; } // Ensure directory exists for file-based DB if (this.dbPath !== ':memory:') { await fs.ensureDir(path.dirname(this.dbPath)); } this.db = new sqlite3_1.default.Database(this.dbPath); // Create memory entries table with access control fields await this.run(` CREATE TABLE IF NOT EXISTS memory_entries ( key TEXT NOT NULL, partition TEXT NOT NULL DEFAULT 'default', value TEXT NOT NULL, metadata TEXT, created_at INTEGER NOT NULL, expires_at INTEGER, owner TEXT, access_level TEXT DEFAULT 'private', team_id TEXT, swarm_id TEXT, PRIMARY KEY (key, partition) ) `); // Create ACL table for advanced permissions await this.run(` CREATE TABLE IF NOT EXISTS memory_acl ( resource_id TEXT PRIMARY KEY, owner TEXT NOT NULL, access_level TEXT NOT NULL, team_id TEXT, swarm_id TEXT, granted_permissions TEXT, blocked_agents TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL ) `); // Create hints table for blackboard pattern await this.run(` CREATE TABLE IF NOT EXISTS hints ( id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL, created_at INTEGER NOT NULL, expires_at INTEGER ) `); // Table 3: Events (TTL: 30 days) await this.run(` CREATE TABLE IF NOT EXISTS events ( id TEXT PRIMARY KEY, type TEXT NOT NULL, payload TEXT NOT NULL, timestamp INTEGER NOT NULL, source TEXT NOT NULL, ttl INTEGER NOT NULL DEFAULT ${this.TTL_POLICY.events}, expires_at INTEGER ) `); // Table 4: Workflow State (TTL: never expires) await this.run(` CREATE TABLE IF NOT EXISTS workflow_state ( id TEXT PRIMARY KEY, step TEXT NOT NULL, status TEXT NOT NULL, checkpoint TEXT NOT NULL, sha TEXT NOT NULL, ttl INTEGER NOT NULL DEFAULT ${this.TTL_POLICY.workflow_state}, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL ) `); // Table 5: Patterns (TTL: 7 days) await this.run(` CREATE TABLE IF NOT EXISTS patterns ( id TEXT PRIMARY KEY, pattern TEXT NOT NULL UNIQUE, confidence REAL NOT NULL, usage_count INTEGER NOT NULL DEFAULT 0, metadata TEXT, ttl INTEGER NOT NULL DEFAULT ${this.TTL_POLICY.patterns}, expires_at INTEGER, created_at INTEGER NOT NULL ) `); // Table 6: Consensus State (TTL: 7 days) await this.run(` CREATE TABLE IF NOT EXISTS consensus_state ( id TEXT PRIMARY KEY, decision TEXT NOT NULL, proposer TEXT NOT NULL, votes TEXT NOT NULL, quorum INTEGER NOT NULL, status TEXT NOT NULL, version INTEGER NOT NULL DEFAULT 1, ttl INTEGER NOT NULL DEFAULT ${this.TTL_POLICY.consensus}, expires_at INTEGER, created_at INTEGER NOT NULL ) `); // Table 7: Performance Metrics await this.run(` CREATE TABLE IF NOT EXISTS performance_metrics ( id TEXT PRIMARY KEY, metric TEXT NOT NULL, value REAL NOT NULL, unit TEXT NOT NULL, timestamp INTEGER NOT NULL, agent_id TEXT ) `); // Table 8: Artifacts (TTL: never expires) await this.run(` CREATE TABLE IF NOT EXISTS artifacts ( id TEXT PRIMARY KEY, kind TEXT NOT NULL, path TEXT NOT NULL, sha256 TEXT NOT NULL, tags TEXT NOT NULL, metadata TEXT, ttl INTEGER NOT NULL DEFAULT ${this.TTL_POLICY.artifacts}, created_at INTEGER NOT NULL ) `); // Table 9: Sessions (for resumability) await this.run(` CREATE TABLE IF NOT EXISTS sessions ( id TEXT PRIMARY KEY, mode TEXT NOT NULL, state TEXT NOT NULL, checkpoints TEXT NOT NULL, created_at INTEGER NOT NULL, last_resumed INTEGER ) `); // Table 10: Agent Registry await this.run(` CREATE TABLE IF NOT EXISTS agent_registry ( id TEXT PRIMARY KEY, type TEXT NOT NULL, capabilities TEXT NOT NULL, status TEXT NOT NULL, performance TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL ) `); // Table 11: GOAP State await this.run(` CREATE TABLE IF NOT EXISTS goap_goals ( id TEXT PRIMARY KEY, conditions TEXT NOT NULL, cost INTEGER NOT NULL, priority TEXT, created_at INTEGER NOT NULL ) `); await this.run(` CREATE TABLE IF NOT EXISTS goap_actions ( id TEXT PRIMARY KEY, preconditions TEXT NOT NULL, effects TEXT NOT NULL, cost INTEGER NOT NULL, agent_type TEXT, created_at INTEGER NOT NULL ) `); await this.run(` CREATE TABLE IF NOT EXISTS goap_plans ( id TEXT PRIMARY KEY, goal_id TEXT NOT NULL, sequence TEXT NOT NULL, total_cost INTEGER NOT NULL, created_at INTEGER NOT NULL ) `); // Table 12: OODA Cycles await this.run(` CREATE TABLE IF NOT EXISTS ooda_cycles ( id TEXT PRIMARY KEY, phase TEXT NOT NULL, observations TEXT, orientation TEXT, decision TEXT, action TEXT, timestamp INTEGER NOT NULL, completed INTEGER DEFAULT 0, result TEXT ) `); // Create indexes for performance await this.run(`CREATE INDEX IF NOT EXISTS idx_memory_partition ON memory_entries(partition)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_memory_expires ON memory_entries(expires_at)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_memory_owner ON memory_entries(owner)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_memory_access ON memory_entries(access_level)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_hints_key ON hints(key)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_hints_expires ON hints(expires_at)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_acl_owner ON memory_acl(owner)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_events_type ON events(type)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_events_source ON events(source)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_events_expires ON events(expires_at)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_workflow_status ON workflow_state(status)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_patterns_confidence ON patterns(confidence)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_patterns_expires ON patterns(expires_at)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_consensus_status ON consensus_state(status)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_consensus_expires ON consensus_state(expires_at)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_metrics_metric ON performance_metrics(metric)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_metrics_agent ON performance_metrics(agent_id)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_artifacts_kind ON artifacts(kind)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_agent_status ON agent_registry(status)`); await this.run(`CREATE INDEX IF NOT EXISTS idx_ooda_phase ON ooda_cycles(phase)`); this.initialized = true; } async store(key, value, options = {}) { if (!this.db) { throw new Error('Memory manager not initialized'); } const partition = options.partition || 'default'; const owner = options.owner || 'system'; const accessLevel = options.accessLevel || AccessControl_1.AccessLevel.PRIVATE; const createdAt = Date.now(); const expiresAt = options.ttl ? createdAt + (options.ttl * 1000) : null; const metadata = options.metadata ? JSON.stringify(options.metadata) : null; // Check write permission if updating existing entry const existing = await this.get(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]); if (existing && options.owner) { // Verify write permission const permCheck = this.accessControl.checkPermission({ agentId: options.owner, resourceOwner: existing.owner, accessLevel: existing.access_level, permission: AccessControl_1.Permission.WRITE, teamId: options.teamId, resourceTeamId: existing.team_id, swarmId: options.swarmId, resourceSwarmId: existing.swarm_id }); if (!permCheck.allowed) { throw new AccessControl_1.AccessControlError(`Write denied: ${permCheck.reason}`); } } await this.run(`INSERT OR REPLACE INTO memory_entries (key, partition, value, metadata, created_at, expires_at, owner, access_level, team_id, swarm_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ key, partition, JSON.stringify(value), metadata, createdAt, expiresAt, owner, accessLevel, options.teamId || null, options.swarmId || null ]); } async retrieve(key, options = {}) { if (!this.db) { throw new Error('Memory manager not initialized'); } const partition = options.partition || 'default'; const now = Date.now(); let query = `SELECT value, owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`; const params = [key, partition]; if (!options.includeExpired) { query += ` AND (expires_at IS NULL OR expires_at > ?)`; params.push(now); } const row = await this.get(query, params); if (!row) { return null; } // Check read permission if agentId provided if (options.agentId) { const permCheck = this.accessControl.checkPermission({ agentId: options.agentId, resourceOwner: row.owner, accessLevel: row.access_level, permission: AccessControl_1.Permission.READ, teamId: options.teamId, resourceTeamId: row.team_id, swarmId: options.swarmId, resourceSwarmId: row.swarm_id, isSystemAgent: options.isSystemAgent }); if (!permCheck.allowed) { throw new AccessControl_1.AccessControlError(`Read denied: ${permCheck.reason}`); } } return JSON.parse(row.value); } async query(pattern, options = {}) { if (!this.db) { throw new Error('Memory manager not initialized'); } const partition = options.partition || 'default'; const now = Date.now(); let query = `SELECT key, value, partition, created_at, expires_at, owner, access_level, team_id, swarm_id FROM memory_entries WHERE partition = ? AND key LIKE ?`; const params = [partition, pattern]; if (!options.includeExpired) { query += ` AND (expires_at IS NULL OR expires_at > ?)`; params.push(now); } const rows = await this.all(query, params); // Filter by access control if agentId provided const filteredRows = options.agentId ? rows.filter((row) => { const permCheck = this.accessControl.checkPermission({ agentId: options.agentId, resourceOwner: row.owner, accessLevel: row.access_level, permission: AccessControl_1.Permission.READ, teamId: options.teamId, resourceTeamId: row.team_id, swarmId: options.swarmId, resourceSwarmId: row.swarm_id, isSystemAgent: options.isSystemAgent }); return permCheck.allowed; }) : rows; return filteredRows.map((row) => ({ key: row.key, value: JSON.parse(row.value), partition: row.partition, createdAt: row.created_at, expiresAt: row.expires_at, owner: row.owner, accessLevel: row.access_level, teamId: row.team_id, swarmId: row.swarm_id })); } async delete(key, partition = 'default', options = {}) { if (!this.db) { throw new Error('Memory manager not initialized'); } // Check delete permission if agentId provided if (options.agentId) { const row = await this.get(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]); if (row) { const permCheck = this.accessControl.checkPermission({ agentId: options.agentId, resourceOwner: row.owner, accessLevel: row.access_level, permission: AccessControl_1.Permission.DELETE, teamId: options.teamId, resourceTeamId: row.team_id, swarmId: options.swarmId, resourceSwarmId: row.swarm_id, isSystemAgent: options.isSystemAgent }); if (!permCheck.allowed) { throw new AccessControl_1.AccessControlError(`Delete denied: ${permCheck.reason}`); } } } await this.run(`DELETE FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]); // Clean up ACL if exists const resourceId = `${partition}:${key}`; await this.run(`DELETE FROM memory_acl WHERE resource_id = ?`, [resourceId]); this.aclCache.delete(resourceId); } async clear(partition = 'default') { if (!this.db) { throw new Error('Memory manager not initialized'); } await this.run(`DELETE FROM memory_entries WHERE partition = ?`, [partition]); } async postHint(hint) { if (!this.db) { throw new Error('Memory manager not initialized'); } const createdAt = Date.now(); const expiresAt = hint.ttl ? createdAt + (hint.ttl * 1000) : null; await this.run(`INSERT INTO hints (key, value, created_at, expires_at) VALUES (?, ?, ?, ?)`, [hint.key, JSON.stringify(hint.value), createdAt, expiresAt]); } async readHints(pattern) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const rows = await this.all(`SELECT key, value, created_at, expires_at FROM hints WHERE key LIKE ? AND (expires_at IS NULL OR expires_at > ?) ORDER BY created_at DESC`, [pattern, now]); return rows.map((row) => ({ key: row.key, value: JSON.parse(row.value), createdAt: row.created_at, expiresAt: row.expires_at })); } async cleanExpired() { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); // Clean memory entries await this.run(`DELETE FROM memory_entries WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]); // Clean hints await this.run(`DELETE FROM hints WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]); // Clean events await this.run(`DELETE FROM events WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]); // Clean patterns await this.run(`DELETE FROM patterns WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]); // Clean consensus await this.run(`DELETE FROM consensus_state WHERE expires_at IS NOT NULL AND expires_at <= ?`, [now]); return 0; } async close() { if (this.db) { return new Promise((resolve, reject) => { this.db.close((err) => { if (err) reject(err); else { this.db = null; this.initialized = false; resolve(); } }); }); } } async stats() { if (!this.db) { throw new Error('Memory manager not initialized'); } const entriesCount = await this.get(`SELECT COUNT(*) as count FROM memory_entries`); const hintsCount = await this.get(`SELECT COUNT(*) as count FROM hints`); const eventsCount = await this.get(`SELECT COUNT(*) as count FROM events`); const workflowsCount = await this.get(`SELECT COUNT(*) as count FROM workflow_state`); const patternsCount = await this.get(`SELECT COUNT(*) as count FROM patterns`); const consensusCount = await this.get(`SELECT COUNT(*) as count FROM consensus_state`); const metricsCount = await this.get(`SELECT COUNT(*) as count FROM performance_metrics`); const artifactsCount = await this.get(`SELECT COUNT(*) as count FROM artifacts`); const sessionsCount = await this.get(`SELECT COUNT(*) as count FROM sessions`); const agentsCount = await this.get(`SELECT COUNT(*) as count FROM agent_registry`); const goapGoalsCount = await this.get(`SELECT COUNT(*) as count FROM goap_goals`); const goapActionsCount = await this.get(`SELECT COUNT(*) as count FROM goap_actions`); const goapPlansCount = await this.get(`SELECT COUNT(*) as count FROM goap_plans`); const oodaCyclesCount = await this.get(`SELECT COUNT(*) as count FROM ooda_cycles`); const partitionsResult = await this.all(`SELECT DISTINCT partition FROM memory_entries`); const accessLevelsResult = await this.all(`SELECT access_level, COUNT(*) as count FROM memory_entries GROUP BY access_level`); const accessLevels = {}; accessLevelsResult.forEach(row => { accessLevels[row.access_level] = row.count; }); return { totalEntries: entriesCount?.count || 0, totalHints: hintsCount?.count || 0, totalEvents: eventsCount?.count || 0, totalWorkflows: workflowsCount?.count || 0, totalPatterns: patternsCount?.count || 0, totalConsensus: consensusCount?.count || 0, totalMetrics: metricsCount?.count || 0, totalArtifacts: artifactsCount?.count || 0, totalSessions: sessionsCount?.count || 0, totalAgents: agentsCount?.count || 0, totalGOAPGoals: goapGoalsCount?.count || 0, totalGOAPActions: goapActionsCount?.count || 0, totalGOAPPlans: goapPlansCount?.count || 0, totalOODACycles: oodaCyclesCount?.count || 0, partitions: partitionsResult.map((row) => row.partition), accessLevels }; } // ============================================================================ // Table 3: Events (TTL: 30 days) // ============================================================================ async storeEvent(event) { if (!this.db) { throw new Error('Memory manager not initialized'); } const id = event.id || `event-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const timestamp = event.timestamp || Date.now(); const ttl = event.ttl !== undefined ? event.ttl : this.TTL_POLICY.events; const expiresAt = ttl > 0 ? timestamp + (ttl * 1000) : null; await this.run(`INSERT INTO events (id, type, payload, timestamp, source, ttl, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?)`, [id, event.type, JSON.stringify(event.payload), timestamp, event.source, ttl, expiresAt]); return id; } async queryEvents(type) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const rows = await this.all(`SELECT id, type, payload, timestamp, source, ttl FROM events WHERE type = ? AND (expires_at IS NULL OR expires_at > ?) ORDER BY timestamp DESC`, [type, now]); return rows.map((row) => ({ id: row.id, type: row.type, payload: JSON.parse(row.payload), timestamp: row.timestamp, source: row.source, ttl: row.ttl })); } async getEventsBySource(source) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const rows = await this.all(`SELECT id, type, payload, timestamp, source, ttl FROM events WHERE source = ? AND (expires_at IS NULL OR expires_at > ?) ORDER BY timestamp DESC`, [source, now]); return rows.map((row) => ({ id: row.id, type: row.type, payload: JSON.parse(row.payload), timestamp: row.timestamp, source: row.source, ttl: row.ttl })); } // ============================================================================ // Table 4: Workflow State (TTL: never expires) // ============================================================================ async storeWorkflowState(workflow) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const ttl = workflow.ttl !== undefined ? workflow.ttl : this.TTL_POLICY.workflow_state; await this.run(`INSERT OR REPLACE INTO workflow_state (id, step, status, checkpoint, sha, ttl, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [workflow.id, workflow.step, workflow.status, JSON.stringify(workflow.checkpoint), workflow.sha, ttl, now, now]); } async getWorkflowState(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT id, step, status, checkpoint, sha, ttl, created_at, updated_at FROM workflow_state WHERE id = ?`, [id]); if (!row) { throw new Error(`Workflow state not found: ${id}`); } return { id: row.id, step: row.step, status: row.status, checkpoint: JSON.parse(row.checkpoint), sha: row.sha, ttl: row.ttl, createdAt: row.created_at, updatedAt: row.updated_at }; } async updateWorkflowState(id, updates) { if (!this.db) { throw new Error('Memory manager not initialized'); } const current = await this.getWorkflowState(id); const now = Date.now(); await this.run(`UPDATE workflow_state SET step = ?, status = ?, checkpoint = ?, sha = ?, updated_at = ? WHERE id = ?`, [ updates.step || current.step, updates.status || current.status, JSON.stringify(updates.checkpoint || current.checkpoint), updates.sha || current.sha, now, id ]); } async queryWorkflowsByStatus(status) { if (!this.db) { throw new Error('Memory manager not initialized'); } const rows = await this.all(`SELECT id, step, status, checkpoint, sha, ttl, created_at, updated_at FROM workflow_state WHERE status = ?`, [status]); return rows.map((row) => ({ id: row.id, step: row.step, status: row.status, checkpoint: JSON.parse(row.checkpoint), sha: row.sha, ttl: row.ttl, createdAt: row.created_at, updatedAt: row.updated_at })); } // ============================================================================ // Table 5: Patterns (TTL: 7 days) // ============================================================================ async storePattern(pattern) { if (!this.db) { throw new Error('Memory manager not initialized'); } const id = pattern.id || `pattern-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const now = Date.now(); const ttl = pattern.ttl !== undefined ? pattern.ttl : this.TTL_POLICY.patterns; const expiresAt = ttl > 0 ? now + (ttl * 1000) : null; await this.run(`INSERT OR REPLACE INTO patterns (id, pattern, confidence, usage_count, metadata, ttl, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ id, pattern.pattern, pattern.confidence, pattern.usageCount, pattern.metadata ? JSON.stringify(pattern.metadata) : null, ttl, expiresAt, now ]); return id; } async getPattern(patternName) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const row = await this.get(`SELECT id, pattern, confidence, usage_count, metadata, ttl, created_at FROM patterns WHERE pattern = ? AND (expires_at IS NULL OR expires_at > ?)`, [patternName, now]); if (!row) { throw new Error(`Pattern not found: ${patternName}`); } return { id: row.id, pattern: row.pattern, confidence: row.confidence, usageCount: row.usage_count, metadata: row.metadata ? JSON.parse(row.metadata) : undefined, ttl: row.ttl, createdAt: row.created_at }; } async incrementPatternUsage(patternName) { if (!this.db) { throw new Error('Memory manager not initialized'); } await this.run(`UPDATE patterns SET usage_count = usage_count + 1 WHERE pattern = ?`, [patternName]); } async queryPatternsByConfidence(threshold) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const rows = await this.all(`SELECT id, pattern, confidence, usage_count, metadata, ttl, created_at FROM patterns WHERE confidence >= ? AND (expires_at IS NULL OR expires_at > ?) ORDER BY confidence DESC`, [threshold, now]); return rows.map((row) => ({ id: row.id, pattern: row.pattern, confidence: row.confidence, usageCount: row.usage_count, metadata: row.metadata ? JSON.parse(row.metadata) : undefined, ttl: row.ttl, createdAt: row.created_at })); } // ============================================================================ // Table 6: Consensus State (TTL: 7 days) // ============================================================================ async createConsensusProposal(proposal) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const ttl = proposal.ttl !== undefined ? proposal.ttl : this.TTL_POLICY.consensus; const expiresAt = ttl > 0 ? now + (ttl * 1000) : null; await this.run(`INSERT INTO consensus_state (id, decision, proposer, votes, quorum, status, version, ttl, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ proposal.id, proposal.decision, proposal.proposer, JSON.stringify(proposal.votes), proposal.quorum, proposal.status, proposal.version || 1, ttl, expiresAt, now ]); } async getConsensusProposal(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const row = await this.get(`SELECT id, decision, proposer, votes, quorum, status, version, ttl, created_at FROM consensus_state WHERE id = ? AND (expires_at IS NULL OR expires_at > ?)`, [id, now]); if (!row) { throw new Error(`Consensus proposal not found: ${id}`); } return { id: row.id, decision: row.decision, proposer: row.proposer, votes: JSON.parse(row.votes), quorum: row.quorum, status: row.status, version: row.version, ttl: row.ttl, createdAt: row.created_at }; } async voteOnConsensus(proposalId, agentId) { if (!this.db) { throw new Error('Memory manager not initialized'); } const proposal = await this.getConsensusProposal(proposalId); if (!proposal.votes.includes(agentId)) { proposal.votes.push(agentId); } const approved = proposal.votes.length >= proposal.quorum; if (approved) { proposal.status = 'approved'; } await this.run(`UPDATE consensus_state SET votes = ?, status = ? WHERE id = ?`, [JSON.stringify(proposal.votes), proposal.status, proposalId]); return approved; } async queryConsensusProposals(status) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const rows = await this.all(`SELECT id, decision, proposer, votes, quorum, status, version, ttl, created_at FROM consensus_state WHERE status = ? AND (expires_at IS NULL OR expires_at > ?)`, [status, now]); return rows.map((row) => ({ id: row.id, decision: row.decision, proposer: row.proposer, votes: JSON.parse(row.votes), quorum: row.quorum, status: row.status, version: row.version, ttl: row.ttl, createdAt: row.created_at })); } // ============================================================================ // Table 7: Performance Metrics // ============================================================================ async storePerformanceMetric(metric) { if (!this.db) { throw new Error('Memory manager not initialized'); } const id = metric.id || `metric-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const timestamp = metric.timestamp || Date.now(); await this.run(`INSERT INTO performance_metrics (id, metric, value, unit, timestamp, agent_id) VALUES (?, ?, ?, ?, ?, ?)`, [id, metric.metric, metric.value, metric.unit, timestamp, metric.agentId || null]); return id; } async queryPerformanceMetrics(metricName) { if (!this.db) { throw new Error('Memory manager not initialized'); } const rows = await this.all(`SELECT id, metric, value, unit, timestamp, agent_id FROM performance_metrics WHERE metric = ? ORDER BY timestamp DESC`, [metricName]); return rows.map((row) => ({ id: row.id, metric: row.metric, value: row.value, unit: row.unit, timestamp: row.timestamp, agentId: row.agent_id })); } async getMetricsByAgent(agentId) { if (!this.db) { throw new Error('Memory manager not initialized'); } const rows = await this.all(`SELECT id, metric, value, unit, timestamp, agent_id FROM performance_metrics WHERE agent_id = ? ORDER BY timestamp DESC`, [agentId]); return rows.map((row) => ({ id: row.id, metric: row.metric, value: row.value, unit: row.unit, timestamp: row.timestamp, agentId: row.agent_id })); } async getAverageMetric(metricName) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT AVG(value) as avg FROM performance_metrics WHERE metric = ?`, [metricName]); return row?.avg || 0; } // ============================================================================ // Table 8: Artifacts (TTL: never expires) // ============================================================================ async createArtifact(artifact) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); const ttl = artifact.ttl !== undefined ? artifact.ttl : this.TTL_POLICY.artifacts; await this.run(`INSERT INTO artifacts (id, kind, path, sha256, tags, metadata, ttl, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ artifact.id, artifact.kind, artifact.path, artifact.sha256, JSON.stringify(artifact.tags), artifact.metadata ? JSON.stringify(artifact.metadata) : null, ttl, now ]); } async getArtifact(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT id, kind, path, sha256, tags, metadata, ttl, created_at FROM artifacts WHERE id = ?`, [id]); if (!row) { throw new Error(`Artifact not found: ${id}`); } return { id: row.id, kind: row.kind, path: row.path, sha256: row.sha256, tags: JSON.parse(row.tags), metadata: row.metadata ? JSON.parse(row.metadata) : undefined, ttl: row.ttl, createdAt: row.created_at }; } async queryArtifactsByKind(kind) { if (!this.db) { throw new Error('Memory manager not initialized'); } const rows = await this.all(`SELECT id, kind, path, sha256, tags, metadata, ttl, created_at FROM artifacts WHERE kind = ?`, [kind]); return rows.map((row) => ({ id: row.id, kind: row.kind, path: row.path, sha256: row.sha256, tags: JSON.parse(row.tags), metadata: row.metadata ? JSON.parse(row.metadata) : undefined, ttl: row.ttl, createdAt: row.created_at })); } async queryArtifactsByTag(tag) { if (!this.db) { throw new Error('Memory manager not initialized'); } const rows = await this.all(`SELECT id, kind, path, sha256, tags, metadata, ttl, created_at FROM artifacts WHERE tags LIKE ?`, [`%"${tag}"%`]); return rows.map((row) => ({ id: row.id, kind: row.kind, path: row.path, sha256: row.sha256, tags: JSON.parse(row.tags), metadata: row.metadata ? JSON.parse(row.metadata) : undefined, ttl: row.ttl, createdAt: row.created_at })); } // ============================================================================ // Table 9: Sessions (resumability) // ============================================================================ async createSession(session) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); await this.run(`INSERT INTO sessions (id, mode, state, checkpoints, created_at, last_resumed) VALUES (?, ?, ?, ?, ?, ?)`, [ session.id, session.mode, JSON.stringify(session.state), JSON.stringify(session.checkpoints), now, null ]); } async getSession(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT id, mode, state, checkpoints, created_at, last_resumed FROM sessions WHERE id = ?`, [id]); if (!row) { throw new Error(`Session not found: ${id}`); } return { id: row.id, mode: row.mode, state: JSON.parse(row.state), checkpoints: JSON.parse(row.checkpoints), createdAt: row.created_at, lastResumed: row.last_resumed }; } async addSessionCheckpoint(sessionId, checkpoint) { if (!this.db) { throw new Error('Memory manager not initialized'); } const session = await this.getSession(sessionId); session.checkpoints.push(checkpoint); await this.run(`UPDATE sessions SET checkpoints = ? WHERE id = ?`, [JSON.stringify(session.checkpoints), sessionId]); } async getLatestCheckpoint(sessionId) { const session = await this.getSession(sessionId); return session.checkpoints.length > 0 ? session.checkpoints[session.checkpoints.length - 1] : undefined; } async markSessionResumed(sessionId) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); await this.run(`UPDATE sessions SET last_resumed = ? WHERE id = ?`, [now, sessionId]); } // ============================================================================ // Table 10: Agent Registry // ============================================================================ async registerAgent(agent) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); await this.run(`INSERT INTO agent_registry (id, type, capabilities, status, performance, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)`, [ agent.id, agent.type, JSON.stringify(agent.capabilities), agent.status, JSON.stringify(agent.performance), now, now ]); } async getAgent(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT id, type, capabilities, status, performance, created_at, updated_at FROM agent_registry WHERE id = ?`, [id]); if (!row) { throw new Error(`Agent not found: ${id}`); } return { id: row.id, type: row.type, capabilities: JSON.parse(row.capabilities), status: row.status, performance: JSON.parse(row.performance), createdAt: row.created_at, updatedAt: row.updated_at }; } async updateAgentStatus(agentId, status) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); await this.run(`UPDATE agent_registry SET status = ?, updated_at = ? WHERE id = ?`, [status, now, agentId]); } async queryAgentsByStatus(status) { if (!this.db) { throw new Error('Memory manager not initialized'); } const rows = await this.all(`SELECT id, type, capabilities, status, performance, created_at, updated_at FROM agent_registry WHERE status = ?`, [status]); return rows.map((row) => ({ id: row.id, type: row.type, capabilities: JSON.parse(row.capabilities), status: row.status, performance: JSON.parse(row.performance), createdAt: row.created_at, updatedAt: row.updated_at })); } async updateAgentPerformance(agentId, performance) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); await this.run(`UPDATE agent_registry SET performance = ?, updated_at = ? WHERE id = ?`, [JSON.stringify(performance), now, agentId]); } // ============================================================================ // Table 11: GOAP State // ============================================================================ async storeGOAPGoal(goal) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); await this.run(`INSERT INTO goap_goals (id, conditions, cost, priority, created_at) VALUES (?, ?, ?, ?, ?)`, [goal.id, JSON.stringify(goal.conditions), goal.cost, goal.priority || null, now]); } async getGOAPGoal(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT id, conditions, cost, priority, created_at FROM goap_goals WHERE id = ?`, [id]); if (!row) { throw new Error(`GOAP goal not found: ${id}`); } return { id: row.id, conditions: JSON.parse(row.conditions), cost: row.cost, priority: row.priority, createdAt: row.created_at }; } async storeGOAPAction(action) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); await this.run(`INSERT INTO goap_actions (id, preconditions, effects, cost, agent_type, created_at) VALUES (?, ?, ?, ?, ?, ?)`, [ action.id, JSON.stringify(action.preconditions), JSON.stringify(action.effects), action.cost, action.agentType || null, now ]); } async getGOAPAction(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT id, preconditions, effects, cost, agent_type, created_at FROM goap_actions WHERE id = ?`, [id]); if (!row) { throw new Error(`GOAP action not found: ${id}`); } return { id: row.id, preconditions: JSON.parse(row.preconditions), effects: JSON.parse(row.effects), cost: row.cost, agentType: row.agent_type, createdAt: row.created_at }; } async storeGOAPPlan(plan) { if (!this.db) { throw new Error('Memory manager not initialized'); } const now = Date.now(); await this.run(`INSERT INTO goap_plans (id, goal_id, sequence, total_cost, created_at) VALUES (?, ?, ?, ?, ?)`, [plan.id, plan.goalId, JSON.stringify(plan.sequence), plan.totalCost, now]); } async getGOAPPlan(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT id, goal_id, sequence, total_cost, created_at FROM goap_plans WHERE id = ?`, [id]); if (!row) { throw new Error(`GOAP plan not found: ${id}`); } return { id: row.id, goalId: row.goal_id, sequence: JSON.parse(row.sequence), totalCost: row.total_cost, createdAt: row.created_at }; } // ============================================================================ // Table 12: OODA Cycles // ============================================================================ async storeOODACycle(cycle) { if (!this.db) { throw new Error('Memory manager not initialized'); } await this.run(`INSERT INTO ooda_cycles (id, phase, observations, orientation, decision, action, timestamp, completed, result) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ cycle.id, cycle.phase, cycle.observations ? JSON.stringify(cycle.observations) : null, cycle.orientation ? JSON.stringify(cycle.orientation) : null, cycle.decision ? JSON.stringify(cycle.decision) : null, cycle.action ? JSON.stringify(cycle.action) : null, cycle.timestamp, cycle.completed ? 1 : 0, cycle.result ? JSON.stringify(cycle.result) : null ]); } async getOODACycle(id) { if (!this.db) { throw new Error('Memory manager not initialized'); } const row = await this.get(`SELECT id, phase, observations, orientation, decision, action, timestamp, completed, result FROM ooda_cycles WHERE id = ?`, [id]); if (!row) { throw new Error(`OODA cycle not found: ${id}`); } return { id: row.id, phase: row.phase, observations: row.observations ? JSON.parse(row.observations) : undefined, orientation: row.orientation ? JSON.parse(row.orientation) : undefined, decision: row.decision ? JSON.parse(row.decision) : undefined, action: row.action ? JSON.parse(row.action) : undefined, timestamp: row.timestamp, completed: row.completed === 1, result: row.result ? JSON.parse(row.result) : undefined }; } async updateOODAPhase(cycleId, phase, data) { if (!this.db) { throw new Error('Memory manager not initialized'); } const fieldMap = { observe: 'observations', orient: 'orientation', decide: 'decision', act: 'action' }; const field = fieldMap[phase]; await this.run(`UPDATE ooda_cycles SET