chore(qw): cleanup post-review (préfixes BUS, événements monitor, import io)
Some checks failed
tests / Lint (ruff + black) (push) Successful in 14s
tests / Tests unitaires (sans GPU) (push) Failing after 14s
tests / Tests sécurité (critique) (push) Has been skipped

- 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) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-05-06 00:08:22 +02:00
parent f5c33477f0
commit 83be93e121
2 changed files with 16 additions and 6 deletions

View File

@@ -9,9 +9,12 @@ Stratégie en cascade :
Émet sur le bus lea:* l'event monitor_routed avec la source de la décision. Émet sur le bus lea:* l'event monitor_routed avec la source de la décision.
""" """
import logging
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
logger = logging.getLogger(__name__)
@dataclass @dataclass
class MonitorTarget: class MonitorTarget:
@@ -76,6 +79,10 @@ def resolve_target_monitor(
if m is not None: if m is not None:
return _to_target(m, source="action") return _to_target(m, source="action")
# Index invalide → on tombe sur le fallback focus # 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 # 2. Fallback focus actif
focused_idx = session_state.get("last_focused_monitor") focused_idx = session_state.get("last_focused_monitor")
@@ -83,6 +90,10 @@ def resolve_target_monitor(
m = _find_monitor(geometry, int(focused_idx)) m = _find_monitor(geometry, int(focused_idx))
if m is not None: if m is not None:
return _to_target(m, source="focus") 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]) # 3. Fallback composite (backward compat — comportement actuel mss.monitors[0])
return _COMPOSITE_FALLBACK return _COMPOSITE_FALLBACK

View File

@@ -11,7 +11,6 @@ le replay continue avec uniquement les déclaratifs (fallback safe).
""" """
import base64 import base64
import io
import json import json
import logging import logging
import os import os
@@ -77,7 +76,7 @@ def build_pause_payload(
existing_labels=[c["label"] for c in checks], existing_labels=[c["label"] for c in checks],
) )
except Exception as e: 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 = [] additional = []
for a in additional: for a in additional:
@@ -159,21 +158,21 @@ Réponds UNIQUEMENT en JSON :
timeout=timeout_s, timeout=timeout_s,
) )
if response.status_code != 200: 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 [] return []
text = response.json().get("response", "").strip() text = response.json().get("response", "").strip()
except requests.Timeout: 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 [] return []
except Exception as e: 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 [] return []
# format=json garantit normalement du JSON valide # format=json garantit normalement du JSON valide
try: try:
parsed = json.loads(text) parsed = json.loads(text)
except json.JSONDecodeError as e: 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 [] return []
additional = parsed.get("additional_checks") or [] additional = parsed.get("additional_checks") or []