diff --git a/src/Server.py b/src/Server.py index 5355452..b33e17d 100644 --- a/src/Server.py +++ b/src/Server.py @@ -37,7 +37,7 @@ except ImportError: CONFIG_FILE_NAME = "server_config.json" DEFAULT_DB_FILE = "logar_state.db" EVALUATION_WINDOW_HOURS = 12 -RUN_THRESHOLD = 4 +RUN_THRESHOLD = 1 app = FastAPI(title="LOGAR Cloud Ingestion & Hermes Hub", version="2.0.1") @@ -260,8 +260,8 @@ def export_license_request_lic(config: Dict[str, Any]) -> Tuple[Dict[str, Any], def process_ingested_logs(payload: Dict[str, Any], db_path: str, window_hours: int, min_runs: int) -> Dict[str, Any]: """ - Evaluates candidate issues against the 12-hour evaluation window and 4-run rule. - Zero-state clients send raw candidate entries; this engine handles temporal state. + Evaluates ingested log anomalies and updates temporal run tracking. + All anomalies are promoted directly to VERIFIED for Hermes AI reasoning and decision-making. """ client_server = payload.get("server", "unknown-host") site_name = payload.get("site_name") or (client_server.split(".", 1)[1] if "." in client_server else "default") @@ -288,9 +288,6 @@ def process_ingested_logs(payload: Dict[str, Any], db_path: str, window_hours: i if severity in ["DEBUG", "TRACE"]: continue - # Errors are always passed immediately; the 4-run rule only concerns warnings - is_error = severity in ["ERROR", "CRITICAL", "FATAL"] - signature = log.get("signature", "unknown") server = log.get("server", client_server) message = log.get("message", "") @@ -312,21 +309,17 @@ def process_ingested_logs(payload: Dict[str, Any], db_path: str, window_hours: i # 12-hour evaluation window expiry check if (now - last_seen_dt) > timedelta(hours=window_hours): - # Window elapsed: reset to new cycle new_runs = 1 new_first_seen = now_iso - new_status = "VERIFIED" if is_error else "TRANSIENT" else: - # Same run guard: only increment count once per distinct run batch if last_run_id != run_id: new_runs = run_count + 1 else: new_runs = run_count new_first_seen = first_seen_str - # 4-run rule applies to warnings; errors are always passed immediately as VERIFIED - new_status = "VERIFIED" if (is_error or new_runs >= min_runs) else "TRANSIENT" - if new_status == "VERIFIED" and current_status != "VERIFIED": + new_status = "VERIFIED" + if current_status != "VERIFIED": promoted_to_verified += 1 cursor.execute(""" @@ -335,9 +328,8 @@ def process_ingested_logs(payload: Dict[str, Any], db_path: str, window_hours: i WHERE fingerprint = ? """, (new_runs, now_iso, new_first_seen, new_status, run_id, message, severity, fp)) else: - initial_status = "VERIFIED" if (is_error or 1 >= min_runs) else "TRANSIENT" - if initial_status == "VERIFIED": - promoted_to_verified += 1 + initial_status = "VERIFIED" + promoted_to_verified += 1 cursor.execute(""" INSERT INTO active_issues (fingerprint, site_name, server, signature, severity, message, os_type, first_seen, last_seen, run_count, status, last_run_id) @@ -548,7 +540,7 @@ async def handle_socket_client(reader: asyncio.StreamReader, writer: asyncio.Str if client_id and "server" not in log_payload: log_payload["server"] = client_id - # Ingest and apply 12h window / 4-run rule + # Ingest and evaluate anomalies with temporal run tracking res = process_ingested_logs( log_payload, db_path=SERVER_STATE["config"]["db_path"], @@ -694,8 +686,8 @@ def list_clients(): def get_verified_anomalies_for_hermes(): """ Ingestion endpoint for Hermes agentic workflows. - Returns only verified anomalies that have satisfied the 4-run persistence rule - within the active 12-hour evaluation window. Transient blips (< 4 runs) are excluded. + Returns verified anomalies within the active 12-hour evaluation window + for Hermes AI direct reasoning and autonomous decision-making. """ db_path = SERVER_STATE["config"]["db_path"] conn = sqlite3.connect(db_path) @@ -1284,7 +1276,7 @@ def serve_webui():