# Handoff fin de journée — 11 mai 2026 ## 1. Contexte de la journée - **Objectif initial** : démo Urgence_aiva_demo (rpa_vision_v3) prévue 16h pour l'équipe AIVANOV interne (DG, DSI, médecins, DIM, TIM). - **Décision en cours d'après-midi** : démo reportée, vidéo commentée à enregistrer ultérieurement. - **Workflow utilisé** : `Demo_urgence_2` (`wf_d04d2dc7c118_1778493082`), 18 steps, créé/recordé le matin. - **Sessions** : - Claude Chat (cette session, audit méthode) - Claude Code (cette session, exécution / diagnostics / patches) - Autre session Claude Chat pour S2 arbre de décision (séparée). --- ## 2. État actuel de la stack (snapshot 2026-05-11 17:59 CEST) | Service | Port | PID | État | |---|---|---|---| | Frontend VWB Vite | 3002 | 935784 (node) | ✅ LISTEN | | Backend Flask VWB | 5002 | 4095891 | ✅ LISTEN | | Agent chat / bus SocketIO | 5004 | 3568779 | ✅ LISTEN, bus ESTAB avec Léa (192.168.1.11:1031) | | Streaming server | 5005 | 3830788 | ✅ LISTEN, 61 TIME-WAIT (polling Léa actif) | | Ollama | 11434 | 3169222 + 423007 | ✅ LISTEN | | Léa Windows | — | — | ✅ Polling actif depuis 17:51:23 (dernier démarrage observé). Bus connecté. SSH ESTAB. | Dernier événement backend VWB : `17:59:28 GET /api/v3/replay/state/replay_free_b63cf1aa 200`. --- ## 3. Modifications de code appliquées aujourd'hui (toutes machines) | # | Fichier | Lignes / nature | Statut | Backup | Validation runtime | |---|---|---|---|---|---| | 3.1 | `agent_v0/agent_v1/ui/chat_window.py` | Ajout `self.hide()` dans `_on_paused_resume` après émission resume (L1011) | **ROLLBACKÉ** en fin de journée pour test diagnostique (hypothèse focus système). Hypothèse **infirmée** mais rollback maintenu. | `docs/handoffs/2026-05-11_chat_window_avant_fix.py` | OUI (minimisation observée à 15:13/15:48). Mais cause indirecte suspectée puis disculpée. | | 3.2 | `agent_v0/agent_v1/core/executor.py` | Ajout `time.sleep(0.5)` avant capture screenshot post-click (correction asymétrie click vs type/wait/scroll, L1289) | **ACTIF** côté Windows (déployé via SCP) | `docs/handoffs/2026-05-11_executor_avant_sleep_stabilisation.py` | PARTIELLE (a permis de débloquer le step 3 sans retry forcé en partie). | | 3.3 | `agent_v0/server_v1/api_stream.py` | Extension `skip_verify` à `click` / `click_anchor` (L3409) | **ROLLBACKÉ** après découverte que la vérif pixel masquait un autre bug (clic à mauvaise position validé comme succès). | `docs/handoffs/2026-05-11_api_stream_avant_skipverify_click.py` | INVALIDÉ (a fait apparaître le bug "clic n'importe où"). | | 3.4 | `visual_workflow_builder/backend/api_v3/dag_execute.py` | Ajout helper `_expand_extract_text_scroll_in_workflow` (+97 lignes) appelé dans `execute_dag()` (L554) | **INERTE** : endpoint `execute-dag` jamais appelé par le bouton "Exécuter" du frontend. | `docs/handoffs/2026-05-11_dag_execute_avant_expand.py` | NON (jamais exécuté). | | 3.5 | `visual_workflow_builder/backend/api_v3/dag_execute.py` (suite) | Ajout helper `_expand_extract_text_scroll_in_actions` (+103 lignes) et appel en tête de `execute_windows()` (L1029) | **ACTIF**. C'est ce patch qui expanse réellement les `extract_text_scroll` en 6 sous-actions atomiques. | `docs/handoffs/2026-05-11_dag_execute_avant_patch_execute_windows.py` | PARTIELLE (jamais exécuté complètement à cause d'autres bloqueurs en amont — window-detection cassée). | | 3.6 | BDD `workflows.db` | Renumérotation `Step.order` de Demo_urgence_2 : 18 steps passés de `order=0` (tous) à `order=0..17` distincts | **ACTIF** | `docs/handoffs/2026-05-11_pre_renum_demo_urgence_2.db` | OUI (badges UI 1..18 corrects, ordre respecté à l'exécution). | | 3.7 | BDD `workflows.db` | Injection `by_text` sur 8 click_anchor de Demo_urgence_2 (orders 2, 4, 6, 8, 10, 13, 14, 16) | **ACTIF** | `docs/handoffs/2026-05-11_pre_inject_bytext_demo_urgence_2.db` | PARTIELLE (présent dans payload, mais pas suffisant pour rattraper la window-detection cassée). | --- ## 4. Diagnostics confirmés ou écartés aujourd'hui ### Confirmés - Le frontend VWB appelle `/execute-windows`, **pas** `/execute-dag` ni `/execute/start`. Les deux derniers endpoints sont **dormants** (legacy/test). - `execute_workflow_thread` itère les steps par `Step.order` SQL croissant (linéaire), les arêtes du canvas ne sont pas persistées en BDD et ne sont pas consultées par le runtime. - `extract_text_scroll` n'était pas implémenté côté agent Léa Windows. Patch d'expansion serveur appliqué (cf 3.5). - Léa fait du template_matching dans une **fenêtre cible** retournée par `get_active_window_rect()` (Win32 `GetForegroundWindow()`). Critère unique = foreground window à l'instant t. Aucun filtre sémantique (titre, ratio, taille minimale autre que `w>50, h>50`). - À **5 occurrences sur 6** dans l'après-midi (15:48, 16:23, 17:02, 17:34, 17:53), `get_active_window_rect()` a retourné une bounding box absurde (typiquement `2560×108 (0, 1492)`). Conséquence : grounding `score=1.00` dans cette bande aberrante → clic à `(80, 1530)` au lieu de `(80, 563)`. - L'absence de `expected_after` sur les click_anchor permet à Léa de continuer le workflow même quand un clic a atteint la mauvaise zone (l'écran "change" pixel-wise sans avoir atteint la page cible). ### Infirmés - L'hypothèse "le fix `self.hide()` causait le déplacement de focus système et donc la mauvaise fenêtre détectée" n'est **pas** validée. Rollback de `chat_window.py` n'a pas restauré la bonne détection de fenêtre (bug `2560×108` réapparu à 17:53:32 après rollback). ### Non identifié - Quel processus Windows exactement est retourné par `GetForegroundWindow()` lors des occurrences foireuses. Le code grounding ne loggue ni `title` ni `app_name` (trou d'observabilité documenté en S3.2.4). --- ## 5. Dette technique S3 — bugs structurels rpa_vision_v3 À traiter en priorité post-démo. Liste exhaustive de tout ce qu'on a identifié aujourd'hui. ### S3.1 — Architecture replay (PRIORITÉ HAUTE) - **S3.1.1** Le `Step.order` BDD n'est pas synchronisé avec l'ordre visuel du canvas VWB. Les modifications d'ordre via drag-and-drop sur le canvas ne mettent pas à jour `step_order` côté BDD. L'agent exécute selon `Step.order` SQL ; le canvas est cosmétique pour l'exécution. - **S3.1.2** Les nouveaux steps créés via le VWB ont systématiquement `step_order = 0`. Le code de création de step n'attribue jamais d'order incrémental. Bug structurel découvert en runtime aujourd'hui. - **S3.1.3** Trois endpoints `/execute-windows`, `/execute-dag`, `/execute/start` coexistent ; un seul est utilisé. Architecture confuse. À simplifier (supprimer les morts ou unifier). - **S3.1.4** Le helper `_expand_extract_text_scroll_in_workflow` patché aujourd'hui sur `execute-dag` est inerte. Si `execute-dag` est réactivé un jour, il faudra synchroniser avec `_expand_extract_text_scroll_in_actions` de `execute-windows`. - **S3.1.5** Le contrat entre `execute_windows` et le streaming server n'est pas clair : certaines actions lisent les paramètres au top-level, d'autres dans `parameters`. Une "rustine défensive" duplique les valeurs aux deux endroits (cf `_expand_extract_text_scroll_in_actions`). À nettoyer. - **S3.1.6** L'action `_concat_text_vars` est marquée serveur-only dans `_SERVER_SIDE_ACTION_TYPES` mais peut être envoyée à Léa par le chemin DAG. Asymétrie à corriger. ### S3.2 — Window-detection et grounding (PRIORITÉ TRÈS HAUTE) - **S3.2.1** `get_active_window_rect()` dans `window_info_crossplatform.py` se base uniquement sur `GetForegroundWindow()` Win32. Aucun filtre sémantique : titre, process, ratio d'aspect, taille minimale réaliste, comparaison à la fenêtre attendue. Conséquence : bug récurrent `2560×108 (0, 1492)` qui a bloqué la démo aujourd'hui. - **S3.2.2** Le mode "apprentissage par observation" de Léa (existant et fonctionnel) a une logique sophistiquée de détection de fenêtre (focus, titre, contexte, réflexes). Le mode "replay via VWB" hérite d'une logique window-detection minimaliste qui n'a jamais été unifiée. Chantier d'unification observation ↔ replay = priorité de fond. - **S3.2.3** Le seul filtre actuel dans `grounding.py:144` est `w > 50 and h > 50`. Pas de docstring, ressemble à un check défensif minimal. À renforcer (h > 400, ratio < 5:1, comparaison au titre attendu). - **S3.2.4** Aucun logging du `title` / `app_name` retourné par `_get_window_rect_windows()`. Trou d'observabilité majeur qui a empêché le diagnostic précis aujourd'hui. **Quick win pour demain** : ajouter 1 ligne de log. - **S3.2.5** Le code path `click_anchor` peut emprunter un chemin "coordonnées passthrough" qui applique des `x_pct`/`y_pct` sur la fenêtre détectée sans vérification croisée par template_matching réel ni OCR du `by_text`. Le `score=1.00` retourné dans ce cas n'est pas un vrai score de match. Le contrat "valider visuellement avant cliquer" est de fait court-circuité quand la fenêtre détectée est correcte ; il est catastrophique quand elle est aberrante. **À investiguer** : identifier précisément la condition qui déclenche ce chemin passthrough vs le chemin "vrai grounding". ### S3.3 — Contrat de validation post-action (PRIORITÉ HAUTE) - **S3.3.1** Un `click_anchor` est validé "réussi" dès que l'écran change pixel-wise. Aucune vérification que la page d'après contient bien le contenu attendu. Léa peut cliquer dans la barre des tâches Windows et déclarer "succès" parce que quelque chose a changé. - **S3.3.2** Le mécanisme `expected_after` (texte attendu sur la page post-clic, vérifié par OCR) existe dans le code mais n'est exposé ni dans le VWB ni utilisé sur les workflows actuels. À activer et à imposer pour les click_anchor critiques. - **S3.3.3** La vérification pixel post-click (`verify_action`) compare AVANT et APRÈS et déclenche un retry si le diff est "ambigu". En cas de navigation entre pages, cette logique génère des retries inutiles. Repensé via `skip_verify` aujourd'hui puis rollbacké. À revisiter. ### S3.4 — Recording VWB (PRIORITÉ MOYENNE) - **S3.4.1** Le recording VWB doit générer automatiquement le `by_text` quand un élément textuel est cliqué (LLM caption ou OCR du voisinage de l'ancre). Sans ça, workflows fragiles (vérifié aujourd'hui : workflow recordé sans `by_text` → comportements aberrants). - **S3.4.2** L'UI Propriétés VWB n'expose pas le champ `by_text` pour édition manuelle. À ajouter. - **S3.4.3** Le champ `variable_name` du VWB accepte des templates `{{...}}` qui sont stockés littéralement (ex : `"{{t_motif_admission}}"`). Devrait soit refuser, soit stripper, soit clarifier le sens du champ. - **S3.4.4** Le VWB n'a pas de validation de cohérence entre l'ordre du canvas et l'ordre BDD à la sauvegarde. Devrait soit refuser la sauvegarde si incohérent, soit recalculer. - **S3.4.5** `extract_text_scroll` peut être créé dans le VWB sans `anchor_id`. Le runtime peut l'expanser via le patch d'aujourd'hui, mais comportement à valider. - **S3.4.6** Hallucination VLM systématique sur les chiffres longs : "25003284" lu comme "250003284" (8 vs 9 chiffres). Probablement lié à `qwen2.5vl:3b` (modèle léger). Affecte la description d'ancre, pas le `target_text` OCR ni le `by_text`. Cosmétique mais visible. ### S3.5 — Synchronisation UI VWB ↔ Léa (PRIORITÉ BASSE) - **S3.5.1** Le PauseDialog du VWB et la bulle Léa s'affichent **en parallèle** sur `pause_for_human`. Aucun n'a la priorité, le premier à répondre gagne. Confusion UX. Quatre options de fix identifiées (A/B/C/D), aucune implémentée aujourd'hui. - **S3.5.2** La bulle Léa cache parfois ses boutons Continuer/Annuler sous le scroll. UX à fixer (boutons en sticky). - **S3.5.3** Le bus SocketIO côté Léa est conditionné par la variable d'environnement `LEA_FEEDBACK_BUS=1`. Si non défini, le bus n'est pas instancié → `pause_for_human` ne peut pas reprendre via Léa. Comportement non documenté. - **S3.5.4** Le service `agent_chat` (port 5004) n'est pas systématiquement démarré. Si absent, le bus reste déconnecté même avec `LEA_FEEDBACK_BUS=1`. À automatiser. ### S3.6 — Observabilité et traçabilité (PRIORITÉ MOYENNE) - **S3.6.1** Le backend Flask VWB ne loggue pas les payloads des requêtes (uniquement werkzeug INFO). Impossible de reconstituer une session passée. Ajouter `@app.before_request` qui loggue body + URL en debug. - **S3.6.2** Le champ `workflows.updated_at` n'est pas rafraîchi lors des modifications de steps. Trompeur. À corriger. - **S3.6.3** `ReplayVerifier` est instancié globalement sans paramètres dans `api_stream.py:52`. Les seuils sont hardcodés dans `replay_verifier.py`, les env vars sont ignorées. Bug architectural à corriger. - **S3.6.4** Le canvas VWB affiche le badge `step.order + 1` (`StepNode.tsx:104`). Bug cosmétique qui crée une divergence entre les badges visibles et l'order BDD. Convention à uniformiser (0-based ou 1-based partout). --- ## 6. Plan de reprise demain matin ### Priorité 1 — Observabilité minimale (15 min) Ajouter dans `grounding.py:152` un log qui affiche `win_info["title"]` et `win_info["app_name"]`. Redéployer Léa. Au prochain run, on saura précisément quelle fenêtre Windows est ramassée à tort. ### Priorité 2 — Sanity check window-detection (30 min) Dans `_get_window_rect_windows()` ou dans le caller : rejeter les fenêtres dont le ratio `width/height > 5` ou hauteur `< 400 px`. Fallback : écran entier. Permet de débloquer le runtime sans refonte profonde. ### Priorité 3 — Unification observation ↔ replay (chantier de fond, plusieurs jours) Identifier dans le code de l'apprentissage par observation les fonctions de détection de fenêtre par titre/process. Les exposer en API interne. Refactor du replay pour les consommer. **C'est le vrai chantier.** --- ## 7. Choses qui marchent bien (à préserver) - Le diagnostic SQL sur la BDD `workflows.db` (commandes `sqlite3` directes ont permis de comprendre rapidement l'état du workflow). - La méthode "investigation lecture seule puis décision" appliquée plusieurs fois aujourd'hui. - Le système de backups binaires de la BDD avant chaque modif structurelle. - La séparation Linux (VWB / streaming / Ollama) et Windows (Léa) qui a permis d'isoler les fixes. - Le watch SQL en monitoring pendant le recording (à utiliser systématiquement à l'avenir). --- ## 8. Choses à NE PAS faire demain - Reprendre les diagnostics où on en est ce soir. **Repartir frais.** - Tenter un fix sans avoir d'abord rétabli l'observabilité (S3.6). - Modifier le code Léa Windows et le code Linux dans le même incrément sans tester chaque étape. - Repousser les nettoyages S3 "encore un peu" → ils sont la cause des problèmes d'aujourd'hui.