feat: replay E2E fonctionnel — 25/25 actions, 0 retries, SomEngine via serveur

Validé sur PC Windows (DESKTOP-58D5CAC, 2560x1600) :
- 8 clics résolus visuellement (1 anchor_template, 1 som_text_match, 6 som_vlm)
- Score moyen 0.75, temps moyen 1.6s
- Texte tapé correctement (bonjour, test word, date, email)
- 0 retries, 2 actions non vérifiées (OK)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-03-31 14:04:41 +02:00
parent 5e0b53cfd1
commit a7de6a488b
79542 changed files with 6091757 additions and 1 deletions

View File

@@ -0,0 +1,646 @@
# Design Document - Corrections Critiques RPA Vision V3
## Vue d'Ensemble
Ce document spécifie le design pour corriger les problèmes critiques identifiés dans RPA Vision V3. Les corrections visent à établir l'exécution automatique des workflows, la stabilité en production, et des performances acceptables tout en préservant la qualité et la logique des fonctionnalités existantes.
## Architecture
L'architecture des corrections suit une approche de **refactoring progressif** qui préserve les fonctionnalités existantes tout en corrigeant les problèmes structurels :
```
┌─────────────────────────────────────────────────────────────────┐
│ Architecture des Corrections Critiques │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │ WorkflowPipeline│ │ ActionExecutor │ │ TargetResolver│ │
│ │ Enhanced │ │ Integration │ │ Optimized │ │
│ │ │ │ │ │ │ │
│ │ • execute_ │◄──►│ • Unified Error │◄──►│ • Spatial │ │
│ │ workflow_step │ │ Handling │ │ Index │ │
│ │ • Error Recovery│ │ • Target │ │ Cache │ │
│ │ • State Mgmt │ │ Resolution │ │ • Memory │ │
│ └─────────────────┘ └─────────────────┘ │ Mgmt │ │
│ │ │ └─────────────┘ │
│ │ │ │ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │ ErrorHandler │ │ DataContracts │ │ ConfigMgr │ │
│ │ Centralized │ │ Standardized │ │ Centralized │ │
│ │ │ │ │ │ │ │
│ │ • Recovery │ │ • BBox (x,y,w,h)│ │ • Validation│ │
│ │ Strategies │ │ • datetime │ │ • Security │ │
│ │ • Escalation │ │ • string IDs │ │ • Env Adapt │ │
│ │ • Audit Trail │ │ • Pydantic │ │ │ │
│ └─────────────────┘ └─────────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
## Composants et Interfaces
### 1. Intégration WorkflowPipeline-ActionExecutor
**Problème :** WorkflowPipeline ne utilise pas ActionExecutor pour l'exécution automatique.
**Solution :** Extension de WorkflowPipeline avec une méthode d'exécution intégrée :
```python
class WorkflowPipeline:
def __init__(self, target_resolver: TargetResolver,
action_executor: ActionExecutor,
error_handler: ErrorHandler):
self.target_resolver = target_resolver
self.action_executor = action_executor
self.error_handler = error_handler
def execute_workflow_step(self, workflow_id: str,
current_state: ScreenState) -> ExecutionResult:
"""
Exécute une étape de workflow de bout en bout
Processus:
1. Matcher l'état actuel avec le workflow
2. Obtenir la prochaine action à exécuter
3. Résoudre la cible avec TargetResolver
4. Exécuter l'action avec ActionExecutor
5. Gérer les erreurs avec ErrorHandler
6. Retourner le résultat détaillé
"""
try:
# 1. Match current state
match_result = self.match_current_state(current_state)
if not match_result:
return ExecutionResult.no_match()
# 2. Get next action
action = self.get_next_action(workflow_id, match_result.node_id)
if not action:
return ExecutionResult.workflow_complete()
# 3. Execute with integrated error handling
result = self.action_executor.execute_action(action, current_state)
return ExecutionResult.success(result, match_result)
except Exception as e:
recovery = self.error_handler.handle_error(e, {
'workflow_id': workflow_id,
'current_state': current_state,
'action': action if 'action' in locals() else None
})
if recovery.should_retry:
return self.execute_workflow_step(workflow_id, current_state)
else:
return ExecutionResult.error(e, recovery)
```
### 2. Gestion d'Erreurs Unifiée
**Problème :** Gestion d'erreurs fragmentée, ErrorHandler non utilisé partout.
**Solution :** Centralisation avec ErrorHandler et stratégies de récupération :
```python
class ErrorHandler:
def __init__(self):
self.recovery_strategies = {
TargetNotFoundError: SpatialFallbackStrategy(),
UIElementChangedError: SemanticVariantStrategy(),
NetworkError: RetryWithBackoffStrategy(),
ValidationError: DataNormalizationStrategy()
}
def handle_error(self, error: Exception, context: Dict[str, Any]) -> RecoveryResult:
"""
Gère une erreur avec stratégie de récupération appropriée
Processus:
1. Identifier le type d'erreur
2. Sélectionner la stratégie de récupération
3. Appliquer la stratégie avec le contexte
4. Logger la tentative de récupération
5. Retourner le résultat de récupération
"""
error_type = type(error)
strategy = self.recovery_strategies.get(error_type)
if not strategy:
return RecoveryResult.escalate(error, "No recovery strategy available")
try:
recovery = strategy.recover(error, context)
self._log_recovery_attempt(error, strategy, recovery, context)
return recovery
except Exception as recovery_error:
return RecoveryResult.escalate(
error,
f"Recovery failed: {recovery_error}",
original_error=error
)
# Pattern d'utilisation dans tous les composants
def risky_operation():
try:
result = perform_operation()
return result
except Exception as e:
recovery = error_handler.handle_error(e, get_context())
if recovery.should_retry:
return risky_operation() # Retry with recovery
else:
raise ProcessingError(f"Operation failed after recovery: {e}")
```
### 3. Résolution des Imports Circulaires
**Problème :** Structure d'imports complexe avec risques de circularité.
**Solution :** Refactoring avec imports lazy et interfaces abstraites :
```python
# core/models/__init__.py - Version corrigée
from typing import TYPE_CHECKING
# Imports directs pour les types de base
from .base_models import BaseModel, BBox, Timestamp
from .ui_element import UIElement
from .screen_state import ScreenState
# Imports lazy pour éviter les cycles
if TYPE_CHECKING:
from .workflow_graph import WorkflowGraph, WorkflowNode
from .resolved_target import ResolvedTarget
def get_workflow_graph():
"""Lazy import pour WorkflowGraph"""
from .workflow_graph import WorkflowGraph
return WorkflowGraph
def get_resolved_target():
"""Lazy import pour ResolvedTarget"""
from .resolved_target import ResolvedTarget
return ResolvedTarget
# Interfaces abstraites pour découpler les composants
from abc import ABC, abstractmethod
class ITargetResolver(ABC):
@abstractmethod
def resolve_target(self, target_spec: 'TargetSpec',
ui_elements: List['UIElement']) -> Optional['ResolvedTarget']:
pass
class IActionExecutor(ABC):
@abstractmethod
def execute_action(self, action: 'Action',
screen_state: 'ScreenState') -> 'ExecutionResult':
pass
```
### 4. Standardisation des Contrats de Données
**Problème :** Formats de données incohérents entre couches.
**Solution :** Standardisation avec Pydantic et utilitaires de conversion :
```python
from pydantic import BaseModel, validator, Field
from typing import Tuple, Union
from datetime import datetime
class BBox(BaseModel):
"""Bounding box standardisée au format (x, y, width, height)"""
x: int = Field(..., ge=0, description="Position X (coin supérieur gauche)")
y: int = Field(..., ge=0, description="Position Y (coin supérieur gauche)")
width: int = Field(..., gt=0, description="Largeur")
height: int = Field(..., gt=0, description="Hauteur")
@validator('*', pre=True)
def validate_positive(cls, v):
if isinstance(v, (int, float)) and v < 0:
raise ValueError("Coordinates must be non-negative")
return int(v)
def to_tuple(self) -> Tuple[int, int, int, int]:
"""Conversion vers tuple (x, y, w, h)"""
return (self.x, self.y, self.width, self.height)
@classmethod
def from_xyxy(cls, x1: int, y1: int, x2: int, y2: int) -> 'BBox':
"""Conversion depuis format (x1, y1, x2, y2)"""
return cls(
x=min(x1, x2),
y=min(y1, y2),
width=abs(x2 - x1),
height=abs(y2 - y1)
)
class UIElement(BaseModel):
"""Élément UI avec contrats de données standardisés"""
element_id: str = Field(..., description="ID unique de l'élément")
bbox: BBox = Field(..., description="Boîte englobante")
timestamp: datetime = Field(default_factory=datetime.now, description="Timestamp de création")
confidence: float = Field(default=1.0, ge=0.0, le=1.0, description="Confiance de détection")
@validator('element_id')
def validate_element_id(cls, v):
if not isinstance(v, str) or not v.strip():
raise ValueError("element_id must be a non-empty string")
return v.strip()
# Utilitaires de conversion sûrs
class DataConverter:
@staticmethod
def ensure_bbox_xywh(bbox: Union[BBox, Tuple, List, Dict]) -> BBox:
"""Assure que bbox est au format (x, y, w, h)"""
if isinstance(bbox, BBox):
return bbox
elif isinstance(bbox, (tuple, list)) and len(bbox) == 4:
return BBox(x=bbox[0], y=bbox[1], width=bbox[2], height=bbox[3])
elif isinstance(bbox, dict):
return BBox(**bbox)
else:
raise ValueError(f"Cannot convert {type(bbox)} to BBox")
@staticmethod
def ensure_datetime(timestamp: Union[datetime, str, int, float]) -> datetime:
"""Assure que timestamp est un objet datetime"""
if isinstance(timestamp, datetime):
return timestamp
elif isinstance(timestamp, str):
return datetime.fromisoformat(timestamp)
elif isinstance(timestamp, (int, float)):
return datetime.fromtimestamp(timestamp)
else:
raise ValueError(f"Cannot convert {type(timestamp)} to datetime")
```
### 5. Optimisation des Performances
**Problème :** Goulots d'étranglement dans TargetResolver et gestion des embeddings.
**Solution :** Cache intelligent et réutilisation des ressources :
```python
from functools import lru_cache
from typing import Optional, Dict, Any
import weakref
class OptimizedTargetResolver:
def __init__(self):
self._spatial_index_cache: Dict[str, Any] = {}
self._embedding_cache = weakref.WeakValueDictionary()
self._model_cache: Dict[str, Any] = {}
@lru_cache(maxsize=100)
def get_spatial_index(self, screen_signature: str) -> 'SpatialIndex':
"""Cache de l'index spatial par signature d'écran"""
if screen_signature not in self._spatial_index_cache:
self._spatial_index_cache[screen_signature] = self._build_spatial_index()
return self._spatial_index_cache[screen_signature]
def get_embedding(self, element_id: str, force_reload: bool = False) -> Optional[np.ndarray]:
"""Lazy loading des embeddings avec cache"""
if not force_reload and element_id in self._embedding_cache:
return self._embedding_cache[element_id]
embedding = self._load_embedding_from_disk(element_id)
if embedding is not None:
self._embedding_cache[element_id] = embedding
return embedding
def get_model(self, model_name: str) -> Any:
"""Cache des modèles ML chargés"""
if model_name not in self._model_cache:
self._model_cache[model_name] = self._load_model(model_name)
return self._model_cache[model_name]
def resolve_target(self, target_spec: TargetSpec,
ui_elements: List[UIElement]) -> Optional[ResolvedTarget]:
"""Résolution optimisée avec réutilisation des ressources"""
# Réutiliser l'index spatial
screen_sig = self._compute_screen_signature(ui_elements)
spatial_index = self.get_spatial_index(screen_sig)
# Éviter les calculs redondants
cache_key = self._compute_resolution_cache_key(target_spec, screen_sig)
if cache_key in self._resolution_cache:
return self._resolution_cache[cache_key]
# Résolution normale avec cache
result = self._resolve_with_cache(target_spec, ui_elements, spatial_index)
self._resolution_cache[cache_key] = result
return result
```
### 6. Gestion Mémoire Robuste
**Problème :** Fuites mémoire et consommation croissante.
**Solution :** Nettoyage automatique et limites effectives :
```python
import gc
import psutil
from threading import Timer
from typing import Dict, Any
class MemoryManager:
def __init__(self, max_memory_mb: int = 1024):
self.max_memory_mb = max_memory_mb
self.cleanup_timer: Optional[Timer] = None
self.resource_registry: Dict[str, Any] = {}
def register_resource(self, resource_id: str, resource: Any,
cleanup_func: callable = None):
"""Enregistre une ressource pour nettoyage automatique"""
self.resource_registry[resource_id] = {
'resource': resource,
'cleanup_func': cleanup_func or (lambda x: None),
'created_at': datetime.now()
}
def check_memory_usage(self) -> float:
"""Vérifie l'utilisation mémoire actuelle"""
process = psutil.Process()
memory_mb = process.memory_info().rss / 1024 / 1024
return memory_mb
def cleanup_if_needed(self):
"""Nettoyage préventif si nécessaire"""
current_memory = self.check_memory_usage()
if current_memory > self.max_memory_mb * 0.8: # 80% threshold
self._perform_cleanup()
def _perform_cleanup(self):
"""Effectue le nettoyage des ressources"""
# 1. Nettoyer les embeddings anciens
self._cleanup_old_embeddings()
# 2. Libérer les ressources GPU
self._cleanup_gpu_resources()
# 3. Vider les caches LRU
self._clear_lru_caches()
# 4. Force garbage collection
gc.collect()
def _cleanup_old_embeddings(self):
"""Nettoie les embeddings anciens"""
cutoff_time = datetime.now() - timedelta(hours=1)
to_remove = []
for resource_id, info in self.resource_registry.items():
if (info['created_at'] < cutoff_time and
'embedding' in resource_id.lower()):
info['cleanup_func'](info['resource'])
to_remove.append(resource_id)
for resource_id in to_remove:
del self.resource_registry[resource_id]
def shutdown(self):
"""Nettoyage complet à l'arrêt"""
for info in self.resource_registry.values():
try:
info['cleanup_func'](info['resource'])
except Exception as e:
logger.warning(f"Error during resource cleanup: {e}")
self.resource_registry.clear()
gc.collect()
# Cache LRU avec limite effective
class EffectiveLRUCache:
def __init__(self, maxsize: int = 128, memory_limit_mb: int = 100):
self.maxsize = maxsize
self.memory_limit_mb = memory_limit_mb
self.cache: Dict[Any, Any] = {}
self.access_order: List[Any] = []
def get(self, key: Any) -> Any:
if key in self.cache:
self.access_order.remove(key)
self.access_order.append(key)
return self.cache[key]
return None
def put(self, key: Any, value: Any):
# Vérifier les limites avant d'ajouter
self._enforce_limits()
if key in self.cache:
self.access_order.remove(key)
elif len(self.cache) >= self.maxsize:
self._evict_lru()
self.cache[key] = value
self.access_order.append(key)
def _enforce_limits(self):
"""Applique les limites de taille et mémoire"""
current_memory = self._estimate_memory_usage()
while (len(self.cache) >= self.maxsize or
current_memory > self.memory_limit_mb):
if not self.access_order:
break
self._evict_lru()
current_memory = self._estimate_memory_usage()
```
## Modèles de Données
### ExecutionResult Étendu
```python
@dataclass
class ExecutionResult:
"""Résultat d'exécution avec métadonnées complètes"""
success: bool
action_executed: Optional[str] = None
target_resolved: Optional[ResolvedTarget] = None
error: Optional[Exception] = None
recovery_applied: Optional[RecoveryResult] = None
performance_metrics: Dict[str, float] = field(default_factory=dict)
correlation_id: str = field(default_factory=lambda: str(uuid.uuid4()))
@classmethod
def success(cls, result: Any, match_result: Any) -> 'ExecutionResult':
return cls(
success=True,
action_executed=str(result.action),
target_resolved=result.target,
performance_metrics=result.metrics
)
@classmethod
def error(cls, error: Exception, recovery: RecoveryResult) -> 'ExecutionResult':
return cls(
success=False,
error=error,
recovery_applied=recovery
)
@dataclass
class RecoveryResult:
"""Résultat d'une tentative de récupération"""
should_retry: bool
strategy_used: str
recovery_data: Dict[str, Any] = field(default_factory=dict)
escalation_reason: Optional[str] = None
@classmethod
def retry(cls, strategy: str, data: Dict[str, Any] = None) -> 'RecoveryResult':
return cls(should_retry=True, strategy_used=strategy, recovery_data=data or {})
@classmethod
def escalate(cls, error: Exception, reason: str, **kwargs) -> 'RecoveryResult':
return cls(
should_retry=False,
strategy_used="escalation",
escalation_reason=reason,
recovery_data=kwargs
)
```
## 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 tout* workflow traité par WorkflowPipeline, ActionExecutor doit être utilisé pour l'exécution des actions
**Valide: Exigences 1.1, 1.2**
### Propriété 2: Gestion d'erreurs unifiée
*Pour toute* erreur survenant dans le système, ErrorHandler doit être utilisé pour appliquer une stratégie de récupération appropriée
**Valide: Exigences 2.1, 2.2**
### Propriété 3: Absence d'imports circulaires
*Pour tout* module du système, l'importation ne doit pas créer de dépendances cycliques
**Valide: Exigences 3.1, 3.3**
### Propriété 4: Cohérence des contrats de données BBox
*Pour toute* coordonnée BBox utilisée dans le système, le format doit être exclusivement (x,y,w,h)
**Valide: Exigences 4.1**
### Propriété 5: Cohérence des timestamps
*Pour tout* timestamp manipulé dans le système, il doit être un objet datetime
**Valide: Exigences 4.2**
### Propriété 6: Réutilisation de l'index spatial
*Pour toute* résolution de TargetResolver avec la même signature d'écran, l'index spatial doit être réutilisé
**Valide: Exigences 5.1**
### Propriété 7: Limites effectives des caches LRU
*Pour tout* cache LRU utilisé, les limites de taille configurées doivent être respectées
**Valide: Exigences 6.1**
### Propriété 8: Libération des ressources GPU
*Pour toute* ressource GPU allouée, elle doit être libérée après utilisation
**Valide: Exigences 6.3**
### Propriété 9: Validation des inputs de sécurité
*Pour tout* input utilisateur reçu, il doit être validé contre les injections malveillantes
**Valide: Exigences 7.2**
### Propriété 10: Interfaces abstraites pour le découplage
*Pour toute* interaction entre composants, elle doit passer par des interfaces abstraites
**Valide: Exigences 8.1**
### Propriété 11: Correlation IDs uniques
*Pour toute* opération effectuée, un correlation ID unique doit être assigné
**Valide: Exigences 9.1**
### Propriété 12: Centralisation des constantes
*Pour toute* constante nécessaire au système, elle doit être centralisée dans core/config.py
**Valide: Exigences 10.1**
## Gestion d'Erreurs
### Stratégies de Récupération
1. **SpatialFallbackStrategy** : Utilise des critères spatiaux alternatifs
2. **SemanticVariantStrategy** : Essaie des variantes sémantiques du texte
3. **RetryWithBackoffStrategy** : Retry avec délai exponentiel
4. **DataNormalizationStrategy** : Normalise et convertit les données
5. **GracefulDegradationStrategy** : Continue avec fonctionnalité réduite
### Escalade d'Erreurs
```python
class ErrorEscalation:
def escalate_error(self, error: Exception, context: Dict[str, Any],
recovery_attempts: List[RecoveryResult]) -> None:
"""
Escalade une erreur après échec des récupérations
Processus:
1. Collecter le contexte complet
2. Documenter les tentatives de récupération
3. Créer un rapport d'erreur détaillé
4. Notifier les systèmes de monitoring
5. Préserver l'état pour diagnostic
"""
```
## Stratégie de Test
### Tests Unitaires
- Test d'intégration WorkflowPipeline-ActionExecutor
- Test des stratégies de récupération d'erreurs
- Test de résolution des imports circulaires
- Test de conversion des contrats de données
- Test des optimisations de performance
- Test de gestion mémoire
### Tests de Propriétés
Utilisation du framework Hypothesis avec 100+ itérations par propriété :
- **Propriété 1** : Intégration WorkflowPipeline-ActionExecutor
- **Propriété 2** : Gestion d'erreurs unifiée
- **Propriété 3** : Absence d'imports circulaires
- **Propriété 4** : Cohérence des contrats de données BBox
- **Propriété 5** : Cohérence des timestamps
- **Propriété 6** : Réutilisation de l'index spatial
- **Propriété 7** : Limites effectives des caches LRU
- **Propriété 8** : Libération des ressources GPU
- **Propriété 9** : Validation des inputs de sécurité
- **Propriété 10** : Interfaces abstraites pour le découplage
- **Propriété 11** : Correlation IDs uniques
- **Propriété 12** : Centralisation des constantes
### Tests d'Intégration
- Exécution de bout en bout des workflows
- Test de charge avec gestion mémoire
- Test de sécurité en environnement de production
- Test de performance avec métriques détaillées
- Test de récupération d'erreurs en conditions réelles
### Validation de Non-Régression
**Principe Critique :** Chaque correction doit préserver la qualité et la logique des fonctionnalités existantes.
```python
class RegressionValidator:
def validate_no_regression(self, before_state: SystemState,
after_state: SystemState) -> ValidationResult:
"""
Valide qu'aucune régression n'a été introduite
Vérifications:
1. Toutes les fonctionnalités existantes fonctionnent
2. Les performances ne se dégradent pas
3. Les contrats d'API sont préservés
4. Les tests existants continuent de passer
5. La qualité du code est maintenue ou améliorée
"""
```

View File

@@ -0,0 +1,141 @@
# Document d'Exigences - Corrections Critiques RPA Vision V3
**Auteur :** Dom, Alice Kiro
**Date :** 20 décembre 2024
## Introduction
Ce document spécifie les exigences pour corriger les problèmes critiques identifiés lors de la revue de code complète de RPA Vision V3. Ces corrections sont essentielles pour permettre l'exécution automatique des workflows, assurer la stabilité en production, et maintenir des performances acceptables.
## Glossaire
- **ActionExecutor** : Composant responsable de l'exécution des actions dans les workflows
- **WorkflowPipeline** : Pipeline principal de traitement des workflows
- **TargetResolver** : Système de résolution des éléments cibles dans l'interface
- **ErrorHandler** : Gestionnaire centralisé des erreurs et stratégies de récupération
- **Contrats de Données** : Formats standardisés pour l'échange de données entre composants
- **Index Spatial** : Structure de données pour l'optimisation des recherches spatiales
- **Gestion Mémoire** : Système de nettoyage automatique des ressources
- **Imports Circulaires** : Dépendances cycliques entre modules Python
## Exigences
### Exigence 1
**Histoire Utilisateur :** En tant que système RPA, je veux que ActionExecutor soit intégré dans WorkflowPipeline, afin que les workflows puissent être exécutés automatiquement de bout en bout.
#### Critères d'Acceptation
1. QUAND WorkflowPipeline traite un workflow, LE Système d'Intégration DOIT utiliser ActionExecutor pour exécuter les actions
2. QUAND une action est exécutée, LE Système d'Intégration DOIT utiliser TargetResolver pour résoudre les éléments cibles
3. QUAND l'exécution d'une action échoue, LE Système d'Intégration DOIT gérer l'erreur avec ErrorHandler
4. QUAND une étape de workflow est complétée, LE Système d'Intégration DOIT retourner un ExecutionResult détaillé
5. QUAND le workflow continue, LE Système d'Intégration DOIT passer à l'étape suivante automatiquement
### Exigence 2
**Histoire Utilisateur :** En tant que développeur système, je veux une gestion d'erreurs unifiée, afin que toutes les erreurs soient traitées de manière cohérente avec des stratégies de récupération appropriées.
#### Critères d'Acceptation
1. QUAND une erreur survient dans n'importe quel composant, LE Système de Gestion d'Erreurs DOIT utiliser ErrorHandler pour la traiter
2. QUAND ErrorHandler traite une erreur, LE Système de Gestion d'Erreurs DOIT appliquer une stratégie de récupération appropriée
3. QUAND une stratégie de récupération échoue, LE Système de Gestion d'Erreurs DOIT escalader l'erreur avec le contexte complet
4. QUAND une erreur est récupérée avec succès, LE Système de Gestion d'Erreurs DOIT logger la récupération pour l'audit
5. QUAND les tentatives de récupération sont épuisées, LE Système de Gestion d'Erreurs DOIT échouer proprement avec un message détaillé
### Exigence 3
**Histoire Utilisateur :** En tant que développeur Python, je veux éliminer les imports circulaires, afin que le système puisse être importé et testé de manière fiable.
#### Critères d'Acceptation
1. QUAND le système démarre, LE Système d'Imports DOIT pouvoir importer tous les modules sans erreur circulaire
2. QUAND core/models/__init__.py est importé, LE Système d'Imports DOIT utiliser des imports lazy pour éviter les cycles
3. QUAND des composants s'importent mutuellement, LE Système d'Imports DOIT utiliser des interfaces abstraites
4. QUAND des imports optionnels sont nécessaires, LE Système d'Imports DOIT les gérer avec des try/except appropriés
5. QUAND l'ordre d'import change, LE Système d'Imports DOIT rester stable et fonctionnel
### Exigence 4
**Histoire Utilisateur :** En tant qu'utilisateur du système, je veux des contrats de données cohérents, afin que les données soient échangées de manière fiable entre tous les composants.
#### Critères d'Acceptation
1. QUAND des coordonnées BBox sont utilisées, LE Système de Contrats DOIT utiliser exclusivement le format (x,y,w,h)
2. QUAND des timestamps sont manipulés, LE Système de Contrats DOIT utiliser exclusivement des objets datetime
3. QUAND des IDs sont assignés, LE Système de Contrats DOIT utiliser exclusivement des strings
4. QUAND des données sont validées, LE Système de Contrats DOIT utiliser Pydantic pour la validation de types
5. QUAND des conversions sont nécessaires, LE Système de Contrats DOIT fournir des utilitaires de conversion sûrs
### Exigence 5
**Histoire Utilisateur :** En tant qu'opérateur système, je veux des performances optimisées, afin que le système réponde rapidement même avec des interfaces complexes.
#### Critères d'Acceptation
1. QUAND TargetResolver résout des éléments, LE Système de Performance DOIT réutiliser l'index spatial entre les résolutions
2. QUAND des embeddings sont nécessaires, LE Système de Performance DOIT implémenter un lazy loading efficace
3. QUAND des modèles ML sont utilisés, LE Système de Performance DOIT mettre en cache les modèles chargés
4. QUAND des calculs redondants sont détectés, LE Système de Performance DOIT les éviter avec un cache intelligent
5. QUAND la résolution se termine, LE Système de Performance DOIT compléter en moins de 100ms pour des UI typiques
### Exigence 6
**Histoire Utilisateur :** En tant qu'administrateur système, je veux une gestion mémoire robuste, afin que le système reste stable lors d'une utilisation prolongée.
#### Critères d'Acceptation
1. QUAND des caches LRU sont utilisés, LE Système de Mémoire DOIT appliquer des limites de taille effectives
2. QUAND des embeddings sont stockés, LE Système de Mémoire DOIT implémenter un nettoyage automatique
3. QUAND des ressources GPU sont allouées, LE Système de Mémoire DOIT les libérer après utilisation
4. QUAND la mémoire atteint un seuil critique, LE Système de Mémoire DOIT déclencher un nettoyage préventif
5. QUAND le système s'arrête, LE Système de Mémoire DOIT libérer toutes les ressources proprement
### Exigence 7
**Histoire Utilisateur :** En tant qu'administrateur de sécurité, je veux un système sécurisé par défaut, afin que le déploiement en production soit sûr.
#### Critères d'Acceptation
1. QUAND l'environnement est en production, LE Système de Sécurité DOIT refuser les clés de chiffrement par défaut
2. QUAND des inputs utilisateur sont reçus, LE Système de Sécurité DOIT les valider contre les injections
3. QUAND des chemins de fichiers sont manipulés, LE Système de Sécurité DOIT prévenir les attaques de traversée
4. QUAND des données sensibles sont loggées, LE Système de Sécurité DOIT les masquer automatiquement
5. QUAND la configuration de sécurité est invalide, LE Système de Sécurité DOIT refuser de démarrer
### Exigence 8
**Histoire Utilisateur :** En tant que développeur, je veux un découplage des composants, afin que le système soit maintenable et testable.
#### Critères d'Acceptation
1. QUAND des composants interagissent, LE Système de Découplage DOIT utiliser des interfaces abstraites
2. QUAND des dépendances sont injectées, LE Système de Découplage DOIT utiliser un système d'injection de dépendances
3. QUAND des tests sont écrits, LE Système de Découplage DOIT permettre le mocking facile des dépendances
4. QUAND des composants évoluent, LE Système de Découplage DOIT maintenir la compatibilité des interfaces
5. QUAND de nouveaux composants sont ajoutés, LE Système de Découplage DOIT s'intégrer sans modification des existants
### Exigence 9
**Histoire Utilisateur :** En tant qu'opérateur système, je veux une observabilité complète, afin de pouvoir diagnostiquer et résoudre les problèmes rapidement.
#### Critères d'Acceptation
1. QUAND des opérations sont effectuées, LE Système d'Observabilité DOIT assigner des correlation IDs uniques
2. QUAND des logs sont émis, LE Système d'Observabilité DOIT utiliser des niveaux de log cohérents
3. QUAND des métriques sont collectées, LE Système d'Observabilité DOIT inclure les métriques de performance
4. QUAND des erreurs surviennent, LE Système d'Observabilité DOIT fournir des traces complètes
5. QUAND le système fonctionne, LE Système d'Observabilité DOIT permettre le monitoring en temps réel
### Exigence 10
**Histoire Utilisateur :** En tant qu'architecte système, je veux une configuration centralisée, afin que tous les paramètres soient gérés de manière cohérente.
#### Critères d'Acceptation
1. QUAND des constantes sont nécessaires, LE Système de Configuration DOIT les centraliser dans core/config.py
2. QUAND des paramètres de modèles ML sont utilisés, LE Système de Configuration DOIT les rendre configurables
3. QUAND la configuration est chargée, LE Système de Configuration DOIT la valider complètement
4. QUAND l'environnement change, LE Système de Configuration DOIT adapter les paramètres automatiquement
5. QUAND des valeurs par défaut sont utilisées, LE Système de Configuration DOIT les documenter clairement

View File

@@ -0,0 +1,237 @@
# Plan d'Implémentation - Corrections Critiques RPA Vision V3
**Auteur :** Dom, Alice Kiro
**Date :** 20 décembre 2024
## PRIORITÉ 1 - CRITIQUE (À faire immédiatement)
- [-] 1. Intégrer ActionExecutor dans WorkflowPipeline
- [x] 1.1 Ajouter execute_workflow_step() à WorkflowPipeline
- Implémenter la méthode d'exécution intégrée
- Connecter avec TargetResolver et ActionExecutor
- Gérer le cycle complet : match → action → exécution → résultat
- _Exigences: 1.1, 1.2, 1.4_
- [x] 1.2 Intégrer la gestion d'erreurs dans l'exécution
- Utiliser ErrorHandler pour toutes les erreurs d'exécution
- Implémenter les stratégies de retry et recovery
- _Exigences: 1.3, 2.1_
- [x] 1.3 Créer ExecutionResult avec métadonnées complètes
- Inclure correlation_id, performance_metrics, recovery_applied
- Assurer la traçabilité complète de l'exécution
- _Exigences: 1.4, 9.1_
- [ ]* 1.4 Écrire un test de propriété pour l'intégration WorkflowPipeline-ActionExecutor
- **Propriété 1: Intégration WorkflowPipeline-ActionExecutor**
- **Valide: Exigences 1.1, 1.2**
- [x] 2. Unifier la gestion d'erreurs avec ErrorHandler
- [x] 2.1 Créer les stratégies de récupération
- SpatialFallbackStrategy pour TargetNotFoundError
- SemanticVariantStrategy pour UIElementChangedError
- RetryWithBackoffStrategy pour NetworkError
- DataNormalizationStrategy pour ValidationError
- _Exigences: 2.2, 2.3_
- [x] 2.2 Implémenter ErrorHandler centralisé
- Mapper les types d'erreurs aux stratégies
- Gérer l'escalade après échec des récupérations
- Logger toutes les tentatives de récupération
- _Exigences: 2.1, 2.4, 2.5_
- [x] 2.3 Appliquer ErrorHandler dans tous les composants critiques
- TargetResolver, ActionExecutor, WorkflowPipeline
- Remplacer les try/catch isolés par des appels à ErrorHandler
- _Exigences: 2.1_
- [ ]* 2.4 Écrire un test de propriété pour la gestion d'erreurs unifiée
- **Propriété 2: Gestion d'erreurs unifiée**
- **Valide: Exigences 2.1, 2.2**
- [x] 3. Corriger les imports circulaires
- [x] 3.1 Refactorer core/models/__init__.py
- Utiliser des imports lazy avec TYPE_CHECKING
- Créer des fonctions get_* pour les imports différés
- _Exigences: 3.2, 3.4_
- [x] 3.2 Créer des interfaces abstraites
- ITargetResolver, IActionExecutor, IErrorHandler
- Découpler les composants avec des interfaces
- _Exigences: 3.3, 8.1_
- [x] 3.3 Tester l'absence d'imports circulaires
- Script de validation des imports
- Test automatisé dans la CI
- _Exigences: 3.1, 3.5_
- [ ]* 3.4 Écrire un test de propriété pour l'absence d'imports circulaires
- **Propriété 3: Absence d'imports circulaires**
- **Valide: Exigences 3.1, 3.3**
- [x] 4. Standardiser les contrats de données
- [x] 4.1 Créer BBox standardisée avec Pydantic
- Format exclusif (x, y, width, height)
- Validation automatique des coordonnées
- Méthodes de conversion from_xyxy(), to_tuple()
- _Exigences: 4.1, 4.4_
- [x] 4.2 Standardiser les timestamps avec datetime
- Remplacer tous les strings par datetime objects
- Créer DataConverter.ensure_datetime()
- _Exigences: 4.2, 4.5_
- [x] 4.3 Standardiser les IDs en strings
- Convertir tous les IDs numériques en strings
- Validation avec Pydantic
- _Exigences: 4.3, 4.4_
- [x] 4.4 Migrer tous les composants vers les nouveaux contrats
- UIElement, ScreenState, ResolvedTarget
- Assurer la compatibilité ascendante pendant la migration
- _Exigences: 4.1, 4.2, 4.3_
- [x]* 4.5 Écrire des tests de propriété pour la cohérence des contrats
- **Propriété 4: Cohérence des contrats de données BBox**
- **Propriété 5: Cohérence des timestamps**
- **Valide: Exigences 4.1, 4.2**
## PRIORITÉ 2 - IMPORTANT (Cette semaine)
- [ ] 5. Optimiser les performances
- [ ] 5.1 Implémenter le cache de l'index spatial
- Cache par signature d'écran dans TargetResolver
- Éviter la reconstruction à chaque résolution
- _Exigences: 5.1_
- [ ] 5.2 Implémenter le lazy loading des embeddings
- WeakValueDictionary pour le cache des embeddings
- Chargement à la demande depuis le disque
- _Exigences: 5.2_
- [ ] 5.3 Implémenter le cache des modèles ML
- Cache persistant des modèles chargés
- Éviter les rechargements multiples
- _Exigences: 5.3_
- [ ] 5.4 Optimiser les calculs redondants
- Cache intelligent pour les calculs de distance/alignement
- Réutilisation entre les résolutions d'ancres
- _Exigences: 5.4_
- [ ]* 5.5 Écrire un test de propriété pour la réutilisation de l'index spatial
- **Propriété 6: Réutilisation de l'index spatial**
- **Valide: Exigences 5.1**
- [-] 6. Améliorer la gestion mémoire
- [x] 6.1 Implémenter EffectiveLRUCache
- Limites de taille ET de mémoire effectives
- Éviction basée sur l'utilisation mémoire réelle
- _Exigences: 6.1_
- [x] 6.2 Créer MemoryManager pour le nettoyage automatique
- Surveillance de l'utilisation mémoire
- Nettoyage préventif à 80% du seuil
- Registry des ressources avec cleanup automatique
- _Exigences: 6.2, 6.4_
- [x] 6.3 Implémenter la libération des ressources GPU
- Tracking des allocations GPU
- Cleanup automatique après utilisation
- _Exigences: 6.3_
- [x] 6.4 Ajouter le cleanup à l'arrêt du système
- Libération propre de toutes les ressources
- Garbage collection forcé
- _Exigences: 6.5_
- [ ]* 6.5 Écrire des tests de propriété pour la gestion mémoire
- **Propriété 7: Limites effectives des caches LRU**
- **Propriété 8: Libération des ressources GPU**
- **Valide: Exigences 6.1, 6.3**
- [-] 7. Sécuriser le système
- [x] 7.1 Forcer la configuration sécurisée en production
- Validation des clés de chiffrement non-par-défaut
- Refus de démarrage avec configuration insécurisée
- _Exigences: 7.1, 7.5_
- [x] 7.2 Implémenter la validation des inputs utilisateur
- Protection contre les injections SQL/NoSQL
- Validation des chemins de fichiers
- Sanitization des données loggées
- _Exigences: 7.2, 7.3, 7.4_
- [ ]* 7.3 Écrire un test de propriété pour la validation des inputs
- **Propriété 9: Validation des inputs de sécurité**
- **Valide: Exigences 7.2**
## PRIORITÉ 3 - AMÉLIORATION (Prochaine itération)
- [ ] 8. Découpler les composants
- [ ] 8.1 Implémenter l'injection de dépendances
- Container DI simple pour les composants principaux
- Configuration des dépendances via interfaces
- _Exigences: 8.2_
- [ ] 8.2 Créer des interfaces abstraites complètes
- Toutes les interactions inter-composants via interfaces
- Faciliter le mocking pour les tests
- _Exigences: 8.1, 8.3_
- [ ]* 8.3 Écrire un test de propriété pour les interfaces abstraites
- **Propriété 10: Interfaces abstraites pour le découplage**
- **Valide: Exigences 8.1**
- [ ] 9. Améliorer l'observabilité
- [ ] 9.1 Implémenter les correlation IDs
- UUID unique pour chaque opération
- Propagation à travers tous les composants
- _Exigences: 9.1_
- [ ] 9.2 Standardiser les niveaux de logging
- Cohérence des niveaux DEBUG/INFO/WARNING/ERROR
- Structured logging avec contexte
- _Exigences: 9.2_
- [ ] 9.3 Ajouter les métriques de performance
- Collecte automatique des métriques de timing
- Métriques de succès/échec par composant
- _Exigences: 9.3_
- [ ] 9.4 Implémenter les traces d'erreur complètes
- Stack traces avec contexte d'exécution
- Chaînage des erreurs et récupérations
- _Exigences: 9.4_
- [ ]* 9.5 Écrire un test de propriété pour les correlation IDs
- **Propriété 11: Correlation IDs uniques**
- **Valide: Exigences 9.1**
- [ ] 10. Centraliser la configuration
- [ ] 10.1 Migrer toutes les constantes vers core/config.py
- Identifier et migrer les constantes hardcodées
- Grouper par domaine fonctionnel
- _Exigences: 10.1_
- [ ] 10.2 Rendre les paramètres ML configurables
- Seuils, poids, hyperparamètres externalisés
- Configuration par environnement
- _Exigences: 10.2_
- [ ] 10.3 Implémenter la validation de configuration
- Validation Pydantic de toute la configuration
- Valeurs par défaut documentées
- _Exigences: 10.3, 10.5_
- [ ] 10.4 Adapter la configuration par environnement
- Profils dev/staging/production
- Override automatique selon ENVIRONMENT
- _Exigences: 10.4_
- [ ]* 10.5 Écrire un test de propriété pour la centralisation des constantes
- **Propriété 12: Centralisation des constantes**
- **Valide: Exigences 10.1**
## VALIDATION ET INTÉGRATION
- [ ] 11. Tests de non-régression
- [ ] 11.1 Valider que toutes les fonctionnalités existantes fonctionnent
- Exécuter la suite de tests complète
- Vérifier les contrats d'API existants
- _Toutes les exigences_
- [ ] 11.2 Valider les performances
- Benchmarks avant/après les corrections
- Assurer qu'aucune dégradation n'est introduite
- _Exigences: 5.5_
- [ ] 11.3 Tests d'intégration de bout en bout
- Workflows complets avec les corrections appliquées
- Scénarios réels de production
- _Toutes les exigences_
- [ ] 12. Point de contrôle final - S'assurer que tous les tests passent
- S'assurer que tous les tests passent, demander à l'utilisateur si des questions se posent.
## NOTES IMPORTANTES
### Préservation de la Qualité
- **Chaque correction doit préserver les fonctionnalités existantes**
- **Tests de non-régression obligatoires avant chaque merge**
- **Validation des performances à chaque étape**
### Ordre d'Exécution
- **Priorité 1 doit être complétée avant Priorité 2**
- **Tests de propriétés exécutés en parallèle du développement**
- **Validation continue avec les tests existants**
### Gestion des Risques
- **Backup des composants critiques avant modification**
- **Rollback plan pour chaque correction majeure**
- **Monitoring continu pendant le déploiement**