Files
rpa_vision_v3/docs/PLAN_ACTION_VWB.md
Dom 447fbb2c6e
Some checks failed
security-audit / Bandit (scan statique) (push) Successful in 12s
security-audit / pip-audit (CVE dépendances) (push) Successful in 10s
security-audit / Scan secrets (grep) (push) Successful in 8s
tests / Lint (ruff + black) (push) Successful in 13s
tests / Tests unitaires (sans GPU) (push) Failing after 14s
tests / Tests sécurité (critique) (push) Has been skipped
chore: sauvegarde complète avant factorisation executor
Point de sauvegarde incluant les fichiers non committés des sessions
précédentes (systemd, docs, agents, GPU manager).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 17:03:44 +02:00

18 KiB
Raw Blame History

Plan d'action VWB — 13 avril 2026

Audit ciblé du Visual Workflow Builder (visual_workflow_builder/) — backend Flask port 5002, frontend React+Vite port 3002 — suite aux retours flous de Dom : « la bibliothèque s'efface tout le temps » + idée d'importer les workflows Léa pour les corriger.


Section A — État des lieux

Stack réelle en production (PIDs live)

  • Backend 5002backend/app.py (Flask complet, blueprints v3, SQLAlchemy) — c'est celui qui sert le VWB
  • Backend 5003backend/app_lightweight.py (serveur HTTP natif fallback, 1451 lignes, mode quasi-inutile aujourd'hui)
  • Frontend 3002frontend_v4/ (Vite + React 18, @xyflow/react, TypeScript) — actif
  • BDD utiliséebackend/instance/workflows.db (via .env DATABASE_URL=sqlite:///workflows.db) — 3 workflows dedans (« Classement de dossier », « bloc notes », « Onlyoffice »), tous source='manual', aucun review_status
  • BDD fantômebackend/instance/vwb_v3.db (schema identique, 0 workflows) — zombie de app.py ligne 47 ('sqlite:///vwb_v3.db' en défaut)

Ce qui marche bien

  • API v3 est complète et propre : 44 routes réparties (session, workflow, capture, execute, match, review, learned_workflows, dag_execute). Modèles SQLAlchemy avec champs review (source, review_status, review_feedback, reviewed_at).
  • Pont Léa ↔ VWB déjà implémenté et câblé :
    • Backend : api_v3/learned_workflows.py (459 l.) + services/learned_workflow_bridge.py (604 l.)
    • Frontend : services/api.ts expose getLearnedWorkflows, importLearnedWorkflow, exportForLea ; components/WorkflowSelector.tsx charge et propose d'importer les workflows non-importés
    • Endpoints fonctionnels : logs du 15 avril montrent GET /api/v3/learned-workflows?os=linux → 200
  • Système de review : composants ReviewModal.tsx, WorkflowValidation.tsx, WorkflowManagerModal.tsx + backend api_v3/review.py prêt. Un workflow importé arrive en review_status='pending_review'.
  • Tests backend localisés : backend/tests/ (test_models.py, test_coaching_api.py). Workflow CRUD complet.
  • Logs rotatifs propres (backend/logs/vwb.log, 5 MB × 3).

Ce qui est cassé / douteux

  1. BUG CRITIQUE — Bibliothèque de captures qui s'efface Fichier : frontend_v4/src/components/CaptureLibrary.tsx lignes 25-62

    • Stockage dans sessionStorage (clé captureLibrary_v2) → purgé à chaque fermeture d'onglet ou redémarrage du navigateur
    • Cap arbitraire à 50 captures max (slice(0, 49))
    • Les captures sont des base64 PNG → sessionStorage ne tient pas plus de quelques dizaines de Mo au total
    • C'est très probablement le bug que Dom décrit
  2. BUG — Deux composants concurrents pour la même bibliothèque

    • CaptureLibrary.tsx écrit dans sessionStorage['captureLibrary_v2']
    • CapturePanel.tsx lignes 51-62 écrit dans sessionStorage['captureLibrary'] (ancienne clé, jamais migrée à l'envers)
    • Résultat : deux listes de captures tenues en parallèle, désynchronisées, invisibles l'une pour l'autre
  3. Base fantôme vwb_v3.db

    • app.py l.47 : 'sqlite:///vwb_v3.db' en défaut
    • Si un jour .env n'est pas chargé (ex : systemd mal configuré), le VWB passe silencieusement sur l'autre BDD vide et Dom voit ses workflows disparaître
    • Dette : deux fichiers instance/ (backend/instance/ et visual_workflow_builder/instance/) créent de la confusion
  4. 404 en prod — /api/correction-packs/stats

    • Logs récents : deux 404 à chaque chargement
    • La route n'existe pas côté backend, elle est appelée par le frontend legacy (frontend/src/hooks/useCorrectionPacks.ts)
    • Dom voit sans doute des erreurs CORS/404 dans la console réseau selon quel frontend il ouvre
  5. Double logging (tous les logs en double)

    • app.py attache un handler au root logger + Flask attache le sien → chaque ligne loguée deux fois
    • Bruit dans les logs, rend le debug plus dur
  6. Confusion run.sh vs run_v4.sh

    • run.sh lance frontend legacy port 3000 (via webpack react-scripts) + app.py
    • run_v4.sh lance frontend_v4 port 3002 + app.py
    • Les deux coexistent, Dom peut cliquer sur l'un ou l'autre sans savoir
    • launch.sh mentionné dans le README n'existe pas (README obsolète)
  7. Workflow « Unnamed Workflow »

    • Les JSON Léa ont souvent "name": "Unnamed Workflow" (cf. notepad_enriched.json)
    • L'import les reprend tel quel — la liste du VWB devient illisible vite
  8. Tests d'intégration VWB datent de janvier

    • tests/integration/test_vwb_*.py : 6 fichiers
    • tests/property/test_vwb_frontend_v2_* : 14 fichiers — ciblent frontend/ (v2), pas frontend_v4/
    • Aucun test cible le pont learned_workflows → pas de garde-fou pour C2

Dette technique identifiable

  • 3 backends Flask (app.py, app_lightweight.py, app_catalogue_simple.py) pour 403 + 1451 + 1370 lignes = 3224 lignes. Un seul tourne.
  • 2 frontends (frontend/ = react-scripts v2, frontend_v4/ = Vite v4) avec duplication partielle des composants — seul le v4 est vivant
  • 2 bases SQLite nommées différemment, schéma identique
  • catalog_routes.py.backup_20260122_163105 (127 Ko) traîne dans le repo
  • Screenshots .screenshot2026-*.png (8 fichiers × ~220 Ko) traînent à la racine backend
  • Migrations Alembic présentes mais un seul fichier (001_initial_schema.py) alors que le schéma a évolué (review_status ajouté après)

Section B — Quick wins (< 1 jour chacun)

Classés par ratio impact/effort décroissant :

B1. 🔥 Migrer la bibliothèque de captures de sessionStorage vers localStorage

Effort : 30 min Impact : résout le bug principal rapporté par Dom

  • Remplacer sessionStorage.* par localStorage.* dans CaptureLibrary.tsx et CapturePanel.tsx
  • Unifier sur une seule clé captureLibrary_v3 (migration ascendante depuis les deux anciennes)
  • Augmenter le cap à 200 captures + ajouter un bouton « vider la bibliothèque »
  • Attention : localStorage plafonne ~5 Mo, les PNG base64 saturent vite — meilleure option : persister côté backend via /api/v3/capture/library (ajout d'une petite table) et ne garder que des IDs+thumbnails en localStorage

B2. 🔥 Renommer le fichier « Unnamed Workflow » à l'import

Effort : 20 min Impact : moyen (lisibilité immédiate dans la liste)

  • api_v3/learned_workflows.py l.210 : si wf_meta["name"] == "Unnamed Workflow"f"Appris {datetime:%d/%m %H:%M}"
  • Idem exposer ce nom dans WorkflowSelector.tsx ligne 120 quand on affiche la liste learned

B3. Supprimer la BDD fantôme

Effort : 15 min Impact : élimine un foot-gun discret

  • Modifier app.py l.47 : défaut 'sqlite:///workflows.db' (aligné sur .env)
  • Supprimer backend/instance/vwb_v3.db + visual_workflow_builder/instance/workflows.db (vestige)
  • Documenter dans le .env.example le chemin absolu recommandé

B4. Corriger le double logging

Effort : 15 min Impact : faible (quality-of-life debug)

  • app.py l.40 : remplacer logging.getLogger().addHandler(...) par app.logger.addHandler(...) et logging.getLogger('werkzeug').addHandler(...), puis propagate = False

B5. Supprimer le 404 /api/correction-packs/stats

Effort : 20 min Impact : faible (erreurs dans la console navigateur)

  • Option A (propre) : stubber la route dans api/correction_packs.py qui retourne {"success": true, "stats": {"total": 0}}
  • Option B : retirer l'appel côté frontend/src/hooks/useCorrectionPacks.ts ligne 229
  • Option B préférable si le frontend legacy est condamné (voir E1)

B6. Nettoyer les fichiers parasites

Effort : 10 min Impact : cosmétique + réduire la confusion

  • Supprimer backend/catalog_routes.py.backup_20260122_163105 (127 Ko)
  • Supprimer les 8 screenshots .screenshot2026-*.png à la racine backend
  • .gitignore : ajouter *.screenshot*.png, *.backup_*

B7. Clarifier run.sh

Effort : 20 min Impact : moyen (Dom et moi perdons du temps sur quel frontend lancer)

  • Renommer run.shrun_legacy.sh avec bandeau warning
  • Mettre à jour README.md du VWB pour refléter run_v4.sh comme canonique
  • Supprimer la mention launch.sh qui n'existe pas

Total Quick Wins : ~2h30 de dev pour résoudre la douleur principale + 4 dettes visibles.


Section C — Chantiers moyens (1-3 jours)

C1. Finaliser le flux « Import Léa → review VWB → replay »

Effort : 1 jour Contexte : toute la plomberie existe (backend+frontend), mais la boucle n'est pas testée end-to-end depuis le premier replay réussi du 13 avril. Actuellement source='learned_import' déclenche bien review_status='pending_review', mais :

  • Le frontend n'a pas de banner « ⚠ 2 workflows importés en attente de review » visible au démarrage (il y a bien un pendingReviewCount dans App.tsx mais je n'ai pas vérifié son affichage)
  • Quand Dom ouvre un workflow en pending_review, aucun indicateur visuel sur les étapes automatiquement générées par le bridge (ex: warning sur les compound décomposés, warning sur les by_position convertis en x_pct/y_pct)
  • Pas de bouton « rejouer le workflow tel quel sans review » pour tester vite

Actions :

  1. Vérifier l'affichage pendingReviewCount dans le header + ajouter un badge coloré
  2. Dans StepNode.tsx, afficher un ⚠️ quand step.parameters.compound_steps existe ou quand metadata.core_edge_id manque d'info
  3. Exposer les warnings retournés par l'import dans un panneau dépliant sur le workflow importé
  4. Bouton « Valider et exécuter » qui passe review_status='approved' puis lance le replay via /execute

C2. Persister la bibliothèque de captures côté serveur

Effort : 1,5 jour Contexte : extension de B1 si on veut une bibliothèque réellement persistante et partagée entre sessions/machines

  • Nouvelle table captures_library(id, screenshot_b64, timestamp, label, favorite, workflow_id NULL)
  • Endpoints GET/POST/DELETE /api/v3/captures/library
  • CaptureLibrary.tsx : fetch initial + mutations, plus de localStorage
  • Bonus : associer une capture à un step (fav pour référence future)

C3. Unifier les deux frontends — retirer frontend/ (legacy)

Effort : 2 jours (avec vérif de non-régression) Contexte : frontend/ (v2 React 19 + MUI + Redux) n'est plus maintenu, frontend_v4/ (Vite + xyflow) est la cible. 14 tests tests/property/test_vwb_frontend_v2_* pointent vers le v2.

  • Auditer ce que le v4 ne fait pas encore (CorrectionPacksDashboard, CoachingPanel, etc.) → décider si on porte ou si on abandonne
  • Archiver frontend/ dans _archives/ ou le supprimer
  • Désactiver run.sh ou le refaire pointer sur v4
  • Porter ou supprimer les tests test_vwb_frontend_v2_*

C4. Consolider les 3 app*.py

Effort : 1 jour Contexte : app.py est le seul utilisé pour le VWB. app_lightweight.py sert uniquement à l'endpoint catalogue VLM sur 5003 (un seul endpoint utile). app_catalogue_simple.py n'est plus référencé.

  • Supprimer app_catalogue_simple.py
  • Déplacer le seul endpoint utile de app_lightweight.py dans app.py + retirer le port 5003 de services.conf
  • Supprimer app_lightweight.py
  • Gain : -2800 lignes, un seul point d'entrée

C5. Lier étape VWB ↔ screenshot source du workflow Léa

Effort : 2 jours Contexte : actuellement quand on importe un workflow Léa, les steps sont des actions sans contexte visuel. Pour pouvoir « corriger visuellement » (idée Dom), il faut que chaque step affiche :

  • Le screenshot from_node (état avant l'action)
  • Le screenshot to_node (état après)
  • Les bbox cliquées (target)
  • Les workflows Léa contiennent déjà des screenshot_hash dans leurs nodes (à vérifier dans notepad_enriched.json)
  • Modifier convert_learned_to_vwb_steps pour persister les screenshots en tant que VisualAnchor + anchor_id sur le step
  • Enrichir StepNode.tsx pour afficher la vignette

Note : c'est ce qui donne du sens à l'idée de Dom. Sans ça, l'import Léa→VWB donne des étapes abstraites « click(x=42%, y=68%) » que personne ne peut corriger visuellement.


Section D — Chantiers lourds (>1 semaine)

D1. Refonte du stockage workflow : un seul format canonique

Effort : 1-2 semaines Justification : aujourd'hui on a 2 formats (core JSON de Léa vs SQLite VWB) avec un bridge. Le bridge perd de l'information (ex: compound décomposé, metadata core/screenshots abandonnés en route). À chaque nouvelle feature du core (C2 aujourd'hui, grounding, extraction, etc.) il faut mettre à jour le bridge.

Proposition : VWB stocke directement le format core JSON (ou un surset strict). Les « steps » VWB deviennent une vue dérivée du graphe core, pas une copie. Les corrections humaines modifient le JSON core.

À faire seulement si l'import Léa→VWB devient un flux majeur et que le bridge montre ses limites. Pour l'instant, le bridge fait le job.

D2. Mode collaboratif / multi-utilisateurs

Effort : 2-3 semaines Justification : aucune pour aujourd'hui. Dom est seul à utiliser le VWB. À garder dans le coin de la tête pour quand les premiers clients testeront.


Section E — Non-décisions

Choses qu'on ne fera pas, pour se prémunir des tentations.

E1. Ne PAS réécrire le frontend en v5

Pourquoi : le v4 Vite+xyflow est récent (mars 2026), propre, bien structuré. Pas de raison architecturale. La migration v3→v4 a déjà coûté cher (cf. nombreux CORRECTION_TYPESCRIPT_*.md en janvier).

E2. Ne PAS unifier instance/*.db en PostgreSQL

Pourquoi : SQLite convient pour un outil desktop mono-utilisateur. PostgreSQL ajoute une dépendance runtime sans valeur tangible tant qu'on est seul. Le .env mentionne déjà l'option, gardée pour plus tard.

E3. Ne PAS porter CorrectionPacksDashboard sur le v4

Pourquoi : la fonctionnalité « correction packs » est en doublon conceptuel avec le nouveau flux review_status + learned_workflow_bridge. Autant fermer proprement correction_packs (C4 bis) plutôt que le migrer.

E4. Ne PAS rajouter de tests property pour le v4 tout de suite

Pourquoi : 14 tests test_vwb_frontend_v2_* existent déjà et ne tournent plus (pointent vers le v2). Avant de recréer des tests property, il faut décider si on garde le v2 ou pas (C3). Refaire 14 tests pour les jeter dans 2 semaines = gâchis.

E5. Ne PAS implémenter le mode WebSocket realtime pour le VWB

Pourquoi : le polling actuel (500 ms dans App.tsx) suffit pour l'usage. WebSocket existe déjà (socketio) mais n'est câblé nulle part dans le v4. On peut l'ajouter quand une vraie feature le demande (ex: collaborative editing = E1/D2 → pas maintenant).


Section F — Recommandation d'ordre

Semaine 1 — quick wins utilisateur (jour J)

  1. B1 — localStorage pour CaptureLibrary (30 min) → résout le bug principal
  2. B2 — nom lisible à l'import (20 min) → la liste devient utilisable
  3. B3 — supprimer BDD fantôme (15 min) → évite un bug futur
  4. B6 — nettoyer les fichiers parasites (10 min) → hygiène
  5. B7 — clarifier run.sh (20 min) → moins de confusion

Total : ~2h de dev pour un retour utilisateur net dès demain.

Semaine 1 — chantier moyen utile (jours J+1 à J+3) 6. C1 — finaliser le flux « Import Léa → review → replay ». C'est la VALEUR DIRECTE de l'idée de Dom : « importer les workflows Léa pour les corriger visuellement ».

Semaine 2 — étendre la valeur (si C1 tient la route) 7. C5 — lier step ↔ screenshot source. C'est ce qui transforme le VWB en vrai outil de correction visuelle. Sans ça, l'import Léa est abstrait.

Semaine 3+ — consolidation (quand bande passante) 8. C3 — retirer frontend legacy (gain de clarté) 9. C4 — consolider les 3 app*.py (gain dette) 10. C2 — bibliothèque captures serveur (si B1 montre ses limites)

Justification globale :

  • Les 2h de quick wins donnent à Dom une expérience visible et immédiate (bibliothèque qui ne s'efface plus, liste lisible, moins de bruit).
  • C1 capitalise sur l'investissement existant (le pont Léa/VWB est déjà codé à 80%, il faut juste finir le dernier kilomètre — les warnings visuels et le bouton « valider et exécuter »).
  • C5 est le vrai game-changer pour l'idée de Dom, mais ne vaut le coup que si C1 a confirmé que le flux globalement fonctionne. Si C1 révèle que le bridge perd trop d'info, on saute direct à D1 (refonte).
  • C3/C4 sont de la dette : on s'en occupe quand on a quelqu'un sous la main pour pas ralentir les features.

À éviter : commencer par C3 ou C4 (dette) parce qu'aucun impact utilisateur visible → pas de ROI court terme.


Risques identifiés

  • Backup BDD : backend/instance/backups/ contient un seul backup du 23/01. Aucune rotation automatique. Risque de perte : 3 workflows seulement mais ce sont ceux de Dom → ajouter un backup quotidien via backup_ssd.sh (déjà existant à la racine ~/ai/).
  • localStorage quota : B1 seul ne suffira pas à long terme. Prévoir C2 si Dom fait plus de 50-100 captures en PNG base64.
  • Modèle Workflow sans cascade sur source='learned_import' : si Dom supprime un workflow importé, rien ne met à jour le JSON core sur disque → divergence. Acceptable tant que l'import est monodirectionnel (disque → VWB) mais à surveiller.

Métriques de succès

  • Bibliothèque persiste après reload navigateur : testable manuellement en 30 s
  • Liste de workflows ne contient plus « Unnamed Workflow » : testable via SQL
  • Un workflow Léa importé a un badge « à réviser » visible, et le bouton « Valider et exécuter » le fait tourner sans quitter le VWB
  • 0 warning 404 dans backend/logs/vwb.log après B5
  • run_v4.sh unique script documenté dans README