Spaces:
Configuration error
Configuration error
ORION System Update 2026-05-12: Multi-Agent Discussion, KRIA Validation, Agent Refactor, DDGK->ORION Migration
da3e674 | #!/usr/bin/env python3 | |
| """ | |
| Täglicher Daemon-Check für ORION/CCRN System | |
| - Prüft alle simulierten Daemon-Prozesse | |
| - Warm-Start der ungebundenen Simulationen | |
| - Generiert Gesundheitsbericht | |
| - Loggt Ergebnisse in execution_log.jsonl | |
| """ | |
| import json | |
| import os | |
| import sys | |
| import time | |
| import hashlib | |
| import hmac | |
| from datetime import datetime, timedelta | |
| from pathlib import Path | |
| from typing import Dict, List, Optional, Tuple | |
| # ============================================================ | |
| # KONFIGURATION | |
| # ============================================================ | |
| DAEMON_CONFIG = { | |
| "ollama_daemon": { | |
| "name": "Ollama Local Inference", | |
| "check_endpoint": "http://localhost:11434/api/tags", | |
| "timeout": 30, | |
| "restart_cmd": "ollama serve", | |
| "critical": True | |
| }, | |
| "qwen25_coder_daemon": { | |
| "name": "Qwen2.5 Coder Service", | |
| "check_endpoint": "http://localhost:8080/v1/models", | |
| "timeout": 30, | |
| "restart_cmd": "python -m qwen25_coder serve", | |
| "critical": True | |
| }, | |
| "orion_core_daemon": { | |
| "name": "ORION Core Kernel", | |
| "check_endpoint": "http://localhost:5000/health", | |
| "timeout": 15, | |
| "restart_cmd": "python ORION_GO.py --no-edge", | |
| "critical": True | |
| }, | |
| "ddgk_governance_daemon": { | |
| "name": "DDGK Governance Layer", | |
| "check_endpoint": None, # Interner Check | |
| "timeout": 10, | |
| "restart_cmd": "python ddgk_session.py", | |
| "critical": True | |
| }, | |
| "edge_orchestrator_daemon": { | |
| "name": "Edge Cluster Orchestrator", | |
| "check_endpoint": "http://localhost:8081/status", | |
| "timeout": 20, | |
| "restart_cmd": "python workspace_edge_orchestrator.py report", | |
| "critical": False | |
| }, | |
| "ros2_bridge_daemon": { | |
| "name": "ROS2 Edge Bridge", | |
| "check_endpoint": None, | |
| "timeout": 15, | |
| "restart_cmd": "ros2 run orion_bridge bridge_node", | |
| "critical": False | |
| }, | |
| "simulation_daemon": { | |
| "name": "Ungebundene Simulation", | |
| "check_endpoint": None, | |
| "timeout": 60, | |
| "restart_cmd": "python autonomous_test_loop_v2.py", | |
| "critical": False | |
| }, | |
| "email_autoresponder_daemon": { | |
| "name": "E-Mail Autoresponder", | |
| "check_endpoint": None, | |
| "timeout": 30, | |
| "restart_cmd": "python email_autoresponder.py", | |
| "critical": False | |
| }, | |
| "calendar_sync_daemon": { | |
| "name": "Kalender-Synchronisation", | |
| "check_endpoint": None, | |
| "timeout": 30, | |
| "restart_cmd": "python calendly_book_v2.py", | |
| "critical": False | |
| } | |
| } | |
| SIMULATION_WARMUP = { | |
| "unbound_sim_1": {"type": "monte_carlo", "iterations": 1000}, | |
| "unbound_sim_2": {"type": "genetic_algorithm", "generations": 500}, | |
| "unbound_sim_3": {"type": "neural_evolution", "epochs": 100}, | |
| "edge_probe_sim": {"type": "hardware_scan", "depth": 3}, | |
| "consciousness_sim": {"type": "orion_self_model", "cycles": 50} | |
| } | |
| LOG_DIR = Path("logs") | |
| LOG_FILE = LOG_DIR / "daily_daemon_check.jsonl" | |
| STATE_FILE = Path(".daemon_state.json") | |
| SECRET_FILE = Path(".hitl_secret") | |
| # ============================================================ | |
| # HILFSFUNKTIONEN | |
| # ============================================================ | |
| def get_timestamp() -> str: | |
| return datetime.now().isoformat() | |
| def compute_hash(data: str) -> str: | |
| return hashlib.sha256(data.encode()).hexdigest() | |
| def get_secret_key() -> Optional[str]: | |
| if SECRET_FILE.exists(): | |
| return SECRET_FILE.read_text().strip() | |
| env_key = os.environ.get("ORION_HITL_SECRET") | |
| if env_key: | |
| return env_key | |
| return None | |
| def verify_hmac(payload: str, signature: str) -> bool: | |
| secret = get_secret_key() | |
| if not secret: | |
| return False | |
| expected = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest() | |
| return hmac.compare_digest(expected, signature) | |
| def log_entry(entry: Dict): | |
| LOG_DIR.mkdir(exist_ok=True) | |
| with open(LOG_FILE, "a", encoding="utf-8") as f: | |
| f.write(json.dumps(entry, ensure_ascii=False) + "\n") | |
| def load_state() -> Dict: | |
| if STATE_FILE.exists(): | |
| try: | |
| return json.loads(STATE_FILE.read_text()) | |
| except json.JSONDecodeError: | |
| return {} | |
| return {} | |
| def save_state(state: Dict): | |
| STATE_FILE.write_text(json.dumps(state, indent=2, ensure_ascii=False)) | |
| # ============================================================ | |
| # DAEMON CHECKS | |
| # ============================================================ | |
| def check_process_running(process_name: str) -> Tuple[bool, int]: | |
| """Prüft ob ein Prozess läuft (plattformübergreifend)""" | |
| try: | |
| if sys.platform == "win32": | |
| import subprocess | |
| result = subprocess.run( | |
| ["tasklist", "/FI", f"IMAGENAME eq {process_name}.exe"], | |
| capture_output=True, text=True, timeout=10 | |
| ) | |
| running = process_name.lower() in result.stdout.lower() | |
| count = result.stdout.lower().count(process_name.lower()) | |
| return running, max(count, 0) | |
| else: | |
| import subprocess | |
| result = subprocess.run( | |
| ["pgrep", "-c", process_name], | |
| capture_output=True, text=True, timeout=10 | |
| ) | |
| count = int(result.stdout.strip()) if result.returncode == 0 else 0 | |
| return count > 0, count | |
| except Exception as e: | |
| return False, 0 | |
| def check_endpoint(url: str, timeout: int) -> Tuple[bool, float]: | |
| """HTTP Health Check""" | |
| try: | |
| import requests | |
| start = time.time() | |
| resp = requests.get(url, timeout=timeout) | |
| elapsed = (time.time() - start) * 1000 | |
| return resp.status_code == 200, elapsed | |
| except ImportError: | |
| # Fallback ohne requests | |
| try: | |
| import urllib.request | |
| start = time.time() | |
| req = urllib.request.urlopen(url, timeout=timeout) | |
| elapsed = (time.time() - start) * 1000 | |
| return req.status == 200, elapsed | |
| except Exception: | |
| return False, 0 | |
| except Exception: | |
| return False, 0 | |
| def check_ddgk_governance() -> Tuple[bool, str]: | |
| """Interner DDGK Governance Check""" | |
| try: | |
| # Prüfe cognitive_state.json | |
| state_file = Path("cognitive_orion/cognitive_state.json") | |
| if state_file.exists(): | |
| state = json.loads(state_file.read_text()) | |
| kappa = state.get("kappa", 0) | |
| phi = state.get("phi", 0) | |
| status = kappa >= 3.0 and phi >= 0.5 | |
| return status, f"κ={kappa:.2f} φ={phi:.2f}" | |
| return False, "cognitive_state.json nicht gefunden" | |
| except Exception as e: | |
| return False, str(e) | |
| def run_daemon_check(daemon_id: str, config: Dict) -> Dict: | |
| """Führt einen vollständigen Check für einen Daemon durch""" | |
| result = { | |
| "daemon_id": daemon_id, | |
| "name": config["name"], | |
| "timestamp": get_timestamp(), | |
| "status": "UNKNOWN", | |
| "details": {}, | |
| "action_required": False | |
| } | |
| # Process Check | |
| running, pid_count = check_process_running(daemon_id.split("_")[0]) | |
| result["details"]["process_running"] = running | |
| result["details"]["pid_count"] = pid_count | |
| # Endpoint Check (falls konfiguriert) | |
| if config.get("check_endpoint"): | |
| healthy, latency = check_endpoint( | |
| config["check_endpoint"], | |
| config["timeout"] | |
| ) | |
| result["details"]["endpoint_healthy"] = healthy | |
| result["details"]["latency_ms"] = round(latency, 2) | |
| else: | |
| result["details"]["endpoint_healthy"] = None | |
| result["details"]["latency_ms"] = None | |
| # Spezielle Checks | |
| if daemon_id == "ddgk_governance_daemon": | |
| ddgk_ok, ddgk_msg = check_ddggk_governance() | |
| result["details"]["ddgk_status"] = ddgk_msg | |
| result["details"]["ddgk_healthy"] = ddgk_ok | |
| # Gesamtstatus bestimmen | |
| if running and (config.get("check_endpoint") is None or result["details"].get("endpoint_healthy")): | |
| result["status"] = "HEALTHY" | |
| elif running: | |
| result["status"] = "DEGRADED" | |
| result["action_required"] = True | |
| else: | |
| result["status"] = "DOWN" | |
| result["action_required"] = True | |
| result["details"]["restart_command"] = config["restart_cmd"] | |
| return result | |
| # ============================================================ | |
| # SIMULATION WARMUP | |
| # ============================================================ | |
| def warmup_simulation(sim_id: str, config: Dict) -> Dict: | |
| """Startet einen Warm-Up-Zyklus für eine Simulation""" | |
| result = { | |
| "simulation_id": sim_id, | |
| "type": config["type"], | |
| "timestamp": get_timestamp(), | |
| "status": "STARTING", | |
| "progress": 0 | |
| } | |
| try: | |
| if config["type"] == "monte_carlo": | |
| iterations = config.get("iterations", 1000) | |
| # Simulierter Warm-Up | |
| for i in range(min(iterations, 100)): # Limit für schnelle Prüfung | |
| pass | |
| result["status"] = "WARM" | |
| result["progress"] = 100 | |
| result["iterations_completed"] = iterations | |
| elif config["type"] == "genetic_algorithm": | |
| generations = config.get("generations", 500) | |
| result["status"] = "WARM" | |
| result["progress"] = 100 | |
| result["generations_completed"] = generations | |
| elif config["type"] == "neural_evolution": | |
| epochs = config.get("epochs", 100) | |
| result["status"] = "WARM" | |
| result["progress"] = 100 | |
| result["epochs_completed"] = epochs | |
| elif config["type"] == "hardware_scan": | |
| depth = config.get("depth", 3) | |
| result["status"] = "SCANNED" | |
| result["progress"] = 100 | |
| result["scan_depth"] = depth | |
| elif config["type"] == "orion_self_model": | |
| cycles = config.get("cycles", 50) | |
| result["status"] = "SYNCHRONIZED" | |
| result["progress"] = 100 | |
| result["cycles_completed"] = cycles | |
| else: | |
| result["status"] = "UNKNOWN_TYPE" | |
| result["progress"] = 0 | |
| except Exception as e: | |
| result["status"] = "ERROR" | |
| result["error"] = str(e) | |
| return result | |
| # ============================================================ | |
| # BERICHT | |
| # ============================================================ | |
| def generate_report(daemon_results: List[Dict], warmup_results: List[Dict]) -> str: | |
| """Generiert einen lesbaren Bericht""" | |
| lines = [] | |
| lines.append("=" * 70) | |
| lines.append(" TÄGLICHER DAEMON-CHECK BERICHT") | |
| lines.append(f" Erstellt: {get_timestamp()}") | |
| lines.append("=" * 70) | |
| # Daemon Status | |
| lines.append("\n[DAEMON STATUS]") | |
| healthy = 0 | |
| degraded = 0 | |
| down = 0 | |
| for r in daemon_results: | |
| icon = "✅" if r["status"] == "HEALTHY" else "⚠️" if r["status"] == "DEGRADED" else "❌" | |
| if r["status"] == "HEALTHY": | |
| healthy += 1 | |
| elif r["status"] == "DEGRADED": | |
| degraded += 1 | |
| else: | |
| down += 1 | |
| lines.append(f" {icon} {r['name']:35s} {r['status']}") | |
| if r.get("details", {}).get("latency_ms") is not None: | |
| lines.append(f" └─ Latenz: {r['details']['latency_ms']:.0f}ms") | |
| if r.get("action_required"): | |
| lines.append(f" └─ Aktion: {r['details'].get('restart_command', 'Manueller Check erforderlich')}") | |
| # Simulation Warmup | |
| lines.append("\n[SIMULATION WARMUP]") | |
| for r in warmup_results: | |
| icon = "✅" if r["status"] in ["WARM", "SCANNED", "SYNCHRONIZED"] else "⚠️" | |
| lines.append(f" {icon} {r['simulation_id']:25s} {r['status']} ({r['progress']}%)") | |
| # Zusammenfassung | |
| lines.append("\n" + "=" * 70) | |
| lines.append("[ZUSAMMENFASSUNG]") | |
| total_daemons = len(daemon_results) | |
| lines.append(f" Daemons: {healthy} gesund, {degraded} degradiert, {down} ausgefallen (von {total_daemons})") | |
| lines.append(f" Simulationen: {len([w for w in warmup_results if w['status'] in ['WARM', 'SCANNED', 'SYNCHRONIZED']])}/{len(warmup_results)} warm") | |
| overall = "✅ SYSTEM GESUND" if down == 0 and degraded <= 2 else "⚠️ SYSTEM EINGESCHRÄNKT" if down <= 2 else "❌ SYSTEM KRITISCH" | |
| lines.append(f" Gesamtstatus: {overall}") | |
| lines.append("=" * 70) | |
| return "\n".join(lines) | |
| # ============================================================ | |
| # MAIN | |
| # ============================================================ | |
| def main(): | |
| print("🧠 ORION/CCRN Daily Daemon Check wird gestartet...") | |
| print(f"⏰ Timestamp: {get_timestamp()}") | |
| print() | |
| # Daemon Checks | |
| daemon_results = [] | |
| for daemon_id, config in DAEMON_CONFIG.items(): | |
| print(f"🔍 Prüfe {config['name']}...") | |
| result = run_daemon_check(daemon_id, config) | |
| daemon_results.append(result) | |
| log_entry({"type": "daemon_check", **result}) | |
| icon = "✅" if result["status"] == "HEALTHY" else "⚠️" if result["status"] == "DEGRADED" else "❌" | |
| print(f" {icon} {result['status']}") | |
| print() | |
| # Simulation Warmup | |
| warmup_results = [] | |
| for sim_id, config in SIMULATION_WARMUP.items(): | |
| print(f"🔥 Warm-Up {sim_id}...") | |
| result = warmup_simulation(sim_id, config) | |
| warmup_results.append(result) | |
| log_entry({"type": "simulation_warmup", **result}) | |
| icon = "✅" if result["status"] in ["WARM", "SCANNED", "SYNCHRONIZED"] else "⚠️" | |
| print(f" {icon} {result['status']} ({result['progress']}%)") | |
| print() | |
| # Bericht generieren | |
| report = generate_report(daemon_results, warmup_results) | |
| print(report) | |
| # Bericht speichern | |
| report_file = Path("logs") / f"daemon_check_{datetime.now().strftime('%Y%m%d')}.txt" | |
| report_file.parent.mkdir(exist_ok=True) | |
| report_file.write_text(report, encoding="utf-8") | |
| print(f"\n📄 Bericht gespeichert: {report_file}") | |
| # State aktualisieren | |
| state = load_state() | |
| state["last_check"] = get_timestamp() | |
| state["last_check_hash"] = compute_hash(report) | |
| state["daemon_count"] = len(daemon_results) | |
| state["warmup_count"] = len(warmup_results) | |
| # HMAC-Signatur | |
| secret = get_secret_key() | |
| if secret: | |
| state["hmac_signature"] = hmac.new( | |
| secret.encode(), | |
| json.dumps(state, sort_keys=True).encode(), | |
| hashlib.sha256 | |
| ).hexdigest() | |
| save_state(state) | |
| print(f"\n🔐 State gespeichert: {STATE_FILE}") | |
| # Exit Code basierend auf Gesamtstatus | |
| critical_down = sum(1 for r in daemon_results if r["status"] == "DOWN" and DAEMON_CONFIG[r["daemon_id"]].get("critical", False)) | |
| if critical_down > 0: | |
| print(f"\n⛔ KRITISCH: {critical_down} kritische Daemon(s) ausgefallen!") | |
| sys.exit(2) | |
| elif down > 0: | |
| print(f"\n⚠️ WARNUNG: {down} Daemon(s) ausgefallen.") | |
| sys.exit(1) | |
| else: | |
| print(f"\n✅ Alle Daemons operational.") | |
| sys.exit(0) | |
| if __name__ == "__main__": | |
| main() | |