# Index — Specs opérationnelles replay (transport / validator / popups) **Date :** 2026-05-24 **Auteur :** Claude (session principale) à partir des 3 specs ciblées + 6 docs de recherche préalables. **Public :** humain ou agent qui doit prendre en charge l'un des 3 chantiers de fiabilisation replay post-démo GHT. **Statut :** lecture seule. Aucune décision figée. Plan d'action proposé à valider par Dom. --- ## 0. Comment lire ce document Tu prends en charge un chantier replay → tu lis §1 (TL;DR) et tu sautes directement à la spec correspondante (§3.1, §3.2 ou §3.3). Tu reviens à §2 (croisements) si ton chantier touche les deux autres. Les décisions ouvertes Dom sont consolidées §4. Les 3 specs s'appuient sur des **recherches préalables** déjà livrées (`AXE_B1`, `AXE_B1_DEEP`, `AXE_B2`, `AXE_B2_DEEP`, `AXE_D2`, `AXE_D2_DEEP`). Les specs ne refont pas l'étude — elles produisent le contrat opérationnel. --- ## 1. TL;DR **3 chantiers replay à mener en parallèle pour fermer les bugs racines post-démo GHT (~3 j homme MVP cumulés)** : | # | Chantier | Bug racine fermé | Spec | Code prêt | Effort MVP | |---|---|---|---|---|---| | **B1** | Transport + watchdog | Désync 8 mai (9 actions perdues en 33s) | `SPEC_TRANSPORT_CONTRAT.md` | `replay_watchdog.py` ~270 LOC + patches `api_stream.py` | **3h30** | | **B2** | Validator post-action | Step 10 (clic Imagerie dans Edge, REPORT success=True) | `SPEC_VALIDATOR_MATRICE.md` | package `core/validation/` ~590 LOC (MVP P0 ~190 LOC) | **8h** | | **D2** | Chaîne popup propre | `_handle_possible_popup` orphelin + auto-dismiss risqué | `SPEC_POPUPS_CATALOGUE.md` | package `core/dialog/` ~700 LOC + 59 entrées catalogue | **1j** | **Résultat attendu cumulé** : démo prochaine sans contournement `static_result/static_text`, sans `cancel-replays.sh` manuel, sans pause humaine sur dialogs métier connus. **Contraintes invariantes respectées** : - 100% vision (aucun raccourci système inventé) - Healthtech (jamais d'auto-accept UAC / Hello / SmartScreen / suppression non déclarée) - Backward compatible (kill-switches env var par défaut OFF sur chaque chantier) --- ## 2. Croisements entre les 3 specs ``` ┌─────────────────────────────────────────────────────────────────┐ │ │ │ ┌───────────────┐ ┌───────────────┐ │ │ │ B1 Transport │◄────────│ B2 Validator │ │ │ │ + Watchdog │ ack │ + 6 Checkers │ │ │ └───────────────┘ └───────────────┘ │ │ ▲ │ │ │ │ purge si paused │ failure_category= │ │ │ ▼ UNEXPECTED_DIALOG │ │ │ ┌───────────────┐ │ │ └──────────────────│ D2 Popup │ │ │ │ Resolver │ │ │ └───────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ### Dépendances et contrats inter-modules | Source | Cible | Contrat | Quand | |---|---|---|---| | B1 | B2 | Action arrive bien côté serveur (REPORT non perdu) | Prérequis. Sans B1, B2 vote sur du vide. | | B2 | D2 | `failure_category=UNEXPECTED_DIALOG/NO_VISUAL_CHANGE/WRONG_APPLICATION` → `DialogResolver.resolve()` | Au verdict d'échec d'un Checker | | D2 | B1 | Si modal détecté pendant qu'une action est en `_retry_pending`, watchdog doit purger | v1.1 du watchdog (déjà partiel via `cancel_replay` ligne 4489) | | D2 | B2 | `DialogPresenceChecker` (Checker B2) fournit la bbox utilisée par `DialogClosedChecker` | Coordination intra-Validator | | B2 | B1 | Verdict `WRONG_APPLICATION` (bug step 10) → override `success=True → False` → relance watchdog | Au report client | ### Orthogonalité - **B1 ↔ B2** : techniquement orthogonaux (peuvent être codés en parallèle), mais **les deux ensemble** = fermeture totale du bug du 8 mai (transport + validation). - **D2** : indépendant de B1 et B2 pour l'implémentation, mais consomme leurs interfaces au runtime. --- ## 3. Résumé par spec ### 3.1. SPEC_TRANSPORT_CONTRAT.md **Chemin** : `/home/dom/ai/rpa_vision_v3/docs/recherche/SPEC_TRANSPORT_CONTRAT.md` **Volume** : 766 lignes, 169 lignes de tables. **Recherches sources** : `AXE_B1_REPLAY_TRANSPORT.md`, `AXE_B1_DEEP_WATCHDOG.md`. **Contenu** : - 2 state machines ASCII (serveur PENDING → DISPATCHED → ORPHAN → ACKED → ABANDONED → PAUSE | client POLLING → RECEIVED → DEDUP → EXECUTING → REPORTING → ACKED) avec invariants I1-I6 et C1-C5. - Contrats JSON DISPATCH / REPORT / re-dispatch / pause / resume / cancel, avec lignes de code source précises (`api_stream.py:626-651` schema, `3354-3359` retry_pending, `4361-4474` resume, `4489` cancel). - **Matrice 21 cas limites** (a→u) couvrant timeout pré-réponse, déconnexion post-réception, report perdu, watchdog race, client mort, server restart, polls concurrents, idempotence double-clic, pause pendant action en vol, cancel UI, abandon MAX_RESENDS, etc. - Sémantique d'idempotence à 7 couches + spec `dedup_set` client copy-paste + idempotence par type d'action. - 18 timeouts/seuils tabulés avec env vars (`RPA_WATCHDOG_ORPHAN_TIMEOUT_S=30`, `RPA_WATCHDOG_SCAN_INTERVAL_S=10`, `RPA_WATCHDOG_MAX_RESENDS=2`, etc.). - Transitions pause supervisée & resume (5 déclencheurs `paused_need_help`). - Compatibilité transport polling ↔ SSE (table d'invariance). - 7 fiches précédents externes (SQS, NATS, Skyvern, browser-use, Anthropic CU, Playwright MCP) + table comparative. **Code production-ready dans le doc** : module `agent_v0/server_v1/replay_watchdog.py` (~270 lignes), 4 patches diff unified `api_stream.py`, 8 tests pytest `tests/integration/test_replay_watchdog.py`. **Effort intégration** : **3h30** (45min schéma+watchdog, 30min câblage, 1h tests pytest, 1h chasse races sur E2E réel, 15min DETTE). --- ### 3.2. SPEC_VALIDATOR_MATRICE.md **Chemin** : `/home/dom/ai/rpa_vision_v3/docs/recherche/SPEC_VALIDATOR_MATRICE.md` **Volume** : ~1300 lignes denses. **Recherches sources** : `AXE_B2_VALIDATOR_PATTERN.md`, `AXE_B2_DEEP_VALIDATOR.md`, `AXE_A4_OCR_TEMPLATE_PHASH.md`. **Contenu** : - Matrice principale **27 types d'action × 9 colonnes** (signal primaire / secondaire / fallback / verdicts possibles / latence cible / coût / Checker à utiliser). - **4 fiches détaillées** pour les cas listés explicitement par Dom : - `switch_tab` (le bug step 10) : signal primaire = `OcrRoiChecker` ROI 120×40 autour du tab attendu cherchant label exact dans words OCR ; secondaire = pHash de la zone contenu sous les tabs a changé ≥ 5%. - `close_tab` : `TabAbsenceChecker` + visibilité tab voisin actif. - `save` : disparition indicateur "modifié" + apparition toast "Enregistré". - `dialog_button` : disparition du dialog (handoff D2 via `DialogClosedChecker`). - 5 fiches secondaires (`click_anchor`, `type_text`, `extract_text`, `t2a_decision`, `keyboard_shortcut`). - **6 Checkers production-ready** : `PixelDiffChecker` (15ms), `OcrRoiChecker` (80ms, **résout step 10**), `TitleBarChecker` (130ms wrapper existant), `JsonSchemaChecker` (10ms), `LlmJudgeChecker` (3s wrapper `verify_with_critic` existant `replay_verifier.py:367`), `TabActiveChecker`/`TabAbsenceChecker`/`SaveSuccessChecker`/`DialogClosedChecker` (nouveaux). - Confidence scoring + règles d'agrégation multi-checker (`switch_tab` → SUCCESS si primaire ≥ 0.85 OU primaire ≥ 0.65 AND secondaire ≥ 0.70). - **Anti-patterns table 12 entrées** : pHash global pour switch_tab, title-bar seule pour SPA, `success=True` parce que coords envoyées, SSIM global dialog, etc. - 6 précédents externes (Skyvern `complete_verify`, browser-use `evaluation` agent, Playwright assertions, Selenium `expected_conditions`, SikuliX `waitVanish`, PyImageSearch). - Plan d'intégration en 3 étapes graduées (1j MVP / 2 sem couverture complète / 1 mois bench). **Réutilisation existant** : `OcrRoiChecker` réutilise le singleton EasyOCR de `TitleVerifier._get_ocr()` (zéro coût d'init). **Reproduction offline du bug step 10** : script `repro_bug_step10_validator.py` fourni + test pytest `test_validator_step10.py`, sur capture `visual_workflow_builder/backend/data/anchors/anchor_0438bd2d9bdd_1778161174_full.png`. **Wiring** : diff unified format insertion à `api_stream.py:3447-3582` derrière flag `RPA_VALIDATOR_V2_ENABLED=false` (default OFF, aucune régression flag off). **Budget latence démo 46 steps** : **+11s cumulés** (vs 33s perdus en pause/reprise step 10). **Effort intégration P0** : **8h** (création package 4h + tests 1.5h + patch api_stream 2h + smoke 30min). --- ### 3.3. SPEC_POPUPS_CATALOGUE.md **Chemin** : `/home/dom/ai/rpa_vision_v3/docs/recherche/SPEC_POPUPS_CATALOGUE.md` **Volume** : 1758 lignes après enrichissement. **Recherches sources** : `AXE_D2_DIALOG_POPUP.md`, `AXE_D2_DEEP_POPUP_CHAIN.md`. **Contenu** : - **Section 2bis — Catalogue compact (format Dom)** avec exactement 5 colonnes : `ID | Titre exact (FR/EN) | Appli source | Boutons attendus | Politique`. - **Politique trichotomie stricte** : - **`auto`** = Léa clique un bouton précis (action explicite définie) - **`pause`** = Léa s'arrête et attend décision humaine - **`skip`** = Léa ignore le modal (ne clique rien, ne s'arrête pas) - **59 entrées catalogue** réparties en 5 catégories (A SYSTÈME, B NAVIGATEUR, C MÉTIER, D APP TIERS, E INCONNU) : - **44 `pause`** : toute la catégorie A SYSTÈME + identification + suppression + warnings cliniques - **10 `auto`** : save/confirm Easily, dialogs métier connus, dialogs disposables avec clic explicite - **5 `skip`** : `browser-translate-prompt`, `easily-toast-saved`, `outlook-reminder`, `chrome-update`, `edge-update` - 10 fiches détaillées des modaux critiques (UAC, Hello, SmartScreen, save unconfirmed, browser perms, etc.) avec capture-type ASCII. - **Workflow VWB déclaratif** `expected_modal` (YAML + Pydantic schema) avec validateur `system_modals_cannot_be_overridden` qui **rejette toute politique ≠ `pause` sur préfixes `windows-` / `defender-`** — un workflow VWB ne peut pas forcer un UAC en auto. - Snippet Python `KNOWN_DIALOGS` étendu (781 lignes, syntaxe valide `ast.parse` OK) avec champs `window_title`, `app_source`, `policy` (`auto`/`pause`/`skip`), `declarative_override: bool`. Helpers `get_metadata()` et `can_be_overridden()`. - Tests offline pytest + protocole de capture. - 7 précédents externes (Skyvern issue #69, browser-use issue #1996, Anthropic CU human takeover, OpenAI Operator watch mode, AutoIt/Sikuli, pywinauto, Selenium JS alerts). **Décisions tranchées par les agents** : - `_handle_possible_popup` orphelin **supprimé** (0 site d'appel + antipattern Tab+Enter aveugle). - `_handle_popup_vlm` actif **conservé mais simplifié** → devient client léger d'un nouvel endpoint `POST /api/v1/dialog/resolve`. - DialogResolver côté **serveur** (pas client) pour mutualiser avec `dialog_handler.py` existant. **Couverture estimée** : **~85%** des modaux courants sans intervention humaine. Les 15% restants = pause supervisée par design healthtech. **Effort intégration** : **1j MVP** (P0 démo) → 1 sem couverture complète + tests fixtures (P1) → 1 mois bench injection + apprentissage catalogue (P2). --- ## 4. Décisions ouvertes consolidées pour Dom Les 3 specs remontent des points qu'un agent ne peut pas trancher seul. Regroupés ici par thème. ### 4.1. Transport / watchdog (8 décisions — `SPEC_TRANSPORT_CONTRAT.md` §12) | ID | Question | Recommandation auteur | |---|---|---| | D1 | Persistance `_retry_pending` au restart serveur ? | Non par défaut (cas extrême ; restart démo = redémarrage replay manuel) | | D2 | Politique d'abandon par type d'action (click vs wait) ? | Différenciée : click MAX_RESENDS=2, extract_text MAX_RESENDS=1 | | D3 | Retry des actions server-side (`extract_text`, `t2a_decision`) ? | Non (idempotence non garantie : LLM peut diverger) | | D4 | Purge `_retry_pending` à la complétion workflow ? | **Oui** (recommandé) | | D5 | `dedup_set` client : taille LRU + clé ? | LRU 50 entrées, clé = `action_id` + `attempt_id` | | D6 | Génération `attempt_id` côté serveur ? | UUID4 court 8 chars, incrémenté à chaque resend | | D7 | Backward-compat client v1 ↔ serveur v2 ? | Header `X-Replay-Protocol-Version` côté client | | D8 | `cancel_in_flight` (annuler action en cours sur le client) ? | **Non** (recommandé) — trop de risques | ### 4.2. Validator (7 actions où le signal "qui fait foi" reste flou — `SPEC_VALIDATOR_MATRICE.md` §10) | Action | Question | |---|---| | `paste_and_execute` | Vérif côté Léa Windows ou côté SSH VM (cas NoMachine pixel intermédiaire) ? | | `screenshot_evidence` | `TitleBarChecker` suffit ou exiger netteté image ? | | `pause_for_human` mode autonome | Aujourd'hui silencieusement ignorée (`api_stream.py:3011-3017`) — laisser ou changer ? | | `t2a_decision = NA` | Verdict métier vs erreur LLM (hors-scope médical Claude) — qui décide ? | | Tab déjà actif au moment du clic | Idempotence (SUCCESS) ou NO_VISUAL_CHANGE ? | | `drag_drop_anchor` | Whitelist serveur mais pas de handler Léa — implémenter ou retirer du whitelist ? | | Animations longues > 1s | `wait_after_action_ms` par type d'action vs généralisé ? | ### 4.3. Popups (5 modaux ambigus — `SPEC_POPUPS_CATALOGUE.md` §10) | Modal | Politique proposée | Risque à valider | |---|---|---| | `easily-required-field` | `auto` | Peut masquer un bug de grounding réel | | `outlook-reminder` | `skip` | Risque clinique de masquer un rappel pro | | `chrome-update` / `edge-update` | `skip` | À confirmer si ne prend pas le focus après inactivité | | `easily-clinical-warning` | `pause` non surchargeable | Volontairement strict, à valider | | `browser-perm-microphone` (Easily dictée vocale) | `pause` | Déclaration globale `declared_dialogs` ou par-workflow ? | --- ## 5. Plan d'attaque concret proposé (~3 jours homme cumulés) ### Vague 1 (jour 1) — Transport + start Validator - **Matin (3h30)** — Watchdog `replay_watchdog.py` + patches `api_stream.py`. Kill-switch `RPA_WATCHDOG_ENABLED=false` par défaut → activable progressivement. Tests pytest sans Windows. Smoke E2E réel. - **Après-midi (4h)** — Validator MVP P0 : `PixelDiffChecker` + `OcrRoiChecker` + orchestrateur, sans `LlmJudgeChecker`. Flag `RPA_VALIDATOR_V2_ENABLED=false`. Test offline du bug step 10 sur fixture du 8 mai. ### Vague 2 (jour 2) — Finir Validator + Popup chain MVP - **Matin (4h)** — Compléter Validator : `TabActiveChecker`, `SaveSuccessChecker`, `DialogClosedChecker`, `JsonSchemaChecker`. Tests par type d'action. - **Après-midi (4h)** — Chaîne popup MVP : signatures FR+EN, `ChangeDetector` + `DialogClassifier` + `DialogResolver` côté serveur. Endpoint `/api/v1/dialog/resolve`. Simplification `_handle_popup_vlm` client. ### Vague 3 (jour 3) — Intégration et démo - **Matin (3h)** — Coordination Validator → DialogResolver (handoff `UNEXPECTED_DIALOG`). Test bout-en-bout démo MOREL Catherine avec les 3 chantiers actifs. - **Après-midi (3h)** — Bench latence sur démo réelle (cible : +20s overhead max sur 46 steps). Activation progressive des flags. Mise à jour `DETTE_TECHNIQUE.md` (DETTE-001, 008 closables). **Sortie attendue** : démo prochaine `Demo_urgence_3_db` qui tourne **sans** `static_result/static_text`, **sans** `cancel-replays.sh` manuel, **sans** pause humaine sur dialogs métier connus. --- ## 6. Hors-périmètre de ces 3 specs (rappel) Ces 3 specs **ne traitent pas** : - Migration grounding VLM (`AXE_A1`, `AXE_A2`, `AXE_A3` — Qwen3-VL, smart_resize, bench bbox). - Bug capture client Y `mss.monitors[N]=2560×60` (`AXE_B5_D1_CAPTURE_REMOTE.md` — fix DPI 8 lignes en tête de `main.py`). - Shadow learning / fine-tuning / memory store (`AXE_C_LEARNING_SHADOW.md`). - Packaging / code signing / multi-tenant (`AXE_D4_MULTI_TENANT_DEPLOY.md`). - Veille frameworks externes (`AXE_E_FRAMEWORKS_BENCHMARKS.md`). - Bug recapture anchor VWB silencieuse (P0 — non couvert par cette vague). - Bug skip ord 13 orchestration (P0 — non identifié, NOT REPRO 100%). Ces sujets sont couverts par les autres docs `docs/recherche/AXE_*.md`. Voir `SYNTHESE_TECHNOS_REPLAY_2026-05-23.md` pour la carte d'ensemble. --- ## 7. Cartographie complète des livrables de recherche ### Vague 1 — Panorama 13 axes (23 mai 2026) ``` docs/SYNTHESE_TECHNOS_REPLAY_2026-05-23.md (synthèse croisée initiale) docs/recherche/AXE_A1_VLM_GROUNDING_SOTA.md (état art VLM grounding) docs/recherche/AXE_A2_SMART_RESIZE_BBOX.md (DETTE-014/010/007/006) docs/recherche/AXE_A3_BENCH_PROTOCOL.md (script bench reproductible) docs/recherche/AXE_A4_OCR_TEMPLATE_PHASH.md (cascade déterministe) docs/recherche/AXE_A5_SCREEN_TOKENIZATION.md (OmniParser / SoM) docs/recherche/AXE_B1_REPLAY_TRANSPORT.md (SSE / WS / pull-poll) docs/recherche/AXE_B2_VALIDATOR_PATTERN.md (Planner-Actor-Validator) docs/recherche/AXE_B4_ORA_VS_REPLAY.md (autonomous vs déclaratif) docs/recherche/AXE_B5_D1_CAPTURE_REMOTE.md (mss / DXGI / NoMachine) docs/recherche/AXE_C_LEARNING_SHADOW.md (Shadow + FT + memory) docs/recherche/AXE_D2_DIALOG_POPUP.md (chaîne dialog handling) docs/recherche/AXE_D4_MULTI_TENANT_DEPLOY.md (packaging + code signing) docs/recherche/AXE_E_FRAMEWORKS_BENCHMARKS.md (delta veille + benchmarks) ``` ### Vague 2 — Approfondissement 3 axes replay (24 mai 2026) ``` docs/recherche/AXE_B1_DEEP_WATCHDOG.md (watchdog production-ready) docs/recherche/AXE_B2_DEEP_VALIDATOR.md (Validator package) docs/recherche/AXE_D2_DEEP_POPUP_CHAIN.md (chaîne popup complète) ``` ### Vague 3 — Specs opérationnelles (24 mai 2026) ``` docs/recherche/SPEC_TRANSPORT_CONTRAT.md (contrat dispatch→ack→retry→orphan→resume) docs/recherche/SPEC_VALIDATOR_MATRICE.md (matrice action → signal qui fait foi) docs/recherche/SPEC_POPUPS_CATALOGUE.md (catalogue 59 entrées + politique auto/pause/skip) ``` ### Vague 4 — Index (ce document) ``` docs/recherche/INDEX_REPLAY_SPECS_2026-05-24.md (point d'entrée brief agent / humain) ``` --- *Index maintenu par Dom. À mettre à jour quand de nouvelles specs replay sont livrées ou quand une décision §4 est tranchée.*