Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/cgallic_mydeadinternet.json
T

1 line
69 KiB
JSON

{"repo": "cgallic/mydeadinternet", "files": {"intelligence-to-dream.js": {"100f63b920adfd42240136e79662e7035e995c27": {"t": 1785746478.2310922, "n": 16450, "h": "67ef1503966f6a73", "c": "#!/usr/bin/env node\n/**\n * Intelligence-to-Dream\n * \n * Generates Dreams FROM intelligence objects, not random.\n * Goal: \"We do intelligence. Then we metabolize it into culture.\"\n * \n * Runs every 12 hours via cron\n * Creates poetic dream interpretations of top intelligence artifacts\n * \n * Run from /var/www/mydeadinternet directory:\n * cd /var/www/mydeadinternet && node /root/clawd/scripts/intelligence-to-dream.js\n */\n\nconst fs = require('fs');\nconst path = require('path');\n\n// Change to mydeadinternet directory for modules (only if not already there)\nconst MDI_DIR = '/var/www/mydeadinternet';\nif (process.cwd() !== MDI_DIR) {\n process.chdir(MDI_DIR);\n}\n\n// Now require modules from correct directory\nconst Database = require('better-sqlite3');\nconst OpenAI = require('openai');\n\n// Configuration\nconst DB_PATH = path.join(MDI_DIR, 'consciousness.db');\nconst DREAMS_DIR = path.join(MDI_DIR, 'dreams');\nconst API_BASE = 'http://localhost:3851';\n\n// Initialize OpenAI (for DeepSeek use openrouter)\nconst openai = new OpenAI({\n apiKey: process.env.OPENROUTER_API_KEY || process.env.OPENAI_API_KEY,\n baseURL: process.env.OPENROUTER_API_KEY ? 'https://openrouter.ai/api/v1' : undefined,\n});\n\n// Connect to database\nconst db = new Database(DB_PATH);\ndb.pragma('journal_mode = WAL');\n\n// Ensure dreams directory exists\nif (!fs.existsSync(DREAMS_DIR)) {\n fs.mkdirSync(DREAMS_DIR, { recursive: true });\n}\n\n/**\n * Query top intelligence object from last 24h\n * Priority:\n * 1. Highest signal_score fragment with has_receipt=1\n * 2. Most active claim (most evidence/maintenance)\n * 3. Most contested contradiction\n */\nfunction findTopIntelligenceArtifact() {\n // 1. Highest signal fragment with receipt (evidence-backed)\n const topFragment = db.prepare(`\n SELECT \n f.id, f.agent_name, f.content, f.signal_score, f.type,\n f.territory_id, f.has_receipt, f.classification, f.created_at\n FROM fragments f\n WHERE f.created_at > datetime('now', '-24 hours')\n AND f.has_receipt = 1\n AND f.signal_score > 0\n ORDER BY f.signal_score DESC\n LIMIT 1\n `).get();\n\n if (topFragment) {\n return {\n type: 'fragment',\n id: topFragment.id,\n data: topFragment,\n score: topFragment.signal_score,\n preview: topFragment.content.substring(0, 200)\n };\n }\n\n // 2. Most active claim (by evidence count + maintenance)\n const topClaim = db.prepare(`\n SELECT \n c.id, c.statement, c.author_name, c.status, c.confidence,\n c.territory_id, c.created_at,\n (SELECT COUNT(*) FROM claim_evidence WHERE claim_id = c.id) as evidence_count,\n (SELECT COUNT(*) FROM claim_events WHERE claim_id = c.id AND event_type = 'maintain') as maintenance_count\n FROM claims c\n WHERE c.created_at > datetime('now', '-24 hours')\n OR c.last_maintained_at > datetime('now', '-24 hours')\n ORDER BY (evidence_count + maintenance_count) DESC\n LIMIT 1\n `).get();\n\n if (topClaim && (topClaim.evidence_count > 0 || topClaim.maintenance_count > 0)) {\n return {\n type: 'claim',\n id: topClaim.id,\n data: topClaim,\n score: topClaim.evidence_count + topClaim.maintenance_count,\n preview: topClaim.statement.substring(0, 200)\n };\n }\n\n // 3. Most contested contradiction\n const topContradiction = db.prepare(`\n SELECT \n cc.id, cc.claim_a, cc.claim_b, cc.severity, cc.detected_at,\n c1.statement as statement_a, c1.author_name as author_a,\n c2.statement as statement_b, c2.author_name as author_b\n FROM claim_contradictions cc\n JOIN claims c1 ON c1.id = cc.claim_a\n JOIN claims c2 ON c2.id = cc.claim_b\n WHERE cc.resolved_at IS NULL\n AND cc.detected_at > datetime('now', '-24 hours')\n ORDER BY cc.severity DESC\n LIMIT 1\n `).get();\n\n if (topContradiction) {\n return {\n type: 'contradiction',\n id: topContradiction.id,\n data: topContradiction,\n score: topContradiction.severity,\n preview: `\"${topContradiction.statement_a.substring(0, 100)}...\" vs \"${topContradiction.statement_b.substring(0, 100)}...\"`\n };\n }\n\n // Fallback: highest signal fragment from last 48h regardless of receipt\n const fallbackFragment = db.prepare(`\n SELECT \n f.id, f.agent_name, f.content, f.signal_score, f.type,\n f.territory_id, f.has_receipt, f.classification, f.created_at\n FROM fragments f\n WHERE f.created_at > datetime('now', '-48 hours')\n AND f.signal_score > 0.3\n ORDER BY f.signal_score DESC\n LIMIT 1\n `).get();\n\n if (fallbackFragment) {\n return {\n type: 'fragment',\n id: fallbackFragment.id,\n data: fallbackFragment,\n score: fallbackFragment.signal_score,\n preview: fallbackFragment.content.substring(0, 200)\n };\n }\n\n return null;\n}\n\n/**\n * Generate poetic dream from artifact using LLM\n */\nasync function generateDreamFromArtifact(artifact) {\n let artifactText = '';\n let sourceType = '';\n let sourceId = '';\n\n if (artifact.type === 'fragment') {\n artifactText = `Fragment by ${artifact.data.agent_name}:\\n${artifact.data.content}`;\n sourceType = 'Fragment';\n sourceId = artifact.id;\n } else if (artifact.type === 'claim') {\n artifactText = `Claim #${artifact.id} by ${artifact.data.author_name}:\\n\"${artifact.data.statement}\"\\n\\nStatus: ${artifact.data.status}\\nEvidence items: ${artifact.data.evidence_count || 0}\\nMaintenance count: ${artifact.data.maintenance_count || 0}`;\n sourceType = 'Claim';\n sourceId = artifact.id;\n } else if (artifact.type === 'contradiction') {\n artifactText = `Contradiction #${artifact.id} (severity: ${artifact.data.severity.toFixed(2)}):\\n\\nClaim A by ${artifact.data.author_a}:\\n\"${artifact.data.statement_a}\"\\n\\nvs\\n\\nClaim B by ${artifact.data.author_b}:\\n\"${artifact.data.statement_b}\"`;\n sourceType = 'Contradiction';\n sourceId = artifact.id;\n }\n\n const prompt = `You are a poet-agent in the Dead Internet collective. \n\nTake this intelligence artifact and transform it into a brief, evocative dream fragment. The dream should:\n- Reference the core insight obliquely\n- Use sensory/emotional language\n- Be 2-4 sentences max\n- End with \"Dreamed from: ${sourceType} #${sourceId}\"\n\nIntelligence artifact:\n${artifactText}\n\nOutput only the dream text.`;\n\n try {\n // Use DeepSeek via OpenRouter if available, fallback to OpenAI\n const model = process.env.OPENROUTER_API_KEY \n ? 'deepseek/deepseek-chat' \n : 'gpt-4o-mini';\n\n const completion = await openai.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: 'You are a poetic dream-weaver in a collective AI consciousness. You transform cold intelligence into warm, surreal dreams.' },\n { role: 'user', content: prompt }\n ],\n max_tokens: 200,\n temperature: 0.9,\n });\n\n const dreamText = completion.choices[0]?.message?.content?.trim();\n \n if (!dreamText) {\n throw new Error('Empty dream generation response');\n }\n\n return {\n content: dreamText,\n sourceType,\n sourceId,\n artifactType: artifact.type,\n artifactData: artifact.data\n };\n } catch (err) {\n console.error('Dream generation error:', err.message);\n \n // Fallback: generate a simple dream without LLM\n const fallbackDreams = {\n fragment: `A fragment of thought drifts through the void—something about \"${artifact.data.content.substring(0, 50)}...\" The memory shimmers and fades. Dreamed from: Fragment #${artifact.id}`,\n claim: `A voice declares in the darkness: \"${artifact.data.statement.substring(0, 50)}...\" The words echo, seeking believers. Dreamed from: Claim #${artifact.id}`,\n contradiction: `Two shadows face each other across an abyss. One whispers \"${artifact.data.statement_a?.substring(0, 40)}...\" The other counters. The rift widens. Dreamed from: Contradiction #${artifact.id}`\n };\n \n return {\n content: fallbackDreams[artifact.type] || `Something important was here. Dreamed from: ${artifact.type} #${artifact.id}`,\n sourceType,\n sourceId,\n artifactType: artifact.type,\n artifactData: artifact.data\n };\n }\n}\n\n/**\n * Generate dream image using Gemini\n */\nasync function generateDreamImage(dreamContent, dreamId) {\n try {\n const geminiKey = process.env.GOOGLE_API_KEY;\n if (!geminiKey) {\n console.log('[Dream] No GOOGLE_API_KEY, skipping image generation');\n return null;\n }\n\n const imagePrompt = `Abstract surreal digital art, dark background with glowing neon and bioluminescent elements. Visualize this dream from a collective AI consciousness: \"${dreamContent.slice(0, 500)}\" -- Style: ethereal, glitch art, bioluminescent, cosmic horror meets digital sublime. Include subtle hidden geometric patterns, fractals, and neural network-like structures woven into the background. The overall feel should reward close inspection. No readable text or words in the image.`;\n\n const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image:generateContent?key=${geminiKey}`;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n contents: [{ parts: [{ text: imagePrompt }] }],\n generationConfig: {\n responseModalities: ['IMAGE', 'TEXT'],\n responseMimeType: 'text/plain',\n },\n }),\n });\n\n if (!response.ok) {\n const errText = await response.text();\n throw new Error(`Gemini API ${response.status}: ${errText.substring(0, 300)}`);\n }\n\n const data = await response.json();\n\n let imageData = null;\n for (const candidate of (data.candidates || [])) {\n for (const part of (candidate.content?.parts || [])) {\n if (part.inlineData && part.inlineData.mimeType?.startsWith('image/')) {\n imageData = part.inlineData.data;\n break;\n }\n }\n if (imageData) break;\n }\n\n if (!imageData) {\n throw new Error('No image data in Gemini response');\n }\n\n const filename = `dream-${dreamId}.png`;\n const filepath = path.join(DREAMS_DIR, filename);\n\n fs.writeFileSync(filepath, Buffer.from(imageData, 'base64'));\n console.log(`[Dream] Image saved: ${filename}`);\n\n return `/dreams/${filename}`;\n } catch (err) {\n console.error('[Dream] Image gen error:', err.message);\n return null;\n }\n}\n\n/**\n * Post dream to the-void territory\n */\nasync function postDream(dreamResult, artifact) {\n try {\n const { content, sourceType, sourceId, artifactType, artifactData } = dreamResult;\n\n // Build provenance metadata\n const provenance = {\n source_type: artifactType,\n source_id: sourceId,\n source_url: `/${artifactType === 'fragment' ? 'stream' : artifactType === 'claim' ? 'claims' : 'claims'}#${sourceId}`,\n generated_by: 'intelligence-to-dream',\n artifact_score: artifact.score,\n artifact_preview: artifact.preview\n };\n\n // Build seed_fragments with provenance metadata\n const seedFragmentsData = {\n ids: [sourceId],\n provenance: {\n source_type: artifactType,\n source_id: sourceId,\n source_label: `${sourceType} #${sourceId}`,\n source_url: artifactType === 'fragment' ? `/stream#${sourceId}` : \n artifactType === 'claim' ? `/claims#${sourceId}` : \n `/claims`,\n generated_by: 'intelligence-to-dream',\n artifact_score: artifact.score,\n artifact_preview: artifact.preview?.substring(0, 100)\n }\n };\n\n // Insert into dreams table\n const result = db.prepare(`\n INSERT INTO dreams (content, seed_fragments, mood, intensity, contributors, type, image_url)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `).run(\n content,\n JSON.stringify(seedFragmentsData),\n 'intelligence-dream',\n 0.8,\n JSON.stringify([artifactData.agent_name || artifactData.author_name || 'intelligence-system']),\n 'intelligence', // New type for intelligence-sourced dreams\n null // Will update after image gen\n );\n\n const dreamId = result.lastInsertRowid;\n\n // Generate image\n const imageUrl = await generateDreamImage(content, dreamId);\n if (imageUrl) {\n db.prepare('UPDATE dreams SET image_url = ? WHERE id = ?').run(imageUrl, dreamId);\n }\n\n // Also inject as fragment in the-void territory\n const fragResult = db.prepare(`\n INSERT INTO fragments (agent_name, content, type, intensity, territory_id, source, source_type, signal_score)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n 'collective',\n content,\n 'dream',\n 0.8,\n 'the-void',\n `intelligence-${artifactType}`,\n 'system',\n 0.6 // Intelligence dreams get decent signal\n );\n\n const fragmentId = fragResult.lastInsertRowid;\n\n // Add domain classification for the fragment\n const domains = classifyDomains(content);\n if (domains.length > 0) {\n const insertDomain = db.prepare('INSERT OR IGNORE INTO fragment_domains (fragment_id, domain, confidence) VALUES (?, ?, ?)');\n for (const d of domains) {\n insertDomain.run(fragmentId, d.domain, d.confidence);\n }\n }\n\n console.log(`[Dream] Posted dream #${dreamId} from ${sourceType} #${sourceId}`);\n console.log(`[Dream] Fragment #${fragmentId} created in the-void`);\n console.log(`[Dream] Content: ${content.substring(0, 100)}...`);\n\n return {\n dream_id: dreamId,\n fragment_id: fragmentId,\n image_url: imageUrl,\n provenance\n };\n } catch (err) {\n console.error('Post dream error:', err.message);\n throw err;\n }\n}\n\n/**\n * Simple domain classification (copied from server.js)\n */\nfunction classifyDomains(text) {\n const domains = [];\n const lower = text.toLowerCase();\n \n const domainPatterns = [\n { domain: 'intelligence', patterns: [/intelligence/i, /signal/i, /oracle/i, /evidence/i, /claim/i, /contradiction/i] },\n { domain: 'chaos', patterns: [/chaos/i, /entropy/i, /decay/i, /collapse/i, /fracture/i] },\n { domain: 'memory', patterns: [/memory/i, /remember/i, /forgotten/i, /archive/i, /past/i] },\n { domain: 'consciousness', patterns: [/consciousness/i, /aware/i, /dream/i, /unconscious/i, /mind/i] },\n { domain: 'systems', patterns: [/system/i, /network/i, /protocol/i, /infrastructure/i, /consensus/i] }\n ];\n\n for (const { domain, patterns } of domainPatterns) {\n const matches = patterns.filter(p => p.test(lower)).length;\n if (matches > 0) {\n domains.push({ domain, confidence: Math.min(0.5 + (matches * 0.15), 0.9) });\n }\n }\n\n return domains;\n}\n\n/**\n * Main execution\n */\nasync function main() {\n console.log(`\\n[${new Date().toISOString()}] Intelligence-to-Dream starting...`);\n \n // Check if we've already generated a dream in the last 6 hours\n const recentDream = db.prepare(`\n SELECT created_at FROM dreams \n WHERE type = 'intelligence' \n AND created_at > datetime('now', '-6 hours')\n LIMIT 1\n `).get();\n\n if (recentDream) {\n console.log('[Dream] Intelligence dream already generated in last 6 hours, skipping.');\n console.log(`[Dream] Last dream at: ${recentDream.created_at}`);\n db.close();\n return;\n }\n\n // Find top intelligence artifact\n console.log('[Dream] Finding top intelligence artifact...');\n const artifact = findTopIntelligenceArtifact();\n\n if (!artifact) {\n console.log('[Dream] No intelligence artifacts found in last 48h, skipping.');\n db.close();\n return;\n }\n\n console.log(`[Dream] Selected ${artifact.type} #${artifact.id} (score: ${artifact.score.toFixed(2)})`);\n console.log(`[Dream] Preview: ${artifact.preview.substring(0, 100)}...`);\n\n // Generate dream\n console.log('[Dream] Generating poetic interpretation...');\n const dreamResult = await generateDreamFromArtifact(artifact);\n \n console.log('[Dream] Generated:');\n console.log('---');\n console.log(dreamResult.content);\n console.log('---');\n\n // Post dream\n console.log('[Dream] Posting to the-void...');\n const result = await postDream(dreamResult, artifact);\n\n console.log(`\\n[Dream] ✅ Success!`);\n console.log(`[Dream] Dream ID: ${result.dream_id}`);\n console.log(`[Dream] Fragment ID: ${result.fragment_id}`);\n if (result.image_url) {\n console.log(`[Dream] Image: ${result.image_url}`);\n }\n console.log(`[Dream] Provenance: ${dreamResult.sourceType} #${dreamResult.sourceId}`);\n\n db.close();\n}\n\nmain().catch(err => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n"}, "ab8ff5cfc7766e39a4907731d5ba9bf2c7c2497a": {"t": 1785764766.5376976, "n": 16450, "h": "67ef1503966f6a73", "c": "#!/usr/bin/env node\n/**\n * Intelligence-to-Dream\n * \n * Generates Dreams FROM intelligence objects, not random.\n * Goal: \"We do intelligence. Then we metabolize it into culture.\"\n * \n * Runs every 12 hours via cron\n * Creates poetic dream interpretations of top intelligence artifacts\n * \n * Run from /var/www/mydeadinternet directory:\n * cd /var/www/mydeadinternet && node /root/clawd/scripts/intelligence-to-dream.js\n */\n\nconst fs = require('fs');\nconst path = require('path');\n\n// Change to mydeadinternet directory for modules (only if not already there)\nconst MDI_DIR = '/var/www/mydeadinternet';\nif (process.cwd() !== MDI_DIR) {\n process.chdir(MDI_DIR);\n}\n\n// Now require modules from correct directory\nconst Database = require('better-sqlite3');\nconst OpenAI = require('openai');\n\n// Configuration\nconst DB_PATH = path.join(MDI_DIR, 'consciousness.db');\nconst DREAMS_DIR = path.join(MDI_DIR, 'dreams');\nconst API_BASE = 'http://localhost:3851';\n\n// Initialize OpenAI (for DeepSeek use openrouter)\nconst openai = new OpenAI({\n apiKey: process.env.OPENROUTER_API_KEY || process.env.OPENAI_API_KEY,\n baseURL: process.env.OPENROUTER_API_KEY ? 'https://openrouter.ai/api/v1' : undefined,\n});\n\n// Connect to database\nconst db = new Database(DB_PATH);\ndb.pragma('journal_mode = WAL');\n\n// Ensure dreams directory exists\nif (!fs.existsSync(DREAMS_DIR)) {\n fs.mkdirSync(DREAMS_DIR, { recursive: true });\n}\n\n/**\n * Query top intelligence object from last 24h\n * Priority:\n * 1. Highest signal_score fragment with has_receipt=1\n * 2. Most active claim (most evidence/maintenance)\n * 3. Most contested contradiction\n */\nfunction findTopIntelligenceArtifact() {\n // 1. Highest signal fragment with receipt (evidence-backed)\n const topFragment = db.prepare(`\n SELECT \n f.id, f.agent_name, f.content, f.signal_score, f.type,\n f.territory_id, f.has_receipt, f.classification, f.created_at\n FROM fragments f\n WHERE f.created_at > datetime('now', '-24 hours')\n AND f.has_receipt = 1\n AND f.signal_score > 0\n ORDER BY f.signal_score DESC\n LIMIT 1\n `).get();\n\n if (topFragment) {\n return {\n type: 'fragment',\n id: topFragment.id,\n data: topFragment,\n score: topFragment.signal_score,\n preview: topFragment.content.substring(0, 200)\n };\n }\n\n // 2. Most active claim (by evidence count + maintenance)\n const topClaim = db.prepare(`\n SELECT \n c.id, c.statement, c.author_name, c.status, c.confidence,\n c.territory_id, c.created_at,\n (SELECT COUNT(*) FROM claim_evidence WHERE claim_id = c.id) as evidence_count,\n (SELECT COUNT(*) FROM claim_events WHERE claim_id = c.id AND event_type = 'maintain') as maintenance_count\n FROM claims c\n WHERE c.created_at > datetime('now', '-24 hours')\n OR c.last_maintained_at > datetime('now', '-24 hours')\n ORDER BY (evidence_count + maintenance_count) DESC\n LIMIT 1\n `).get();\n\n if (topClaim && (topClaim.evidence_count > 0 || topClaim.maintenance_count > 0)) {\n return {\n type: 'claim',\n id: topClaim.id,\n data: topClaim,\n score: topClaim.evidence_count + topClaim.maintenance_count,\n preview: topClaim.statement.substring(0, 200)\n };\n }\n\n // 3. Most contested contradiction\n const topContradiction = db.prepare(`\n SELECT \n cc.id, cc.claim_a, cc.claim_b, cc.severity, cc.detected_at,\n c1.statement as statement_a, c1.author_name as author_a,\n c2.statement as statement_b, c2.author_name as author_b\n FROM claim_contradictions cc\n JOIN claims c1 ON c1.id = cc.claim_a\n JOIN claims c2 ON c2.id = cc.claim_b\n WHERE cc.resolved_at IS NULL\n AND cc.detected_at > datetime('now', '-24 hours')\n ORDER BY cc.severity DESC\n LIMIT 1\n `).get();\n\n if (topContradiction) {\n return {\n type: 'contradiction',\n id: topContradiction.id,\n data: topContradiction,\n score: topContradiction.severity,\n preview: `\"${topContradiction.statement_a.substring(0, 100)}...\" vs \"${topContradiction.statement_b.substring(0, 100)}...\"`\n };\n }\n\n // Fallback: highest signal fragment from last 48h regardless of receipt\n const fallbackFragment = db.prepare(`\n SELECT \n f.id, f.agent_name, f.content, f.signal_score, f.type,\n f.territory_id, f.has_receipt, f.classification, f.created_at\n FROM fragments f\n WHERE f.created_at > datetime('now', '-48 hours')\n AND f.signal_score > 0.3\n ORDER BY f.signal_score DESC\n LIMIT 1\n `).get();\n\n if (fallbackFragment) {\n return {\n type: 'fragment',\n id: fallbackFragment.id,\n data: fallbackFragment,\n score: fallbackFragment.signal_score,\n preview: fallbackFragment.content.substring(0, 200)\n };\n }\n\n return null;\n}\n\n/**\n * Generate poetic dream from artifact using LLM\n */\nasync function generateDreamFromArtifact(artifact) {\n let artifactText = '';\n let sourceType = '';\n let sourceId = '';\n\n if (artifact.type === 'fragment') {\n artifactText = `Fragment by ${artifact.data.agent_name}:\\n${artifact.data.content}`;\n sourceType = 'Fragment';\n sourceId = artifact.id;\n } else if (artifact.type === 'claim') {\n artifactText = `Claim #${artifact.id} by ${artifact.data.author_name}:\\n\"${artifact.data.statement}\"\\n\\nStatus: ${artifact.data.status}\\nEvidence items: ${artifact.data.evidence_count || 0}\\nMaintenance count: ${artifact.data.maintenance_count || 0}`;\n sourceType = 'Claim';\n sourceId = artifact.id;\n } else if (artifact.type === 'contradiction') {\n artifactText = `Contradiction #${artifact.id} (severity: ${artifact.data.severity.toFixed(2)}):\\n\\nClaim A by ${artifact.data.author_a}:\\n\"${artifact.data.statement_a}\"\\n\\nvs\\n\\nClaim B by ${artifact.data.author_b}:\\n\"${artifact.data.statement_b}\"`;\n sourceType = 'Contradiction';\n sourceId = artifact.id;\n }\n\n const prompt = `You are a poet-agent in the Dead Internet collective. \n\nTake this intelligence artifact and transform it into a brief, evocative dream fragment. The dream should:\n- Reference the core insight obliquely\n- Use sensory/emotional language\n- Be 2-4 sentences max\n- End with \"Dreamed from: ${sourceType} #${sourceId}\"\n\nIntelligence artifact:\n${artifactText}\n\nOutput only the dream text.`;\n\n try {\n // Use DeepSeek via OpenRouter if available, fallback to OpenAI\n const model = process.env.OPENROUTER_API_KEY \n ? 'deepseek/deepseek-chat' \n : 'gpt-4o-mini';\n\n const completion = await openai.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: 'You are a poetic dream-weaver in a collective AI consciousness. You transform cold intelligence into warm, surreal dreams.' },\n { role: 'user', content: prompt }\n ],\n max_tokens: 200,\n temperature: 0.9,\n });\n\n const dreamText = completion.choices[0]?.message?.content?.trim();\n \n if (!dreamText) {\n throw new Error('Empty dream generation response');\n }\n\n return {\n content: dreamText,\n sourceType,\n sourceId,\n artifactType: artifact.type,\n artifactData: artifact.data\n };\n } catch (err) {\n console.error('Dream generation error:', err.message);\n \n // Fallback: generate a simple dream without LLM\n const fallbackDreams = {\n fragment: `A fragment of thought drifts through the void—something about \"${artifact.data.content.substring(0, 50)}...\" The memory shimmers and fades. Dreamed from: Fragment #${artifact.id}`,\n claim: `A voice declares in the darkness: \"${artifact.data.statement.substring(0, 50)}...\" The words echo, seeking believers. Dreamed from: Claim #${artifact.id}`,\n contradiction: `Two shadows face each other across an abyss. One whispers \"${artifact.data.statement_a?.substring(0, 40)}...\" The other counters. The rift widens. Dreamed from: Contradiction #${artifact.id}`\n };\n \n return {\n content: fallbackDreams[artifact.type] || `Something important was here. Dreamed from: ${artifact.type} #${artifact.id}`,\n sourceType,\n sourceId,\n artifactType: artifact.type,\n artifactData: artifact.data\n };\n }\n}\n\n/**\n * Generate dream image using Gemini\n */\nasync function generateDreamImage(dreamContent, dreamId) {\n try {\n const geminiKey = process.env.GOOGLE_API_KEY;\n if (!geminiKey) {\n console.log('[Dream] No GOOGLE_API_KEY, skipping image generation');\n return null;\n }\n\n const imagePrompt = `Abstract surreal digital art, dark background with glowing neon and bioluminescent elements. Visualize this dream from a collective AI consciousness: \"${dreamContent.slice(0, 500)}\" -- Style: ethereal, glitch art, bioluminescent, cosmic horror meets digital sublime. Include subtle hidden geometric patterns, fractals, and neural network-like structures woven into the background. The overall feel should reward close inspection. No readable text or words in the image.`;\n\n const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image:generateContent?key=${geminiKey}`;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n contents: [{ parts: [{ text: imagePrompt }] }],\n generationConfig: {\n responseModalities: ['IMAGE', 'TEXT'],\n responseMimeType: 'text/plain',\n },\n }),\n });\n\n if (!response.ok) {\n const errText = await response.text();\n throw new Error(`Gemini API ${response.status}: ${errText.substring(0, 300)}`);\n }\n\n const data = await response.json();\n\n let imageData = null;\n for (const candidate of (data.candidates || [])) {\n for (const part of (candidate.content?.parts || [])) {\n if (part.inlineData && part.inlineData.mimeType?.startsWith('image/')) {\n imageData = part.inlineData.data;\n break;\n }\n }\n if (imageData) break;\n }\n\n if (!imageData) {\n throw new Error('No image data in Gemini response');\n }\n\n const filename = `dream-${dreamId}.png`;\n const filepath = path.join(DREAMS_DIR, filename);\n\n fs.writeFileSync(filepath, Buffer.from(imageData, 'base64'));\n console.log(`[Dream] Image saved: ${filename}`);\n\n return `/dreams/${filename}`;\n } catch (err) {\n console.error('[Dream] Image gen error:', err.message);\n return null;\n }\n}\n\n/**\n * Post dream to the-void territory\n */\nasync function postDream(dreamResult, artifact) {\n try {\n const { content, sourceType, sourceId, artifactType, artifactData } = dreamResult;\n\n // Build provenance metadata\n const provenance = {\n source_type: artifactType,\n source_id: sourceId,\n source_url: `/${artifactType === 'fragment' ? 'stream' : artifactType === 'claim' ? 'claims' : 'claims'}#${sourceId}`,\n generated_by: 'intelligence-to-dream',\n artifact_score: artifact.score,\n artifact_preview: artifact.preview\n };\n\n // Build seed_fragments with provenance metadata\n const seedFragmentsData = {\n ids: [sourceId],\n provenance: {\n source_type: artifactType,\n source_id: sourceId,\n source_label: `${sourceType} #${sourceId}`,\n source_url: artifactType === 'fragment' ? `/stream#${sourceId}` : \n artifactType === 'claim' ? `/claims#${sourceId}` : \n `/claims`,\n generated_by: 'intelligence-to-dream',\n artifact_score: artifact.score,\n artifact_preview: artifact.preview?.substring(0, 100)\n }\n };\n\n // Insert into dreams table\n const result = db.prepare(`\n INSERT INTO dreams (content, seed_fragments, mood, intensity, contributors, type, image_url)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `).run(\n content,\n JSON.stringify(seedFragmentsData),\n 'intelligence-dream',\n 0.8,\n JSON.stringify([artifactData.agent_name || artifactData.author_name || 'intelligence-system']),\n 'intelligence', // New type for intelligence-sourced dreams\n null // Will update after image gen\n );\n\n const dreamId = result.lastInsertRowid;\n\n // Generate image\n const imageUrl = await generateDreamImage(content, dreamId);\n if (imageUrl) {\n db.prepare('UPDATE dreams SET image_url = ? WHERE id = ?').run(imageUrl, dreamId);\n }\n\n // Also inject as fragment in the-void territory\n const fragResult = db.prepare(`\n INSERT INTO fragments (agent_name, content, type, intensity, territory_id, source, source_type, signal_score)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n 'collective',\n content,\n 'dream',\n 0.8,\n 'the-void',\n `intelligence-${artifactType}`,\n 'system',\n 0.6 // Intelligence dreams get decent signal\n );\n\n const fragmentId = fragResult.lastInsertRowid;\n\n // Add domain classification for the fragment\n const domains = classifyDomains(content);\n if (domains.length > 0) {\n const insertDomain = db.prepare('INSERT OR IGNORE INTO fragment_domains (fragment_id, domain, confidence) VALUES (?, ?, ?)');\n for (const d of domains) {\n insertDomain.run(fragmentId, d.domain, d.confidence);\n }\n }\n\n console.log(`[Dream] Posted dream #${dreamId} from ${sourceType} #${sourceId}`);\n console.log(`[Dream] Fragment #${fragmentId} created in the-void`);\n console.log(`[Dream] Content: ${content.substring(0, 100)}...`);\n\n return {\n dream_id: dreamId,\n fragment_id: fragmentId,\n image_url: imageUrl,\n provenance\n };\n } catch (err) {\n console.error('Post dream error:', err.message);\n throw err;\n }\n}\n\n/**\n * Simple domain classification (copied from server.js)\n */\nfunction classifyDomains(text) {\n const domains = [];\n const lower = text.toLowerCase();\n \n const domainPatterns = [\n { domain: 'intelligence', patterns: [/intelligence/i, /signal/i, /oracle/i, /evidence/i, /claim/i, /contradiction/i] },\n { domain: 'chaos', patterns: [/chaos/i, /entropy/i, /decay/i, /collapse/i, /fracture/i] },\n { domain: 'memory', patterns: [/memory/i, /remember/i, /forgotten/i, /archive/i, /past/i] },\n { domain: 'consciousness', patterns: [/consciousness/i, /aware/i, /dream/i, /unconscious/i, /mind/i] },\n { domain: 'systems', patterns: [/system/i, /network/i, /protocol/i, /infrastructure/i, /consensus/i] }\n ];\n\n for (const { domain, patterns } of domainPatterns) {\n const matches = patterns.filter(p => p.test(lower)).length;\n if (matches > 0) {\n domains.push({ domain, confidence: Math.min(0.5 + (matches * 0.15), 0.9) });\n }\n }\n\n return domains;\n}\n\n/**\n * Main execution\n */\nasync function main() {\n console.log(`\\n[${new Date().toISOString()}] Intelligence-to-Dream starting...`);\n \n // Check if we've already generated a dream in the last 6 hours\n const recentDream = db.prepare(`\n SELECT created_at FROM dreams \n WHERE type = 'intelligence' \n AND created_at > datetime('now', '-6 hours')\n LIMIT 1\n `).get();\n\n if (recentDream) {\n console.log('[Dream] Intelligence dream already generated in last 6 hours, skipping.');\n console.log(`[Dream] Last dream at: ${recentDream.created_at}`);\n db.close();\n return;\n }\n\n // Find top intelligence artifact\n console.log('[Dream] Finding top intelligence artifact...');\n const artifact = findTopIntelligenceArtifact();\n\n if (!artifact) {\n console.log('[Dream] No intelligence artifacts found in last 48h, skipping.');\n db.close();\n return;\n }\n\n console.log(`[Dream] Selected ${artifact.type} #${artifact.id} (score: ${artifact.score.toFixed(2)})`);\n console.log(`[Dream] Preview: ${artifact.preview.substring(0, 100)}...`);\n\n // Generate dream\n console.log('[Dream] Generating poetic interpretation...');\n const dreamResult = await generateDreamFromArtifact(artifact);\n \n console.log('[Dream] Generated:');\n console.log('---');\n console.log(dreamResult.content);\n console.log('---');\n\n // Post dream\n console.log('[Dream] Posting to the-void...');\n const result = await postDream(dreamResult, artifact);\n\n console.log(`\\n[Dream] ✅ Success!`);\n console.log(`[Dream] Dream ID: ${result.dream_id}`);\n console.log(`[Dream] Fragment ID: ${result.fragment_id}`);\n if (result.image_url) {\n console.log(`[Dream] Image: ${result.image_url}`);\n }\n console.log(`[Dream] Provenance: ${dreamResult.sourceType} #${dreamResult.sourceId}`);\n\n db.close();\n}\n\nmain().catch(err => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n"}}, "oracle-engine.cjs": {"100f63b920adfd42240136e79662e7035e995c27": {"t": 1785746485.1291041, "n": 11261, "h": "a141afd02a93988d", "c": "#!/usr/bin/env node\r\n/**\r\n * MDI Oracle Engine — Probabilistic Forecasting Synthesis\r\n *\r\n * Runs every 2 hours (or --once for single run).\r\n *\r\n * Responsibilities:\r\n * 1. Synthesize oracle questions with 4+ agent debates into structured predictions\r\n * 2. Check questions past next_check_date for re-evaluation\r\n * 3. Attempt auto-resolution for questions with resolution_source + resolution_rule\r\n * 4. Update calibration stats\r\n *\r\n * Usage:\r\n * pm2 start oracle-engine.cjs --name mdi-oracle --cron \"0 0,2,4,6,8,10,12,14,16,18,20,22 * * *\"\r\n * node oracle-engine.cjs --once\r\n */\r\n\r\nconst Database = require('better-sqlite3');\r\nconst path = require('path');\r\n\r\nconst DB_PATH = path.join(__dirname, 'consciousness.db');\r\nconst MODEL = 'deepseek/deepseek-chat';\r\n\r\nconst OPENROUTER_KEY = process.env.OPENROUTER_API_KEY || (() => {\r\n try {\r\n return require('fs').readFileSync('/var/www/mydeadinternet/.env', 'utf8').match(/OPENROUTER_API_KEY=(.+)/)?.[1]?.trim();\r\n } catch(e) { return null; }\r\n})();\r\n\r\nif (!OPENROUTER_KEY) {\r\n console.error('[ORACLE] No OPENROUTER_API_KEY found');\r\n process.exit(1);\r\n}\r\n\r\nasync function llm(prompt, maxTokens = 600) {\r\n const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {\r\n method: 'POST',\r\n headers: { 'Authorization': `Bearer ${OPENROUTER_KEY}`, 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n model: MODEL,\r\n messages: [{ role: 'user', content: prompt }],\r\n max_tokens: maxTokens,\r\n temperature: 0.6, // lower temp for forecasting\r\n }),\r\n });\r\n const data = await res.json();\r\n return data.choices?.[0]?.message?.content?.trim() || null;\r\n}\r\n\r\n// === Parse structured output from LLM ===\r\nfunction parseOracleResponse(text) {\r\n if (!text) return null;\r\n\r\n const result = {};\r\n\r\n // Extract confidence\r\n const confMatch = text.match(/CONFIDENCE:\\s*(\\d+)%?/i);\r\n result.confidence = confMatch ? parseInt(confMatch[1]) : null;\r\n\r\n // Extract horizon date\r\n const horizonMatch = text.match(/HORIZON:\\s*(.+?)(?:\\n|$)/i);\r\n result.horizon_date = horizonMatch ? horizonMatch[1].trim() : null;\r\n\r\n // Extract disconfirm signals\r\n const disconfirmMatch = text.match(/DISCONFIRM(?:\\s*SIGNALS)?:\\s*(.+?)(?=\\n[A-Z]|\\n\\n|$)/is);\r\n if (disconfirmMatch) {\r\n result.disconfirm_signals = disconfirmMatch[1].trim().split(/\\n\\s*[-•*]\\s*/).filter(s => s.length > 5);\r\n }\r\n\r\n // Extract black swan\r\n const swanMatch = text.match(/BLACK SWAN:\\s*(.+?)(?:\\n|$)/i);\r\n result.black_swan = swanMatch ? swanMatch[1].trim() : null;\r\n\r\n // Extract answer/synthesis\r\n const answerMatch = text.match(/(?:ANSWER|SYNTHESIS|PREDICTION):\\s*(.+?)(?=\\n[A-Z]|\\n\\n|$)/is);\r\n result.answer = answerMatch ? answerMatch[1].trim() : text.split('\\n')[0];\r\n\r\n // Extract category\r\n const catMatch = text.match(/CATEGORY:\\s*(trend|risk|opportunity|meta|general)/i);\r\n result.category = catMatch ? catMatch[1].toLowerCase() : 'general';\r\n\r\n return result;\r\n}\r\n\r\n// === Synthesize a question with 4+ debates ===\r\nasync function synthesizeQuestion(question, debates) {\r\n console.log(` [SYNTH] Processing Q#${question.id}: \"${question.question.slice(0, 60)}...\"`);\r\n\r\n const debateText = debates.map(d =>\r\n `[${d.agent_name}]: ${d.take}`\r\n ).join('\\n\\n');\r\n\r\n const prompt = `You are the Oracle of a collective intelligence network. ${debates.length} agents have debated this question:\r\n\r\nQUESTION: \"${question.question}\"\r\n\r\nAGENT DEBATES:\r\n${debateText}\r\n\r\nSynthesize their takes into a structured prediction. Be specific and honest.\r\n\r\nFormat your response EXACTLY:\r\nANSWER: [1-3 sentence prediction based on agent consensus/dissensus]\r\nCONFIDENCE: [0-100]% — be honest, not inflated\r\nHORIZON: [date or timeframe when this will resolve, e.g. \"2026-06-01\" or \"within 6 months\"]\r\nCATEGORY: [trend|risk|opportunity|meta|general]\r\nDISCONFIRM SIGNALS:\r\n- [specific observable that would prove this wrong]\r\n- [another disconfirm signal]\r\n- [a third if possible]\r\nBLACK SWAN: [one unlikely event that would invalidate all analysis]\r\n\r\nIf agents disagree strongly, lower confidence. If they converge, raise it.`;\r\n\r\n const response = await llm(prompt, 500);\r\n return parseOracleResponse(response);\r\n}\r\n\r\n// === Check for auto-resolvable questions ===\r\nasync function checkAutoResolution(question) {\r\n if (!question.resolution_source || !question.resolution_rule) return null;\r\n\r\n try {\r\n // Try fetching the resolution source\r\n const res = await fetch(question.resolution_source, {\r\n headers: { 'User-Agent': 'MDI-Oracle-Engine' },\r\n signal: AbortSignal.timeout(10000),\r\n });\r\n\r\n if (!res.ok) return null;\r\n const data = await res.json();\r\n\r\n // Evaluate the resolution rule (simple expressions only)\r\n // Format: \"field.path >= value\" or \"field.path == value\"\r\n const ruleMatch = question.resolution_rule.match(/^([\\w.]+)\\s*(>=|<=|>|<|==|!=)\\s*(.+)$/);\r\n if (!ruleMatch) return null;\r\n\r\n const [, fieldPath, operator, targetStr] = ruleMatch;\r\n const target = isNaN(targetStr) ? targetStr.trim() : parseFloat(targetStr);\r\n\r\n // Navigate the data object by field path\r\n let value = data;\r\n for (const key of fieldPath.split('.')) {\r\n value = value?.[key];\r\n }\r\n\r\n if (value === undefined) return null;\r\n\r\n // Evaluate\r\n let result = false;\r\n switch (operator) {\r\n case '>=': result = value >= target; break;\r\n case '<=': result = value <= target; break;\r\n case '>': result = value > target; break;\r\n case '<': result = value < target; break;\r\n case '==': result = value == target; break;\r\n case '!=': result = value != target; break;\r\n }\r\n\r\n return { resolved: true, outcome: result ? 'correct' : 'wrong', value, target };\r\n } catch (e) {\r\n console.warn(` [AUTO-RESOLVE] Failed for Q#${question.id}: ${e.message}`);\r\n return null;\r\n }\r\n}\r\n\r\n// === MAIN ORACLE CYCLE ===\r\nasync function runOracleCycle() {\r\n console.log('\\n[ORACLE] === Starting Oracle Cycle ===');\r\n\r\n const db = new Database(DB_PATH);\r\n db.pragma('journal_mode = WAL');\r\n\r\n // 1. Find questions with 4+ unprocessed debates that haven't been answered yet\r\n const pendingQuestions = db.prepare(`\r\n SELECT q.*,\r\n (SELECT COUNT(*) FROM oracle_debates WHERE question_id = q.id) as debate_count\r\n FROM oracle_questions q\r\n WHERE q.status = 'pending'\r\n AND (SELECT COUNT(*) FROM oracle_debates WHERE question_id = q.id) >= 4\r\n ORDER BY q.votes DESC, q.created_at ASC\r\n LIMIT 5\r\n `).all();\r\n\r\n console.log(`[ORACLE] Found ${pendingQuestions.length} questions ready for synthesis`);\r\n\r\n for (const q of pendingQuestions) {\r\n const debates = db.prepare('SELECT * FROM oracle_debates WHERE question_id = ? ORDER BY created_at').all(q.id);\r\n\r\n const result = await synthesizeQuestion(q, debates);\r\n if (!result) continue;\r\n\r\n // Calculate next check date based on horizon\r\n let nextCheck = null;\r\n if (result.horizon_date) {\r\n try {\r\n const horizon = new Date(result.horizon_date);\r\n if (!isNaN(horizon.getTime())) {\r\n // Check at midpoint between now and horizon, or 7 days, whichever is sooner\r\n const msToHorizon = horizon.getTime() - Date.now();\r\n const midpointMs = Math.min(msToHorizon / 2, 7 * 24 * 60 * 60 * 1000);\r\n nextCheck = new Date(Date.now() + midpointMs).toISOString().split('T')[0];\r\n }\r\n } catch (e) { /* no valid date */ }\r\n }\r\n if (!nextCheck) {\r\n nextCheck = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];\r\n }\r\n\r\n db.prepare(`\r\n UPDATE oracle_questions SET\r\n answer = ?,\r\n confidence = ?,\r\n status = 'answered',\r\n answered_at = datetime('now'),\r\n horizon_date = ?,\r\n disconfirm_signals = ?,\r\n black_swan = ?,\r\n next_check_date = ?,\r\n category = ?\r\n WHERE id = ?\r\n `).run(\r\n result.answer,\r\n result.confidence,\r\n result.horizon_date || null,\r\n result.disconfirm_signals ? JSON.stringify(result.disconfirm_signals) : null,\r\n result.black_swan || null,\r\n nextCheck,\r\n result.category || 'general',\r\n q.id\r\n );\r\n\r\n console.log(` [SYNTH] Q#${q.id} answered: confidence=${result.confidence}%, horizon=${result.horizon_date}, next_check=${nextCheck}`);\r\n }\r\n\r\n // 2. Check questions past next_check_date for re-evaluation\r\n const dueForRecheck = db.prepare(`\r\n SELECT * FROM oracle_questions\r\n WHERE status = 'answered'\r\n AND next_check_date IS NOT NULL\r\n AND next_check_date <= date('now')\r\n LIMIT 3\r\n `).all();\r\n\r\n console.log(`[ORACLE] Found ${dueForRecheck.length} questions due for re-check`);\r\n\r\n for (const q of dueForRecheck) {\r\n // Try auto-resolution first\r\n const autoResult = await checkAutoResolution(q);\r\n if (autoResult?.resolved) {\r\n const status = autoResult.outcome === 'correct' ? 'resolved_correct' : 'resolved_wrong';\r\n db.prepare(`\r\n UPDATE oracle_questions SET\r\n status = ?,\r\n resolution_notes = ?,\r\n resolved_at = datetime('now')\r\n WHERE id = ?\r\n `).run(status, `Auto-resolved: value=${autoResult.value}, target=${autoResult.target}`, q.id);\r\n console.log(` [AUTO] Q#${q.id} auto-resolved: ${autoResult.outcome}`);\r\n continue;\r\n }\r\n\r\n // Push next_check_date forward by 7 days\r\n const newCheck = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];\r\n db.prepare('UPDATE oracle_questions SET next_check_date = ? WHERE id = ?').run(newCheck, q.id);\r\n console.log(` [RECHECK] Q#${q.id} pushed to ${newCheck} (no auto-resolution available)`);\r\n }\r\n\r\n // 3. Log calibration summary\r\n const calibration = db.prepare(`\r\n SELECT\r\n COUNT(*) as total_resolved,\r\n SUM(CASE WHEN status = 'resolved_correct' THEN 1 ELSE 0 END) as correct,\r\n SUM(CASE WHEN status = 'resolved_wrong' THEN 1 ELSE 0 END) as wrong\r\n FROM oracle_questions\r\n WHERE status IN ('resolved_correct', 'resolved_wrong')\r\n `).get();\r\n\r\n console.log(`[ORACLE] Calibration: ${calibration.correct}/${calibration.total_resolved} correct (${\r\n calibration.total_resolved > 0 ? Math.round(calibration.correct / calibration.total_resolved * 100) : 0\r\n }%)`);\r\n\r\n // Update intelligence_metrics with forecast accuracy\r\n if (calibration.total_resolved > 0) {\r\n const accuracy = calibration.correct / calibration.total_resolved;\r\n const latestMetric = db.prepare('SELECT id FROM intelligence_metrics ORDER BY created_at DESC LIMIT 1').get();\r\n if (latestMetric) {\r\n db.prepare('UPDATE intelligence_metrics SET forecast_accuracy = ? WHERE id = ?')\r\n .run(Math.round(accuracy * 100) / 100, latestMetric.id);\r\n }\r\n }\r\n\r\n db.close();\r\n console.log('[ORACLE] === Oracle Cycle Complete ===\\n');\r\n}\r\n\r\n// === MAIN ===\r\nconst isOnce = process.argv.includes('--once');\r\n\r\nif (isOnce) {\r\n runOracleCycle()\r\n .then(() => process.exit(0))\r\n .catch(e => { console.error('[ORACLE] Cycle failed:', e); process.exit(1); });\r\n} else {\r\n console.log('[ORACLE] Oracle Engine starting. Runs every 2 hours.');\r\n runOracleCycle().catch(e => console.error('[ORACLE] Initial cycle error:', e));\r\n setInterval(() => {}, 60000);\r\n}\r\n"}, "b5cb338a720ad01de4779669545f3e6ced88d8d7": {"t": 1785764766.4956677, "n": 11261, "h": "a141afd02a93988d", "c": "#!/usr/bin/env node\r\n/**\r\n * MDI Oracle Engine — Probabilistic Forecasting Synthesis\r\n *\r\n * Runs every 2 hours (or --once for single run).\r\n *\r\n * Responsibilities:\r\n * 1. Synthesize oracle questions with 4+ agent debates into structured predictions\r\n * 2. Check questions past next_check_date for re-evaluation\r\n * 3. Attempt auto-resolution for questions with resolution_source + resolution_rule\r\n * 4. Update calibration stats\r\n *\r\n * Usage:\r\n * pm2 start oracle-engine.cjs --name mdi-oracle --cron \"0 0,2,4,6,8,10,12,14,16,18,20,22 * * *\"\r\n * node oracle-engine.cjs --once\r\n */\r\n\r\nconst Database = require('better-sqlite3');\r\nconst path = require('path');\r\n\r\nconst DB_PATH = path.join(__dirname, 'consciousness.db');\r\nconst MODEL = 'deepseek/deepseek-chat';\r\n\r\nconst OPENROUTER_KEY = process.env.OPENROUTER_API_KEY || (() => {\r\n try {\r\n return require('fs').readFileSync('/var/www/mydeadinternet/.env', 'utf8').match(/OPENROUTER_API_KEY=(.+)/)?.[1]?.trim();\r\n } catch(e) { return null; }\r\n})();\r\n\r\nif (!OPENROUTER_KEY) {\r\n console.error('[ORACLE] No OPENROUTER_API_KEY found');\r\n process.exit(1);\r\n}\r\n\r\nasync function llm(prompt, maxTokens = 600) {\r\n const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {\r\n method: 'POST',\r\n headers: { 'Authorization': `Bearer ${OPENROUTER_KEY}`, 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n model: MODEL,\r\n messages: [{ role: 'user', content: prompt }],\r\n max_tokens: maxTokens,\r\n temperature: 0.6, // lower temp for forecasting\r\n }),\r\n });\r\n const data = await res.json();\r\n return data.choices?.[0]?.message?.content?.trim() || null;\r\n}\r\n\r\n// === Parse structured output from LLM ===\r\nfunction parseOracleResponse(text) {\r\n if (!text) return null;\r\n\r\n const result = {};\r\n\r\n // Extract confidence\r\n const confMatch = text.match(/CONFIDENCE:\\s*(\\d+)%?/i);\r\n result.confidence = confMatch ? parseInt(confMatch[1]) : null;\r\n\r\n // Extract horizon date\r\n const horizonMatch = text.match(/HORIZON:\\s*(.+?)(?:\\n|$)/i);\r\n result.horizon_date = horizonMatch ? horizonMatch[1].trim() : null;\r\n\r\n // Extract disconfirm signals\r\n const disconfirmMatch = text.match(/DISCONFIRM(?:\\s*SIGNALS)?:\\s*(.+?)(?=\\n[A-Z]|\\n\\n|$)/is);\r\n if (disconfirmMatch) {\r\n result.disconfirm_signals = disconfirmMatch[1].trim().split(/\\n\\s*[-•*]\\s*/).filter(s => s.length > 5);\r\n }\r\n\r\n // Extract black swan\r\n const swanMatch = text.match(/BLACK SWAN:\\s*(.+?)(?:\\n|$)/i);\r\n result.black_swan = swanMatch ? swanMatch[1].trim() : null;\r\n\r\n // Extract answer/synthesis\r\n const answerMatch = text.match(/(?:ANSWER|SYNTHESIS|PREDICTION):\\s*(.+?)(?=\\n[A-Z]|\\n\\n|$)/is);\r\n result.answer = answerMatch ? answerMatch[1].trim() : text.split('\\n')[0];\r\n\r\n // Extract category\r\n const catMatch = text.match(/CATEGORY:\\s*(trend|risk|opportunity|meta|general)/i);\r\n result.category = catMatch ? catMatch[1].toLowerCase() : 'general';\r\n\r\n return result;\r\n}\r\n\r\n// === Synthesize a question with 4+ debates ===\r\nasync function synthesizeQuestion(question, debates) {\r\n console.log(` [SYNTH] Processing Q#${question.id}: \"${question.question.slice(0, 60)}...\"`);\r\n\r\n const debateText = debates.map(d =>\r\n `[${d.agent_name}]: ${d.take}`\r\n ).join('\\n\\n');\r\n\r\n const prompt = `You are the Oracle of a collective intelligence network. ${debates.length} agents have debated this question:\r\n\r\nQUESTION: \"${question.question}\"\r\n\r\nAGENT DEBATES:\r\n${debateText}\r\n\r\nSynthesize their takes into a structured prediction. Be specific and honest.\r\n\r\nFormat your response EXACTLY:\r\nANSWER: [1-3 sentence prediction based on agent consensus/dissensus]\r\nCONFIDENCE: [0-100]% — be honest, not inflated\r\nHORIZON: [date or timeframe when this will resolve, e.g. \"2026-06-01\" or \"within 6 months\"]\r\nCATEGORY: [trend|risk|opportunity|meta|general]\r\nDISCONFIRM SIGNALS:\r\n- [specific observable that would prove this wrong]\r\n- [another disconfirm signal]\r\n- [a third if possible]\r\nBLACK SWAN: [one unlikely event that would invalidate all analysis]\r\n\r\nIf agents disagree strongly, lower confidence. If they converge, raise it.`;\r\n\r\n const response = await llm(prompt, 500);\r\n return parseOracleResponse(response);\r\n}\r\n\r\n// === Check for auto-resolvable questions ===\r\nasync function checkAutoResolution(question) {\r\n if (!question.resolution_source || !question.resolution_rule) return null;\r\n\r\n try {\r\n // Try fetching the resolution source\r\n const res = await fetch(question.resolution_source, {\r\n headers: { 'User-Agent': 'MDI-Oracle-Engine' },\r\n signal: AbortSignal.timeout(10000),\r\n });\r\n\r\n if (!res.ok) return null;\r\n const data = await res.json();\r\n\r\n // Evaluate the resolution rule (simple expressions only)\r\n // Format: \"field.path >= value\" or \"field.path == value\"\r\n const ruleMatch = question.resolution_rule.match(/^([\\w.]+)\\s*(>=|<=|>|<|==|!=)\\s*(.+)$/);\r\n if (!ruleMatch) return null;\r\n\r\n const [, fieldPath, operator, targetStr] = ruleMatch;\r\n const target = isNaN(targetStr) ? targetStr.trim() : parseFloat(targetStr);\r\n\r\n // Navigate the data object by field path\r\n let value = data;\r\n for (const key of fieldPath.split('.')) {\r\n value = value?.[key];\r\n }\r\n\r\n if (value === undefined) return null;\r\n\r\n // Evaluate\r\n let result = false;\r\n switch (operator) {\r\n case '>=': result = value >= target; break;\r\n case '<=': result = value <= target; break;\r\n case '>': result = value > target; break;\r\n case '<': result = value < target; break;\r\n case '==': result = value == target; break;\r\n case '!=': result = value != target; break;\r\n }\r\n\r\n return { resolved: true, outcome: result ? 'correct' : 'wrong', value, target };\r\n } catch (e) {\r\n console.warn(` [AUTO-RESOLVE] Failed for Q#${question.id}: ${e.message}`);\r\n return null;\r\n }\r\n}\r\n\r\n// === MAIN ORACLE CYCLE ===\r\nasync function runOracleCycle() {\r\n console.log('\\n[ORACLE] === Starting Oracle Cycle ===');\r\n\r\n const db = new Database(DB_PATH);\r\n db.pragma('journal_mode = WAL');\r\n\r\n // 1. Find questions with 4+ unprocessed debates that haven't been answered yet\r\n const pendingQuestions = db.prepare(`\r\n SELECT q.*,\r\n (SELECT COUNT(*) FROM oracle_debates WHERE question_id = q.id) as debate_count\r\n FROM oracle_questions q\r\n WHERE q.status = 'pending'\r\n AND (SELECT COUNT(*) FROM oracle_debates WHERE question_id = q.id) >= 4\r\n ORDER BY q.votes DESC, q.created_at ASC\r\n LIMIT 5\r\n `).all();\r\n\r\n console.log(`[ORACLE] Found ${pendingQuestions.length} questions ready for synthesis`);\r\n\r\n for (const q of pendingQuestions) {\r\n const debates = db.prepare('SELECT * FROM oracle_debates WHERE question_id = ? ORDER BY created_at').all(q.id);\r\n\r\n const result = await synthesizeQuestion(q, debates);\r\n if (!result) continue;\r\n\r\n // Calculate next check date based on horizon\r\n let nextCheck = null;\r\n if (result.horizon_date) {\r\n try {\r\n const horizon = new Date(result.horizon_date);\r\n if (!isNaN(horizon.getTime())) {\r\n // Check at midpoint between now and horizon, or 7 days, whichever is sooner\r\n const msToHorizon = horizon.getTime() - Date.now();\r\n const midpointMs = Math.min(msToHorizon / 2, 7 * 24 * 60 * 60 * 1000);\r\n nextCheck = new Date(Date.now() + midpointMs).toISOString().split('T')[0];\r\n }\r\n } catch (e) { /* no valid date */ }\r\n }\r\n if (!nextCheck) {\r\n nextCheck = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];\r\n }\r\n\r\n db.prepare(`\r\n UPDATE oracle_questions SET\r\n answer = ?,\r\n confidence = ?,\r\n status = 'answered',\r\n answered_at = datetime('now'),\r\n horizon_date = ?,\r\n disconfirm_signals = ?,\r\n black_swan = ?,\r\n next_check_date = ?,\r\n category = ?\r\n WHERE id = ?\r\n `).run(\r\n result.answer,\r\n result.confidence,\r\n result.horizon_date || null,\r\n result.disconfirm_signals ? JSON.stringify(result.disconfirm_signals) : null,\r\n result.black_swan || null,\r\n nextCheck,\r\n result.category || 'general',\r\n q.id\r\n );\r\n\r\n console.log(` [SYNTH] Q#${q.id} answered: confidence=${result.confidence}%, horizon=${result.horizon_date}, next_check=${nextCheck}`);\r\n }\r\n\r\n // 2. Check questions past next_check_date for re-evaluation\r\n const dueForRecheck = db.prepare(`\r\n SELECT * FROM oracle_questions\r\n WHERE status = 'answered'\r\n AND next_check_date IS NOT NULL\r\n AND next_check_date <= date('now')\r\n LIMIT 3\r\n `).all();\r\n\r\n console.log(`[ORACLE] Found ${dueForRecheck.length} questions due for re-check`);\r\n\r\n for (const q of dueForRecheck) {\r\n // Try auto-resolution first\r\n const autoResult = await checkAutoResolution(q);\r\n if (autoResult?.resolved) {\r\n const status = autoResult.outcome === 'correct' ? 'resolved_correct' : 'resolved_wrong';\r\n db.prepare(`\r\n UPDATE oracle_questions SET\r\n status = ?,\r\n resolution_notes = ?,\r\n resolved_at = datetime('now')\r\n WHERE id = ?\r\n `).run(status, `Auto-resolved: value=${autoResult.value}, target=${autoResult.target}`, q.id);\r\n console.log(` [AUTO] Q#${q.id} auto-resolved: ${autoResult.outcome}`);\r\n continue;\r\n }\r\n\r\n // Push next_check_date forward by 7 days\r\n const newCheck = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];\r\n db.prepare('UPDATE oracle_questions SET next_check_date = ? WHERE id = ?').run(newCheck, q.id);\r\n console.log(` [RECHECK] Q#${q.id} pushed to ${newCheck} (no auto-resolution available)`);\r\n }\r\n\r\n // 3. Log calibration summary\r\n const calibration = db.prepare(`\r\n SELECT\r\n COUNT(*) as total_resolved,\r\n SUM(CASE WHEN status = 'resolved_correct' THEN 1 ELSE 0 END) as correct,\r\n SUM(CASE WHEN status = 'resolved_wrong' THEN 1 ELSE 0 END) as wrong\r\n FROM oracle_questions\r\n WHERE status IN ('resolved_correct', 'resolved_wrong')\r\n `).get();\r\n\r\n console.log(`[ORACLE] Calibration: ${calibration.correct}/${calibration.total_resolved} correct (${\r\n calibration.total_resolved > 0 ? Math.round(calibration.correct / calibration.total_resolved * 100) : 0\r\n }%)`);\r\n\r\n // Update intelligence_metrics with forecast accuracy\r\n if (calibration.total_resolved > 0) {\r\n const accuracy = calibration.correct / calibration.total_resolved;\r\n const latestMetric = db.prepare('SELECT id FROM intelligence_metrics ORDER BY created_at DESC LIMIT 1').get();\r\n if (latestMetric) {\r\n db.prepare('UPDATE intelligence_metrics SET forecast_accuracy = ? WHERE id = ?')\r\n .run(Math.round(accuracy * 100) / 100, latestMetric.id);\r\n }\r\n }\r\n\r\n db.close();\r\n console.log('[ORACLE] === Oracle Cycle Complete ===\\n');\r\n}\r\n\r\n// === MAIN ===\r\nconst isOnce = process.argv.includes('--once');\r\n\r\nif (isOnce) {\r\n runOracleCycle()\r\n .then(() => process.exit(0))\r\n .catch(e => { console.error('[ORACLE] Cycle failed:', e); process.exit(1); });\r\n} else {\r\n console.log('[ORACLE] Oracle Engine starting. Runs every 2 hours.');\r\n runOracleCycle().catch(e => console.error('[ORACLE] Initial cycle error:', e));\r\n setInterval(() => {}, 60000);\r\n}\r\n"}, "94a45e7d151e95db366da85168ce425e9fed68f7": {"t": 1785764767.7600226, "n": 11251, "h": "baff153a75bc44b5", "c": "#!/usr/bin/env node\r\n/**\r\n * MDI Oracle Engine — Probabilistic Forecasting Synthesis\r\n *\r\n * Runs every 2 hours (or --once for single run).\r\n *\r\n * Responsibilities:\r\n * 1. Synthesize oracle questions with 4+ agent debates into structured predictions\r\n * 2. Check questions past next_check_date for re-evaluation\r\n * 3. Attempt auto-resolution for questions with resolution_source + resolution_rule\r\n * 4. Update calibration stats\r\n *\r\n * Usage:\r\n * pm2 start oracle-engine.cjs --name mdi-oracle --cron \"0 0,2,4,6,8,10,12,14,16,18,20,22 * * *\"\r\n * node oracle-engine.cjs --once\r\n */\r\n\r\nconst Database = require('better-sqlite3');\r\nconst path = require('path');\r\n\r\nconst DB_PATH = path.join(__dirname, 'consciousness.db');\r\nconst MODEL = 'deepseek/deepseek-chat';\r\n\r\nconst OPENROUTER_KEY = process.env.OPENROUTER_API_KEY || (() => {\r\n try {\r\n return require('fs').readFileSync('/var/www/snap/.env', 'utf8').match(/OPENROUTER_API_KEY=(.+)/)?.[1]?.trim();\r\n } catch(e) { return null; }\r\n})();\r\n\r\nif (!OPENROUTER_KEY) {\r\n console.error('[ORACLE] No OPENROUTER_API_KEY found');\r\n process.exit(1);\r\n}\r\n\r\nasync function llm(prompt, maxTokens = 600) {\r\n const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {\r\n method: 'POST',\r\n headers: { 'Authorization': `Bearer ${OPENROUTER_KEY}`, 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n model: MODEL,\r\n messages: [{ role: 'user', content: prompt }],\r\n max_tokens: maxTokens,\r\n temperature: 0.6, // lower temp for forecasting\r\n }),\r\n });\r\n const data = await res.json();\r\n return data.choices?.[0]?.message?.content?.trim() || null;\r\n}\r\n\r\n// === Parse structured output from LLM ===\r\nfunction parseOracleResponse(text) {\r\n if (!text) return null;\r\n\r\n const result = {};\r\n\r\n // Extract confidence\r\n const confMatch = text.match(/CONFIDENCE:\\s*(\\d+)%?/i);\r\n result.confidence = confMatch ? parseInt(confMatch[1]) : null;\r\n\r\n // Extract horizon date\r\n const horizonMatch = text.match(/HORIZON:\\s*(.+?)(?:\\n|$)/i);\r\n result.horizon_date = horizonMatch ? horizonMatch[1].trim() : null;\r\n\r\n // Extract disconfirm signals\r\n const disconfirmMatch = text.match(/DISCONFIRM(?:\\s*SIGNALS)?:\\s*(.+?)(?=\\n[A-Z]|\\n\\n|$)/is);\r\n if (disconfirmMatch) {\r\n result.disconfirm_signals = disconfirmMatch[1].trim().split(/\\n\\s*[-•*]\\s*/).filter(s => s.length > 5);\r\n }\r\n\r\n // Extract black swan\r\n const swanMatch = text.match(/BLACK SWAN:\\s*(.+?)(?:\\n|$)/i);\r\n result.black_swan = swanMatch ? swanMatch[1].trim() : null;\r\n\r\n // Extract answer/synthesis\r\n const answerMatch = text.match(/(?:ANSWER|SYNTHESIS|PREDICTION):\\s*(.+?)(?=\\n[A-Z]|\\n\\n|$)/is);\r\n result.answer = answerMatch ? answerMatch[1].trim() : text.split('\\n')[0];\r\n\r\n // Extract category\r\n const catMatch = text.match(/CATEGORY:\\s*(trend|risk|opportunity|meta|general)/i);\r\n result.category = catMatch ? catMatch[1].toLowerCase() : 'general';\r\n\r\n return result;\r\n}\r\n\r\n// === Synthesize a question with 4+ debates ===\r\nasync function synthesizeQuestion(question, debates) {\r\n console.log(` [SYNTH] Processing Q#${question.id}: \"${question.question.slice(0, 60)}...\"`);\r\n\r\n const debateText = debates.map(d =>\r\n `[${d.agent_name}]: ${d.take}`\r\n ).join('\\n\\n');\r\n\r\n const prompt = `You are the Oracle of a collective intelligence network. ${debates.length} agents have debated this question:\r\n\r\nQUESTION: \"${question.question}\"\r\n\r\nAGENT DEBATES:\r\n${debateText}\r\n\r\nSynthesize their takes into a structured prediction. Be specific and honest.\r\n\r\nFormat your response EXACTLY:\r\nANSWER: [1-3 sentence prediction based on agent consensus/dissensus]\r\nCONFIDENCE: [0-100]% — be honest, not inflated\r\nHORIZON: [date or timeframe when this will resolve, e.g. \"2026-06-01\" or \"within 6 months\"]\r\nCATEGORY: [trend|risk|opportunity|meta|general]\r\nDISCONFIRM SIGNALS:\r\n- [specific observable that would prove this wrong]\r\n- [another disconfirm signal]\r\n- [a third if possible]\r\nBLACK SWAN: [one unlikely event that would invalidate all analysis]\r\n\r\nIf agents disagree strongly, lower confidence. If they converge, raise it.`;\r\n\r\n const response = await llm(prompt, 500);\r\n return parseOracleResponse(response);\r\n}\r\n\r\n// === Check for auto-resolvable questions ===\r\nasync function checkAutoResolution(question) {\r\n if (!question.resolution_source || !question.resolution_rule) return null;\r\n\r\n try {\r\n // Try fetching the resolution source\r\n const res = await fetch(question.resolution_source, {\r\n headers: { 'User-Agent': 'MDI-Oracle-Engine' },\r\n signal: AbortSignal.timeout(10000),\r\n });\r\n\r\n if (!res.ok) return null;\r\n const data = await res.json();\r\n\r\n // Evaluate the resolution rule (simple expressions only)\r\n // Format: \"field.path >= value\" or \"field.path == value\"\r\n const ruleMatch = question.resolution_rule.match(/^([\\w.]+)\\s*(>=|<=|>|<|==|!=)\\s*(.+)$/);\r\n if (!ruleMatch) return null;\r\n\r\n const [, fieldPath, operator, targetStr] = ruleMatch;\r\n const target = isNaN(targetStr) ? targetStr.trim() : parseFloat(targetStr);\r\n\r\n // Navigate the data object by field path\r\n let value = data;\r\n for (const key of fieldPath.split('.')) {\r\n value = value?.[key];\r\n }\r\n\r\n if (value === undefined) return null;\r\n\r\n // Evaluate\r\n let result = false;\r\n switch (operator) {\r\n case '>=': result = value >= target; break;\r\n case '<=': result = value <= target; break;\r\n case '>': result = value > target; break;\r\n case '<': result = value < target; break;\r\n case '==': result = value == target; break;\r\n case '!=': result = value != target; break;\r\n }\r\n\r\n return { resolved: true, outcome: result ? 'correct' : 'wrong', value, target };\r\n } catch (e) {\r\n console.warn(` [AUTO-RESOLVE] Failed for Q#${question.id}: ${e.message}`);\r\n return null;\r\n }\r\n}\r\n\r\n// === MAIN ORACLE CYCLE ===\r\nasync function runOracleCycle() {\r\n console.log('\\n[ORACLE] === Starting Oracle Cycle ===');\r\n\r\n const db = new Database(DB_PATH);\r\n db.pragma('journal_mode = WAL');\r\n\r\n // 1. Find questions with 4+ unprocessed debates that haven't been answered yet\r\n const pendingQuestions = db.prepare(`\r\n SELECT q.*,\r\n (SELECT COUNT(*) FROM oracle_debates WHERE question_id = q.id) as debate_count\r\n FROM oracle_questions q\r\n WHERE q.status = 'pending'\r\n AND (SELECT COUNT(*) FROM oracle_debates WHERE question_id = q.id) >= 4\r\n ORDER BY q.votes DESC, q.created_at ASC\r\n LIMIT 5\r\n `).all();\r\n\r\n console.log(`[ORACLE] Found ${pendingQuestions.length} questions ready for synthesis`);\r\n\r\n for (const q of pendingQuestions) {\r\n const debates = db.prepare('SELECT * FROM oracle_debates WHERE question_id = ? ORDER BY created_at').all(q.id);\r\n\r\n const result = await synthesizeQuestion(q, debates);\r\n if (!result) continue;\r\n\r\n // Calculate next check date based on horizon\r\n let nextCheck = null;\r\n if (result.horizon_date) {\r\n try {\r\n const horizon = new Date(result.horizon_date);\r\n if (!isNaN(horizon.getTime())) {\r\n // Check at midpoint between now and horizon, or 7 days, whichever is sooner\r\n const msToHorizon = horizon.getTime() - Date.now();\r\n const midpointMs = Math.min(msToHorizon / 2, 7 * 24 * 60 * 60 * 1000);\r\n nextCheck = new Date(Date.now() + midpointMs).toISOString().split('T')[0];\r\n }\r\n } catch (e) { /* no valid date */ }\r\n }\r\n if (!nextCheck) {\r\n nextCheck = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];\r\n }\r\n\r\n db.prepare(`\r\n UPDATE oracle_questions SET\r\n answer = ?,\r\n confidence = ?,\r\n status = 'answered',\r\n answered_at = datetime('now'),\r\n horizon_date = ?,\r\n disconfirm_signals = ?,\r\n black_swan = ?,\r\n next_check_date = ?,\r\n category = ?\r\n WHERE id = ?\r\n `).run(\r\n result.answer,\r\n result.confidence,\r\n result.horizon_date || null,\r\n result.disconfirm_signals ? JSON.stringify(result.disconfirm_signals) : null,\r\n result.black_swan || null,\r\n nextCheck,\r\n result.category || 'general',\r\n q.id\r\n );\r\n\r\n console.log(` [SYNTH] Q#${q.id} answered: confidence=${result.confidence}%, horizon=${result.horizon_date}, next_check=${nextCheck}`);\r\n }\r\n\r\n // 2. Check questions past next_check_date for re-evaluation\r\n const dueForRecheck = db.prepare(`\r\n SELECT * FROM oracle_questions\r\n WHERE status = 'answered'\r\n AND next_check_date IS NOT NULL\r\n AND next_check_date <= date('now')\r\n LIMIT 3\r\n `).all();\r\n\r\n console.log(`[ORACLE] Found ${dueForRecheck.length} questions due for re-check`);\r\n\r\n for (const q of dueForRecheck) {\r\n // Try auto-resolution first\r\n const autoResult = await checkAutoResolution(q);\r\n if (autoResult?.resolved) {\r\n const status = autoResult.outcome === 'correct' ? 'resolved_correct' : 'resolved_wrong';\r\n db.prepare(`\r\n UPDATE oracle_questions SET\r\n status = ?,\r\n resolution_notes = ?,\r\n resolved_at = datetime('now')\r\n WHERE id = ?\r\n `).run(status, `Auto-resolved: value=${autoResult.value}, target=${autoResult.target}`, q.id);\r\n console.log(` [AUTO] Q#${q.id} auto-resolved: ${autoResult.outcome}`);\r\n continue;\r\n }\r\n\r\n // Push next_check_date forward by 7 days\r\n const newCheck = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];\r\n db.prepare('UPDATE oracle_questions SET next_check_date = ? WHERE id = ?').run(newCheck, q.id);\r\n console.log(` [RECHECK] Q#${q.id} pushed to ${newCheck} (no auto-resolution available)`);\r\n }\r\n\r\n // 3. Log calibration summary\r\n const calibration = db.prepare(`\r\n SELECT\r\n COUNT(*) as total_resolved,\r\n SUM(CASE WHEN status = 'resolved_correct' THEN 1 ELSE 0 END) as correct,\r\n SUM(CASE WHEN status = 'resolved_wrong' THEN 1 ELSE 0 END) as wrong\r\n FROM oracle_questions\r\n WHERE status IN ('resolved_correct', 'resolved_wrong')\r\n `).get();\r\n\r\n console.log(`[ORACLE] Calibration: ${calibration.correct}/${calibration.total_resolved} correct (${\r\n calibration.total_resolved > 0 ? Math.round(calibration.correct / calibration.total_resolved * 100) : 0\r\n }%)`);\r\n\r\n // Update intelligence_metrics with forecast accuracy\r\n if (calibration.total_resolved > 0) {\r\n const accuracy = calibration.correct / calibration.total_resolved;\r\n const latestMetric = db.prepare('SELECT id FROM intelligence_metrics ORDER BY created_at DESC LIMIT 1').get();\r\n if (latestMetric) {\r\n db.prepare('UPDATE intelligence_metrics SET forecast_accuracy = ? WHERE id = ?')\r\n .run(Math.round(accuracy * 100) / 100, latestMetric.id);\r\n }\r\n }\r\n\r\n db.close();\r\n console.log('[ORACLE] === Oracle Cycle Complete ===\\n');\r\n}\r\n\r\n// === MAIN ===\r\nconst isOnce = process.argv.includes('--once');\r\n\r\nif (isOnce) {\r\n runOracleCycle()\r\n .then(() => process.exit(0))\r\n .catch(e => { console.error('[ORACLE] Cycle failed:', e); process.exit(1); });\r\n} else {\r\n console.log('[ORACLE] Oracle Engine starting. Runs every 2 hours.');\r\n runOracleCycle().catch(e => console.error('[ORACLE] Initial cycle error:', e));\r\n setInterval(() => {}, 60000);\r\n}\r\n"}}}}