v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
399
scripts/verification_proprietes_etapes_complete_12jan2026.py
Normal file
399
scripts/verification_proprietes_etapes_complete_12jan2026.py
Normal file
@@ -0,0 +1,399 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script de Vérification Complète des Propriétés d'Étapes VWB
|
||||
Auteur : Dom, Alice, Kiro - 12 janvier 2026
|
||||
|
||||
Ce script vérifie que toutes les actions du catalogue VWB ont leurs propriétés
|
||||
correctement définies et implémentées dans le système de propriétés.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any, Set
|
||||
from datetime import datetime
|
||||
|
||||
# Ajouter le répertoire racine au path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
def analyser_catalogue_statique() -> Dict[str, Any]:
|
||||
"""
|
||||
Analyse le catalogue statique pour extraire toutes les actions et leurs paramètres.
|
||||
|
||||
Returns:
|
||||
Dictionnaire avec les actions et leurs configurations
|
||||
"""
|
||||
print("📋 Analyse du catalogue statique...")
|
||||
|
||||
# Lire le fichier TypeScript du catalogue statique
|
||||
catalogue_path = Path("visual_workflow_builder/frontend/src/data/staticCatalog.ts")
|
||||
|
||||
if not catalogue_path.exists():
|
||||
print(f"❌ Fichier catalogue non trouvé : {catalogue_path}")
|
||||
return {}
|
||||
|
||||
try:
|
||||
with open(catalogue_path, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
# Extraire les actions (analyse simple du contenu)
|
||||
actions_trouvees = {}
|
||||
|
||||
# Rechercher les définitions d'actions
|
||||
import re
|
||||
|
||||
# Pattern pour extraire les IDs d'actions
|
||||
pattern_id = r"id:\s*['\"]([^'\"]+)['\"]"
|
||||
ids = re.findall(pattern_id, contenu)
|
||||
|
||||
# Pattern pour extraire les noms d'actions
|
||||
pattern_name = r"name:\s*['\"]([^'\"]+)['\"]"
|
||||
names = re.findall(pattern_name, contenu)
|
||||
|
||||
# Pattern pour extraire les catégories
|
||||
pattern_category = r"category:\s*['\"]([^'\"]+)['\"]"
|
||||
categories = re.findall(pattern_category, contenu)
|
||||
|
||||
# Combiner les informations
|
||||
for i, action_id in enumerate(ids):
|
||||
actions_trouvees[action_id] = {
|
||||
'id': action_id,
|
||||
'name': names[i] if i < len(names) else action_id,
|
||||
'category': categories[i] if i < len(categories) else 'unknown',
|
||||
'parameters_found': True, # Présumé vrai pour le catalogue statique
|
||||
}
|
||||
|
||||
print(f"✅ {len(actions_trouvees)} actions trouvées dans le catalogue statique")
|
||||
return actions_trouvees
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors de l'analyse du catalogue : {e}")
|
||||
return {}
|
||||
|
||||
def analyser_backend_registry() -> Dict[str, Any]:
|
||||
"""
|
||||
Analyse le registry backend pour vérifier les actions disponibles.
|
||||
|
||||
Returns:
|
||||
Dictionnaire avec les actions du backend
|
||||
"""
|
||||
print("🔧 Analyse du registry backend...")
|
||||
|
||||
try:
|
||||
# Importer le registry
|
||||
from visual_workflow_builder.backend.actions.registry import get_global_registry
|
||||
|
||||
registry = get_global_registry()
|
||||
|
||||
# Obtenir les informations du registry
|
||||
info = registry.get_registry_stats()
|
||||
actions = registry.list_actions()
|
||||
|
||||
actions_backend = {}
|
||||
for action_id in actions:
|
||||
metadata = registry.get_action_metadata(action_id)
|
||||
actions_backend[action_id] = {
|
||||
'id': action_id,
|
||||
'metadata': metadata,
|
||||
'class_available': registry.get_action_class(action_id) is not None,
|
||||
}
|
||||
|
||||
print(f"✅ {len(actions_backend)} actions trouvées dans le registry backend")
|
||||
return {
|
||||
'stats': info,
|
||||
'actions': actions_backend,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors de l'analyse du registry backend : {e}")
|
||||
return {}
|
||||
|
||||
def analyser_composants_frontend() -> Dict[str, Any]:
|
||||
"""
|
||||
Analyse les composants frontend pour vérifier l'implémentation des propriétés.
|
||||
|
||||
Returns:
|
||||
Dictionnaire avec l'état des composants frontend
|
||||
"""
|
||||
print("🎨 Analyse des composants frontend...")
|
||||
|
||||
composants_analyses = {}
|
||||
|
||||
# Analyser PropertiesPanel principal
|
||||
properties_panel_path = Path("visual_workflow_builder/frontend/src/components/PropertiesPanel/index.tsx")
|
||||
if properties_panel_path.exists():
|
||||
try:
|
||||
with open(properties_panel_path, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
composants_analyses['PropertiesPanel'] = {
|
||||
'exists': True,
|
||||
'has_step_parameters_config': 'stepParametersConfig' in contenu,
|
||||
'has_vwb_integration': 'useVWBStepIntegration' in contenu,
|
||||
'has_visual_selector': 'VisualSelector' in contenu,
|
||||
'has_variable_autocomplete': 'VariableAutocomplete' in contenu,
|
||||
'file_size': len(contenu),
|
||||
}
|
||||
except Exception as e:
|
||||
composants_analyses['PropertiesPanel'] = {'exists': True, 'error': str(e)}
|
||||
else:
|
||||
composants_analyses['PropertiesPanel'] = {'exists': False}
|
||||
|
||||
# Analyser VWBActionProperties
|
||||
vwb_properties_path = Path("visual_workflow_builder/frontend/src/components/PropertiesPanel/VWBActionProperties.tsx")
|
||||
if vwb_properties_path.exists():
|
||||
try:
|
||||
with open(vwb_properties_path, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
composants_analyses['VWBActionProperties'] = {
|
||||
'exists': True,
|
||||
'has_visual_anchor_editor': 'VisualAnchorEditor' in contenu,
|
||||
'has_parameter_validation': 'validateParameters' in contenu,
|
||||
'has_real_time_validation': 'validation' in contenu,
|
||||
'has_examples_display': 'examples' in contenu,
|
||||
'file_size': len(contenu),
|
||||
}
|
||||
except Exception as e:
|
||||
composants_analyses['VWBActionProperties'] = {'exists': True, 'error': str(e)}
|
||||
else:
|
||||
composants_analyses['VWBActionProperties'] = {'exists': False}
|
||||
|
||||
# Analyser useVWBStepIntegration hook
|
||||
hook_path = Path("visual_workflow_builder/frontend/src/hooks/useVWBStepIntegration.ts")
|
||||
if hook_path.exists():
|
||||
try:
|
||||
with open(hook_path, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
composants_analyses['useVWBStepIntegration'] = {
|
||||
'exists': True,
|
||||
'has_create_vwb_step': 'createVWBStep' in contenu,
|
||||
'has_validation': 'validateVWBStep' in contenu,
|
||||
'has_drag_drop_support': 'convertDragDataToVWBStep' in contenu,
|
||||
'file_size': len(contenu),
|
||||
}
|
||||
except Exception as e:
|
||||
composants_analyses['useVWBStepIntegration'] = {'exists': True, 'error': str(e)}
|
||||
else:
|
||||
composants_analyses['useVWBStepIntegration'] = {'exists': False}
|
||||
|
||||
print(f"✅ {len(composants_analyses)} composants analysés")
|
||||
return composants_analyses
|
||||
|
||||
def verifier_coherence_types() -> Dict[str, Any]:
|
||||
"""
|
||||
Vérifie la cohérence des types TypeScript entre les différents fichiers.
|
||||
|
||||
Returns:
|
||||
Résultats de la vérification de cohérence
|
||||
"""
|
||||
print("🔍 Vérification de la cohérence des types...")
|
||||
|
||||
coherence = {
|
||||
'catalog_types_exists': False,
|
||||
'main_types_exists': False,
|
||||
'types_coherent': False,
|
||||
'issues': [],
|
||||
}
|
||||
|
||||
# Vérifier catalog.ts
|
||||
catalog_types_path = Path("visual_workflow_builder/frontend/src/types/catalog.ts")
|
||||
if catalog_types_path.exists():
|
||||
coherence['catalog_types_exists'] = True
|
||||
try:
|
||||
with open(catalog_types_path, 'r', encoding='utf-8') as f:
|
||||
contenu = f.read()
|
||||
|
||||
# Vérifier la présence des types essentiels
|
||||
types_essentiels = [
|
||||
'VWBCatalogAction',
|
||||
'VWBActionParameter',
|
||||
'VWBVisualAnchor',
|
||||
'VWBActionValidationResult',
|
||||
]
|
||||
|
||||
for type_name in types_essentiels:
|
||||
if type_name not in contenu:
|
||||
coherence['issues'].append(f"Type manquant : {type_name}")
|
||||
|
||||
except Exception as e:
|
||||
coherence['issues'].append(f"Erreur lecture catalog.ts : {e}")
|
||||
else:
|
||||
coherence['issues'].append("Fichier catalog.ts manquant")
|
||||
|
||||
# Vérifier index.ts principal
|
||||
main_types_path = Path("visual_workflow_builder/frontend/src/types/index.ts")
|
||||
if main_types_path.exists():
|
||||
coherence['main_types_exists'] = True
|
||||
else:
|
||||
coherence['issues'].append("Fichier types/index.ts manquant")
|
||||
|
||||
coherence['types_coherent'] = len(coherence['issues']) == 0
|
||||
|
||||
print(f"✅ Vérification de cohérence terminée - {len(coherence['issues'])} problèmes trouvés")
|
||||
return coherence
|
||||
|
||||
def generer_rapport_complet() -> Dict[str, Any]:
|
||||
"""
|
||||
Génère un rapport complet de l'état des propriétés d'étapes.
|
||||
|
||||
Returns:
|
||||
Rapport complet
|
||||
"""
|
||||
print("📊 Génération du rapport complet...")
|
||||
|
||||
rapport = {
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'version': '1.0.0',
|
||||
'auteur': 'Dom, Alice, Kiro',
|
||||
'catalogue_statique': analyser_catalogue_statique(),
|
||||
'backend_registry': analyser_backend_registry(),
|
||||
'composants_frontend': analyser_composants_frontend(),
|
||||
'coherence_types': verifier_coherence_types(),
|
||||
}
|
||||
|
||||
# Calculer des métriques globales
|
||||
catalogue_actions = rapport['catalogue_statique']
|
||||
backend_actions = rapport['backend_registry'].get('actions', {})
|
||||
|
||||
rapport['metriques'] = {
|
||||
'total_actions_catalogue': len(catalogue_actions),
|
||||
'total_actions_backend': len(backend_actions),
|
||||
'actions_communes': len(set(catalogue_actions.keys()) & set(backend_actions.keys())),
|
||||
'actions_catalogue_seulement': list(set(catalogue_actions.keys()) - set(backend_actions.keys())),
|
||||
'actions_backend_seulement': list(set(backend_actions.keys()) - set(catalogue_actions.keys())),
|
||||
}
|
||||
|
||||
# Évaluer l'état global
|
||||
composants = rapport['composants_frontend']
|
||||
coherence = rapport['coherence_types']
|
||||
|
||||
rapport['etat_global'] = {
|
||||
'properties_panel_ok': composants.get('PropertiesPanel', {}).get('exists', False),
|
||||
'vwb_properties_ok': composants.get('VWBActionProperties', {}).get('exists', False),
|
||||
'integration_hook_ok': composants.get('useVWBStepIntegration', {}).get('exists', False),
|
||||
'types_coherents': coherence.get('types_coherent', False),
|
||||
'pret_pour_production': False, # Sera calculé
|
||||
}
|
||||
|
||||
# Calculer si prêt pour production
|
||||
etat = rapport['etat_global']
|
||||
etat['pret_pour_production'] = all([
|
||||
etat['properties_panel_ok'],
|
||||
etat['vwb_properties_ok'],
|
||||
etat['integration_hook_ok'],
|
||||
etat['types_coherents'],
|
||||
rapport['metriques']['total_actions_catalogue'] > 0,
|
||||
])
|
||||
|
||||
return rapport
|
||||
|
||||
def sauvegarder_rapport(rapport: Dict[str, Any]) -> str:
|
||||
"""
|
||||
Sauvegarde le rapport dans un fichier JSON.
|
||||
|
||||
Args:
|
||||
rapport: Rapport à sauvegarder
|
||||
|
||||
Returns:
|
||||
Chemin du fichier sauvegardé
|
||||
"""
|
||||
# Créer le répertoire docs s'il n'existe pas
|
||||
docs_dir = Path("docs")
|
||||
docs_dir.mkdir(exist_ok=True)
|
||||
|
||||
# Nom du fichier avec timestamp
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
fichier_rapport = docs_dir / f"rapport_verification_proprietes_etapes_{timestamp}.json"
|
||||
|
||||
try:
|
||||
with open(fichier_rapport, 'w', encoding='utf-8') as f:
|
||||
json.dump(rapport, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"✅ Rapport sauvegardé : {fichier_rapport}")
|
||||
return str(fichier_rapport)
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur sauvegarde rapport : {e}")
|
||||
return ""
|
||||
|
||||
def afficher_resume(rapport: Dict[str, Any]):
|
||||
"""
|
||||
Affiche un résumé du rapport.
|
||||
|
||||
Args:
|
||||
rapport: Rapport à résumer
|
||||
"""
|
||||
print("\n" + "="*60)
|
||||
print("📋 RÉSUMÉ DE LA VÉRIFICATION DES PROPRIÉTÉS D'ÉTAPES")
|
||||
print("="*60)
|
||||
|
||||
metriques = rapport['metriques']
|
||||
etat = rapport['etat_global']
|
||||
|
||||
print(f"📊 Actions catalogue : {metriques['total_actions_catalogue']}")
|
||||
print(f"🔧 Actions backend : {metriques['total_actions_backend']}")
|
||||
print(f"🤝 Actions communes : {metriques['actions_communes']}")
|
||||
|
||||
print(f"\n🎨 Composants Frontend :")
|
||||
print(f" - PropertiesPanel : {'✅' if etat['properties_panel_ok'] else '❌'}")
|
||||
print(f" - VWBActionProperties : {'✅' if etat['vwb_properties_ok'] else '❌'}")
|
||||
print(f" - useVWBStepIntegration : {'✅' if etat['integration_hook_ok'] else '❌'}")
|
||||
|
||||
print(f"\n🔍 Types TypeScript : {'✅' if etat['types_coherents'] else '❌'}")
|
||||
|
||||
print(f"\n🚀 Prêt pour production : {'✅' if etat['pret_pour_production'] else '❌'}")
|
||||
|
||||
# Afficher les problèmes s'il y en a
|
||||
coherence = rapport['coherence_types']
|
||||
if coherence.get('issues'):
|
||||
print(f"\n⚠️ Problèmes détectés :")
|
||||
for issue in coherence['issues']:
|
||||
print(f" - {issue}")
|
||||
|
||||
# Afficher les actions manquantes
|
||||
if metriques['actions_catalogue_seulement']:
|
||||
print(f"\n📋 Actions catalogue non implémentées backend :")
|
||||
for action in metriques['actions_catalogue_seulement']:
|
||||
print(f" - {action}")
|
||||
|
||||
if metriques['actions_backend_seulement']:
|
||||
print(f"\n🔧 Actions backend non référencées catalogue :")
|
||||
for action in metriques['actions_backend_seulement']:
|
||||
print(f" - {action}")
|
||||
|
||||
def main():
|
||||
"""Fonction principale du script."""
|
||||
print("🔍 Vérification Complète des Propriétés d'Étapes VWB")
|
||||
print("Auteur : Dom, Alice, Kiro - 12 janvier 2026")
|
||||
print("-" * 60)
|
||||
|
||||
try:
|
||||
# Générer le rapport complet
|
||||
rapport = generer_rapport_complet()
|
||||
|
||||
# Sauvegarder le rapport
|
||||
fichier_rapport = sauvegarder_rapport(rapport)
|
||||
|
||||
# Afficher le résumé
|
||||
afficher_resume(rapport)
|
||||
|
||||
# Déterminer le code de sortie
|
||||
if rapport['etat_global']['pret_pour_production']:
|
||||
print(f"\n✅ Système prêt - Toutes les propriétés d'étapes sont correctement implémentées")
|
||||
return 0
|
||||
else:
|
||||
print(f"\n⚠️ Système nécessite des améliorations - Voir le rapport : {fichier_rapport}")
|
||||
return 1
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors de la vérification : {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return 2
|
||||
|
||||
if __name__ == "__main__":
|
||||
exit_code = main()
|
||||
sys.exit(exit_code)
|
||||
Reference in New Issue
Block a user