From 1cbec2806e39966266f765f024a2af759eda9912 Mon Sep 17 00:00:00 2001 From: Dom Date: Wed, 6 May 2026 19:24:53 +0200 Subject: [PATCH] fix(resolve): rebrancher hybrid_text_direct dans _resolve_target_sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit project-quality-guardian (2026-05-06) : la fonction _resolve_by_ocr_text (resolve_engine.py:1447) existait déjà mais n'était appelée QUE depuis _resolve_with_precompiled_order (V4), endpoint sans client côté frontend (Cas #5 du même audit). La cascade legacy _resolve_target_sync sautait directement d'étape 0 (grounding-window) → étape 0' (template icônes) → étape 1 (VLM Quick Find) sans tenter l'OCR direct. Conséquence reproduite ce 2026-05-06 sur le workflow Urgence : chaque action visuelle avec by_text payait 2-23 s de VLM Quick Find (ui-tars-1.5-7b-q8_0 sur Ollama) au lieu de <500 ms d'OCR direct, total replay > 10 min vs quelques secondes attendues. Constat utilisateur : "habituellement on est plutôt à quelques secondes". Régression silencieuse. Modification : Étape 0.5 ajoutée entre l'étape 0' (template icônes) et l'étape 1 (VLM Quick Find). Si by_text_strict est non vide, appel à _resolve_by_ocr_text — fonction docTR existante, cache singleton _V4_OCR_PREDICTOR, score 1.0 si match exact, 0.9 si mot exact, 0.8 si contenu. Seuil de retour : 0.80 (cohérent avec _RESOLUTION_MIN_SCORES["hybrid_text_direct"]). Le method retourné est rebadgé "hybrid_text_direct" pour cohérence avec : - _RESOLUTION_MIN_SCORES (seuil 0.80, ligne 2092) - agent_v0/agent_v1/core/executor.py:1534 (client Windows) - logs Learning historiques ([hybrid_text_direct]) Tests : 39/39 sprint QW + grounding/resolver verts. --- agent_v0/server_v1/resolve_engine.py | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/agent_v0/server_v1/resolve_engine.py b/agent_v0/server_v1/resolve_engine.py index ee2491cf7..a993c13ba 100644 --- a/agent_v0/server_v1/resolve_engine.py +++ b/agent_v0/server_v1/resolve_engine.py @@ -1746,6 +1746,49 @@ def _resolve_target_sync( ) return result + # --------------------------------------------------------------- + # Étape 0.5 : OCR direct (hybrid_text_direct) — chemin rapide + # --------------------------------------------------------------- + # Si on a un texte cible non vide, le localiser par OCR direct + # avant de tomber sur le VLM (~100-300ms vs 2-23s par appel VLM). + # Reconnecté le 2026-05-06 : la fonction _resolve_by_ocr_text + # existait déjà mais n'était appelée QUE depuis le runtime V4 + # (resolve_order pré-compilé), qui n'est pas branché côté frontend + # (cf. audit project-quality-guardian Cas #5). La cascade legacy + # tombait directement sur VLM Quick Find d'où des replays à 23s + # par action visuelle au lieu de <500ms attendus. + # Le method est rebadgé "hybrid_text_direct" (seuil 0.80 dans + # _RESOLUTION_MIN_SCORES, identifiant historique côté client + # Agent V1 et logs Learning). + if by_text_strict: + ocr_result = _resolve_by_ocr_text( + screenshot_path=screenshot_path, + target_text=by_text_strict, + screen_width=screen_width, + screen_height=screen_height, + ) + if ocr_result and ocr_result.get("score", 0) >= 0.80: + ocr_result["method"] = "hybrid_text_direct" + logger.info( + "Strict resolve OCR-DIRECT : OK '%s' → (%.4f, %.4f) score=%.2f", + by_text_strict[:40], + ocr_result.get("x_pct", 0), + ocr_result.get("y_pct", 0), + ocr_result.get("score", 0), + ) + return ocr_result + elif ocr_result: + logger.info( + "Strict resolve OCR-DIRECT : '%s' trouvé score=%.2f < 0.80, passage VLM", + by_text_strict[:40], + ocr_result.get("score", 0), + ) + else: + logger.info( + "Strict resolve OCR-DIRECT : '%s' non trouvé, passage VLM", + by_text_strict[:40], + ) + # --------------------------------------------------------------- # Étape 1 : VLM Quick Find (fallback, multi-image) # ---------------------------------------------------------------