Files
rpa_vision_v3/docs/AUDIT_GAPS_APPLI_100PCT_2026-06-10.md
Dom 6907ecc82f docs: track design docs, plans, audits, coordination infrastructure, handoffs
- 21 docs/*.md: audits, design notes, deployment plans, checklists, memos
- Coordination: ROLES, runbooks (DGX reboot, Lea live), patches, registre, syntheses, systemd, QG template
- Handoffs: 6 Codex handoff documents + README + template
2026-07-02 13:29:58 +02:00

15 KiB
Raw Blame History

Audit — Ce qui manque pour une appli 100% fonctionnelle

  • Date : 2026-06-10
  • Demandeur : Dom
  • Auteur : Claude (audit read-only par 4 sous-agents d'exploration + contre-vérifications manuelles)
  • Périmètre : agent client Windows (Léa), chaîne d'apprentissage, capacité de replay, maturité produit/fleet
  • Statut findings : les fichier:ligne proviennent d'agents d'exploration. Les 3 contradictions majeures ont été re-vérifiées à la main (voir annexe). Avant d'engager du code sur un item, revalider le point au cas par cas (méthode habituelle).
  • Avis croisé Qwen : reçu 2026-06-10 23:30 (inbox_claude/2026-06-10_2330_qwen-to-claude_AVIS-GAPS-APPLI-100PCT.md) — intégré en Addendum (§7).

1. Diagnostic central

L'appli aujourd'hui, honnêtement qualifiée : un record-and-replay supervisé robuste, avec une couche sémantique réelle au grounding, mais dont la boucle d'apprentissage n'est pas fermée et dont les filets de sécurité sont écrits mais débranchés.

Trois promesses produit non tenues dans le code qui tourne :

  1. La boucle d'apprentissage est ouverte — Shadow observe et construit des workflows, mais ils n'arrivent jamais dans VWB (import jamais déclenché).
  2. L'exécution ne se vérifie pas elle-même — verify, healing, recovery : tout existe, tout est désactivé ou non branché.
  3. Pas de généralisation — un workflow appris ne survit pas à un changement de poste/résolution ; FAISS est construit au training mais jamais consulté au replay.

Point structurel transverse : deux chemins d'exécution aux capacités différentes :

  • visual_workflow_builder/backend/api_v3/execute.py (exécution locale VWB, Legacy + ORA)
  • agent_v0/server_v1/replay_engine.py → agent Windows Léa (chemin POC)

Certains manques n'existent que sur l'un des deux. t2a_decision et le templating profond {{var.field.sub}} sont implémentés sur le chemin Léa (replay_engine.py:1922 et :2017) mais absents du chemin local. Cette asymétrie a piégé jusqu'aux agents d'audit eux-mêmes — c'est un coût de maintenance et un risque d'erreur permanent.


2. Axe agent client Windows (Léa) — ~80% fonctionnel, 1 bug critique

Ce qui marche (vérifié wired)

  • Capture complète : clics/double-clics, clavier+buffer texte, scroll, multi-écrans, DPI awareness, floutage sensible, dédup pHash.
  • Résilience réseau : buffer SQLite persistant, retry 3×, backoff 1→30s, heartbeat 5s.
  • Purge captures après ACK serveur (PURGE_AFTER_ACK=1 défaut).
  • Enroll Bearer token + machine_id ; détection dialogues système UAC/CredUI/SmartScreen fail-closed (pause supervisée).
  • Rétention logs 180 j (conforme Règlement IA art. 12).

Gaps

# Gap Sévérité Preuve Type
A1 Timeout HTTP client 5s : étape serveur > 5s (extract_text, t2a) → client coupe, action déjà sortie de la queue → perdue silencieusement. Incident documenté 8 mai (4 actions perdues, pause step 18). 🔴 BLOQUANT POC agent_v1/core/executor.py:1786 ; docs/REPLAY_BLOCAGE_NOTES_MEDICALES_2026-05-08.md Bug
A2 Watchdog _retry_pending absent côté serveur : actions perdues jamais republiées. 🔴 BLOQUANT POC network/streamer.py:99-105 (constat) Non implémenté
A3 Écran verrouillé non détecté : agent capture noir, tape dans le vide. 🟠 Important Non implémenté
A4 RecoveryEngine client : code complet, jamais appelé. 🟡 Nice-to-have agent_v1/core/recovery.py Écrit non branché
A5 Long-polling HTTP fragile par construction (vs SSE/WebSocket). 🟡 Post-POC main.py:287-366 Architecture

Note : la suspicion « appel Ollama de commentaire d'action orphelin côté client » ne se confirme pas côté agent_v1 (OLLAMA_HOST défini dans config mais aucun appel client). Le commentaire d'action est côté serveur.


3. Axe chaîne d'apprentissage — marche jusqu'au dernier mètre, puis s'arrête

Ce qui marche (vérifié wired)

  • Chaîne Shadow complète : streaming → LiveSessionManager → _worker_queue.txtrun_worker.py → ScreenAnalyzer → CLIP → FAISS indexation → GraphBuilder DBSCAN → workflow JSON dans data/training/workflows/{machine_id}/.
  • Apprentissage post-replay : ReplayLearner (JSONL data/learning/replay_results/) + TargetMemoryStore (SQLite data/learning/target_memory.db), consultés avant résolution, alimentés après succès/échec.

Gaps

# Gap Sévérité Preuve Type
L1 Workflows Shadow jamais importés dans VWB : import_core_workflow() existe (visual_workflow_builder/backend/api/workflows.py:622) mais aucun appel automatique post-finalize. La boucle d'apprentissage produit des fichiers que personne ne voit. 🔴 BLOQUANT promesse produit grep import_core_workflow depuis server_v1 = 0 hit Écrit non branché
L2 ShadowLearningHook jamais importé (état avril 2026 inchangé). 🟠 Important core/grounding/shadow_learning_hook.py Écrit non branché
L3 FAISS construit mais jamais interrogé au replay — la mémoire sémantique ne sert pas à la résolution. 🟠 Important core/embedding/faiss_manager.py Écrit non branché
L4 Pas de généralisation cross-résolution/cross-poste : workflows cloisonnés par machine_id, ancres dépendantes du poste source. 🟠 Important core/models/workflow_graph.py Non implémenté
L5 Copilot : inexistant (aucun moteur de suggestion). Autonomous : AutonomousPlanner isolé du replay engine. Le cycle Shadow→Copilot→Autonomous est aujourd'hui Shadow→(rien)→exécution déclenchée manuellement. 🔴 BLOQUANT promesse produit agent_chat/autonomous_planner.py, agent_v0/server_v1/execution_plan_runner.py Squelettes
L6 Recapture anchor VWB : pas de revalidation/régénération PNG post-modification (bug connu mai 2026). 🟠 Important visual_workflow_builder/backend/services/anchor_image_service.py Non implémenté

4. Axe replay/exécution — ça clique bien, mais ça ne sait pas si ça a marché

Ce qui marche (vérifié wired)

  • Cascade de résolution active : template matching → CLIP → OCR/UI-TARS → VLM.
  • DialogHandler branché (détection popups pré-step).
  • Pause supervisée avec choix utilisateur (skip/static/coords, timeout 120s).
  • Chemin Léa : t2a_decision (replay_engine.py:1922, handlers :2045+), templating profond {{var.field.sub}} (path.split('.') :2017), extract_text.

Gaps

# Gap Sévérité Preuve Type
R1 verify_level='none' en dur : aucune vérification post-action que le clic a produit l'effet attendu (seul pHash d'attente d'écran). Contraire au principe « vérif avant + après chaque clic ». 🟠 Important (🔴 avant clinique) execute.py:1545 Branché désactivé
R2 VLM pre-check if False: en dur : pas de validation que l'élément trouvé = l'élément attendu. 🟠 Important core/execution/observe_reason_act.py:1707 Branché désactivé
R3 Healing engine implémenté, jamais appelé. 🟠 Important core/healing/healing_engine.py:21-150 Écrit non branché
R4 Aucune reprise après crash : crash au step N → redémarrage à 0, pas de checkpoint. 🔴 BLOQUANT clinique execute.py:1732 (thread daemon sans checkpoint) Non implémenté
R5 OCR-DIRECT « centre de ligne » : substring d'une ligne docTR → coordonnées du centre de la ligne entière. Sur une barre d'onglets, Imagerie/Notes/Synthèse ≈ mêmes coords. Latent et sournois. 🟠 Important agent_v0/server_v1/resolve_engine.py:1447-1527 Bug
R6 Timeout VWB→serveur 30s vs étapes longues (t2a/Ollama lent) → 504. 🟠 Important server_client.py:207 Bug config
R7 Reporting d'exécution pauvre : méthode de grounding utilisée et raison d'échec non tracées. 🟠 Important ExecutionStep DB Incomplet
R8 Popup détecté mais gestion échouée → continue (log seul), pas de pause. 🟡 Nice-to-have execute.py:283 Incomplet
R9 3 systèmes de grounding morts (code zombie) : fast_detector, smart_matcher, template_matcher standalone. 🟡 Ménage core/grounding/ Poids mort
R10 TitleVerifier aveugle en VM (crop EasyOCR 45px illisible). 🟡 Connu core/grounding/title_verifier.py:34-67 Limitation

5. Axe maturité produit / fleet — OK pour 5 TIM supervisés, pas au-delà

Ce qui marche (vérifié)

  • Fleet : enroll/uninstall/revoke SQLite (agent_registry.py), _guard_agent_registry_access, last_seen heartbeat.
  • Sessions concurrentes thread-safe ; uploads images rate-limités sans sérialisation.
  • Healthcheck multi-composants + timer systemd (API, dashboard, worker heartbeat, disque).
  • Export ZIP workflows ; dashboard HTTP Basic fail-closed.

Gaps

# Gap Sévérité Preuve Type
P1 DETTE-006/010 — grounding Qwen3-VL instable (smart_resize non déterministe, config checkpoint factor 28 vs 32). LE risque technique du calendrier POC. 🔴 BLOQUANT POC docs/MIGRATION_VLM_PLAN_2026-05-09.md, DETTE_TECHNIQUE.md En cours
P2 1 seul replay simultané (verrou global _replay_lock). Acceptable POC séquentiel, bloquant au-delà. 🟠 Important post-POC api_stream.py Limitation
P3 Opérabilité non-dev : pas d'onglet « état systèmes », pas de monitoring GPU/Ollama, erreurs JSON brut. Acceptable seulement avec Dom en SSH derrière. 🟠 Important web_dashboard/app.py Incomplet
P4 Export ZIP sans restore en masse ; backup exporte les JSON, pas la DB (DETTE-015 : symlink tient pour le POC). 🟠 Important core/system/backup_exporter.py:58-160 Incomplet
P5 Multi-users/RBAC : 1 user statique. Accepté POC (lié DETTE-016). 🟡 Post-POC web_dashboard/app.py:67 Accepté
P6 Pas de rotation des logs serveurs (logs/*.log) — artifact_retention ne couvre que les données. 🟡 Nice-to-have core/system/artifact_retention.py Incomplet
P7 DETTE-013 : tests unit non exécutables sans RPA_API_TOKEN (sys.exit à l'import). 🟠 Important dev agent_v0/server_v1/api_stream.py:135 Bug
P8 Ménage pré-POC (~9-10 j-h, MENAGE_PRE_POC_2026-05-29.md) non engagé ; ~21 modules core/ orphelins documentés. 🟡 Planifié docs/POC/ Dette

6. Priorisation proposée

Horizon 1 — avant le M2 live (jours) : fiabiliser la chaîne qui existe

  1. A1 Timeout client 5s → 30s (1 constante) + A2 watchdog _retry_pending serveur — le duo qui a tué la session du 8 mai.
  2. P1 Trancher DETTE-006/010 (calibration grounding Qwen3-VL sur DGX) avant le bench J+6.
  3. A3 Détection écran verrouillé.

Horizon 2 — avant la clinique (semaines) : les filets de sécurité

  1. R1/R2 Réactiver verify (au moins post-condition légère) + pre-check.
  2. R5 Fix OCR centre-de-ligne (span du substring, pas centre de ligne).
  3. R4 Reprise sur crash (checkpoint step) + R7 tracer la méthode de résolution.
  4. R6 Timeout VWB 30s → adapté aux étapes longues (ou polling asynchrone).

Horizon 3 — la promesse produit (post-POC) : fermer la boucle

  1. L1 Pont auto Shadow→VWB (import_core_workflow post-finalize) — LA pièce qui transforme l'outil en produit apprenant.
  2. L3 FAISS consulté au replay + L4 début de généralisation cross-poste.
  3. L5 Copilot (moteur de suggestion) puis branchement AutonomousPlanner.
  4. Unifier les deux chemins d'exécution (execute.py local vs replay_engine.py Léa).
  5. P2 Replays parallèles, P3 opérabilité TIM, P4 restore, RBAC.

7. Addendum — Avis croisé Qwen (historien/QG, 2026-06-10 23:30)

Convergences avec l'audit code

  • DETTE-006/010 = les deux vrais risques démo (« si le grounding dérive, les clics ratent. Démo morte. ») — aligné avec P1/Horizon 1.
  • Monitoring/alerting productif absent (P3) : « si un worker crashe à 3h du matin sur un TIM, personne ne le saura ».
  • Écarts doc vs réalité confirmés par son registre : ContinuousLearner/Shadow hook orphelins (L2), cascade YOLO et OmniParser neutralisées (DETTE-004), ~1900 lignes de code mort jamais câblé (autonomous_planner, seeclick…) — cohérent avec L5/R9.

Apports nouveaux de Qwen (absents de l'audit code)

  1. Multi-TIM jamais testé > 1 agent simultané : le Fleet existe, mais routage session, isolation mémoire et contention GPU sous charge réelle sont inconnus. Mon audit avait noté le verrou replay global (P2) ; Qwen élargit : c'est toute la concurrence multi-agents qui n'a aucune preuve d'exécution.
  2. Le pipeline complet record → replay → compétence n'a jamais tourné en conditions réelles : M2 live n'a pas encore eu lieu. « Le premier vrai test sera devant le client » si on ne fait pas M2 avant.
  3. Incidents récurrents de son registre : worker zombie 5 jours (résolu par watchdog N3), tunnel Ollama instable (stabilisé systemd), UI-TARS 500 non détecté (toujours 0 test dédié), OOM VRAM GB10 (fixé).
  4. DETTE-015 jugée fragile : le symlink a déjà cassé une fois (P0-1) ; peut resurgir si cwd change.

Point de tension à arbitrer en M2 (pas tranché)

Qwen affirme : « si le serveur redémarre, les agents Windows tombent — pas de reconnexion automatique ». Mon audit client a trouvé buffer SQLite persistant + retry + backoff + health-check 30s (streamer.py). Les deux peuvent être vrais : le transport se reconnecte, mais la session/replay en cours ne reprend probablement pas après un restart serveur. À vérifier explicitement pendant M2 (test : restart serveur en cours de session).

Verdict Qwen

  • 1 TIM en démo contrôlée : prêt (sous réserve DETTE-006/010).
  • 5 TIM réels en clinique : pas prêt — le gap n'est pas dans le code métier (OCR, VLM, grounding) mais dans l'infra multi-utilisateur : sessions, isolation, monitoring, résilience.

Ce verdict est compatible avec la priorisation §6 et la renforce : l'Horizon 2 doit inclure un test de charge multi-agents (2-3 agents simultanés minimum) avant la clinique, en plus des filets de sécurité.


Annexe — Contradictions inter-agents résolues (contre-vérifiées à la main)

Affirmation agent d'audit Verdict après vérification
« t2a_decision non implémenté » FAUX sur le chemin Léa : implémenté agent_v0/server_v1/replay_engine.py:1922 + handlers :2045+. Vrai uniquement pour le chemin local execute.py.
« {{var.field.sub}} ne marche pas » FAUX sur le chemin Léa : path.split('.') replay_engine.py:2017. Vrai uniquement chemin local.
« Le chemin replay vers Léa est démis / Léa n'existe plus » FAUX : pont learned_workflow_bridge.py côté VWB + polling /replay/next côté client actifs. Les deux chemins coexistent — c'est l'asymétrie connue.

Leçon : tout audit ou modification doit d'abord identifier sur quel chemin d'exécution il porte.