# Handoff 2026-05-18 — Consolidation post-blocages démo J-3 **Session** : 08:00 → ~09:15 CEST **Démo cible** : "demo 95" Paris **jeudi 21 mai 2026 (J-3)** **Suite de** : `2026-05-17_handoff_session_nomachine.md` --- ## 1. Trois bugs distincts résolus aujourd'hui ### 1.1 Réseau — Windows → VM NoMachine sur port 4001 **Symptôme** : NoMachine Windows ne joignait pas la VM en 4001. **Cascade de causes** (trois bloqueurs successifs, chacun nécessaire) : 1. **UFW politique `deny (routed)`** par défaut → DNAT marchait, FORWARD dropait. Fix posé : ```bash sudo ufw route allow proto tcp from any to 192.168.122.132 port 4000 ``` 2. **`LIBVIRT_FWI` REJECT par défaut** pour tout NEW depuis l'extérieur vers virbr0 → la règle libvirt ACCEPT de fin de chaîne n'était jamais atteinte. Fix initial volatil : ```bash sudo iptables -I LIBVIRT_FWI -d 192.168.122.132 -p tcp --dport 4000 -j ACCEPT ``` 3. **Persistance LIBVIRT_FWI** : hook libvirt créé pour re-injecter la règle à chaque démarrage du réseau `default` : - `/etc/libvirt/hooks/network` (chmod 755) — réagit à `default started begin` - Déclenche : `iptables -I LIBVIRT_FWI 1 -d 192.168.122.132 -p tcp --dport 4000 -j ACCEPT` (idempotent) **Statut** : 3-way handshake Windows↔VM confirmé par tcpdump live. **Non testé en condition reboot** (à valider au prochain `virsh net-destroy default && virsh net-start default`). DNAT 4001→4000 lui-même reste géré par le service existant `/etc/systemd/system/nomachine-vm-forward.service` (script `/usr/local/sbin/nomachine-vm-forward.sh`). ### 1.2 Vision — score template_matching effondré (régression apparente) **Symptôme** : steps `click_anchor` qui passaient à 0.97-0.98 hier donnaient 0.498 (icône Ubuntu) ou 0.757 (Editeur SQL) → cascade VLM/template échoue → `strict_vlm_template_failed`. **Cause établie par mesure pixel-précise** : - Le screenshot envoyé par Léa Windows au serveur fait **800×500 px** (downscale par défaut dans `agent_v0/agent_v1/core/executor.py:2895` — `_capture_screenshot_b64(max_width=800, quality=60)`). - Les ancres sont enregistrées en pixels physiques (ex. 91×90 px sur capture record 2560×1600). - Ratio capture runtime / capture record = 800/2560 = **0.3125** → ancre 91×90 devient 27×27 dans la capture serveur. - La liste multi-scale `resolve_engine.py:130` ne descendait qu'à `0.5` → trou entre 0.5 et l'échelle réelle 0.3 → `cv2.matchTemplate` plafonnait à 0.498. - Vérification chiffrée (script ad hoc sur la capture du fail) : à scale 0.30, score = **0.900** pile, centre détecté au pixel près de la cible attendue. **Fix posé** : extension de la liste multi-scale dans `resolve_engine.py:130`. Avant : ```python for scale in [1.0, 0.9, 1.1, 0.8, 1.2, 0.75, 1.25, 0.6, 1.5, 0.5, 1.75, 2.0]: ``` Après : ```python for scale in [1.0, 0.95, 0.93, 0.9, 1.05, 1.1, 0.85, 0.8, 1.15, 1.2, 0.75, 1.25, 0.6, 1.5, 0.5, 0.4, 0.35, 0.3, 0.25, 1.75, 2.0]: ``` Backup avant modif : `docs/handoffs/2026-05-18_resolve_engine_avant_scales_fix.py`. **Validation runtime** : workflow `linux_db` exécuté de bout en bout, tous les steps visuels OK (LINUX_demo ✓, Activités GNOME ✓, DBeaver ✓, demo_95 ✓, Editeur SQL ✓ à 0.948, etc.). Modif **non commitée**. **Pourquoi la régression est apparue "hier ça marchait"** : la valeur `max_width=800` est ancienne et inchangée. Hypothèse retenue (par élimination, audit serveur+client en agents parallèles) — un changement récent du flux serveur a fait que le screenshot consommé pour le matching est celui downscalé au lieu d'une capture full-res antérieure, OU les 20 tests d'hier étaient sur une configuration où NoMachine cropait différemment et l'écart ne touchait pas le seuil. À investiguer post-démo. ### 1.3 Replay — `paste_and_execute` step 8 (workflow linux_db) **Symptôme** : `paste_and_execute échoué (rc=1) stderr=ERREUR: ydotoold (socket /tmp/.ydotool_socket) absent dans la VM`. **Cause** : ydotoold est démarré à la main depuis hier soir (handoff 17 mai §4) — pas de persistance. Au prochain reboot VM (ou kill manuel), le daemon disparaît. **Fix posé — service systemd persistant** sur la VM : `/etc/systemd/system/ydotoold.service` (créé, enabled, active) : ```ini [Unit] Description=ydotool daemon (input injection pour replay RPA Vision) After=network.target [Service] Type=simple ExecStart=/usr/bin/ydotoold --socket-path=/tmp/.ydotool_socket --socket-perm=0666 Restart=on-failure RestartSec=2 [Install] WantedBy=multi-user.target ``` Effet : démarre au boot VM, redémarre auto si crash, socket en `/tmp/.ydotool_socket` perm 0666. **Clipboard gardien** : toujours géré par `scripts/prepare_clipboard_linuxdb.sh` (pas systématisé, à relancer manuellement après reboot VM — sujet ouvert, voir §3). --- ## 2. Dette technique nouvellement identifiée ### Dette A — Client Léa Windows envoie des captures 800×500 au serveur **Localisation** : `agent_v0/agent_v1/core/executor.py:2895` — défaut `max_width=800` pour `_capture_screenshot_b64`. **Sites appelants à corriger pour forcer full-res** (7 sites) : - ligne 633, 801, 824, 894 (screenshot_before), 935, 989, 1055, 1303 (screenshot_after / result["screenshot"]) → tous sans override, donc tous downscalent à 800 px. - Seules les lignes 1334 et 2147 (resolve_target) passent `max_width=0` (full-res). **Fix recommandé post-démo** : ajouter `max_width=0, quality=75` sur ces 7 sites d'appel (préserver la flexibilité du défaut pour usages de monitoring live). Puis SCP vers `dom@192.168.1.11` + restart Léa. **Workaround actuel** : l'élargissement multi-scale côté serveur (§1.2) compense fonctionnellement la dette. À conserver de toute façon. ### Dette B — Bug `'int' object has no attribute 'get'` dans VLM Quick Find Trace dans les logs du 18 mai 08:35:46 : `VLM Quick Find : exception (20.4s) — 'int' object has no attribute 'get'`. Erreur Python dans le pipeline VLM (pas un crash Ollama). Non bloquant tant que template matching réussit, mais à investiguer. ### Dette C — Persistance du gardien clipboard sur la VM Le script `prepare_clipboard_linuxdb.sh` doit être relancé à la main après chaque reboot VM. Aujourd'hui : oneshot. Possible amélioration : systemd-user service ou systemd timer. Hors scope J-3. --- ## 3. Routine reboot à jour **Au boot hôte Linux** : 1. `systemctl --user start rpa-streaming` — manuel ou auto via session 2. `nomachine-vm-forward.service` — auto via systemd (DNAT 4001→4000) 3. `libvirtd` démarre `default` → hook `/etc/libvirt/hooks/network` injecte `LIBVIRT_FWI ACCEPT 4000` (auto) 4. UFW route allow — persistée par UFW **Au boot VM Ubuntu** : 1. `ydotoold.service` — **auto** (systemd, installé aujourd'hui) 2. `xhost +local:` — manuel, perdu au reboot 3. `prepare_clipboard_linuxdb.sh` — manuel (charge le payload SQL + gardien) **Côté Windows** : 1. Lancer Léa (`run_agent_v1.py`) 2. Ouvrir NoMachine via icône bureau "LINUX_demo" — pointe vers `192.168.1.40:4001` (DNAT vers VM) --- ## 4. État runtime à la clôture de session - `rpa-streaming` actif (PID 1641479+), VLM `qwen2.5vl:7b` chargé - ydotoold actif côté VM (systemd, PID 48926) - Clipboard VM rempli (1635 bytes payload INSERT MOREL, table `requalification_urgence`) - Workflow `linux_db` (9 steps) validé E2E aujourd'hui — temps total ~30s - Workflow `Demo_urgence_3_db` (40 steps) en cours de re-record par Dom au moment du handoff --- ## 5. Action recommandée avant la démo J-3 1. **Commiter** le fix scales `resolve_engine.py:130` (1 ligne) — workflow validé E2E 2. **Tester** un reboot VM pour valider que `ydotoold.service` redémarre bien et que le hook libvirt repose la règle `LIBVIRT_FWI` 3. **Vérifier** que `prepare_clipboard_linuxdb.sh` est ajouté à la procédure pré-démo dans `docs/handoffs/2026-05-17_handoff_session_nomachine.md` §6 (à compléter) 4. **Optionnel** : traiter dette A (`max_width=0` client) si temps avant J-3