From 83be93e12121fff0bf1c64f63cfdab5b100db16b Mon Sep 17 00:00:00 2001 From: Dom Date: Wed, 6 May 2026 00:08:22 +0200 Subject: [PATCH] =?UTF-8?q?chore(qw):=20cleanup=20post-review=20(pr=C3=A9f?= =?UTF-8?q?ixes=20BUS,=20=C3=A9v=C3=A9nements=20monitor,=20import=20io)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - safety_checks_provider : tous les logger.warning d'échec LLM préfixés [BUS] lea:safety_checks_llm_failed avec une raison spécifique (exception, http_status, timeout, network, json_decode). - monitor_router : émission [BUS] lea:monitor_invalid_index si l'index explicite passé dans l'action est hors limites de monitors_geometry, et [BUS] lea:monitor_unavailable si focus actif demandé mais introuvable. Ces deux events permettent au bus de tracer chaque fallback de la cascade de routage QW1. - safety_checks_provider : import io supprimé (inutilisé). Co-Authored-By: Claude Opus 4.7 (1M context) --- agent_v0/server_v1/monitor_router.py | 11 +++++++++++ agent_v0/server_v1/safety_checks_provider.py | 11 +++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/agent_v0/server_v1/monitor_router.py b/agent_v0/server_v1/monitor_router.py index 58652b6ac..81341f037 100644 --- a/agent_v0/server_v1/monitor_router.py +++ b/agent_v0/server_v1/monitor_router.py @@ -9,9 +9,12 @@ Stratégie en cascade : Émet sur le bus lea:* l'event monitor_routed avec la source de la décision. """ +import logging from dataclasses import dataclass from typing import Any, Dict, List, Optional +logger = logging.getLogger(__name__) + @dataclass class MonitorTarget: @@ -76,6 +79,10 @@ def resolve_target_monitor( if m is not None: return _to_target(m, source="action") # Index invalide → on tombe sur le fallback focus + logger.warning( + "[BUS] lea:monitor_invalid_index requested=%d available_idx=%s", + int(explicit_idx), [g.get("idx") for g in geometry], + ) # 2. Fallback focus actif focused_idx = session_state.get("last_focused_monitor") @@ -83,6 +90,10 @@ def resolve_target_monitor( m = _find_monitor(geometry, int(focused_idx)) if m is not None: return _to_target(m, source="focus") + logger.warning( + "[BUS] lea:monitor_unavailable focused_idx=%d available_idx=%s", + int(focused_idx), [g.get("idx") for g in geometry], + ) # 3. Fallback composite (backward compat — comportement actuel mss.monitors[0]) return _COMPOSITE_FALLBACK diff --git a/agent_v0/server_v1/safety_checks_provider.py b/agent_v0/server_v1/safety_checks_provider.py index a7bc4148f..3031fbe04 100644 --- a/agent_v0/server_v1/safety_checks_provider.py +++ b/agent_v0/server_v1/safety_checks_provider.py @@ -11,7 +11,6 @@ le replay continue avec uniquement les déclaratifs (fallback safe). """ import base64 -import io import json import logging import os @@ -77,7 +76,7 @@ def build_pause_payload( existing_labels=[c["label"] for c in checks], ) except Exception as e: - logger.warning("safety_checks LLM exception (%s) — fallback safe", e) + logger.warning("[BUS] lea:safety_checks_llm_failed reason=exception detail=%s", e) additional = [] for a in additional: @@ -159,21 +158,21 @@ Réponds UNIQUEMENT en JSON : timeout=timeout_s, ) if response.status_code != 200: - logger.warning("safety_checks LLM HTTP %s", response.status_code) + logger.warning("[BUS] lea:safety_checks_llm_failed reason=http_status detail=%s", response.status_code) return [] text = response.json().get("response", "").strip() except requests.Timeout: - logger.warning("safety_checks LLM timeout (%ss)", timeout_s) + logger.warning("[BUS] lea:safety_checks_llm_failed reason=timeout detail=%ss", timeout_s) return [] except Exception as e: - logger.warning("safety_checks LLM erreur réseau: %s", e) + logger.warning("[BUS] lea:safety_checks_llm_failed reason=network detail=%s", e) return [] # format=json garantit normalement du JSON valide try: parsed = json.loads(text) except json.JSONDecodeError as e: - logger.warning("safety_checks LLM JSON invalide (%s) — fallback safe", e) + logger.warning("[BUS] lea:safety_checks_llm_failed reason=json_decode detail=%s", e) return [] additional = parsed.get("additional_checks") or []