Files
rpa_vision_v3/docs/LESSONS_LEARNED_GHT_2026-05.md

234 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Lessons Learned — Sprint démo GHT 5→19 mai 2026
**Objectif du document** : inventaire factuel des 15 jours de bug-chasing pré-démo GHT. À relire AVANT d'attaquer ARES et Anouste pour ne pas refaire les mêmes diagnostics.
**Pas de prose, pas de plan d'action ici** — juste « ce qui marche » / « ce qui ne marche pas » + références.
## Périmètre
- **Période** : 2026-05-05 → 2026-05-19 (15 jours)
- **Branches** : `feature/qw-suite-mai` (travail) → `backup/post-demo-2026-05-19` (commit `5ea4960e6`)
- **Référence "ça marchait" antérieure** : tag `demo-stable-2026-05-12` (commit `2eeaa806b`), branche `demo/ght-2026-05-08` (commit `56e869c46`)
- **Démo livrée** : vidéo `Demo_urgence_3_db` (`wf_483910cdd851_1778750587`, 46 steps), patiente MOREL Catherine, décision UHCD, 1750 €
---
## ✅ Ce qui marche (validé empiriquement pendant le sprint)
### Pipeline visuel / résolution UI
| Élément | Statut | Référence |
|---|---|---|
| Template matching multi-scale étendu (0.25 → 2.0) | scores ≥ 0.9 retrouvés sur capture downscalée 800×500 | `resolve_engine.py:130`, handoff 18 mai §1.2 |
| `hybrid_text_direct` rebranché dans cascade strict (mode legacy) | actif depuis commit `1cbec2806` | audit F2.4.4 |
| Exemption drift > 0.20 si `template_matching ≥ 0.95` ou `hybrid_text_direct ≥ 0.80` | actif, évite faux rejets sur high-confidence | `resolve_engine.py:2367-2390`, audit F2.2.1, DETTE-002 |
| Fallback heartbeat full-screen si capture client tronquée < 1200×800 | actif, élargi le 7 mai par `7233df2bb` | `api_stream.py:4422`, audit F2.2.6 |
| Anchors `by_text` (LINUX_demo, Tables, demo_95) ciblage textuel anti-faux-positif | validé sur Demo_urgence_3_db ord 29/35/36 | handoff 16 mai §4 |
| LoopDetector composite (screen_static + action_repeat + retry) | actif par défaut | `loop_detector.py`, commit `2a51a844b` |
| SafetyChecksProvider hybride (déclaratif + LLM contextuel) | actif sur `safety_level == medical_critical` | commit `7c6945171`, audit F2.3.4 |
| MonitorRouter (résolution écran cible multi-monitor) | actif, enrichissement heartbeat `monitor_index + monitors_geometry` | commits `6582a69d3`, `b1a3aa16f`, `2d71e2a24` |
### Workflow `linux_db` (NoMachine + DBeaver VM Ubuntu)
| Élément | Statut |
|---|---|
| Clics simples traversent NoMachine vers la VM | OK (pynput → SendInput → NoMachine → VM) |
| Bypass Ctrl+V/Ctrl+Enter via `ydotool` directement dans la VM | fix retenu (NoMachine en passive grab mange Ctrl) |
| `ydotoold` daemon persistant via service systemd | installé 18 mai, redémarre au boot VM |
| Gardien clipboard `prepare_clipboard_linuxdb.sh` (wl-copy + xsel boucle 0.5s) | actif, recharge VM clipboard |
| Workflow `linux_db` (7-9 steps) E2E sur VM Ubuntu en ~30s | validé 18 mai |
| Hook libvirt `/etc/libvirt/hooks/network` injecte `LIBVIRT_FWI ACCEPT 4000` | installé 18 mai, à valider au reboot |
| DNAT 4001→4000 via `nomachine-vm-forward.service` | persistant |
| UFW `route allow 4000 → 192.168.122.132` | persistant |
### LLM / Modèles
| Élément | Statut |
|---|---|
| `gemma4:latest` retenu pour `safety_checks` (bench rigoureux) | commit `0a02a6ec9`, BENCH_SAFETY_CHECKS_2026-05-06.md |
| `gemma4:31b-cloud` pour `t2a_decision` MOREL | qualité clinique propre observée (run 8 du 12 mai) |
| `qwen3-next:80b-cloud` testé qualité OK | switch ponctuel, pas durable |
| `qwen2.5vl:7b` pour VLM | configuré via `.env.local`, déborde CPU sur RTX 5070 12GB (acceptable car fallback) |
| `InfiGUI-G1-3B` Transformers grounding | 3.9 GB VRAM, permanent depuis 7 jours, principal |
| Bypass LLM via `static_result` / `static_text` (`replay_engine.py`) | court-circuit Ollama pour MOREL UHCD 1750 € — utilisé en démo |
| Module `smart_resize` officiel Qwen3-VL (commit `0d7bcd18a`) | commité mais ⚠ calé sur mauvaise référence patch_size — voir DETTE-014 |
| Bench `bench_t2a_dryrun.py` + `t2a_mappings.py` (commit `f2212e77e`) | outillage standalone 11 dossiers POC |
| `build_dpi_enriched` extraction déterministe horaires/classifications (commit `9872f4510`) | 41/41 tests verts |
### Infra & déploiement
| Élément | Statut |
|---|---|
| Service systemd `rpa-streaming` | actif, restart propre |
| Backup tarball post-démo `_archives/rpa_vision_v3_post_demo_20260519_142940.tar.gz` (8.9 GB) | SHA256 vérifié |
| Backup git `backup/post-demo-2026-05-19` poussé sur gitea (627 fichiers, 468 anchors) | commit `5ea4960e6` |
| 12+ backups DB `workflows.db.bak.*` jalonnant la session | présents dans `visual_workflow_builder/backend/instance/` |
| Registre `docs/DETTE_TECHNIQUE.md` créé (14 entrées) | actif depuis 9 mai |
### Méthodes de travail (sanctuariser)
| Méthode | Origine |
|---|---|
| `git status --short` SYSTÉMATIQUE en début de session | incident commit composite 12 mai (4 backend + 2 frontend stagés non liés) |
| Sauvegarde + fork AVANT chantiers parallèles | appliqué 12 mai, a payé |
| Instrumenter AVANT optimiser | corrigé 2 fois le cap (baseline run 4 + mesure parallélisme v2) |
| Test Ollama direct 30s AVANT pari sur connaissance LLM | `gemma3:27b` aurait été retenu par erreur sinon |
| Mesurer 2 conditions COMPARABLES, jamais cold-start vs warm | parallélisme ratio 2.7× → 1.27× corrigé |
| Diff PNG anchor avant/après recapture | aurait économisé 15 jours de bug-chasing (cause racine bug P0 #1) |
---
## ❌ Ce qui ne marche pas (cause connue ou hypothèse, contournement noté)
### 🔴 Bugs P0 racines (NON résolus — démo a tourné grâce aux contournements)
| Bug | Cause connue | Contournement | Fix réel à faire |
|---|---|---|---|
| **VWB recapture anchor ne régénère pas le PNG** | inconnue — `capture.py` réutilise PNG existant ou écrit avant screenshot ; 2 anchors capturés à 8j d'intervalle bit-à-bit identiques | recapture inutile, accepter régressions mystérieuses | audit `visual_workflow_builder/backend/api_v3/capture.py` |
| **Stop VWB ne purge pas la queue serveur** | VWB n'appelle pas `POST /api/v1/traces/stream/replay/<id>/cancel` au clic Stop | script `./scripts/cancel-replays.sh` manuel | brancher Stop → cancel côté frontend |
| **Coord client Léa Y cassé (÷ ~27)** | `mss.monitors[1]` retourne intermittemment `2560×60` au lieu de `2560×1600``y_pct × 60 = 16 px` (clic en haut écran) | aucun — bug intermittent | `agent_v0/agent_v1/core/executor.py:606-617`, ajouter fallback `if height < 200: reject` |
| **Bug skip ord 13 orchestration** (intermittent, run 8 du 12 mai) | non identifiée — transition serveur → visuel → serveur (mécanisme server-side action) | aucun, NOT REPRO 100% | trace `replay_fb0c9882_state.json` ; investiguer `replay_engine.py` + `api_stream.py` |
| **Bug échelle pixel grounding Ollama** (smart_resize non-déterministe) | DETTE-006 + DETTE-010 + DETTE-014 — checkpoint Qwen3-VL utilise `Qwen2VLImageProcessorFast` avec `patch_size=16` (factor=32, non 28) ; module `smart_resize.py` calé sur mauvaise référence | non posé | réaligner après lecture `image_processing_qwen2_vl_fast` |
### ⚠ Bugs P1 (workaround dispo)
| Bug | Cause | Workaround |
|---|---|---|
| Léa état mémoire dégradé (bulle paused n'apparaît plus après plusieurs replays) | `_last_pause_msg_shown` + `_chat_window_ref` jamais reset | restart Léa Windows |
| `delay_before` / `delay_after` ignorés au runtime | non lus par executor.py | fix partiel `dag_execute.py` pour `duration_ms` ; généraliser à `delay_before/after` |
| Léa interprète `action=null + replay_paused=true` comme "fin du replay" | `main.py` désactive `_replay_active` à tort | fix proposé `executor.py:1875` retourner `True` (non appliqué — nécessite SCP + restart Léa) |
| VWB frontend cache après modif DB | pas d'invalidation cache React | Ctrl+Shift+R obligatoire |
| `paste:true` ne fonctionne pas Windows → VM Ubuntu via NoMachine | NoMachine ne propage pas clipboard (ou `win32clipboard.SetClipboardText` plante silencieusement) | bypass via `ydotool` dans la VM (voir ✅) |
| Léa client envoie captures **800×500** au serveur | défaut `max_width=800` dans `executor.py:2895`, 7 sites d'appel sans override | compensé côté serveur par multi-scale étendu (✅) — fix client à poser : `max_width=0` sur 7 sites + SCP |
| `RPA_VLM_MODEL=gemma4:e4b` hardcoded dans Léa Windows (tag inexistant) | `executor.py` lignes 1569, 1700, 2248 | exporter `RPA_VLM_MODEL=qwen2.5vl:7b` env Windows |
| NoMachine viewer Windows freeze (clics avalés après quelques minutes) | NoMachine 9.5.7, pattern intermittent | restart NoMachine + plein écran obligatoire |
| Bug `'int' object has no attribute 'get'` VLM Quick Find | exception Python, non bloquant | DETTE B handoff 18 mai |
| Bug `get_target_memory_store` import dans `replay_memory.py` | import cassé | non bloquant mais empêche apprentissage corrections humaines |
| Démarrage Léa très lent (3-6 min au lancement) | chargement modèles ML | investiguer |
| Léa peut crasher silencieusement sous Windows | non identifié (mémoire ? exception ?) | quick-restart avant démo |
| Bouton "Stop" disparaît côté VWB UI alors que replay actif serveur | désynchro UI/serveur | confondant, à fixer |
| DAG edges visuelles VWB ne se sauvegardent pas | seul `steps.order` fait foi | confondant, à fixer |
| Capture VWB fallback `mss` Linux échoue sur Wayland natif | `XGetImage failed` | dépendance Léa Windows OBLIGATOIRE pour capturer |
### 🚫 Code orphelin / débranché (audit 8 mai)
| Code | Statut | Référence |
|---|---|---|
| `_resolve_by_yolo` défini, importé, **jamais appelé** | cascade OmniParser/YOLO neutralisée | DETTE-004, F2.4.1 |
| `_fuzzy_match` importé `api_stream.py:4372` mais jamais appelé | import mort | F2.5.2 |
| `VisualEmbeddingManager` + `ScreenshotValidationManager` (`core/visual/*`) définis mais jamais instanciés | mémoire visuelle orpheline | DETTE-005 |
| `ShadowLearningHook` (`core/grounding/shadow_learning_hook.py`) défini mais jamais instancié | Phase 6 FAST→SMART→THINK non câblée à Shadow | DETTE-009 |
| `_handle_possible_popup` (client) défini, **0 site d'appel** | fonction morte côté Léa, remplacée par `_handle_popup_vlm` | F5.5.1 |
| Pre-check VLM par-clic désactivé par `if False:` (`observe_reason_act.py:1704-1713`) | actif depuis 25 avril, commentaire « pipeline FAST→SMART→THINK a déjà validé » | DETTE-008, F6.1.1 |
| Pre-check OCR sémantique gardé par flag `RPA_ENABLE_TEXT_PRECHECK=false` par défaut | extinction explicite 8 mai pour démo GHT | DETTE-001, F2.3.1, F2.6.2 |
| Self-healing Win+D au retry 1 reverté (`22c0a2ba6`) | cercle vicieux observé | DETTE-003, F2.2.3 |
| Trois implémentations `smart_resize` coexistent (server.py, infigui_worker.py, module officiel) | unification post-démo Kerella | DETTE-007 |
| `pause_for_human` ignorée silencieusement en mode autonome (sans `safety_checks`) | actif `api_stream.py:3011-3017` | F2.6.5 |
### Anti-méthode observée (autocritique)
| Erreur | Conséquence |
|---|---|
| Modifs locales empilées sans validation à chaque étape | 15 jours de dérive depuis `demo-stable-2026-05-12` |
| Pas de smoke-test reproductible entre démos | régressions silencieuses découvertes par hasard |
| Bug VWB recapture anchor non détecté pendant 15 jours | cause racine n°1 des régressions, restée invisible |
| Workarounds empilés (cancel-replays.sh, bypass LLM static, pause humaine NoMachine) | dette technique non remboursée |
| Recapture en aveugle (Dom a recapturé des anchors en pensant fixer, le bug était VWB) | effort gaspillé |
| Apprentissage workflow via VWB-recording au lieu de mode Shadow Léa | divergence VWB ↔ Léa, 5 bugs P0 |
---
## ⚠ Contournements ACTIFS à connaître absolument
À sortir avant chaque nouveau run / déploiement client. Ces hacks **ne survivront pas** à un environnement propre.
| Contournement | Localisation | Risque |
|---|---|---|
| Bypass auth NPM `/aiva-urgence/` | `proxy_host/10.conf` (hors git) | écrasé si UI NPM touchée |
| Bypass LLM `static_result/static_text` MOREL | `replay_engine.py` steps 12-14 Demo_urgence_3_db | démo seulement, pas réutilisable client |
| Script `scripts/cancel-replays.sh` | manuel après chaque Stop VWB | oublié → replay zombie |
| `prepare_clipboard_linuxdb.sh` à relancer après reboot VM | non auto | clipboard vide → paste vide |
| `xhost +local:` à refaire après reboot VM | non auto | xsel échoue |
| Bypass Ctrl+V via `ydotool` au lieu de NoMachine clipboard | architectural, OK | dépend de la VM, pas Windows pur |
| Mot de passe `loli` en clair dans les scripts SSH/sudo | DETTE 5/16 mai | à remplacer par clé SSH + sudoers NOPASSWD |
| `RPA_VLM_MODEL=gemma4:e4b` hardcoded Léa | env var Windows à exporter | popup VLM 404 sinon |
| Flag pré-check OCR off par défaut | `RPA_ENABLE_TEXT_PRECHECK=false` | clics au pif si VLM/template échouent |
| Drift exemption template ≥ 0.95 / hybrid ≥ 0.80 | `resolve_engine.py:2367-2390` | accepte position visuelle même hors zone enregistrée |
| Fallback heartbeat sur capture < 1200×800 | `api_stream.py:4422` | risque image stale si heartbeat ancien |
---
## 🧠 Constats produit (à intégrer dans le pivot post-démo)
1. **Erreur stratégique identifiée par Dom (19 mai)** : apprendre via VWB-recording au lieu de Shadow Léa = deux représentations divergentes (anchors capturés à un moment T, replay à T+N). Origine des 5 bugs P0.
2. **VWB et Léa non unifiés** : VWB édite un script explicite que Léa rejoue. Pas de réinterprétation au runtime. Unification réelle = 4-6 semaines (refonte paradigme, hors fenêtre 15j POC).
3. **gemma3:27b CONFABULE sur PMSI français** (invente acronymes GEMSA, présente avec assurance maximale) — ne JAMAIS l'envisager comme fallback `gemma4` sur T2A.
4. **gemma4:31b** a conscience d'incertitude (bloc *Thinking*) — mais confond CCMU/GEMSA avec logique GHM. Libellé complet PMSI obligatoire dans FAITS_CALCULÉS.
5. **Ollama Cloud 503** vécue 12 mai → robustesse non couverte pour démo. Pas de fallback local équivalent qualité testé.
6. **Communication Dom ↔ Claude Code × 2 ↔ Claude session principale** : déperdition observée (3 arbitrages décision retransmis 2 fois). Pointer Claude Code vers fichiers de référence rédigés en session principale, pas paraphraser en chat.
---
## Références
### Commits clés (5 → 19 mai)
- `5ea4960e6` (19 mai) — backup snapshot post-démo GHT
- `f2212e77e` (12 mai) — bench_t2a_dryrun.py + t2a_mappings.py
- `9872f4510` (12 mai) — build_dpi_enriched extraction déterministe
- `2eeaa806b` (9 mai) — **tag `demo-stable-2026-05-12` — référence "ça marchait"**
- `bfbf0f9c3` (9 mai) — refactor parser bbox_2d centralisé
- `0d7bcd18a` (9 mai) — module smart_resize officiel (⚠ DETTE-014)
- `88ed103de` (9 mai) — création registre DETTE_TECHNIQUE.md
- `731b5bcae` (8 mai) — réactivation pré-check OCR calibrage chirurgical
- `56e869c46` (8 mai) — flag pré-check OCR off par défaut **(branche `demo/ght-2026-05-08`)**
- `7847a0e82` (7 mai) — toast paused supervisée + threshold FIND-TEXT 0.75
- `40440f1ca` (7 mai) — cure régression b584bbabc fallback aveugle
- `f62fda575` / `7233df2bb` (7 mai) — fallback heartbeat image tronquée + execution_mode supervised
- `1cbec2806` (6 mai) — rebrancher hybrid_text_direct
- `22c0a2ba6` (6 mai) — **revert** self-healing Win+D auto (cercle vicieux)
- `c969f93a2` (6 mai) — self-healing Win+D auto retry 1 (reverté)
- `864530c85` (6 mai) — `_async_replay_lock` helper + 17 endpoints async non-bloquants
- `0a02a6ec9` (6 mai) — bench rigoureux LLM safety_checks → `gemma4:latest`
- `2a51a844b` (5 mai) — LoopDetector composite
- `7c6945171` (5 mai) — SafetyChecksProvider hybride
### Handoffs détaillés
- `docs/handoffs/2026-05-19_handoff_post_demo_GHT.md` — bilan démo + 5 bugs P0
- `docs/handoffs/2026-05-18_handoff_consolidation.md` — UFW/LIBVIRT, template multi-scale, ydotoold systemd
- `docs/handoffs/2026-05-17_handoff_session_nomachine.md` — NoMachine freeze + `gemma4:e4b`
- `docs/handoffs/2026-05-16_handoff_ydotool_clipboard.md` — bypass Ctrl+V via ydotool
- `docs/handoffs/2026-05-16_handoff_demo3_workflow.md` — création Demo_urgence_3_db + linux_db
- `docs/handoffs/2026-05-13_inventaire_anchors_interop.md` — inventaire anchors
- `docs/handoffs/2026-05-12_handoff_fin_journee.md` — bug skip ord 13, bench A.1 paste, 8 arbitrages décision
- `docs/handoffs/2026-05-12_brief_S1_build_dpi_enriched.md` — brief V3 décision
- `docs/handoffs/2026-05-12_audit_complet_decision_t2a.md` — audit t2a_decision
### Audits & rapports
- `docs/DETTE_TECHNIQUE.md` — 14 entrées
- `docs/AUDIT_CONTROLES_DEBRANCHES_2026-05-08.md` — audit serveur+client 50+ findings
- `docs/AUDIT_DIM_TIM_DEMO_GHT_2026-05-08.md` — audit médecin DIM + TIM
- `docs/AUDIT_MEMOIRE_CLAUDE_2026-05-08.md` — santé index mémoire
- `docs/AUDIT_BDD_WORKFLOW_2026-05-10.md` — audit BDD workflows
- `docs/BUG_PRECHECK_SPATIAL_BLINDNESS_2026-05-08.md` — DETTE-001
- `docs/BENCH_SAFETY_CHECKS_2026-05-06.md` — bench LLM safety_checks
- `docs/BENCH_T2A_DECISION_11DOSSIERS.md` — bench décision
- `docs/MIGRATION_VLM_PLAN_2026-05-09.md` — plan migration VLM (DETTE-006, DETTE-010, DETTE-014)
- `docs/INVESTIGATION_MEMOIRE_VISUELLE_ORPHELINE_2026-05-09.md` — DETTE-005, DETTE-009
### Backups
| Type | Localisation |
|---|---|
| Tarball post-démo | `/home/dom/ai/_archives/rpa_vision_v3_post_demo_20260519_142940.tar.gz` (8.9 GB, SHA256 `7ab84f22d5a4...`) |
| Branche git backup | `backup/post-demo-2026-05-19` sur gitea (commit `5ea4960e6`) |
| Tag stable référence | `demo-stable-2026-05-12` (commit `2eeaa806b`) |
| Branche démo référence | `demo/ght-2026-05-08` (commit `56e869c46`) |
| Backups DB workflows | `visual_workflow_builder/backend/instance/workflows.db.bak.*` (12+ jalons) |
---
*Document maintenu par Dom. Toute nouvelle leçon (succès ou échec) à ajouter dans la section appropriée. Pas de remplissage — uniquement faits sourcés.*