# Design Document - Intégration ActionExecutor/WorkflowPipeline ## Vue d'Ensemble Ce document spécifie le design pour l'intégration complète entre ActionExecutor et WorkflowPipeline dans RPA Vision V3. Cette intégration établit le pipeline d'exécution automatique des workflows, connectant la résolution d'état avec l'exécution d'actions physiques tout en préservant la robustesse et les performances du système. ## Architecture L'architecture d'intégration suit un modèle de **pipeline d'exécution unifié** qui orchestre tous les composants nécessaires : ``` ┌─────────────────────────────────────────────────────────────────┐ │ Architecture d'Intégration ActionExecutor │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │ │ │ WorkflowPipeline│ │ ExecutionEngine │ │ActionExecutor│ │ │ │ Enhanced │ │ Orchestrator │ │ Enhanced │ │ │ │ │ │ │ │ │ │ │ │ • State Match │◄──►│ • Context Mgmt │◄──►│ • Target │ │ │ │ • Action Plan │ │ • Error Recovery│ │ Resolution│ │ │ │ • Flow Control │ │ • Metrics │ │ • Physical │ │ │ │ • Learning │ │ • Audit Trail │ │ Execution │ │ │ └─────────────────┘ └─────────────────┘ └─────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │ │ │ ExecutionContext│ │ PerformanceOpt │ │ LearningInt │ │ │ │ Manager │ │ Engine │ │ egration │ │ │ │ │ │ │ │ │ │ │ │ • State Tracking│ │ • Cache Mgmt │ │ • Pattern │ │ │ │ • Variable Mgmt │ │ • Resource Opt │ │ Learning │ │ │ │ • History │ │ • Priority Mgmt │ │ • Model │ │ │ │ • Validation │ │ • Adaptive Exec │ │ Update │ │ │ └─────────────────┘ └─────────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ## Composants et Interfaces ### 1. ExecutionEngine - Orchestrateur Central Le cœur de l'intégration qui coordonne tous les composants : ```python class ExecutionEngine: def __init__(self, workflow_pipeline: WorkflowPipeline, action_executor: ActionExecutor, target_resolver: TargetResolver, context_manager: ExecutionContextManager, performance_optimizer: PerformanceOptimizer, learning_integration: LearningIntegration): self.workflow_pipeline = workflow_pipeline self.action_executor = action_executor self.target_resolver = target_resolver self.context_manager = context_manager self.performance_optimizer = performance_optimizer self.learning_integration = learning_integration def execute_workflow_step(self, workflow_id: str, current_state: ScreenState) -> StepExecutionResult: """ Exécute une étape complète de workflow avec intégration totale Pipeline d'exécution: 1. Préparer le contexte d'exécution 2. Matcher l'état actuel avec le workflow 3. Planifier la prochaine action 4. Résoudre la cible si nécessaire 5. Exécuter l'action physique 6. Capturer les résultats et métriques 7. Mettre à jour le contexte et l'apprentissage 8. Gérer les erreurs et récupérations """ execution_id = str(uuid.uuid4()) try: # 1. Préparer le contexte context = self.context_manager.prepare_execution_context( workflow_id, current_state, execution_id ) # 2. Matcher l'état match_result = self.workflow_pipeline.match_current_state( current_state, context ) if not match_result: return StepExecutionResult.no_match(execution_id, context) # 3. Planifier l'action action_plan = self.workflow_pipeline.get_next_action( workflow_id, match_result.node_id, context ) if not action_plan: return StepExecutionResult.workflow_complete(execution_id, context) # 4. Optimiser l'exécution optimized_plan = self.performance_optimizer.optimize_execution( action_plan, current_state, context ) # 5. Exécuter avec intégration complète execution_result = self._execute_action_integrated( optimized_plan, current_state, context ) # 6. Post-traitement final_result = self._post_process_execution( execution_result, context, match_result ) return final_result except Exception as e: return self._handle_execution_error(e, context, execution_id) def _execute_action_integrated(self, action_plan: ActionPlan, current_state: ScreenState, context: ExecutionContext) -> ActionExecutionResult: """Exécution intégrée avec résolution de cible et métriques""" start_time = time.time() # Résolution de cible si nécessaire if action_plan.requires_target_resolution: target_result = self.target_resolver.resolve_target( action_plan.target_spec, current_state.ui_elements ) if not target_result: raise TargetResolutionError( f"Cannot resolve target for action {action_plan.action_type}" ) context.resolved_target = target_result # Exécution physique action_result = self.action_executor.execute_action( action_plan.action, current_state, context ) # Capture des métriques execution_time = time.time() - start_time context.add_metric('execution_time', execution_time) context.add_metric('target_resolution_time', getattr(context.resolved_target, 'resolution_time', 0)) return ActionExecutionResult( success=action_result.success, action_plan=action_plan, action_result=action_result, context=context, execution_time=execution_time ) ``` ### 2. ExecutionContextManager - Gestion du Contexte Gère le contexte riche d'exécution avec état, variables et historique : ```python class ExecutionContextManager: def __init__(self): self.context_cache = {} self.variable_manager = VariableManager() self.history_tracker = ExecutionHistoryTracker() def prepare_execution_context(self, workflow_id: str, current_state: ScreenState, execution_id: str) -> ExecutionContext: """ Prépare un contexte d'exécution complet Composants du contexte: - État actuel de l'écran - Variables du workflow - Historique des actions - Métriques de performance - Métadonnées d'audit """ # Récupérer ou créer le contexte du workflow workflow_context = self.context_cache.get(workflow_id) if not workflow_context: workflow_context = self._create_workflow_context(workflow_id) self.context_cache[workflow_id] = workflow_context # Créer le contexte d'exécution execution_context = ExecutionContext( execution_id=execution_id, workflow_id=workflow_id, current_state=current_state, variables=self.variable_manager.get_variables(workflow_id), history=self.history_tracker.get_recent_history(workflow_id, limit=10), workflow_context=workflow_context, created_at=datetime.now(), metrics={} ) # Validation du contexte self._validate_context_integrity(execution_context) return execution_context def update_context_after_execution(self, context: ExecutionContext, execution_result: ActionExecutionResult) -> None: """Met à jour le contexte après exécution""" # Mettre à jour les variables si modifiées if execution_result.variable_changes: self.variable_manager.update_variables( context.workflow_id, execution_result.variable_changes ) context.variables.update(execution_result.variable_changes) # Ajouter à l'historique self.history_tracker.add_execution( context.workflow_id, execution_result ) # Mettre à jour les métriques context.metrics.update(execution_result.metrics) # Validation post-exécution self._validate_context_integrity(context) def _validate_context_integrity(self, context: ExecutionContext) -> None: """Valide l'intégrité du contexte et corrige les incohérences""" # Vérifier la cohérence des variables if not self.variable_manager.validate_variables(context.variables): logger.warning(f"Variable inconsistency detected in {context.execution_id}") context.variables = self.variable_manager.repair_variables( context.workflow_id, context.variables ) # Vérifier la cohérence de l'état if not self._validate_state_consistency(context.current_state): logger.warning(f"State inconsistency detected in {context.execution_id}") context.add_flag('state_inconsistency_detected') # Vérifier l'historique if not self.history_tracker.validate_history_sequence(context.history): logger.warning(f"History inconsistency detected in {context.execution_id}") context.history = self.history_tracker.repair_history( context.workflow_id ) @dataclass class ExecutionContext: """Contexte riche d'exécution""" execution_id: str workflow_id: str current_state: ScreenState variables: Dict[str, Any] history: List[ActionExecutionResult] workflow_context: Dict[str, Any] created_at: datetime metrics: Dict[str, float] resolved_target: Optional[ResolvedTarget] = None flags: Set[str] = field(default_factory=set) def add_metric(self, name: str, value: float) -> None: self.metrics[name] = value def add_flag(self, flag: str) -> None: self.flags.add(flag) def has_flag(self, flag: str) -> bool: return flag in self.flags ``` ### 3. RobustnessEngine - Gestion d'Erreurs et Récupération Système robuste de gestion d'erreurs avec stratégies de récupération : ```python class RobustnessEngine: def __init__(self): self.recovery_strategies = { TargetNotFoundError: [ SpatialFallbackStrategy(), SemanticVariantStrategy(), UIRefreshStrategy() ], ActionExecutionError: [ RetryWithDelayStrategy(), AlternativeActionStrategy(), ContextResetStrategy() ], InterfaceChangedError: [ DynamicAdaptationStrategy(), RelearningStrategy(), FallbackModeStrategy() ] } def handle_execution_error(self, error: Exception, context: ExecutionContext, action_plan: ActionPlan) -> RecoveryResult: """ Gère les erreurs d'exécution avec récupération intelligente Processus de récupération: 1. Classifier l'erreur 2. Sélectionner les stratégies appropriées 3. Appliquer les stratégies en séquence 4. Évaluer le succès de la récupération 5. Logger pour l'apprentissage """ error_type = type(error) strategies = self.recovery_strategies.get(error_type, []) recovery_attempts = [] for strategy in strategies: try: recovery_result = strategy.attempt_recovery( error, context, action_plan ) recovery_attempts.append(recovery_result) if recovery_result.success: self._log_successful_recovery( error, strategy, recovery_result, context ) return RecoveryResult.success( strategy=strategy, result=recovery_result, attempts=recovery_attempts ) except Exception as recovery_error: recovery_attempts.append(RecoveryAttempt.failed( strategy=strategy, error=recovery_error )) # Toutes les récupérations ont échoué return RecoveryResult.escalate( original_error=error, recovery_attempts=recovery_attempts, context=context ) def adapt_to_interface_change(self, old_state: ScreenState, new_state: ScreenState, context: ExecutionContext) -> AdaptationResult: """Adaptation dynamique aux changements d'interface""" # Analyser les changements changes = self._analyze_interface_changes(old_state, new_state) # Adapter le contexte adapted_context = self._adapt_context_to_changes(context, changes) # Mettre à jour les stratégies de résolution updated_strategies = self._update_resolution_strategies(changes) return AdaptationResult( adapted_context=adapted_context, updated_strategies=updated_strategies, change_summary=changes ) class SpatialFallbackStrategy(RecoveryStrategy): def attempt_recovery(self, error: TargetNotFoundError, context: ExecutionContext, action_plan: ActionPlan) -> RecoveryAttempt: """Récupération par fallback spatial""" # Essayer des critères spatiaux alternatifs alternative_specs = self._generate_spatial_alternatives( action_plan.target_spec ) for alt_spec in alternative_specs: target_result = context.target_resolver.resolve_target( alt_spec, context.current_state.ui_elements ) if target_result: return RecoveryAttempt.success( strategy="spatial_fallback", recovered_target=target_result, alternative_spec=alt_spec ) return RecoveryAttempt.failed( strategy="spatial_fallback", reason="No spatial alternatives found" ) ``` ### 4. PerformanceOptimizer - Optimisation des Performances Optimisation intelligente des performances avec cache et priorisation : ```python class PerformanceOptimizer: def __init__(self): self.interface_analysis_cache = LRUCache(maxsize=100) self.action_execution_cache = LRUCache(maxsize=50) self.roi_priority_manager = ROIPriorityManager() def optimize_execution(self, action_plan: ActionPlan, current_state: ScreenState, context: ExecutionContext) -> OptimizedActionPlan: """ Optimise l'exécution d'une action Optimisations: - Réutilisation des analyses d'interface - Cache des résolutions similaires - Priorisation des zones d'intérêt - Adaptation aux ressources disponibles """ # Vérifier le cache pour des actions similaires cache_key = self._compute_action_cache_key(action_plan, current_state) cached_result = self.action_execution_cache.get(cache_key) if cached_result and self._is_cache_valid(cached_result, current_state): return OptimizedActionPlan.from_cache(cached_result, action_plan) # Optimiser l'analyse d'interface optimized_analysis = self._optimize_interface_analysis( current_state, action_plan.target_spec ) # Prioriser les zones d'intérêt prioritized_regions = self.roi_priority_manager.prioritize_regions( current_state, action_plan ) # Adapter aux ressources disponibles resource_adapted_plan = self._adapt_to_resources( action_plan, context.get_available_resources() ) optimized_plan = OptimizedActionPlan( original_plan=action_plan, optimized_analysis=optimized_analysis, prioritized_regions=prioritized_regions, resource_adaptations=resource_adapted_plan, cache_key=cache_key ) # Mettre en cache pour les futures utilisations self.action_execution_cache.put(cache_key, optimized_plan) return optimized_plan def _optimize_interface_analysis(self, current_state: ScreenState, target_spec: TargetSpec) -> OptimizedAnalysis: """Optimise l'analyse d'interface avec réutilisation""" state_signature = self._compute_state_signature(current_state) # Vérifier le cache d'analyse cached_analysis = self.interface_analysis_cache.get(state_signature) if cached_analysis: return cached_analysis.adapt_for_target(target_spec) # Nouvelle analyse optimisée analysis = InterfaceAnalyzer.analyze_optimized( current_state, target_spec ) self.interface_analysis_cache.put(state_signature, analysis) return analysis def _adapt_to_resources(self, action_plan: ActionPlan, available_resources: ResourceInfo) -> ResourceAdaptedPlan: """Adapte le plan aux ressources disponibles""" if available_resources.memory_pressure > 0.8: # Réduire la complexité de l'analyse return action_plan.with_reduced_complexity() if available_resources.cpu_usage > 0.9: # Utiliser des stratégies moins intensives return action_plan.with_lightweight_strategies() if available_resources.gpu_available: # Utiliser l'accélération GPU si disponible return action_plan.with_gpu_acceleration() return action_plan # Pas d'adaptation nécessaire ``` ## Modèles de Données ### StepExecutionResult Complet ```python @dataclass class StepExecutionResult: """Résultat complet d'exécution d'étape""" execution_id: str workflow_id: str success: bool step_type: str # Résultats d'exécution action_executed: Optional[ActionPlan] = None target_resolved: Optional[ResolvedTarget] = None action_result: Optional[ActionResult] = None # Contexte et état execution_context: Optional[ExecutionContext] = None state_before: Optional[ScreenState] = None state_after: Optional[ScreenState] = None # Gestion d'erreurs error: Optional[Exception] = None recovery_applied: Optional[RecoveryResult] = None # Métriques et performance performance_metrics: Dict[str, float] = field(default_factory=dict) execution_time: float = 0.0 # Apprentissage et audit learning_data: Dict[str, Any] = field(default_factory=dict) audit_trail: List[AuditEntry] = field(default_factory=list) # Métadonnées created_at: datetime = field(default_factory=datetime.now) correlation_id: str = field(default_factory=lambda: str(uuid.uuid4())) @classmethod def success(cls, execution_id: str, workflow_id: str, action_result: ActionExecutionResult, context: ExecutionContext) -> 'StepExecutionResult': return cls( execution_id=execution_id, workflow_id=workflow_id, success=True, step_type="action_execution", action_executed=action_result.action_plan, target_resolved=context.resolved_target, action_result=action_result.action_result, execution_context=context, performance_metrics=action_result.metrics, execution_time=action_result.execution_time ) @classmethod def no_match(cls, execution_id: str, context: ExecutionContext) -> 'StepExecutionResult': return cls( execution_id=execution_id, workflow_id=context.workflow_id, success=False, step_type="state_matching", execution_context=context, audit_trail=[AuditEntry.no_match(context.current_state)] ) ``` ## Propriétés de Correction *Une propriété est une caractéristique ou un comportement qui doit être vrai dans toutes les exécutions valides d'un système - essentiellement, une déclaration formelle sur ce que le système doit faire. Les propriétés servent de pont entre les spécifications lisibles par l'homme et les garanties de correction vérifiables par machine.* ### Propriété 1: Intégration WorkflowPipeline-ActionExecutor *Pour toute* action identifiée par WorkflowPipeline, ActionExecutor doit être utilisé pour l'exécution **Valide: Exigences 1.1, 1.2** ### Propriété 2: Ordre de résolution de cible *Pour toute* action nécessitant une résolution de cible, TargetResolver doit être appelé avant ActionExecutor **Valide: Exigences 1.2** ### Propriété 3: Capture complète des résultats *Pour toute* exécution d'action complétée, le résultat doit contenir toutes les métadonnées requises **Valide: Exigences 1.3** ### Propriété 4: Gestion des échecs d'action *Pour tout* échec d'action, les stratégies de récupération appropriées doivent être appliquées **Valide: Exigences 1.4, 3.1** ### Propriété 5: Progression automatique du workflow *Pour tout* workflow en cours, les étapes doivent s'enchaîner automatiquement après succès **Valide: Exigences 1.5** ### Propriété 6: Contexte d'écran disponible *Pour toute* action exécutée, l'état actuel de l'écran doit être disponible dans le contexte **Valide: Exigences 2.1** ### Propriété 7: Accès aux variables du workflow *Pour toute* action nécessitant des variables, elles doivent être accessibles dans le contexte **Valide: Exigences 2.2** ### Propriété 8: Historique des actions maintenu *Pour toute* exécution d'action, l'historique des actions précédentes doit être disponible **Valide: Exigences 2.3** ### Propriété 9: Mise à jour du contexte *Pour toute* action modifiant l'état, le contexte doit être mis à jour pour les actions suivantes **Valide: Exigences 2.4** ### Propriété 10: Détection d'incohérences du contexte *Pour tout* contexte corrompu détecté, des corrections doivent être appliquées automatiquement **Valide: Exigences 2.5** ### Propriété 11: Récupération automatique des échecs temporaires *Pour tout* échec temporaire d'action, une tentative de récupération automatique doit être effectuée **Valide: Exigences 3.1** ### Propriété 12: Stratégies alternatives de résolution *Pour tout* échec de résolution de cible, des stratégies alternatives doivent être tentées **Valide: Exigences 3.2** ### Propriété 13: Adaptation dynamique aux changements d'interface *Pour tout* changement d'interface détecté, le système doit s'adapter dynamiquement **Valide: Exigences 3.3** ### Propriété 14: Escalade avec contexte complet *Pour tout* échec de récupération, l'escalade doit inclure le contexte complet **Valide: Exigences 3.4** ### Propriété 15: Logging des récupérations réussies *Pour toute* récupération réussie, elle doit être loggée pour l'apprentissage **Valide: Exigences 3.5** ### Propriété 16: Mesure du temps de résolution *Pour toute* action exécutée, le temps de résolution de cible doit être mesuré **Valide: Exigences 4.1** ### Propriété 17: Mesure du temps d'exécution *Pour toute* action exécutée, le temps d'exécution physique doit être mesuré **Valide: Exigences 4.2** ### Propriété 18: Calcul des métriques de succès *Pour toute* étape de workflow complétée, les métriques de succès doivent être calculées **Valide: Exigences 4.3** ### Propriété 19: Enregistrement des métriques d'échec *Pour toute* erreur survenant, les métriques d'échec et de récupération doivent être enregistrées **Valide: Exigences 4.4** ### Propriété 20: Rapport de performance complet *Pour tout* workflow terminé, un rapport de performance complet doit être fourni **Valide: Exigences 4.5** ### Propriété 21: Enregistrement des paramètres de succès *Pour toute* action exécutée avec succès, les paramètres de succès doivent être enregistrés pour l'apprentissage **Valide: Exigences 5.1** ### Propriété 22: Renforcement des patterns de matching *Pour toute* résolution de cible réussie, les patterns de matching doivent être renforcés **Valide: Exigences 5.2** ### Propriété 23: Apprentissage à partir des récupérations *Pour toute* action échouant puis réussissant après récupération, la récupération doit être apprise **Valide: Exigences 5.3** ### Propriété 24: Adaptation des modèles aux évolutions d'interface *Pour toute* évolution d'interface détectée, les modèles de reconnaissance doivent être adaptés **Valide: Exigences 5.4** ### Propriété 25: Optimisation basée sur les patterns récurrents *Pour tout* pattern récurrent détecté, les stratégies de résolution doivent être optimisées **Valide: Exigences 5.5** ### Propriété 26: Création d'enregistrements d'audit *Pour toute* étape de workflow commençant, un enregistrement d'audit détaillé doit être créé **Valide: Exigences 6.1** ### Propriété 27: Enregistrement complet des actions *Pour toute* action exécutée, tous les paramètres et résultats doivent être enregistrés **Valide: Exigences 6.2** ### Propriété 28: Documentation du raisonnement *Pour toute* décision prise par le système, le raisonnement doit être documenté **Valide: Exigences 6.3** ### Propriété 29: Capture du contexte d'erreur *Pour toute* erreur survenant, le contexte complet doit être capturé **Valide: Exigences 6.4** ### Propriété 30: Trace complète pour audit *Pour toute* exécution terminée, une trace complète doit être fournie pour l'audit **Valide: Exigences 6.5** ### Propriété 31: Intégration de nouveaux types d'actions *Pour tout* nouveau type d'action défini, il doit pouvoir être intégré sans modification du pipeline **Valide: Exigences 7.1** ### Propriété 32: Support des stratégies personnalisées *Pour toute* stratégie de résolution personnalisée, elle doit être supportée via des plugins **Valide: Exigences 7.2** ### Propriété 33: Définition de post-conditions personnalisées *Pour toute* post-condition spécifique requise, elle doit pouvoir être définie **Valide: Exigences 7.3** ### Propriété 34: Ajout de métriques personnalisées *Pour toute* métrique personnalisée nécessaire, elle doit pouvoir être ajoutée **Valide: Exigences 7.4** ### Propriété 35: Réutilisation des analyses d'interface *Pour toute* résolution de cible multiple nécessaire, les analyses d'interface doivent être réutilisées **Valide: Exigences 8.2** ### Propriété 36: Optimisation par cache des actions similaires *Pour toute* action similaire exécutée, l'optimisation par cache doit être utilisée **Valide: Exigences 8.3** ### Propriété 37: Priorisation des zones d'intérêt *Pour toute* interface complexe, les zones d'intérêt doivent être priorisées **Valide: Exigences 8.4** ### Propriété 38: Adaptation aux ressources limitées *Pour toute* situation de ressources limitées, la stratégie d'exécution doit être adaptée **Valide: Exigences 8.5** ## Gestion d'Erreurs ### Stratégies de Récupération Spécialisées 1. **SpatialFallbackStrategy** : Utilise des critères spatiaux alternatifs 2. **SemanticVariantStrategy** : Essaie des variantes sémantiques 3. **UIRefreshStrategy** : Rafraîchit l'analyse de l'interface 4. **DynamicAdaptationStrategy** : S'adapte aux changements d'interface 5. **RelearningStrategy** : Réapprend les patterns de l'interface ### Escalade Intelligente ```python class IntelligentEscalation: def escalate_with_context(self, error: Exception, recovery_attempts: List[RecoveryAttempt], context: ExecutionContext) -> EscalationResult: """ Escalade intelligente avec contexte complet Informations d'escalade: 1. Erreur originale avec stack trace 2. Toutes les tentatives de récupération 3. Contexte d'exécution complet 4. État de l'interface au moment de l'erreur 5. Recommandations pour la résolution manuelle """ ``` ## Stratégie de Test ### Tests Unitaires - Test d'intégration ExecutionEngine avec tous les composants - Test de gestion du contexte d'exécution - Test des stratégies de récupération d'erreurs - Test des optimisations de performance - Test de l'apprentissage intégré - Test de la traçabilité et audit ### Tests de Propriétés Utilisation du framework Hypothesis avec 100+ itérations par propriété pour toutes les 38 propriétés définies. ### Tests d'Intégration - Exécution de workflows complets de bout en bout - Test de performance avec interfaces complexes - Test de robustesse avec erreurs simulées - Test d'apprentissage avec évolution d'interface - Test de charge avec exécution parallèle ### Validation de Non-Régression **Principe Critique :** L'intégration doit préserver toutes les fonctionnalités existantes de WorkflowPipeline et ActionExecutor tout en ajoutant les nouvelles capacités. ```python class IntegrationRegressionValidator: def validate_no_regression(self, before_integration: SystemState, after_integration: SystemState) -> ValidationResult: """ Valide qu'aucune régression n'a été introduite par l'intégration Vérifications: 1. Toutes les fonctionnalités WorkflowPipeline préservées 2. Toutes les fonctionnalités ActionExecutor préservées 3. Performances maintenues ou améliorées 4. Contrats d'API inchangés 5. Tests existants continuent de passer """ ```