From 651455cb47cf15b1e406c528a9966b4a912735d8 Mon Sep 17 00:00:00 2001 From: Myron Blair Date: Wed, 1 Jul 2026 03:49:10 -0500 Subject: [PATCH] Fix guardian mode: create missing tables on startup, fix conversations column name - Add CREATE TABLE IF NOT EXISTS for guardian_config and guardian_events in reactor lifespan so tables are created automatically on next restart - Fix conversations column bug: reactor used 'message' but schema has 'content'; fix INSERT and SELECT queries to use content (SELECT aliases it as 'message' so the JSON response key stays the same) - Add guardian tables to schema.sql for documentation Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01X8tDRrQqgLjqXebMCBNcP3 --- db/schema.sql | 37 +++++++++++++++++++++++++++++++++++++ deploy/reactor.py | 33 +++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 705fee3..b87638a 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -441,4 +441,41 @@ CREATE TABLE `users` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +-- +-- Table structure for table `guardian_config` +-- + +CREATE TABLE IF NOT EXISTS `guardian_config` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `key_name` varchar(64) NOT NULL, + `value` varchar(255) NOT NULL DEFAULT '', + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `uk_key` (`key_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Table structure for table `guardian_events` +-- + +CREATE TABLE IF NOT EXISTS `guardian_events` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `event_type` varchar(64) NOT NULL, + `severity` enum('info','warning','critical') NOT NULL DEFAULT 'info', + `agent_id` varchar(64) NOT NULL DEFAULT '', + `hostname` varchar(128) NOT NULL DEFAULT '', + `metric` varchar(64) NOT NULL DEFAULT '', + `value` float NOT NULL DEFAULT 0, + `threshold` float NOT NULL DEFAULT 0, + `message` text NOT NULL, + `ai_analysis` text NOT NULL DEFAULT '', + `acknowledged` tinyint(1) NOT NULL DEFAULT 0, + `created_at` datetime NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + KEY `idx_severity` (`severity`), + KEY `idx_ack` (`acknowledged`), + KEY `idx_created` (`created_at`), + KEY `idx_agent` (`agent_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + -- Dump completed on 2026-06-29 23:15:44 diff --git a/deploy/reactor.py b/deploy/reactor.py index 7519758..01ee171 100644 --- a/deploy/reactor.py +++ b/deploy/reactor.py @@ -1051,7 +1051,7 @@ async def _guardian_inject_chat(message: str) -> None: """Write a proactive JARVIS message into the conversations table so the HUD picks it up.""" try: await db_execute( - """INSERT INTO conversations (session_id, role, message, created_at) + """INSERT INTO conversations (session_id, role, content, created_at) VALUES ('guardian', 'assistant', %s, NOW())""", (message,) ) @@ -1806,7 +1806,7 @@ Keep the tone confident and action-oriented. Format with clear sections. Under 4 # Store in conversations so HUD can surface it await db_execute( - "INSERT INTO conversations (session_id, role, message, created_at) VALUES ('guardian','assistant',%s,NOW())", + "INSERT INTO conversations (session_id, role, content, created_at) VALUES ('guardian','assistant',%s,NOW())", (review_text,) ) @@ -2209,6 +2209,31 @@ async def lifespan(app: FastAPI): log.info(f"◈ JARVIS Arc Reactor v{VERSION} starting on {HOST}:{PORT}") await get_pool() await db_execute("UPDATE arc_status SET started_at=NOW(), last_heartbeat=NOW(), version=%s WHERE id=1", (VERSION,)) + await db_execute("""CREATE TABLE IF NOT EXISTS guardian_config ( + id INT AUTO_INCREMENT PRIMARY KEY, + key_name VARCHAR(64) NOT NULL, + value VARCHAR(255) NOT NULL DEFAULT '', + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uk_key (key_name) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci""") + await db_execute("""CREATE TABLE IF NOT EXISTS guardian_events ( + id INT AUTO_INCREMENT PRIMARY KEY, + event_type VARCHAR(64) NOT NULL, + severity ENUM('info','warning','critical') NOT NULL DEFAULT 'info', + agent_id VARCHAR(64) NOT NULL DEFAULT '', + hostname VARCHAR(128) NOT NULL DEFAULT '', + metric VARCHAR(64) NOT NULL DEFAULT '', + value FLOAT NOT NULL DEFAULT 0, + threshold FLOAT NOT NULL DEFAULT 0, + message TEXT NOT NULL, + ai_analysis TEXT NOT NULL DEFAULT '', + acknowledged TINYINT(1) NOT NULL DEFAULT 0, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + KEY idx_severity (severity), + KEY idx_ack (acknowledged), + KEY idx_created (created_at), + KEY idx_agent (agent_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci""") asyncio.create_task(job_poller()) asyncio.create_task(heartbeat_loop()) asyncio.create_task(guardian_loop()) @@ -2728,13 +2753,13 @@ async def guardian_chat_events(since: str = ""): """Return proactive guardian messages injected into conversations.""" if since: rows = await db_fetchall( - "SELECT id, message, created_at FROM conversations " + "SELECT id, content AS message, created_at FROM conversations " "WHERE session_id='guardian' AND created_at > %s ORDER BY created_at ASC", (since,) ) else: rows = await db_fetchall( - "SELECT id, message, created_at FROM conversations " + "SELECT id, content AS message, created_at FROM conversations " "WHERE session_id='guardian' ORDER BY created_at DESC LIMIT 10" ) return rows or []