# AXE D2 — Gestion des modaux & popups imprévus **Date :** 2026-05-23 **Auteur :** agent recherche (dispatch session principale) **Périmètre :** stratégie pour gérer en 100% vision les modaux Windows / navigateur / métier qui interrompent un replay Léa. **Statut :** brief de recherche — aucune modification de code proposée. Décisions = Dom. --- ## 1. TL;DR + recommandation architecture ### 1.1. Diagnostic - Le projet a déjà 80% de l'outillage : `core/grounding/dialog_handler.py` (EasyOCR + InfiGUI + fallback OCR direct) couvre la **résolution** d'un dialog connu. - Trois lacunes documentées : 1. Côté **client Léa**, `_handle_possible_popup` est défini avec **0 site d'appel** (`LESSONS_LEARNED_GHT_2026-05.md`, F5.5.1) — il existe également un `_handle_popup_vlm` qui prend le relais mais sans déclencheur générique. 2. Pas de **détecteur d'apparition** (la cascade ne sait pas qu'un modal vient d'apparaître — elle continue à viser l'élément initial, qui est désormais masqué). 3. Pas de **politique de fail-safe** différenciée par type de modal (UAC ≠ "fichier déjà existe" ≠ Windows Hello). - Anti-pattern interdit (`feedback_100pct_visual.md`) : inventer un raccourci Win+R / Ctrl+X / Échap-systématique. La cascade reste **OCR → template → VLM**, jamais "réflexe magique". ### 1.2. Recommandation Une stack en trois couches, branchée APRÈS chaque action (et au démarrage du tick d'observation), réutilisant le code existant : ``` ChangeDetector ──► DialogClassifier ──► DialogResolver (léger, < 50ms) (OCR titre + LLM) (catalogue déclaratif + InfiGUI/OCR + escalation) ``` 1. **ChangeDetector** — détecte qu'un modal *vient d'apparaître*. Combinaison foreground-window-change (Windows API côté client) + screenshot diff région centrale + heuristiques visuelles (ombre, centrage). Latence cible < 50 ms. 2. **DialogClassifier** — décide *quoi faire* (catalog match → action déterministe ; sinon → VLM pour catégoriser). Réutilise `_read_title` + `KNOWN_DIALOGS` du `dialog_handler.py` actuel, étend avec une catégorisation par type (`UAC` / `HELLO` / `SMARTSCREEN` / `BROWSER_PERM` / `METIER_SAVE` / `INCONNU`). 3. **DialogResolver** — applique la **matrice modal → action** (§5). En santé : aucun auto-accept système (UAC/Hello/SmartScreen) — uniquement pause supervisée. Auto-dismiss déterministe **uniquement** pour les modaux métier déclarés dans le workflow (ex. "fichier déjà existe → Oui"). Cette stack résout **mécaniquement** la dépendance avec AXE_B2 (Validator) : un modal non détecté = un Validator post-action raté ; un Validator sémantique strict force le détecteur à être appelé avant le verdict. --- ## 2. Taxonomie des modaux Windows 11 / navigateur (mai 2026) Sept catégories qui couvrent ~95% des cas terrain healthtech. ### 2.1. UAC (User Account Control) - **Quand** : installation, élévation `runas`, modification système. - **Aspect visuel** : fond bleu ou assombri global (secure desktop), titre `Contrôle de compte d'utilisateur`, deux boutons `Oui` / `Non` ou champ mot de passe administrateur. - **Particularité** : sur **secure desktop**, screenshot Léa peut être noir/inaccessible (`pyautogui` ne voit rien). Microsoft a livré des fixes UAC en oct. 2025 → janv. 2026 (KB5063878 / KB5074109) — quelques replays plantent encore sur 24H2 idle/locked. - **Politique healthtech recommandée** : **JAMAIS auto-accept**. Pause supervisée immédiate. ### 2.2. Windows Hello / WebAuthn / FIDO2 - **Quand** : déverrouillage app sensible (gestionnaire de mots de passe, Outlook), site avec WebAuthn, élévation UAC configurée pour exiger biométrie. - **Aspect visuel** : popup système centré, icône empreinte ou caméra, message "Touchez le capteur" ou "Saisissez votre code PIN". - **Particularité** : nécessite **interaction physique humaine** par construction. Aucune solution 100% vision ne peut résoudre. Anti-pattern absolu : tenter de cliquer "Annuler" pour passer outre. - **Politique** : pause supervisée + **tip** suggérant "désactiver Windows Hello pour la session de démo" en config préalable. ### 2.3. Microsoft Defender SmartScreen - **Quand** : exe non signé, téléchargement suspect, premier lancement Léa. - **Aspect visuel** : bandeau bleu ciel "Windows a protégé votre PC", lien "Informations complémentaires" qui révèle le bouton "Exécuter quand même". - **Politique** : pause supervisée + log security. Notre `feedback_auth_dialogs_runtime.md` rappelle d'anticiper AVANT démo client (signature code, allowlist hash SHA256 — voir `project_code_signing.md`). ### 2.4. Permissions navigateur (caméra, micro, notifications, géoloc, clipboard) - **Quand** : première visite site `https://`, démo Easily Assure si elle demande accès clipboard / notifications. - **Aspect visuel** : popup ancrée à l'URL bar (Chrome/Edge), boutons `Autoriser` / `Bloquer`. Variant inline overlay (Edge 2026). - **Particularité critique sécurité (CVE-2026-0628 janv. 2026)** : malveillances via extensions Chrome qui détournent des permissions. Auto-accept = risque RGPD/HDS. - **Politique** : **déclaratif dans le workflow** ("À cette étape, autoriser le micro") ou pause supervisée. Aucun auto-accept générique. ### 2.5. Dialog métier (sauvegarde, écrasement, perte de modifications) - **Quand** : fermeture document non sauvé, "fichier existe déjà", "Voulez-vous quitter ?". - **Aspect visuel** : popup applicative au-dessus de la fenêtre parente, OCR titre fiable, boutons texte clair (`Oui` / `Non` / `Annuler` / `Enregistrer`). - **Politique** : **catalogue déclaratif**. C'est exactement ce que `KNOWN_DIALOGS` du `dialog_handler.py` actuel gère. Résolution InfiGUI + fallback OCR direct. ### 2.6. Avertissements / erreurs applicatives (popup OK) - **Quand** : timeout réseau, validation backend KO, message info-utilisateur. - **Aspect visuel** : popup centré, icône triangle/croix, un seul bouton `OK` / `Fermer`. - **Politique** : auto-dismiss déterministe SAUF si message critique (regex blocklist "données perdues", "supprimé"). Log obligatoire. ### 2.7. Modaux inattendus / inconnus (notification push Teams, Outlook reminder, popup mise à jour, cookie banner, newsletter) - **Quand** : tout le temps, surtout en démo live (Slack ping, Outlook reminder à xx:00, popup Windows Update). - **Aspect visuel** : très variable. Souvent en coin (toast) plutôt que centré, mais peut voler le focus. - **Politique** : VLM classifier (catégoriser : "publicité" / "système" / "métier inconnu") → pause supervisée avec proposition humaine ou auto-dismiss conservateur (Échap visuel via clic croix détectée). --- ## 3. Comparaison frameworks 2026 | Framework | Détection modal | Politique | Pause humaine | Catalogue déclaratif | |---|---|---|---|---| | **Anthropic Computer Use** (avril 2026) | classifiers anti-prompt-injection détectent screenshots suspects → demande confirmation user | permission-first par défaut, refuse "high-risk", monitor model peut pause | oui (Auto Mode mai 2026 = classifier décide auto-approve vs prompt) | non public | | **OpenAI Operator / ChatGPT Agent** (juillet 2025 → 2026) | "monitor model" surveille comportement suspect ; CAPTCHA / login → cède le contrôle à l'humain (screenshots OFF pendant ce temps) | confirme avant action critique, prend la main sur prompts sécurité | oui, prend-le-relais explicite | non | | **Skyvern 2.0** (oct. 2025) | **Validator** regarde écran post-action, détecte "popup blocked the click", redonne main au Planner pour retry | retry visuel ; built-in TOTP / 2FA / file downloads | non documenté publiquement | implicite via Validator | | **browser-use** (issue #1996 ouvert mai 2026) | **pas de solution intégrée** — la communauté demande explicitement une infra générique | au cas par cas | non | non | | **Cradle** (R&D fin 2025) | screenshot-only, demande au VLM principal d'identifier popup à chaque tick | dépend prompt | non | non | | **PopSweeper** (recherche acad. 2024, applicable mobile) | classifier deux étages **ResNet50 + MobileNetV2** + **YOLO-World** pour bouton croix ; image-diff 100 ms tick ; **60 ms par frame** | auto-dismiss centré sur close-button | non | non | | **rpa_vision_v3 (actuel)** | aucun détecteur ; `dialog_handler.py` ne s'exécute que si appelé explicitement | catalogue déclaratif + InfiGUI/OCR fallback | feedback_failure_is_learning oui | oui (`KNOWN_DIALOGS`) | **Lecture** : - Skyvern et OpenAI Operator **valident l'idée centrale** : un Validator strict détecte le modal indirectement (action attendue échoue → l'écran a changé sans cause connue → modal). - Anthropic et OpenAI **convergent** sur le "monitor model" parallèle qui pause sans toucher au workflow principal. - PopSweeper démontre qu'un détecteur **léger spécialisé** (CNN custom < 60 ms) suffit pour ne PAS ajouter de coût VLM à chaque tick. - L'écosystème open source (browser-use) n'a **toujours pas** de solution générique — le sujet est ouvert. --- ## 4. Architecture proposée pour rpa_vision_v3 ### 4.1. Vue d'ensemble ``` ┌───────────────────────────────────────────┐ │ Léa (Windows client) │ │ │ action click ───►│ executor │ │ │ │ │ ▼ │ │ perform_click │ │ │ │ │ ▼ │ │ ChangeDetector ◄─── screenshot t+1 ──┐ │ │ │ │ │ │ ▼ │ │ │ is_modal_appeared? │ │ │ │ │ │ │ no ┴ yes │ │ │ │ │ │ │ ▼ │ │ │ DialogClassifier │ │ │ │ │ │ │ ▼ │ │ │ type ∈ {UAC, HELLO, SMART, PERM, │ │ │ SAVE, OK, INCONNU} │ │ │ │ │ │ │ ▼ │ │ │ DialogResolver │ │ │ │ │ │ │ ▼ │ │ │ policy(type, workflow_ctx) │ │ │ │ │ │ │ ▼ │ │ │ ┌─ AUTO_DISMISS (OK trivial) │ │ │ ├─ DECLARATIVE (catalog match) │ │ │ ├─ ASK_HUMAN (pause supervisée) │ │ │ └─ ESCALATE_SECURITY (log + pause) │ │ │ │ │ │ ▼ │ │ │ resume_or_wait │ │ │ │ │ └───────────────────────────────────────┘ │ ▼ serveur (api_stream) │ ▼ report dialog event + replay state ``` ### 4.2. Étendre `core/grounding/dialog_handler.py` existant Le fichier actuel (lecture seule pour ce doc, voir Read) fait déjà : - `_read_title` (EasyOCR full-screen, `fr+en`, GPU) - catalogue `KNOWN_DIALOGS` ordonné (popups modaux prioritaires avant fenêtres parents) - `_click_via_infigui` (UI-TARS / InfiGUI grounder déjà branché) - `_click_via_ocr` (fallback OCR direct) - retour `dict` avec `handled / title / dialog_type / action / position / time_ms` **À ajouter (esquisses, pas de code à committer) :** ```python # core/grounding/change_detector.py — nouveau fichier proposé from dataclasses import dataclass from typing import Optional, Tuple import time import numpy as np @dataclass class ChangeSignal: """Signal qu'un changement écran significatif vient d'apparaître.""" is_modal: bool # heuristique modal vs scroll normal foreground_hwnd_changed: bool # côté Windows uniquement diff_ratio: float # 0.0 = identique, 1.0 = tout différent central_diff_ratio: float # diff zone centrale (modaux centrés) timestamp: float class ChangeDetector: """Détecte qu'un modal *vient d'apparaître* sans appeler le VLM principal. Stratégie : 1) foreground window change (Windows API, ~1 ms) 2) screenshot diff centre vs périphérie (numpy diff sur sous-region, ~10 ms) 3) heuristique "centré + bordure assombrie" (modal pattern, ~5 ms) Budget total cible : < 50 ms pour ne PAS ralentir la boucle replay. """ def __init__(self): self._last_screenshot = None self._last_hwnd = None def detect(self, screenshot_pil) -> ChangeSignal: t0 = time.time() arr = np.asarray(screenshot_pil.convert("L")) fg_changed = self._check_foreground_changed() diff_ratio = 0.0 central_diff = 0.0 if self._last_screenshot is not None: prev = np.asarray(self._last_screenshot.convert("L")) if prev.shape == arr.shape: diff = np.abs(prev.astype(int) - arr.astype(int)) diff_ratio = float((diff > 25).mean()) # zone centrale = modaux Windows typiques h, w = arr.shape cy0, cy1 = h // 4, 3 * h // 4 cx0, cx1 = w // 4, 3 * w // 4 central_diff = float((diff[cy0:cy1, cx0:cx1] > 25).mean()) is_modal = ( fg_changed or (central_diff > 0.10 and diff_ratio < 0.40) # changement centré ) self._last_screenshot = screenshot_pil return ChangeSignal( is_modal=is_modal, foreground_hwnd_changed=fg_changed, diff_ratio=diff_ratio, central_diff_ratio=central_diff, timestamp=t0, ) def _check_foreground_changed(self) -> bool: """Côté Windows uniquement — sinon retourne False.""" try: import ctypes # noqa hwnd = ctypes.windll.user32.GetForegroundWindow() changed = (self._last_hwnd is not None) and (hwnd != self._last_hwnd) self._last_hwnd = hwnd return changed except Exception: return False ``` **Note importante** : `feedback_popup_vlm.md` documente que `GetForegroundWindow` est **non fiable seul** (retourne 0 en SSH, popups Windows modernes partagent hwnd du parent). On l'utilise comme **signal complémentaire**, jamais comme source unique. La détection finale repose sur le diff écran (vision). ### 4.3. DialogClassifier — extension du `dialog_handler.py` ```python # core/grounding/dialog_classifier.py — proposition from enum import Enum class DialogType(str, Enum): UAC = "uac" HELLO = "windows_hello" SMARTSCREEN = "defender_smartscreen" BROWSER_PERMISSION = "browser_permission" METIER_SAVE = "metier_save" # match catalog KNOWN_DIALOGS METIER_CONFIRM = "metier_confirm" OK_TRIVIAL = "ok_trivial" # popup avec 1 seul bouton OK INCONNU = "inconnu" # Signatures texte par type (extension du catalogue actuel) TYPE_SIGNATURES = { DialogType.UAC: [ "contrôle de compte d'utilisateur", "user account control", "voulez-vous autoriser cette application", ], DialogType.HELLO: [ "windows hello", "saisissez votre code pin", "touchez le capteur d'empreintes", ], DialogType.SMARTSCREEN: [ "windows a protégé votre pc", "smartscreen", "informations complémentaires", ], DialogType.BROWSER_PERMISSION: [ "autoriser", "bloquer", "souhaite utiliser votre caméra", "souhaite utiliser votre microphone", "souhaite afficher des notifications", ], # METIER_SAVE et METIER_CONFIRM = KNOWN_DIALOGS existant } class DialogClassifier: """Classifie un dialogue détecté en type connu. Stratégie cascade : 1) match signatures texte (OCR titre) — ~150 ms (EasyOCR cache) 2) si pas de match → VLM compact (qwen3-vl:8b) avec prompt "Classify this dialog: uac / hello / smartscreen / browser_perm / metier / unknown" — ~1.7 s 3) fallback : INCONNU """ def classify(self, screenshot_pil, ocr_text: str) -> DialogType: text = ocr_text.lower() for dtype, signatures in TYPE_SIGNATURES.items(): for sig in signatures: if sig in text: return dtype # Catalogue métier existant (KNOWN_DIALOGS du dialog_handler.py) from core.grounding.dialog_handler import KNOWN_DIALOGS for key in KNOWN_DIALOGS: if key in text: return DialogType.METIER_SAVE # ou METIER_CONFIRM selon key # Fallback VLM si rien ne matche et qu'on a un signal modal fort return self._classify_via_vlm(screenshot_pil) or DialogType.INCONNU def _classify_via_vlm(self, screenshot_pil) -> Optional[DialogType]: # Appel qwen3-vl:8b via Ollama LAN (port 11434) # Prompt court, format=json strict # ⚠ qwen3-vl:8b ignore parfois format=json — fallback regex sur stdout ... ``` ### 4.4. DialogResolver — politique par type Voir matrice §5 ci-dessous. Le resolver applique la politique et émet un événement structuré au serveur : ```python @dataclass class DialogEvent: type: DialogType title_ocr: str policy_applied: str # "auto_dismiss" / "declarative" / "ask_human" / "escalate_security" action_taken: Optional[str] # "click 'Oui' (123,456)" / "paused" duration_ms: float screenshot_path: str # toujours archivé pour audit ``` --- ## 5. Matrice modal → action | Type | Détection signature | Politique healthtech | Action concrète | Audit | |---|---|---|---|---| | **UAC** | "contrôle de compte", "user account control" | **escalate_security + ask_human** — JAMAIS auto-accept | `pause_for_human` ; toast "élévation requise — opérateur valide" | log full + screenshot | | **Windows Hello** | "windows hello", "code pin", "touchez le capteur" | **ask_human** — interaction physique requise par construction | pause + tip pré-démo : "désactiver Hello pour la session" (paramètres Windows) | log | | **Defender SmartScreen** | "windows a protégé votre pc", "smartscreen" | **escalate_security + ask_human** | pause + log security ; rappel `project_code_signing.md` (signature SHA256) | log full | | **Permission navigateur** (cam/mic/notif/geoloc) | "souhaite utiliser votre", "autoriser / bloquer" | **declarative** si déclaré dans workflow ; sinon **ask_human** | catalog match → click `Autoriser` ; sinon pause | log + screenshot | | **Métier sauvegarde** ("Voulez-vous enregistrer ?", "Enregistrer sous") | `KNOWN_DIALOGS` existant | **declarative** | InfiGUI click `Enregistrer` (catalog priority basse — fenêtre parent) | log standard | | **Métier confirmation** ("Voulez-vous remplacer ?", "Existe déjà", "Écraser") | `KNOWN_DIALOGS` priorité HAUTE | **declarative** | InfiGUI click `Oui` ; fallback OCR direct (code actuel) | log standard | | **OK trivial** (erreur app, info) | 1 seul bouton détecté, mots-clés "erreur/error/warning" ; pas de mot blocklist | **auto_dismiss** | click `OK` | log standard | | **OK trivial SUSPECT** (mots-clés "supprimé", "perdu", "irréversible") | blocklist regex | **ask_human** | pause | log full | | **INCONNU** | aucun match | **ask_human** par défaut (pas d'auto-dismiss aveugle) | pause + capture VLM pour catégorisation a posteriori → enrichit catalogue | log full | **Garde-fou healthtech** : tout dialog non métier listé dans `KNOWN_DIALOGS` ou dans le workflow déclaratif **escalade en pause supervisée** par défaut. C'est cohérent avec `feedback_failure_is_learning.md` (échec = pause, pas stop) et le constat OpenAI/Anthropic 2026 (login/sécurité → cède la main à l'humain). --- ## 6. Détection rapide d'apparition de modal Trois pistes, à composer plutôt qu'à choisir : ### 6.1. Foreground window change (Windows API) - **Coût** : ~1 ms. - **Fiabilité** : faible seul (`feedback_popup_vlm.md` 27 mars 2026 : popups Windows modernes partagent hwnd du parent, retourne 0 en SSH). - **Usage** : **signal complémentaire** dans `ChangeSignal`, jamais source unique. ```python import ctypes hwnd = ctypes.windll.user32.GetForegroundWindow() title_buf = ctypes.create_unicode_buffer(256) ctypes.windll.user32.GetWindowTextW(hwnd, title_buf, 256) # Comparer hwnd_n vs hwnd_n-1 ; titre dans title_buf.value ``` ### 6.2. Screenshot diff zone centrale vs périphérie - **Coût** : ~10 ms (numpy `abs(prev - curr) > seuil`, downscale 1/4). - **Fiabilité** : bonne pour modaux centrés (UAC, dialog métier, Hello). Faible pour toasts en coin. - **Heuristique** : `central_diff_ratio > 0.10` **ET** `diff_ratio < 0.40` → modal centré probable (le centre change beaucoup, le reste peu). - **Pattern visuel auxiliaire** : zone "assombrie" en bordure (`secure desktop` UAC = pixels < 50 en luminance sur > 60% de l'écran). ### 6.3. PopSweeper-style classifier (option future, si latence VLM trop forte) - ResNet50 + MobileNetV2 deux étages → 60 ms/frame, 91.7% précision sur RICO (mobile). - À envisager **uniquement** si la détection diff+heuristique laisse passer trop de cas. Pour l'instant, surcoût d'un modèle dédié non justifié — l'OCR titre + signatures couvre 80%. ### 6.4. Pas de pHash global pour détection modal `feedback_phash_vs_dialog_in_vm.md` est explicite : **pHash global est inadapté** à la cascade de modaux en VM. Le pHash compare des images entières, masquant les changements locaux qui sont précisément l'indice d'un modal. Utiliser screenshot diff zoné OU OCR titre — pas pHash global. --- ## 7. Activation de `_handle_possible_popup` orphelin ### 7.1. État actuel - **Côté client (Léa Windows)** : `_handle_possible_popup` défini, **0 site d'appel** (`LESSONS_LEARNED_GHT_2026-05.md`, F5.5.1). Un `_handle_popup_vlm` existe en parallèle (le "remplacement" mentionné dans l'audit) mais sans déclencheur générique. - **Côté serveur** : `core/grounding/dialog_handler.py` (étudié pour ce doc) — handler complet, ne se déclenche que si on l'appelle explicitement. - **Constat memoire 27 mars 2026** : `qwen3-vl:8b` détecte popup en 3.6 s avec coordonnées précises depuis le client (appel direct LAN port 11434), pas via le serveur. Donc le VLM-post-clic est **techniquement validé**. ### 7.2. Câblage proposé (sans modifier le code dans ce doc) Le pattern à brancher dans `agent_v1/core/executor.py` ressemble à : ``` def perform_click(self, x, y, ...): screenshot_before = grab() do_click(x, y) time.sleep(short_delay) screenshot_after = grab() signal = ChangeDetector().detect(screenshot_after) if signal.is_modal: ocr_text = read_ocr(screenshot_after) dtype = DialogClassifier().classify(screenshot_after, ocr_text) event = DialogResolver(policy).resolve(dtype, screenshot_after, workflow_ctx) report_to_server(event) if event.policy_applied == "ask_human": return WAIT_HUMAN return OK ``` **Sites d'appel à brancher** (à valider avec Dom avant tout commit) : 1. Après chaque `_replay_action` côté client (suit la mémoire 27 mars). 2. Avant chaque vérification de Validator post-action (cohérence AXE_B2). 3. Au démarrage du tick d'observation `observe_reason_act` côté serveur (capture un modal apparu pendant un wait long). ### 7.3. Décision sur `_handle_popup_vlm` vs `_handle_possible_popup` À trancher avec Dom : garder UN seul handler (probablement `_handle_popup_vlm` qui appelle l'extension proposée ici), supprimer l'orphelin. Sinon dette technique persistante (DETTE-XXX à créer si décision prise). --- ## 8. Anti-patterns à proscrire ### 8.1. Hardcoder un raccourci système "fix" `feedback_100pct_visual.md` est sans appel : **JAMAIS** : - `keyboard.press_and_release('escape')` pour "fermer un popup". - `keyboard.press_and_release('win+r')` pour "ouvrir un truc rapidement". - `keyboard.press_and_release('ctrl+x')` pour "annuler". Raisons : - Casse le récit "Léa comprend visuellement". Démontage immédiat face à un DSI healthtech. - Échappe à la cascade de validation (OCR → template → VLM). - Effets de bord imprévisibles : Échap dans un formulaire peut purger des données saisies ; Win+R sur un secure desktop ne fait rien et perd l'état. **Exception unique** : `gesture_catalog.py` autorise les réflexes système **explicitement référencés** (voir `feedback_lea_reflexes_catalog.md`). Mais c'est une **composition** orchestrée, pas un "fix popup ad hoc". ### 8.2. Auto-accept système (UAC, Hello, SmartScreen) Interdit en healthtech. Toujours pause supervisée. Cohérent avec FDA / RGPD / HDS — un agent qui élève des privilèges seul est un risque inacceptable. ### 8.3. pHash global pour détecter un modal Voir §6.4. Utiliser screenshot diff zoné + OCR titre. ### 8.4. Polling VLM principal à chaque tick Latence Qwen2.5-VL = 8-11 s par appel (synthèse `MIGRATION_VLM_PLAN_2026-05-09.md`). Détection modal doit rester < 100 ms — sinon on bloque la boucle replay. Le VLM est appelé **uniquement** quand le ChangeDetector signale `is_modal=True` ET que le catalogue texte n'a pas matché. ### 8.5. Tenter de "désactiver" Windows Hello programmatiquement Solution = config humaine pré-démo, pas action runtime de l'agent. L'agent **détecte et escalade**, il ne modifie pas la config sécurité Windows. --- ## 9. Liens forts avec les autres AXES et la dette projet - **AXE_A4 (OCR/Template/pHash)** : la **détection** modal réutilise screenshot diff zoné — surface à coordonner avec la décision pHash de A4 (pas pHash global ici). - **AXE_A5 (Screen Tokenization)** : un parser d'écran qui produit la liste de regions interactives détecte aussi les "boutons de modaux" — la classification peut bénéficier de cette liste sans coût VLM supplémentaire. - **AXE_B2 (Validator)** : dépendance forte. Un Validator strict (texte attendu présent dans la zone visée) **force** l'appel au DialogResolver quand le check post-action échoue. Sans ce couplage, un modal non vu reste un échec silencieux (cf. bug step 10 démo 8 mai : Imagerie cliqué dans bandeau Edge, REPORT success=True). - **AXE_A3 (Bench Protocol)** : ajouter un harness "modal injection" — pendant un replay test, injecter UAC simulé / popup métier / SmartScreen factice, mesurer detect→classify→resolve latency et taux pause vs auto-dismiss. - **DETTE existante** : DETTE-008 (`if False:` pré-check VLM par-clic, `observe_reason_act.py:1704-1713`) sera **résolue** par le ChangeDetector léger — on n'a plus besoin d'un VLM par clic, le détecteur fait le filtrage en amont. - **`feedback_capture_purge_policy.md`** : screenshots de DialogEvent à conserver pour audit (RGPD / HDS) — politique de rétention à valider avec Dom. --- ## 10. Sources (liens cliquables) ### Frameworks comparés (publications, blogs, papers) - [Anthropic Computer Use tool — docs API](https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/computer-use-tool) - [Anthropic Claude Desktop browser permissions controversy (avril 2026)](https://www.sovereignmagazine.com/article/anthropic-claude-desktop-browser-permissions) - [Anthropic — Auto Mode permission classifier (mars 2026)](https://medium.com/@joe.njenga/anthropic-adds-new-claude-code-auto-mode-no-more-permission-modes-52c8094ab742) - [OpenAI Operator System Card](https://openai.com/index/operator-system-card/) - [OpenAI ChatGPT Agent System Card — juillet 2025](https://cdn.openai.com/pdf/839e66fc-602c-48bf-81d3-b21eacc3459d/chatgpt_agent_system_card.pdf) - [ChatGPT Agent — login takeover + screenshot OFF](https://help.openai.com/en/articles/11752874-chatgpt-agent) - [Skyvern — AI RPA Guide (oct. 2025)](https://www.skyvern.com/blog/ai-rpa-guide-intelligent-browser-automation/) - [Skyvern — API-less Legacy System Automation (mai 2026)](https://www.skyvern.com/blog/api-less-system-automation-tools-legacy-enterprise/) - [Skyvern GitHub — Planner-Actor-Validator](https://github.com/Skyvern-AI/skyvern) - [browser-use — Issue #1996 : Need Robust Strategy for Handling Dynamic Popups (ouvert mai 2026)](https://github.com/browser-use/browser-use/issues/1996) - [OmniParser V2 — Microsoft Research](https://microsoft.github.io/OmniParser/) - [OmniParser arXiv 2408.00203](https://arxiv.org/abs/2408.00203) - [UI-TARS arXiv 2501.12326](https://arxiv.org/abs/2501.12326) ### Détection popup, classifiers légers - [PopSweeper — arXiv 2412.02933 (déc. 2024)](https://arxiv.org/abs/2412.02933) - [PopSweeper — HTML lecture directe](https://arxiv.org/html/2412.02933v1) - [ShowUI — arXiv 2411.17465 (2B GUI grounding)](https://arxiv.org/pdf/2411.17465) - [ZonUI-3B cross-resolution GUI grounding](https://arxiv.org/pdf/2506.23491) ### Sécurité Windows 11 / browser - [Microsoft KB UAC fixes oct. 2025 → janv. 2026 — Microsoft Q&A](https://learn.microsoft.com/en-nz/answers/questions/5733506/windows-uac-prompt-becomes-unresponsive-after-cred) - [NinjaOne — Change UAC Behavior Windows 11](https://www.ninjaone.com/blog/change-uac-behavior-for-administrators-in-windows-11/) - [CVE-2026-0628 Chrome Gemini Live panel takeover](https://news.corksafetyalerts.com/chrome-flaw-allowed-extensions-to-hijack-googles-ai-assistant-camera-and-microphone/) - [AI-powered phishing leveraging camera/mic permissions (2026)](https://www.scworld.com/brief/ai-powered-phishing-campaign-leverages-hardware-access-for-data-theft) ### Safety gates / human-in-the-loop healthcare - [Agentic Workflow Approval Gate Framework (4 gate types)](https://www.digitalapplied.com/blog/agentic-workflow-approval-gate-framework-governance) - [AI Agents for Healthcare — Architecture and Safety Guide (Momentum)](https://www.themomentum.ai/blog/ai-agents-healthcare-architecture-safety-implementation) - [Human-in-the-Loop Agentic AI (Elementum)](https://www.elementum.ai/blog/human-in-the-loop-agentic-ai) ### Références internes (à charger en parallèle de ce doc) - `docs/SYNTHESE_TECHNOS_REPLAY_2026-05-23.md` (synthèse maîtresse) - `docs/LESSONS_LEARNED_GHT_2026-05.md` (zones popup F5.5.1, F6.1.1, DETTE-008) - `core/grounding/dialog_handler.py` (commit `487bcb861`) - `memory/feedback_popup_vlm.md` (VLM post-clic, pas ctypes seul) - `memory/feedback_lea_reflexes_catalog.md` (gesture_catalog autorisé, pas hardcode ad hoc) - `memory/feedback_phash_vs_dialog_in_vm.md` (pas pHash global) - `memory/feedback_100pct_visual.md` (jamais raccourci inventé) - `memory/feedback_auth_dialogs_runtime.md` (anticiper Hello/UAC/Basic Auth AVANT démo) --- ## 11. Hors-périmètre de ce doc À demander à Dom si besoin avant action : - Décision finale sur unification `_handle_possible_popup` orphelin vs `_handle_popup_vlm` (les deux côté client). - Politique de rétention RGPD/HDS des screenshots `DialogEvent` (par défaut `data/runner_captures/dialogs/` purge ACK serveur). - Choix exact du modèle VLM compact pour la classification fallback (qwen3-vl:8b acceptable mais ignore parfois `format=json` Ollama — voir §2.4 synthèse). - Bench de la latence `ChangeDetector` sur capture réelle 2560×1600 (cible < 50 ms à vérifier empiriquement). - Politique sur la suppression auto de toasts (Teams, Outlook) pendant démo : déclaratif "do not disturb" en amont vs détection runtime. --- *Document de recherche. Lecture seule. Toute mise en code = décision explicite Dom puis chirurgie itérative supervisée (CLAUDE.md projet).*