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>
18 KiB
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 5002 →
backend/app.py(Flask complet, blueprints v3, SQLAlchemy) — c'est celui qui sert le VWB - Backend 5003 →
backend/app_lightweight.py(serveur HTTP natif fallback, 1451 lignes, mode quasi-inutile aujourd'hui) - Frontend 3002 →
frontend_v4/(Vite + React 18,@xyflow/react, TypeScript) — actif - BDD utilisée →
backend/instance/workflows.db(via.env DATABASE_URL=sqlite:///workflows.db) — 3 workflows dedans (« Classement de dossier », « bloc notes », « Onlyoffice »), toussource='manual', aucunreview_status - BDD fantôme →
backend/instance/vwb_v3.db(schema identique, 0 workflows) — zombie deapp.pyligne 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.tsexposegetLearnedWorkflows,importLearnedWorkflow,exportForLea;components/WorkflowSelector.tsxcharge et propose d'importer les workflows non-importés - Endpoints fonctionnels : logs du 15 avril montrent
GET /api/v3/learned-workflows?os=linux → 200
- Backend :
- Système de review : composants
ReviewModal.tsx,WorkflowValidation.tsx,WorkflowManagerModal.tsx+ backendapi_v3/review.pyprêt. Un workflow importé arrive enreview_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
-
BUG CRITIQUE — Bibliothèque de captures qui s'efface Fichier :
frontend_v4/src/components/CaptureLibrary.tsxlignes 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
- Stockage dans
-
BUG — Deux composants concurrents pour la même bibliothèque
CaptureLibrary.tsxécrit danssessionStorage['captureLibrary_v2']CapturePanel.tsxlignes 51-62 écrit danssessionStorage['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
-
Base fantôme
vwb_v3.dbapp.pyl.47 :'sqlite:///vwb_v3.db'en défaut- Si un jour
.envn'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/etvisual_workflow_builder/instance/) créent de la confusion
-
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
-
Double logging (tous les logs en double)
app.pyattache un handler au root logger + Flask attache le sien → chaque ligne loguée deux fois- Bruit dans les logs, rend le debug plus dur
-
Confusion run.sh vs run_v4.sh
run.shlance frontend legacy port 3000 (via webpack react-scripts) + app.pyrun_v4.shlance frontend_v4 port 3002 + app.py- Les deux coexistent, Dom peut cliquer sur l'un ou l'autre sans savoir
launch.shmentionné dans le README n'existe pas (README obsolète)
-
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
- Les JSON Léa ont souvent
-
Tests d'intégration VWB datent de janvier
tests/integration/test_vwb_*.py: 6 fichierstests/property/test_vwb_frontend_v2_*: 14 fichiers — ciblentfrontend/(v2), pasfrontend_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_statusajouté 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.*parlocalStorage.*dansCaptureLibrary.tsxetCapturePanel.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 :
localStorageplafonne ~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.pyl.210 : siwf_meta["name"] == "Unnamed Workflow"→f"Appris {datetime:%d/%m %H:%M}"- Idem exposer ce nom dans
WorkflowSelector.tsxligne 120 quand on affiche la liste learned
B3. Supprimer la BDD fantôme
Effort : 15 min Impact : élimine un foot-gun discret
- Modifier
app.pyl.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.examplele chemin absolu recommandé
B4. Corriger le double logging
Effort : 15 min Impact : faible (quality-of-life debug)
app.pyl.40 : remplacerlogging.getLogger().addHandler(...)parapp.logger.addHandler(...)etlogging.getLogger('werkzeug').addHandler(...), puispropagate = 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.pyqui retourne{"success": true, "stats": {"total": 0}} - Option B : retirer l'appel côté
frontend/src/hooks/useCorrectionPacks.tsligne 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.sh→run_legacy.shavec bandeau warning - Mettre à jour
README.mddu VWB pour refléterrun_v4.shcomme canonique - Supprimer la mention
launch.shqui 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
pendingReviewCountdansApp.tsxmais 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 lescompounddécomposés, warning sur lesby_positionconvertis enx_pct/y_pct) - Pas de bouton « rejouer le workflow tel quel sans review » pour tester vite
Actions :
- Vérifier l'affichage
pendingReviewCountdans le header + ajouter un badge coloré - Dans
StepNode.tsx, afficher un ⚠️ quandstep.parameters.compound_stepsexiste ou quandmetadata.core_edge_idmanque d'info - Exposer les
warningsretournés par l'import dans un panneau dépliant sur le workflow importé - 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.shou 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.pydansapp.py+ retirer le port 5003 deservices.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_hashdans leurs nodes (à vérifier dansnotepad_enriched.json) - Modifier
convert_learned_to_vwb_stepspour persister les screenshots en tant queVisualAnchor+anchor_idsur le step - Enrichir
StepNode.tsxpour 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)
- B1 — localStorage pour CaptureLibrary (30 min) → résout le bug principal
- B2 — nom lisible à l'import (20 min) → la liste devient utilisable
- B3 — supprimer BDD fantôme (15 min) → évite un bug futur
- B6 — nettoyer les fichiers parasites (10 min) → hygiène
- 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 viabackup_ssd.sh(déjà existant à la racine~/ai/). localStoragequota : B1 seul ne suffira pas à long terme. Prévoir C2 si Dom fait plus de 50-100 captures en PNG base64.- Modèle
Workflowsans 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.logaprès B5 run_v4.shunique script documenté dans README