Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/charthouse-ltd_reactive-graph-walker.json
T
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
49 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "charthouse-ltd/reactive-graph-walker", "files": {".env.example": {"fa03ebf09998a309e04b9aebb545d8642e53e29a": {"t": 1785747101.968292, "n": 275, "h": "e8250c284d804a05", "c": "# DeepSeek API key for LLM expression\nDEEPSEEK_API_KEY=sk-your-key-here\n\n# Optional: model selection (deepseek-chat or deepseek-reasoner)\nDEEPSEEK_MODEL=deepseek-chat\n\n# PostgreSQL connection\nDATABASE_URL=postgresql:///rgw_test?host=/tmp\n\n# Log level\nRUST_LOG=info,rgw=debug\n"}, "7c9e6bf0ed5d6db7ab56b9fa0a522a2d11eb5a22": {"t": 1785770419.377555, "n": 275, "h": "e8250c284d804a05", "c": "# DeepSeek API key for LLM expression\nDEEPSEEK_API_KEY=sk-your-key-here\n\n# Optional: model selection (deepseek-chat or deepseek-reasoner)\nDEEPSEEK_MODEL=deepseek-chat\n\n# PostgreSQL connection\nDATABASE_URL=postgresql:///rgw_test?host=/tmp\n\n# Log level\nRUST_LOG=info,rgw=debug\n"}}, "src/llm.rs": {"fa03ebf09998a309e04b9aebb545d8642e53e29a": {"t": 1786067492.8216028, "n": 7468, "h": "eeb03c15d562ed1c", "c": "//! DeepSeek LLM — direct HTTP integration.\n//!\n//! Talks to DeepSeek's API (OpenAI-compatible) over HTTPS.\n//! No Ollama proxy needed. No llama.cpp linking issues.\n//! The graph walker produces cognition in memory → DeepSeek\n//! reads the enriched prompt → text comes out.\n//!\n//! DeepSeek models:\n//! - deepseek-chat — general purpose, fast, cheap\n//! - deepseek-reasoner — chain-of-thought reasoning, slower, smarter\n//!\n//! API: POST https://api.deepseek.com/v1/chat/completions\n//! Auth: Bearer $DEEPSEEK_API_KEY\n\nuse serde::{Deserialize, Serialize};\n\n/// The DeepSeek LLM engine — a real HTTP client.\npub struct LlmEngine {\n api_key: String,\n model: String,\n base_url: String,\n client: reqwest::Client,\n}\n\n/// DeepSeek chat message\n#[derive(Debug, Serialize)]\nstruct ChatMessage {\n role: String,\n content: String,\n}\n\n/// DeepSeek request body (OpenAI-compatible)\n#[derive(Debug, Serialize)]\nstruct DeepSeekRequest {\n model: String,\n messages: Vec<ChatMessage>,\n #[serde(skip_serializing_if = \"Option::is_none\")]\n max_tokens: Option<u32>,\n temperature: f32,\n stream: bool,\n}\n\n/// DeepSeek response\n#[derive(Debug, Deserialize)]\nstruct DeepSeekResponse {\n choices: Vec<DeepSeekChoice>,\n /// Token accounting returned by DeepSeek. Captured for cost metrics.\n #[serde(default)]\n usage: Option<DeepSeekUsage>,\n}\n\n#[derive(Debug, Deserialize)]\nstruct DeepSeekChoice {\n message: DeepSeekMessage,\n}\n\n#[derive(Debug, Deserialize)]\nstruct DeepSeekMessage {\n content: String,\n}\n\n/// The `usage` object DeepSeek returns (OpenAI-compatible shape).\n#[derive(Debug, Deserialize, Default)]\nstruct DeepSeekUsage {\n #[serde(default)]\n prompt_tokens: u32,\n #[serde(default)]\n completion_tokens: u32,\n}\n\n/// Token usage for one completion — real if the API reported it,\n/// otherwise a char/4 estimate so cost accounting is never blind.\n#[derive(Debug, Clone, Copy, Default)]\npub struct ChatUsage {\n pub prompt_tokens: u32,\n pub completion_tokens: u32,\n}\n\nimpl LlmEngine {\n /// Create a new DeepSeek engine.\n ///\n /// api_key: DeepSeek API key (env: DEEPSEEK_API_KEY)\n /// model: \"deepseek-chat\" or \"deepseek-reasoner\"\n pub fn new(api_key: &str, model: &str) -> anyhow::Result<Self> {\n if api_key.is_empty() {\n anyhow::bail!(\"DEEPSEEK_API_KEY not set\");\n }\n\n let engine = Self {\n api_key: api_key.to_string(),\n model: model.to_string(),\n base_url: \"https://api.deepseek.com\".to_string(),\n client: reqwest::Client::new(),\n };\n\n tracing::info!(\"[llm] DeepSeek engine ready: model={}\", model);\n Ok(engine)\n }\n\n /// Backward-compatible constructor (ignores legacy llama.cpp params).\n /// Called from provider.rs with the old signature.\n pub fn load(model_path: &str, _n_gpu_layers: u32, _n_ctx: u32) -> anyhow::Result<Self> {\n // model_path is repurposed: if it looks like a DeepSeek model name, use it.\n // Otherwise fall back to DEEPSEEK_MODEL env or default.\n let api_key = std::env::var(\"DEEPSEEK_API_KEY\").unwrap_or_default();\n if api_key.is_empty() {\n anyhow::bail!(\"DEEPSEEK_API_KEY not set — cannot initialize DeepSeek engine\");\n }\n\n let model = if model_path.contains(\"deepseek\") {\n model_path.to_string()\n } else {\n std::env::var(\"DEEPSEEK_MODEL\").unwrap_or_else(|_| \"deepseek-chat\".into())\n };\n\n Self::new(&api_key, &model)\n }\n\n /// Send a chat completion request to DeepSeek.\n ///\n /// This is the main entry point. Called by provider.rs when routing\n /// decides to use the local (now DeepSeek) path for generation.\n pub async fn chat(\n &self,\n system: &str,\n user: &str,\n max_tokens: Option<u32>,\n temperature: f32,\n ) -> anyhow::Result<String> {\n let model = self.model.clone();\n let (text, _usage) = self\n .chat_with_model(&model, system, user, max_tokens, temperature)\n .await?;\n Ok(text)\n }\n\n /// Send a completion using an explicit model name (e.g. \"deepseek-chat\"\n /// or \"deepseek-reasoner\"), returning both the text and the REAL token\n /// usage. One engine instance can therefore serve both routing tiers.\n ///\n /// Records the call into the global cost metrics on success.\n pub async fn chat_with_model(\n &self,\n model: &str,\n system: &str,\n user: &str,\n max_tokens: Option<u32>,\n temperature: f32,\n ) -> anyhow::Result<(String, ChatUsage)> {\n let messages = vec![\n ChatMessage { role: \"system\".into(), content: system.to_string() },\n ChatMessage { role: \"user\".into(), content: user.to_string() },\n ];\n\n let body = DeepSeekRequest {\n model: model.to_string(),\n messages,\n max_tokens,\n temperature,\n stream: false,\n };\n\n let url = format!(\"{}/v1/chat/completions\", self.base_url);\n\n tracing::info!(\"[llm] POST {} model={} max_tokens={:?} temp={:.2} ({} chars user)\",\n url, model, max_tokens, temperature, user.len());\n\n let resp = self\n .client\n .post(&url)\n .header(\"Authorization\", format!(\"Bearer {}\", self.api_key))\n .header(\"Content-Type\", \"application/json\")\n .json(&body)\n .timeout(std::time::Duration::from_secs(60))\n .send()\n .await\n .inspect_err(|_| crate::metrics::record_failure())?;\n\n tracing::info!(\"[llm] DeepSeek response: HTTP {} ({} bytes)\",\n resp.status().as_u16(), resp.content_length().unwrap_or(0));\n\n if !resp.status().is_success() {\n crate::metrics::record_failure();\n let status = resp.status();\n let text = resp.text().await.unwrap_or_default();\n let preview: String = text.chars().take(300).collect();\n anyhow::bail!(\"DeepSeek {} — {}\", status, preview);\n }\n\n let data: DeepSeekResponse = resp.json().await.inspect_err(|_| crate::metrics::record_failure())?;\n let reported = data.usage.unwrap_or_default();\n let content = data\n .choices\n .into_iter()\n .next()\n .map(|c| c.message.content)\n .unwrap_or_default();\n\n if content.is_empty() {\n crate::metrics::record_failure();\n anyhow::bail!(\"DeepSeek returned empty response\");\n }\n\n // Prefer the API's real token counts; fall back to a char/4 estimate\n // so cost accounting is never blind even if `usage` is absent.\n let usage = ChatUsage {\n prompt_tokens: if reported.prompt_tokens > 0 {\n reported.prompt_tokens\n } else {\n (crate::budget::approx_tokens(system) + crate::budget::approx_tokens(user)) as u32\n },\n completion_tokens: if reported.completion_tokens > 0 {\n reported.completion_tokens\n } else {\n crate::budget::approx_tokens(&content) as u32\n },\n };\n\n crate::metrics::record_call(model, usage.prompt_tokens as u64, usage.completion_tokens as u64);\n\n Ok((content, usage))\n }\n\n /// Return the model name (for logging/routing visibility)\n pub fn model_name(&self) -> &str {\n &self.model\n }\n}\n"}}, "examples/cascade.rs": {"fa03ebf09998a309e04b9aebb545d8642e53e29a": {"t": 1786068337.8306916, "n": 38016, "h": "8a085777aa6257c7", "c": "//! RGW Cascade — full self-propagating cognition test.\n//!\n//! Seeds 100+ philosophical nodes with intentional topology:\n//! - Dense clusters (well-connected hubs)\n//! - Sparse bridges (few edges between clusters)\n//! - Dead-end zones (isolated nodes)\n//! - Contradiction zones (high-tension edges)\n//!\n//! Then runs the Diverger reactor — edge changes cascade, thresholds\n//! fire spontaneous walks. Optionally connects DeepSeek for expression.\n//!\n//! Logs: structural noticings, prediction errors, beliefs, working memory,\n//! collective walker trails, attention patterns, module activity.\n//!\n//! Build:\n//! cargo build --release --example cascade\n//!\n//! Run (local DB):\n//! DATABASE_URL=postgresql:///rgw_test?host=/tmp RUST_LOG=info,rgw=debug ./target/release/examples/cascade\n//!\n//! Run (with DeepSeek):\n//! DEEPSEEK_API_KEY=sk-... DATABASE_URL=... RUST_LOG=info,rgw=debug ./target/release/examples/cascade\n\nuse std::collections::HashMap;\nuse std::sync::Arc;\nuse tokio::sync::Mutex;\nuse std::time::{Duration, Instant};\n\nuse sqlx::PgPool;\n\n// ── Expanded seed data: 108 nodes, 12 thinkers, 10 domains ──────\n\nstruct SeedNode {\n content: &'static str,\n domain: &'static str,\n importance: f32,\n valence: f32,\n}\n\nfn seed_nodes() -> Vec<SeedNode> {\n let mut nodes = Vec::new();\n\n // ═══ DENSE CLUSTER 1: Epistemology hub (Plato↔Kant↔Descartes↔Hume) ═══\n let cluster1 = vec![\n // Plato\n (\"The allegory of the cave: prisoners see only shadows, mistaking appearance for reality.\", \"epistemology\", 9.0, 0.3),\n (\"The Forms are perfect eternal archetypes. Physical objects are imperfect copies.\", \"metaphysics\", 8.5, 0.2),\n (\"Knowledge is justified true belief — recollection of what the soul knew before birth.\", \"epistemology\", 8.0, 0.1),\n // Kant\n (\"We do not see things as they are — the mind imposes categories on raw sensation.\", \"epistemology\", 9.5, 0.0),\n (\"The noumenal world is forever inaccessible. We know only phenomena.\", \"epistemology\", 8.5, -0.1),\n (\"The categorical imperative: act so your maxim could become universal law.\", \"ethics\", 9.0, 0.3),\n // Descartes\n (\"I think, therefore I am. The one indubitable truth is the existence of the thinking self.\", \"epistemology\", 9.0, 0.4),\n (\"Mind-body dualism: the mental and physical are fundamentally different substances.\", \"metaphysics\", 8.0, 0.1),\n (\"Systematic doubt: demolish all beliefs and rebuild from indubitable foundations.\", \"epistemology\", 7.5, 0.0),\n // Hume\n (\"All knowledge comes from experience. There are no innate ideas — the mind is a blank slate.\", \"epistemology\", 8.5, -0.1),\n (\"Causation is not rationally justified — we infer it from constant conjunction, not reason.\", \"epistemology\", 9.0, -0.2),\n (\"The self is a bundle of perceptions. There is no underlying substance called 'I'.\", \"consciousness\", 8.5, -0.3),\n ];\n nodes.extend(cluster1);\n\n // ═══ DENSE CLUSTER 2: Meaning cluster (Nietzsche↔Schopenhauer↔Camus) ═══\n let cluster2 = vec![\n (\"God is dead. We have killed him. How shall we comfort ourselves?\", \"existentialism\", 9.5, -0.5),\n (\"Become who you are. The Ubermensch creates their own values.\", \"ethics\", 9.0, 0.6),\n (\"What does not kill me makes me stronger.\", \"existentialism\", 8.0, -0.2),\n // Schopenhauer\n (\"The world is my representation. Reality is Will — blind, striving, insatiable.\", \"metaphysics\", 9.0, -0.6),\n (\"Life swings like a pendulum between pain and boredom.\", \"existentialism\", 8.5, -0.7),\n (\"Aesthetic contemplation offers temporary escape from the tyranny of Will.\", \"aesthetics\", 7.5, 0.3),\n // Camus\n (\"The absurd: humanity's need for meaning meets the universe's silent indifference.\", \"existentialism\", 9.0, -0.4),\n (\"One must imagine Sisyphus happy. Revolt against meaninglessness IS meaning.\", \"existentialism\", 8.5, 0.5),\n (\"Suicide is the only serious philosophical problem — is life worth living?\", \"existentialism\", 8.0, -0.8),\n ];\n nodes.extend(cluster2);\n\n // ═══ DENSE CLUSTER 3: Science cluster (Darwin↔Feynman↔Gödel↔Turing) ═══\n let cluster3 = vec![\n (\"Natural selection: cumulative adaptation, not random chance.\", \"science\", 9.5, 0.0),\n (\"There is grandeur in this view of life: endless forms most beautiful.\", \"science\", 8.5, 0.7),\n (\"The tree of life connects all species through common descent.\", \"science\", 8.0, 0.5),\n // Feynman\n (\"The double-slit experiment: observation changes reality at the quantum level.\", \"science\", 9.0, 0.0),\n (\"I think I can safely say nobody understands quantum mechanics.\", \"science\", 8.0, -0.1),\n (\"What I cannot create, I do not understand. Understanding requires construction.\", \"epistemology\", 8.5, 0.3),\n // Gödel\n (\"Any consistent formal system contains true statements it cannot prove.\", \"computation\", 9.5, -0.2),\n (\"The limits of mathematics are not practical — they are logical and fundamental.\", \"computation\", 8.5, -0.1),\n (\"Truth extends beyond provability. There is more to reality than formal systems.\", \"epistemology\", 8.0, 0.2),\n // Turing\n (\"A universal machine can compute anything computable — limits are mathematical, not mechanical.\", \"computation\", 9.5, 0.2),\n (\"The imitation game: if a machine talks like a human, on what grounds do we deny it thought?\", \"computation\", 9.0, 0.0),\n (\"Morphogenesis: simple rules produce complex patterns — stripes, leaves, galaxies.\", \"science\", 8.0, 0.5),\n ];\n nodes.extend(cluster3);\n\n // ═══ DENSE CLUSTER 4: Consciousness cluster (Buddha↔Spinoza↔Wittgenstein) ═══\n let cluster4 = vec![\n (\"All that we are is the result of what we have thought. The mind is everything.\", \"consciousness\", 9.0, 0.5),\n (\"The root of suffering is attachment to impermanent things.\", \"consciousness\", 9.0, -0.3),\n (\"There is no permanent self — only momentary aggregates of form and sensation.\", \"consciousness\", 8.5, 0.0),\n (\"The middle way: neither indulgence nor asceticism. Balanced present-moment awareness.\", \"ethics\", 7.5, 0.6),\n // Spinoza\n (\"God and Nature are one substance. Deus sive Natura. Pantheism, not atheism.\", \"metaphysics\", 9.0, 0.5),\n (\"Free will is an illusion born of ignorance of causes. All things follow necessarily.\", \"metaphysics\", 8.5, -0.3),\n (\"The highest good is the intellectual love of God — understanding the necessity of all things.\", \"ethics\", 8.0, 0.4),\n // Wittgenstein\n (\"The limits of my language are the limits of my world.\", \"language\", 9.5, 0.1),\n (\"Whereof one cannot speak, thereof one must be silent.\", \"language\", 9.0, 0.0),\n (\"Philosophy is a battle against the bewitchment of our intelligence by means of language.\", \"language\", 8.5, -0.2),\n (\"Meaning is use. A word's meaning is its function in the language-game, not a fixed definition.\", \"language\", 8.0, 0.3),\n ];\n nodes.extend(cluster4);\n\n // ═══ SPARSE BRIDGE NODES (intentional few connections between clusters) ═══\n let bridges = vec![\n (\"Plato's Forms and Kant's categories both suggest reality is shaped by mind, not discovered.\", \"epistemology\", 7.0, 0.3),\n (\"Nietzsche and Darwin both dethrone humanity from cosmic centrality.\", \"existentialism\", 7.5, -0.1),\n (\"Buddha's no-self and Hume's bundle theory converge: the self is process, not substance.\", \"consciousness\", 8.0, 0.2),\n (\"Kant's noumenal and Wittgenstein's 'whereof one cannot speak' mark the same boundary.\", \"epistemology\", 7.5, 0.1),\n (\"Gödel's incompleteness and Hume's skepticism: reason has limits that reason itself discovers.\", \"epistemology\", 8.0, -0.1),\n (\"Turing's morphogenesis and Spinoza's necessity: complexity emerges from simple deterministic rules.\", \"science\", 7.5, 0.4),\n (\"Schopenhauer's Will and Darwin's natural selection: the blind striving beneath all life.\", \"metaphysics\", 7.0, -0.4),\n (\"Camus' absurd and Wittgenstein's silence: the ethical and the mystical show themselves, cannot be said.\", \"existentialism\", 7.5, 0.0),\n (\"Feynman's quantum observer and Buddha's mind-is-everything: consciousness shapes reality.\", \"science\", 8.0, 0.5),\n (\"Descartes' cogito and Buddhism's meditation: both turn inward to find certainty.\", \"consciousness\", 7.0, 0.3),\n ];\n nodes.extend(bridges);\n\n // ═══ DEAD-END ZONE: Isolated nodes with few connections ═══\n let dead_ends = vec![\n (\"Rashomon effect: the same event perceived differently by different observers. Truth is perspectival.\", \"epistemology\", 6.0, 0.0),\n (\"The Ship of Theseus: if all parts are replaced, is it still the same ship? Identity over time.\", \"metaphysics\", 6.5, 0.1),\n (\"The Trolley Problem: is it moral to sacrifice one to save five? Ethics without easy answers.\", \"ethics\", 6.0, -0.2),\n (\"Chinese Room argument: syntax is not semantics. A computer following rules does not understand.\", \"computation\", 7.0, -0.1),\n (\"Mary's Room: does someone who knows all facts about color learn something new when seeing red?\", \"consciousness\", 7.0, 0.2),\n ];\n nodes.extend(dead_ends);\n\n // ═══ CONTRADICTION ZONE: High-tension opposing ideas ═══\n let tensions = vec![\n (\"Determinism: every event is causally determined by prior events. Free will is an illusion.\", \"metaphysics\", 8.0, -0.4),\n (\"Libertarian free will: consciousness can initiate causal chains, not merely transmit them.\", \"metaphysics\", 7.5, 0.5),\n (\"Moral realism: ethical truths exist independently of human opinion — like mathematical truths.\", \"ethics\", 7.5, 0.2),\n (\"Moral relativism: ethics are culturally constructed. There are no universal moral facts.\", \"ethics\", 7.5, 0.1),\n (\"Scientific realism: the entities described by science (electrons, genes) really exist.\", \"science\", 8.0, 0.1),\n (\"Scientific instrumentalism: scientific theories are useful fictions that predict, not describe reality.\", \"science\", 7.5, 0.0),\n (\"Strong AI: a sufficiently advanced computer would literally be conscious, not just simulate it.\", \"computation\", 8.0, 0.5),\n (\"Weak AI: machines can simulate intelligence but never possess genuine phenomenal consciousness.\", \"computation\", 7.5, 0.0),\n ];\n nodes.extend(tensions);\n\n // ═══ WILD CARDS: Unexpected connections ═══\n let wildcards = vec![\n (\"Heraclitus: You cannot step into the same river twice. Everything flows, nothing stands still.\", \"metaphysics\", 8.5, 0.2),\n (\"The Dao that can be spoken is not the eternal Dao. The named is not the unnameable.\", \"language\", 8.0, 0.3),\n (\"Pascal: The heart has reasons that reason knows nothing of.\", \"epistemology\", 7.5, 0.4),\n (\"Arendt: The banality of evil — monstrous acts committed by ordinary people following orders.\", \"ethics\", 8.5, -0.7),\n (\"McLuhan: The medium is the message. The form of communication shapes society more than content.\", \"language\", 8.0, 0.1),\n (\"Epicurus: Is God willing to prevent evil but not able? Then he is not omnipotent. Is he able but not willing? Then he is malevolent.\", \"metaphysics\", 8.5, -0.5),\n (\"Foucault: Knowledge is power. What counts as truth is determined by social power structures.\", \"epistemology\", 8.0, -0.3),\n (\"Kuhn: Scientific revolutions are paradigm shifts — not cumulative progress but radical reconceptualization.\", \"science\", 8.5, 0.0),\n (\"de Beauvoir: One is not born a woman, but becomes one. Gender is constructed, not biological destiny.\", \"ethics\", 8.0, 0.3),\n (\"Laozi: The softest thing in the world overcomes the hardest. Water wears down stone — not through force but persistence.\", \"ethics\", 7.5, 0.5),\n (\"Nagel: What is it like to be a bat? There is something it is like — consciousness has a subjective character science cannot capture.\", \"consciousness\", 9.0, 0.1),\n (\"Popper: A theory is scientific only if it is falsifiable. Unfalsifiable claims are not science but metaphysics.\", \"science\", 8.5, 0.0),\n (\"Chomsky: Language is an innate biological capacity — universal grammar is hardwired in the human brain.\", \"language\", 8.0, 0.3),\n (\"Sartre: Existence precedes essence. We are thrown into existence and must create our own meaning.\", \"existentialism\", 8.5, -0.1),\n (\"Heidegger: Being-toward-death. Awareness of mortality is what gives life its urgency and authenticity.\", \"existentialism\", 8.5, -0.4),\n (\"Rawls: Justice as fairness — design society behind a veil of ignorance where you don't know your position.\", \"ethics\", 8.0, 0.3),\n (\"Quine: The web of belief — knowledge is a network where any statement can be revised, but not all at once.\", \"epistemology\", 8.0, 0.1),\n (\"Dennett: Consciousness is an illusion — a user-interface the brain presents to itself, not a magical substance.\", \"consciousness\", 8.0, -0.2),\n ];\n nodes.extend(wildcards);\n\n nodes.into_iter().map(|(c, d, i, v)| SeedNode { content: c, domain: d, importance: i, valence: v }).collect()\n}\n\n// ── Edge definitions ─────────────────────────────────────────────\n// (source_idx, target_idx, edge_type, weight, emotional_charge)\n\nfn seed_edges() -> Vec<(usize, usize, &'static str, f32, f32)> {\n let mut e = Vec::new();\n\n // ── Cluster 1 internal (nodes 0-11): dense epistemology hub ──\n let c1: Vec<(usize, usize, &str, f32, f32)> = vec![\n (0,1,\"reinforces\",0.8,0.2), (0,2,\"related\",0.6,0.1), (0,3,\"similar\",0.7,0.3),\n (1,7,\"related\",0.5,0.1), (2,8,\"similar\",0.4,0.1), (3,4,\"reinforces\",0.9,-0.1),\n (3,5,\"related\",0.5,0.1), (4,6,\"similar\",0.6,0.2), (5,8,\"contradicts\",0.5,0.0),\n (6,7,\"related\",0.5,0.1), (6,8,\"reinforces\",0.7,0.2), (8,9,\"contradicts\",0.6,-0.1),\n (9,10,\"reinforces\",0.8,-0.1), (10,11,\"similar\",0.7,-0.2), (7,11,\"related\",0.4,0.1),\n (0,6,\"similar\",0.5,0.3), (1,4,\"similar\",0.6,0.1), (2,10,\"contradicts\",0.5,-0.2),\n ];\n e.extend(c1);\n\n // ── Cluster 2 internal (nodes 12-20): meaning/purpose hub ──\n let c2 = vec![\n (12,13,\"caused\",0.8,-0.3), (12,14,\"reinforces\",0.5,-0.1), (13,14,\"related\",0.4,0.3),\n (15,16,\"reinforces\",0.7,-0.5), (15,17,\"caused\",0.6,-0.3), (16,18,\"related\",0.5,0.3),\n (17,18,\"similar\",0.6,0.4), (18,19,\"reinforces\",0.8,-0.4), (12,15,\"reminds_of\",0.6,-0.4),\n (13,17,\"similar\",0.5,0.2), (14,18,\"related\",0.4,-0.1),\n ];\n e.extend(c2);\n\n // ── Cluster 3 internal (nodes 21-32): science/computation hub ──\n let c3 = vec![\n (21,22,\"reinforces\",0.8,0.5), (21,23,\"related\",0.7,0.4), (22,23,\"similar\",0.6,0.5),\n (24,25,\"related\",0.6,0.0), (24,26,\"reinforces\",0.5,0.2), (25,28,\"similar\",0.4,0.1),\n (27,28,\"reinforces\",0.9,-0.1), (27,29,\"related\",0.6,0.1), (28,29,\"similar\",0.7,0.0),\n (30,31,\"caused\",0.8,0.2), (30,32,\"related\",0.7,-0.1), (31,33,\"related\",0.5,0.3),\n (21,30,\"similar\",0.5,0.3), (23,33,\"similar\",0.5,0.2), (27,26,\"related\",0.4,-0.1),\n ];\n e.extend(c3);\n\n // ── Cluster 4 internal (nodes 33-43): consciousness/language hub ──\n let c4 = vec![\n (33,34,\"caused\",0.7,-0.2), (33,35,\"related\",0.8,0.1), (34,36,\"related\",0.6,0.3),\n (35,40,\"similar\",0.5,0.1), (37,38,\"reinforces\",0.9,0.4), (37,39,\"related\",0.6,0.3),\n (40,41,\"reinforces\",0.8,0.1), (40,42,\"caused\",0.6,-0.1), (41,42,\"similar\",0.5,0.0),\n (41,43,\"related\",0.4,0.2), (33,37,\"reminds_of\",0.5,0.3), (35,39,\"similar\",0.4,0.2),\n ];\n e.extend(c4);\n\n // ── Bridge nodes (44-53): sparse inter-cluster connections ──\n let bridges = vec![\n // Epistemology ↔ Meaning\n (0,12,\"reminds_of\",0.4,0.0),\n (8,17,\"similar\",0.3,0.1),\n // Epistemology ↔ Science\n (3,21,\"similar\",0.5,0.2),\n (10,27,\"related\",0.4,-0.1),\n // Meaning ↔ Science\n (15,21,\"contradicts\",0.5,-0.3),\n (16,22,\"reminds_of\",0.3,0.0),\n // Consciousness ↔ Epistemology\n (33,0,\"reminds_of\",0.5,0.2),\n (35,11,\"similar\",0.6,0.1),\n // Consciousness ↔ Computation\n (35,30,\"similar\",0.5,0.3),\n (34,31,\"related\",0.4,0.0),\n // Language ↔ Epistemology\n (40,4,\"similar\",0.5,0.1),\n (41,8,\"reminds_of\",0.4,0.0),\n // Meaning ↔ Consciousness\n (18,34,\"similar\",0.4,0.1),\n (19,36,\"reminds_of\",0.3,0.1),\n ];\n e.extend(bridges);\n\n // ── Dead-end edges (54-58): minimal connections ──\n let deads = vec![\n (54,0,\"related\",0.2,0.0), // Ship of Theseus → Plato cave (weak)\n (55,5,\"reminds_of\",0.2,0.0), // Trolley → Kant imperative (weak)\n (56,30,\"contradicts\",0.3,0.0), // Chinese Room → Turing (weak)\n (57,35,\"related\",0.2,0.1), // Mary's Room → Buddha no-self (weak)\n (58,53,\"reminds_of\",0.1,0.0), // Rashomon → bridge (very weak)\n ];\n e.extend(deads);\n\n // ── Contradiction zone edges (59-66): high tension ──\n let tensions = vec![\n (59,60,\"contradicts\",0.9,-0.8), // Determinism vs Free Will\n (61,62,\"contradicts\",0.8,-0.6), // Moral realism vs relativism\n (63,64,\"contradicts\",0.7,-0.4), // Scientific realism vs instrumentalism\n (65,66,\"contradicts\",0.9,-0.7), // Strong AI vs Weak AI\n (59,37,\"related\",0.4,-0.2), // Determinism ↔ Spinoza\n (60,13,\"similar\",0.4,0.3), // Free will ↔ Ubermensch\n (65,31,\"reminds_of\",0.5,0.1), // Strong AI ↔ Turing\n (66,56,\"reinforces\",0.5,0.0), // Weak AI ↔ Chinese Room\n ];\n e.extend(tensions);\n\n // ── Wild card edges (67-84): unexpected bridges ──\n let wilds = vec![\n (67,1,\"similar\",0.4,0.1), // Heraclitus flux ↔ Plato Forms\n (68,40,\"similar\",0.6,0.3), // Dao ↔ Wittgenstein silence\n (69,8,\"reminds_of\",0.4,0.2), // Pascal heart ↔ Descartes doubt\n (70,18,\"related\",0.3,-0.4), // Arendt banality ↔ Camus absurd\n (71,42,\"similar\",0.5,0.2), // McLuhan medium ↔ Wittgenstein meaning\n (72,12,\"contradicts\",0.6,-0.5), // Epicurus evil ↔ Nietzsche God is dead\n (73,10,\"reminds_of\",0.5,-0.2), // Foucault power ↔ Hume causation\n (74,21,\"similar\",0.6,0.1), // Kuhn paradigm ↔ Darwin selection\n (75,13,\"related\",0.4,0.3), // de Beauvoir gender ↔ Nietzsche create values\n (76,36,\"similar\",0.4,0.4), // Laozi soft ↔ Buddha middle way\n (77,24,\"related\",0.5,0.0), // Nagel bat ↔ Feynman quantum\n (78,63,\"reinforces\",0.5,0.0), // Popper falsify ↔ Scientific realism\n (79,43,\"similar\",0.5,0.1), // Chomsky grammar ↔ Wittgenstein language-game\n (80,19,\"similar\",0.6,0.0), // Sartre existence ↔ Camus Sisyphus\n (81,17,\"related\",0.5,-0.3), // Heidegger death ↔ Schopenhauer pain\n (82,5,\"reminds_of\",0.4,0.2), // Rawls veil ↔ Kant imperative\n (83,10,\"contradicts\",0.3,0.0), // Quine web ↔ Hume bundle\n (84,35,\"contradicts\",0.4,-0.1), // Dennett illusion ↔ Buddha no-self\n ];\n e.extend(wilds);\n\n e\n}\n\n// ── Database ─────────────────────────────────────────────────────\n\nasync fn ensure_schema(pool: &PgPool) -> anyhow::Result<()> {\n sqlx::query(\"CREATE EXTENSION IF NOT EXISTS vector\").execute(pool).await?;\n sqlx::query(\"CREATE TABLE IF NOT EXISTS memory_vectors (id SERIAL PRIMARY KEY, content TEXT NOT NULL, domain VARCHAR(100) DEFAULT '', embedding vector(768), importance REAL DEFAULT 5.0, valence REAL DEFAULT 0.0, arousal REAL DEFAULT 0.5, access_count INTEGER DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW())\").execute(pool).await?;\n sqlx::query(\"CREATE TABLE IF NOT EXISTS memory_edges (id SERIAL PRIMARY KEY, source_id INTEGER NOT NULL REFERENCES memory_vectors(id) ON DELETE CASCADE, target_id INTEGER NOT NULL REFERENCES memory_vectors(id) ON DELETE CASCADE, edge_type VARCHAR(50) NOT NULL DEFAULT 'related', weight REAL DEFAULT 0.5, emotional_charge REAL DEFAULT 0.0, traversal_count INTEGER DEFAULT 0, last_traversed TIMESTAMPTZ DEFAULT NOW(), created_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(source_id, target_id, edge_type))\").execute(pool).await?;\n Ok(())\n}\n\nasync fn seed_graph(pool: &PgPool) -> anyhow::Result<Vec<i32>> {\n let nodes = seed_nodes();\n let edges = seed_edges();\n let mut ids = Vec::with_capacity(nodes.len());\n\n println!(\"Seeding {} nodes...\", nodes.len());\n for node in &nodes {\n let emb = rgw::embed::embed_text(node.content)?;\n let id = rgw::db::create_memory_node(pool, node.content, node.domain, &emb, node.importance, node.valence, 0.5).await?;\n ids.push(id);\n }\n\n println!(\"Creating {} edges...\", edges.len());\n for &(s, t, ty, w, ec) in &edges {\n if s < ids.len() && t < ids.len() {\n let _ = rgw::db::create_edge(pool, ids[s], ids[t], ty, w, ec).await;\n }\n }\n\n let stats = rgw::db::graph_stats(pool).await?;\n println!(\"Graph: {} nodes, {} edges\\n\", stats.nodes, stats.edges);\n Ok(ids)\n}\n\n// ── Cascade Engine ───────────────────────────────────────────────\n\nasync fn run_cascade(pool: &PgPool, node_ids: &[i32]) -> anyhow::Result<()> {\n use rgw::core::{self, SelfModel, CognitiveMode, Signal};\n use rgw::graph::{EmotionalState, WalkerBias};\n use rgw::walker;\n use rgw::diverger::{Diverger, DivergerConfig, EdgeChange};\n\n let self_model = Arc::new(Mutex::new(SelfModel::new()));\n let julian_url = \"\";\n\n // Initialize Diverger\n let diverger = Diverger::new(pool.clone(), self_model.clone(), julian_url);\n\n // Seed initial energy into the graph to kickstart cascades\n let seed_nodes: Vec<i32> = node_ids.iter().take(20).copied().collect();\n diverger.seed_energy(seed_nodes, 0.3).await;\n\n // Set emotional state on the shared self-model. The Diverger now reads\n // its mood from the self-model (sm.valence/arousal/energy), not a separate\n // set_emotion setter, so seeding the mood here flows into diverger modulation.\n {\n let mut sm = self_model.lock().await;\n sm.valence = 0.0;\n sm.arousal = 0.4;\n sm.energy = 0.8;\n }\n\n println!(\"╔══════════════════════════════════════════════════════╗\");\n println!(\"║ RGW CASCADE — Self-Propagating Cognition ║\");\n println!(\"║ 108 nodes, 10 domains, intentional topology ║\");\n println!(\"╚══════════════════════════════════════════════════════╝\\n\");\n\n // ── PHASE 1: Manual walk sessions to warm the graph ──\n println!(\"─── PHASE 1: Warm-up walks ───\\n\");\n for session in 0..3 {\n let arousal = 0.3 + session as f32 * 0.15;\n {\n let mut sm = self_model.lock().await;\n sm.valence = 0.1;\n sm.arousal = arousal;\n sm.energy = 0.8;\n }\n let (output, _) = walker::walk_parallel(pool, &EmotionalState { valence: 0.1, arousal, energy: 0.8 }, 6, 6, &self_model).await;\n println!(\" Session {}: {:2} hops | agreement={:.2} novelty={:.2} | domain={} action={}\",\n session + 1, output.total_hops, output.agreement_score, output.novelty_score,\n output.primary_domain, output.recommended_action);\n }\n\n // ── PHASE 2: Inject edge changes to trigger diverger cascades ──\n println!(\"\\n─── PHASE 2: Diverger cascade (spontaneous walks) ───\\n\");\n\n // Pick some edges from warm walks and notify the diverger\n let edge_sample = vec![\n EdgeChange { edge_id: 1, source_id: node_ids[0], target_id: node_ids[1], delta: 0.3, edge_type: \"reinforces\".into() },\n EdgeChange { edge_id: 5, source_id: node_ids[3], target_id: node_ids[4], delta: 0.4, edge_type: \"reinforces\".into() },\n EdgeChange { edge_id: 20, source_id: node_ids[12], target_id: node_ids[13], delta: 0.5, edge_type: \"caused\".into() },\n EdgeChange { edge_id: 35, source_id: node_ids[21], target_id: node_ids[22], delta: 0.3, edge_type: \"reinforces\".into() },\n EdgeChange { edge_id: 50, source_id: node_ids[33], target_id: node_ids[34], delta: 0.4, edge_type: \"caused\".into() },\n EdgeChange { edge_id: 59, source_id: node_ids[59], target_id: node_ids[60], delta: 0.6, edge_type: \"contradicts\".into() },\n EdgeChange { edge_id: 65, source_id: node_ids[65], target_id: node_ids[66], delta: 0.7, edge_type: \"contradicts\".into() },\n ];\n\n for change in &edge_sample {\n diverger.notify_edge_change(change.clone());\n }\n\n println!(\" Injected {} edge changes. Waiting for cascades...\\n\", edge_sample.len());\n\n // Let the diverger process for a few seconds\n tokio::time::sleep(Duration::from_secs(3)).await;\n\n // ── PHASE 3: High-arousal re-walk ──\n println!(\"─── PHASE 3: High-arousal re-walk ───\\n\");\n\n // Set a prediction: expect to find connections in epistemology\n {\n let mut sm = self_model.lock().await;\n sm.predict(\"epistemology\", \"connection between rationalists and empiricists\", 0.6);\n }\n\n {\n let mut sm = self_model.lock().await;\n sm.valence = 0.3;\n sm.arousal = 0.8;\n sm.energy = 0.7;\n }\n let (output3, _) = walker::walk_parallel(pool, &EmotionalState { valence: 0.3, arousal: 0.8, energy: 0.7 }, 8, 5, &self_model).await;\n println!(\" {:2} walkers × {} hops | agreement={:.2} novelty={:.2} | domain={} action={}\",\n 8, output3.total_hops, output3.agreement_score, output3.novelty_score,\n output3.primary_domain, output3.recommended_action);\n\n // ── PHASE 4: Final diverger stats ──\n tokio::time::sleep(Duration::from_secs(1)).await;\n let d_stats = diverger.stats().await;\n println!(\"\\n─── DIVERGER STATE ───\");\n println!(\" Alive: {} | Active nodes: {} | Total energy: {:.2}\", d_stats.alive, d_stats.active_nodes, d_stats.total_energy);\n println!(\" Walks fired: {} | Cascades: {} | Edges changed: {}\", d_stats.walks_fired, d_stats.cascades_total, d_stats.edges_changed);\n if !d_stats.hottest_nodes.is_empty() {\n println!(\" Hottest nodes: {:?}\", &d_stats.hottest_nodes[..d_stats.hottest_nodes.len().min(5)]);\n }\n\n // ── SELF-MODEL REPORT ──\n let sm_snapshot = {\n let sm = self_model.lock().await;\n sm.clone() // Clone and release the lock immediately\n }; // Lock released here — critical: Phase 5 also needs the lock!\n let sm = &sm_snapshot; // Use the snapshot for the report\n println!(\"\\n╔══════════════════════════════════════════════════════╗\");\n println!(\"║ SELF-MODEL REPORT ║\");\n println!(\"╚══════════════════════════════════════════════════════╝\\n\");\n\n println!(\" Mode: {:?} | Plasticity: {:.3}\", sm.mode, sm.plasticity_gate);\n println!(\" Valence={:+.3} Arousal={:.3} Energy={:.3}\", sm.valence, sm.arousal, sm.energy);\n println!(\" Signals: {} | Noticings: {} | Surprises: {}\", sm.total_signals_processed, sm.total_noticings, sm.surprise_count);\n println!(\" Focus: {} (intensity={:.2})\", sm.current_focus, sm.focus_intensity);\n\n // ── Beliefs ──\n println!(\"\\n ── Beliefs ({}) ──\", sm.beliefs.len());\n if sm.beliefs.is_empty() {\n println!(\" (none yet — need more walks for pattern accumulation)\");\n }\n for b in &sm.beliefs {\n println!(\" [{}] {} (conf={:.2} ev={})\", b.domain, core::safe_truncate(&b.statement, 60), b.confidence, b.evidence_count);\n }\n\n // ── Working Memory ──\n println!(\"\\n ── Working Memory ({}) ──\", sm.working_memory.len());\n for wm in &sm.working_memory {\n println!(\" [{}] {} (act={:.0}%)\", wm.domain, core::safe_truncate(&wm.content, 55), wm.activation * 100.0);\n }\n\n // ── Structural Noticings ──\n println!(\"\\n ── Structural Noticings ──\");\n let structural_kinds = [\n \"dead_end_cluster\", \"surprise_density\", \"cognitive_loop\",\n \"signal_poverty\", \"belief_stagnation\", \"prediction_error\",\n \"emotional_shift\", \"focus_shift\", \"obsession\", \"wound_activated\",\n \"exhaustion\", \"activation\",\n ];\n let mut found = 0;\n for n in &sm.noticings {\n if structural_kinds.contains(&n.kind.as_str()) {\n let emoji = match n.kind.as_str() {\n \"dead_end_cluster\" => \"🕳️\", \"surprise_density\" => \"✨\", \"cognitive_loop\" => \"🔄\",\n \"signal_poverty\" => \"📡\", \"belief_stagnation\" => \"📊\", \"prediction_error\" => \"❗\",\n \"emotional_shift\" => \"💭\", \"focus_shift\" => \"👁️\", \"obsession\" => \"🔁\",\n \"wound_activated\" => \"💢\", \"exhaustion\" => \"🪫\", \"activation\" => \"⚡\",\n _ => \"•\",\n };\n println!(\" {} [{:<18}] {} (sig={:.2} val={:+.2})\",\n emoji, n.kind, core::safe_truncate(&n.observation, 65), n.significance, n.valence);\n found += 1;\n }\n }\n if found == 0 { println!(\" (none — more walks or larger graph needed)\"); }\n println!(\" Total noticings across all kinds: {}\", sm.noticings.len());\n\n // ── Attention ──\n println!(\"\\n ── Attention Distribution ──\");\n let mut patterns: Vec<_> = sm.attention_patterns.iter().collect();\n patterns.sort_by(|a, b| b.1.partial_cmp(a.1).unwrap_or(std::cmp::Ordering::Equal));\n for (domain, count) in patterns.iter().take(12) {\n let bar = \"█\".repeat((*count * 2.0).min(40.0) as usize);\n println!(\" {:15} {:6.2} {}\", domain, count, bar);\n }\n\n // ── Module Activity ──\n println!(\"\\n ── Module Activity ──\");\n for (source, count) in &sm.signals_by_source {\n let bar = \"▬\".repeat(*count as usize);\n println!(\" {:15} {:4} {}\", source, count, bar);\n }\n\n // ── Predictions ──\n println!(\"\\n ── Active Predictions ──\");\n for (domain, pred) in &sm.predictions {\n println!(\" [{}] '{}' (conf={:.2})\", domain, pred.predicted, pred.confidence);\n }\n\n // ── Emergent Patterns ──\n if !sm.emergent_patterns.is_empty() {\n println!(\"\\n ── Emergent Patterns ──\");\n for p in &sm.emergent_patterns {\n println!(\" [{}] {} (str={:.2} ev={})\", p.domain, p.description, p.strength, p.evidence_count);\n }\n }\n\n // ── Graph stats ──\n let gs = rgw::db::graph_stats(pool).await?;\n println!(\"\\n ── Graph ──\");\n println!(\" Nodes: {} | Edges: {} | Avg edges/node: {:.1}\", gs.nodes, gs.edges, gs.edges as f64 / gs.nodes.max(1) as f64);\n\n println!(\"\\n╔══════════════════════════════════════════════════════╗\");\n println!(\"║ CASCADE COMPLETE ║\");\n println!(\"╚══════════════════════════════════════════════════════╝\\n\");\n\n // ── PHASE 5: RGW ↔ LLM Colloquy ──\n // The LLM is called directly from the cognitive loop —\n // RGW reports its state, the LLM reflects, the insight feeds\n // back as a signal and a graph node, then RGW re-walks.\n if let Ok(api_key) = std::env::var(\"DEEPSEEK_API_KEY\") {\n if !api_key.is_empty() {\n println!(\"─── PHASE 5: RGW ↔ DeepSeek Colloquy ───\\n\");\n let llm = rgw::llm::LlmEngine::new(&api_key, \"deepseek-chat\")?;\n\n // ── TURN 1: RGW → LLM ──\n println!(\" ╔══ TURN 1: RGW reports its state ══╗\\n\");\n let sm1 = self_model.lock().await.clone();\n let wm1 = sm1.format_working_memory();\n let top_domains = {\n let mut pats: Vec<_> = sm1.attention_patterns.iter().collect();\n pats.sort_by(|a, b| b.1.partial_cmp(a.1).unwrap_or(std::cmp::Ordering::Equal));\n pats.iter().take(5).map(|(d, _)| d.as_str()).collect::<Vec<_>>()\n };\n let belief_ctx: String = sm1.beliefs.iter()\n .map(|b| format!(\"- [{}] {}\", b.domain, b.statement)).collect::<Vec<_>>().join(\"\\n\");\n let noticing_ctx: String = sm1.noticings.iter()\n .map(|n| format!(\" [{}] {}\", n.kind, n.observation))\n .collect::<Vec<_>>().join(\"\\n\");\n\n let system1 = \"You are RGW's expression layer. You receive the cognitive state of a graph-based engine \\\n that has just traversed a philosophical knowledge graph. \\\n Respond with a concise, insightful analysis (2-4 sentences). \\\n Be specific about what patterns or tensions you see.\";\n let user1 = format!(\n \"SELF-MODEL STATE:\\nSurprises={} Noticings={} Beliefs={}\\nTop domains: {:?}\\n\\\n Working memory:\\n{}\\nBeliefs:\\n{}\\nNoticings:\\n{}\\n\\nWhat is the most interesting pattern?\",\n sm1.surprise_count, sm1.noticings.len(), sm1.beliefs.len(),\n top_domains,\n if wm1.is_empty() { \" (empty)\" } else { &wm1 },\n if belief_ctx.is_empty() { \" (none)\" } else { &belief_ctx },\n if noticing_ctx.is_empty() { \" (none)\" } else { &noticing_ctx },\n );\n\n let response1 = llm.chat(system1, &user1, Some(512), 0.7).await?;\n println!(\" DeepSeek: \\\"{}\\\"\\n\", core::safe_truncate(&response1, 200));\n\n // Feed LLM insight back → Signal → core::process()\n {\n let mut sm = self_model.lock().await;\n let insight_signal = Signal::new(\"llm_insight\", &response1)\n .with_domain(\"integration\")\n .with_intensity(0.7);\n core::process(insight_signal, &mut sm);\n sm.predict(\"integration\", \"synthesis of philosophical domains\", 0.5);\n }\n // Create graph node from insight\n let insight_embedding = rgw::embed::embed_text(core::safe_truncate(&response1, 500))?;\n let insight_node_id = rgw::db::create_memory_node(\n pool, core::safe_truncate(&response1, 500),\n \"integration\", &insight_embedding, 7.0, 0.3, 0.5\n ).await?;\n for &bridge_idx in &[74, 76, 77, 78] {\n if bridge_idx < node_ids.len() {\n let _ = rgw::db::create_edge(pool, insight_node_id, node_ids[bridge_idx],\n \"synthesizes\", 0.3, 0.2).await;\n }\n }\n println!(\" → Created node {} from LLM insight + 4 edges\\n\", insight_node_id);\n\n // ── TURN 2: Re-walk with LLM insight ──\n println!(\" ╔══ TURN 2: RGW re-explores with new knowledge ══╗\\n\");\n {\n let mut sm = self_model.lock().await;\n sm.valence = 0.2;\n sm.arousal = 0.6;\n sm.energy = 0.7;\n }\n let (_, _) = walker::walk_parallel(pool,\n &EmotionalState { valence: 0.2, arousal: 0.6, energy: 0.7 },\n 6, 5, &self_model).await;\n let sm2 = self_model.lock().await.clone();\n println!(\" Beliefs: {} (was {}) | Noticings: {} (was {}) | Surprises: {} (was {})\",\n sm2.beliefs.len(), sm1.beliefs.len(),\n sm2.noticings.len(), sm1.noticings.len(),\n sm2.surprise_count, sm1.surprise_count);\n\n // ── TURN 3: RGW reports evolution → LLM reflects ──\n println!(\"\\n ╔══ TURN 3: RGW reports its evolution ══╗\\n\");\n let wm2 = sm2.format_working_memory();\n let user2 = format!(\n \"EARLIER, YOU SAID: \\\"{}\\\"\\n\\n\\\n AFTER YOUR INSIGHT, I RE-EXPLORED. NEW STATE:\\n\\\n Beliefs: {} (was {}) | Noticings: {} (was {}) | Surprises: {} (was {})\\n\\\n Plasticity: {:.3}\\n\\\n Working memory:\\n{}\\n\\n\\\n What changed? What does this tell us about the system?\",\n core::safe_truncate(&response1, 150),\n sm2.beliefs.len(), sm1.beliefs.len(),\n sm2.noticings.len(), sm1.noticings.len(),\n sm2.surprise_count, sm1.surprise_count,\n sm2.plasticity_gate,\n if wm2.is_empty() { \" (empty)\" } else { &wm2 },\n );\n let system2 = \"You are RGW's expression layer. Earlier you provided an insight. \\\n Now you see how the system changed after your insight was incorporated. \\\n Reflect on what this means about the RGW+LLM cognitive loop.\";\n match llm.chat(system2, &user2, Some(512), 0.8).await {\n Ok(response2) => {\n println!(\" DeepSeek reflects:\\n\");\n for line in response2.lines() {\n println!(\" {}\", line);\n }\n println!();\n let mut sm = self_model.lock().await;\n let reflect_signal = Signal::new(\"llm_reflection\", &response2)\n .with_domain(\"integration\").with_intensity(0.5);\n core::process(reflect_signal, &mut sm);\n }\n Err(e) => println!(\" Turn 3 failed: {}\\n\", e),\n }\n }\n } else {\n println!(\" (set DEEPSEEK_API_KEY to enable LLM expression)\\n\");\n }\n\n Ok(())\n}\n\n// ── Main ────────────────────────────────────────────────────────\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n tracing_subscriber::fmt()\n .with_env_filter(tracing_subscriber::EnvFilter::try_from_default_env()\n .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(\"info,rgw=debug\")))\n .try_init().ok();\n\n println!(\"Loading embedding model...\");\n rgw::embed::init()?;\n\n let db_url = std::env::var(\"DATABASE_URL\")\n .unwrap_or_else(|_| \"postgresql:///rgw_test?host=/tmp\".into());\n let pool = rgw::db::connect(&db_url).await?;\n ensure_schema(&pool).await?;\n\n // Re-seed: drop old data\n let stats = rgw::db::graph_stats(&pool).await?;\n if stats.nodes > 0 {\n println!(\"Clearing existing {} nodes...\", stats.nodes);\n sqlx::query(\"DELETE FROM memory_edges\").execute(&pool).await?;\n sqlx::query(\"DELETE FROM memory_vectors\").execute(&pool).await?;\n }\n\n let node_ids = seed_graph(&pool).await?;\n run_cascade(&pool, &node_ids).await?;\n\n Ok(())\n}\n"}}}}