|
| 1 | +# Analyse et Points d'Amélioration - Cortex CLI |
| 2 | + |
| 3 | +Date: 2026-01-27 |
| 4 | +Version analysée: 0.0.4 |
| 5 | + |
| 6 | +## Résumé Exécutif |
| 7 | + |
| 8 | +La CLI Cortex est une application bien structurée et fonctionnelle avec une architecture modulaire. Cette analyse identifie les points d'amélioration potentiels organisés par catégorie de priorité. |
| 9 | + |
| 10 | +--- |
| 11 | + |
| 12 | +## 🔴 Points Critiques (Haute Priorité) |
| 13 | + |
| 14 | +### 1. **Gestion des Erreurs Inconsistante** |
| 15 | + |
| 16 | +**Fichiers concernés:** `login.rs`, `main.rs` |
| 17 | + |
| 18 | +**Problème:** Les fonctions de login utilisent `std::process::exit()` directement au lieu de propager les erreurs, ce qui empêche une gestion correcte des ressources et les tests. |
| 19 | + |
| 20 | +```rust |
| 21 | +// Actuel (login.rs) |
| 22 | +pub async fn run_login_with_api_key(...) -> ! { |
| 23 | + // ... |
| 24 | + std::process::exit(0); |
| 25 | +} |
| 26 | +``` |
| 27 | + |
| 28 | +**Recommandation:** Retourner `Result<()>` et laisser le caller gérer l'exit code. |
| 29 | + |
| 30 | +```rust |
| 31 | +pub async fn run_login_with_api_key(...) -> Result<()> { |
| 32 | + // ... |
| 33 | + Ok(()) |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +### 2. **Validation des Entrées Utilisateur** |
| 40 | + |
| 41 | +**Fichiers concernés:** `agent_cmd.rs`, `mcp_cmd.rs`, `run_cmd.rs` |
| 42 | + |
| 43 | +**Points positifs:** De bonnes validations existent déjà (ex: `validate_server_name`, `validate_url`). |
| 44 | + |
| 45 | +**Points à améliorer:** |
| 46 | + |
| 47 | +- **agent_cmd.rs:**: Les noms d'agents vides sont bien validés, mais la validation est dispersée dans `run_create` et `run_generate`. |
| 48 | + |
| 49 | +```rust |
| 50 | +// Suggestion: Centraliser la validation |
| 51 | +fn validate_agent_name(name: &str) -> Result<()> { |
| 52 | + if name.trim().is_empty() { |
| 53 | + bail!("Agent name cannot be empty"); |
| 54 | + } |
| 55 | + if !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') { |
| 56 | + bail!("Agent name must contain only alphanumeric characters, hyphens, and underscores"); |
| 57 | + } |
| 58 | + Ok(()) |
| 59 | +} |
| 60 | +``` |
| 61 | + |
| 62 | +--- |
| 63 | + |
| 64 | +### 3. **Constantes et Timeouts Non Configurables** |
| 65 | + |
| 66 | +**Fichiers concernés:** `mcp_cmd.rs`, `scrape_cmd.rs`, `debug_cmd.rs` |
| 67 | + |
| 68 | +**Problème:** Plusieurs constantes sont hardcodées sans possibilité de configuration. |
| 69 | + |
| 70 | +```rust |
| 71 | +// mcp_cmd.rs |
| 72 | +const MAX_SERVER_NAME_LENGTH: usize = 64; |
| 73 | +const MAX_URL_LENGTH: usize = 2048; |
| 74 | +const MAX_ENV_VARS: usize = 50; |
| 75 | + |
| 76 | +// scrape_cmd.rs |
| 77 | +const MAX_FILE_SIZE: u64 = 10 * 1024 * 1024; // Dans run_cmd.rs |
| 78 | + |
| 79 | +// debug_cmd.rs - interval minimum hardcodé |
| 80 | +let interval_ms = if args.interval == 0 { 500 } else if args.interval < 100 { 100 } else { args.interval }; |
| 81 | +``` |
| 82 | + |
| 83 | +**Recommandation:** Centraliser ces constantes dans un module de configuration ou les rendre configurables via `config.toml`. |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +## 🟠 Points Importants (Priorité Moyenne) |
| 88 | + |
| 89 | +### 4. **Duplication de Code pour la Résolution des Session IDs** |
| 90 | + |
| 91 | +**Fichiers concernés:** `main.rs`, `export_cmd.rs`, `import_cmd.rs`, `run_cmd.rs`, `debug_cmd.rs` |
| 92 | + |
| 93 | +**Problème:** La logique de résolution des session IDs (full UUID ou prefix 8 chars) est dupliquée dans plusieurs fichiers. |
| 94 | + |
| 95 | +```rust |
| 96 | +// Pattern répété dans 5+ fichiers: |
| 97 | +let conversation_id: ConversationId = match session_id.parse() { |
| 98 | + Ok(id) => id, |
| 99 | + Err(_) => { |
| 100 | + if session_id.len() == 8 { |
| 101 | + // Try to find a session with matching prefix... |
| 102 | + } |
| 103 | + } |
| 104 | +}; |
| 105 | +``` |
| 106 | + |
| 107 | +**Recommandation:** Extraire dans un module commun: |
| 108 | + |
| 109 | +```rust |
| 110 | +// Dans un nouveau fichier: src/session_utils.rs |
| 111 | +pub fn resolve_session_id( |
| 112 | + session_id: &str, |
| 113 | + fabric_home: &PathBuf |
| 114 | +) -> Result<ConversationId> { |
| 115 | + // Logique centralisée |
| 116 | +} |
| 117 | +``` |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +### 5. **Absence de Logging Structuré** |
| 122 | + |
| 123 | +**Fichiers concernés:** Tous |
| 124 | + |
| 125 | +**Problème:** Le logging utilise `eprintln!` et `println!` de manière inconsistante. Pas d'utilisation systématique de `tracing`. |
| 126 | + |
| 127 | +```rust |
| 128 | +// Actuel |
| 129 | +eprintln!("Warning: Failed to start mDNS advertising: {e}"); |
| 130 | +println!("✓ Added stdio MCP server '{name}'"); |
| 131 | + |
| 132 | +// Recommandé avec tracing |
| 133 | +tracing::warn!("Failed to start mDNS advertising: {}", e); |
| 134 | +tracing::info!(server_name = %name, "Added stdio MCP server"); |
| 135 | +``` |
| 136 | + |
| 137 | +**Recommandation:** Standardiser avec `tracing` pour: |
| 138 | +- Logging JSON structuré |
| 139 | +- Filtrage par niveau |
| 140 | +- Contexte de spans |
| 141 | + |
| 142 | +--- |
| 143 | + |
| 144 | +### 6. **Tests Manquants ou Incomplets** |
| 145 | + |
| 146 | +**Fichiers concernés:** Plusieurs modules |
| 147 | + |
| 148 | +| Module | Couverture Tests | |
| 149 | +|--------|------------------| |
| 150 | +| `agent_cmd.rs` | ✅ Bonne (frontmatter, mode parsing) | |
| 151 | +| `mcp_cmd.rs` | ⚠️ Absente (pas de tests) | |
| 152 | +| `run_cmd.rs` | ✅ Bonne (model spec, mime types) | |
| 153 | +| `login.rs` | ⚠️ Absente (difficile avec exit) | |
| 154 | +| `scrape_cmd.rs` | ✅ Bonne (HTML to markdown) | |
| 155 | +| `github_cmd.rs` | ⚠️ Nécessite mocking | |
| 156 | +| `stats_cmd.rs` | ✅ Bonne | |
| 157 | + |
| 158 | +**Recommandation:** Ajouter des tests d'intégration et améliorer la couverture des modules critiques. |
| 159 | + |
| 160 | +--- |
| 161 | + |
| 162 | +### 7. **Documentation API Incomplète** |
| 163 | + |
| 164 | +**Fichiers concernés:** `lib.rs`, tous les modules |
| 165 | + |
| 166 | +**Problème:** Les modules publics manquent de documentation rustdoc complète. |
| 167 | + |
| 168 | +```rust |
| 169 | +// Actuel (lib.rs) |
| 170 | +pub mod acp_cmd; |
| 171 | +pub mod agent_cmd; |
| 172 | +// etc. |
| 173 | + |
| 174 | +// Recommandé |
| 175 | +/// ACP (Agent Communication Protocol) server commands for IDE integration. |
| 176 | +/// |
| 177 | +/// This module provides commands for running the ACP server which enables |
| 178 | +/// real-time communication with IDEs like Zed. |
| 179 | +pub mod acp_cmd; |
| 180 | +``` |
| 181 | + |
| 182 | +--- |
| 183 | + |
| 184 | +## 🟡 Points d'Optimisation (Priorité Basse) |
| 185 | + |
| 186 | +### 8. **Allocations String Évitables** |
| 187 | + |
| 188 | +**Fichiers concernés:** `scrape_cmd.rs`, `stats_cmd.rs` |
| 189 | + |
| 190 | +```rust |
| 191 | +// scrape_cmd.rs - Allocation répétée dans la boucle |
| 192 | +for line in content.lines() { |
| 193 | + let trimmed = line.trim().to_string(); // Allocation évitable |
| 194 | +} |
| 195 | + |
| 196 | +// Mieux |
| 197 | +for line in content.lines() { |
| 198 | + let trimmed = line.trim(); // &str suffit souvent |
| 199 | +} |
| 200 | +``` |
| 201 | + |
| 202 | +--- |
| 203 | + |
| 204 | +### 9. **Async/Await Non Utilisé Où Approprié** |
| 205 | + |
| 206 | +**Fichiers concernés:** `debug_cmd.rs`, certaines fonctions sync inutilement async |
| 207 | + |
| 208 | +```rust |
| 209 | +// Fonction qui n'utilise pas vraiment async |
| 210 | +async fn run_config(args: ConfigArgs) -> Result<()> { |
| 211 | + // Pas d'opérations async dans le corps |
| 212 | +} |
| 213 | +``` |
| 214 | + |
| 215 | +**Recommandation:** Marquer comme sync ou utiliser `spawn_blocking` pour les opérations CPU-bound. |
| 216 | + |
| 217 | +--- |
| 218 | + |
| 219 | +### 10. **Gestion de la Progression des Downloads** |
| 220 | + |
| 221 | +**Fichiers concernés:** `upgrade_cmd.rs` |
| 222 | + |
| 223 | +```rust |
| 224 | +// Actuel - flush stdout non géré dans la closure |
| 225 | +.download_update(info, |progress| { |
| 226 | + let pct = (progress.downloaded as f64 / progress.total as f64 * 100.0) as u32; |
| 227 | + print!("\r Downloading... {}% ({}/{})", pct, progress.downloaded, progress.total); |
| 228 | + let _ = stdout().flush(); // Silently ignore errors |
| 229 | +}) |
| 230 | +``` |
| 231 | + |
| 232 | +**Recommandation:** Utiliser un writer dédié avec meilleure gestion des erreurs. |
| 233 | + |
| 234 | +--- |
| 235 | + |
| 236 | +## 🔵 Améliorations Fonctionnelles Suggérées |
| 237 | + |
| 238 | +### 11. **Support Manquant pour `McpServer`** |
| 239 | + |
| 240 | +**Fichier:** `main.rs` |
| 241 | + |
| 242 | +```rust |
| 243 | +Some(Commands::McpServer) => { |
| 244 | + eprintln!("MCP server mode not yet implemented"); |
| 245 | + Ok(()) |
| 246 | +} |
| 247 | +``` |
| 248 | + |
| 249 | +**Recommandation:** Implémenter ou supprimer de l'interface CLI. |
| 250 | + |
| 251 | +--- |
| 252 | + |
| 253 | +### 12. **Feature Flags Hardcodés** |
| 254 | + |
| 255 | +**Fichier:** `main.rs` |
| 256 | + |
| 257 | +```rust |
| 258 | +async fn list_features() -> Result<()> { |
| 259 | + let features = [ |
| 260 | + ("unified_exec", "stable", true), |
| 261 | + ("web_search", "beta", false), |
| 262 | + // ... hardcodé |
| 263 | + ]; |
| 264 | +} |
| 265 | +``` |
| 266 | + |
| 267 | +**Recommandation:** Charger depuis la configuration ou le runtime. |
| 268 | + |
| 269 | +--- |
| 270 | + |
| 271 | +### 13. **Amélioration du Shell Completion** |
| 272 | + |
| 273 | +**Fichier:** `main.rs` |
| 274 | + |
| 275 | +```rust |
| 276 | +// Actuel - supporte seulement les shells de base |
| 277 | +#[arg(value_enum, default_value_t = Shell::Bash)] |
| 278 | +shell: Shell, |
| 279 | +``` |
| 280 | + |
| 281 | +**Recommandation:** |
| 282 | +- Ajouter support Nushell, Elvish |
| 283 | +- Auto-détection du shell courant |
| 284 | + |
| 285 | +--- |
| 286 | + |
| 287 | +## 📊 Métriques de Qualité |
| 288 | + |
| 289 | +### Complexité Cyclomatique Élevée |
| 290 | + |
| 291 | +| Fonction | Fichier | Complexité | |
| 292 | +|----------|---------|------------| |
| 293 | +| `process_node_to_markdown` | scrape_cmd.rs | ~40+ | |
| 294 | +| `run_debug` | mcp_cmd.rs | ~25+ | |
| 295 | +| `run_create` | agent_cmd.rs | ~20+ | |
| 296 | +| `run_local` | run_cmd.rs | ~20+ | |
| 297 | + |
| 298 | +**Recommandation:** Refactoriser en sous-fonctions plus petites. |
| 299 | + |
| 300 | +--- |
| 301 | + |
| 302 | +### Dépendances Non Utilisées ou Optionnelles |
| 303 | + |
| 304 | +```toml |
| 305 | +# Cargo.toml - À vérifier si vraiment utilisées partout |
| 306 | +serde_yaml = "0.9" # Utilisé uniquement pour agent parsing |
| 307 | +scraper = "0.22" # Uniquement pour scrape_cmd |
| 308 | +hostname = { workspace = true } # Uniquement pour mDNS |
| 309 | +``` |
| 310 | + |
| 311 | +**Recommandation:** Rendre ces dépendances optionnelles avec feature flags. |
| 312 | + |
| 313 | +--- |
| 314 | + |
| 315 | +## ✅ Points Positifs Notables |
| 316 | + |
| 317 | +1. **Excellente validation de sécurité** dans `mcp_cmd.rs` (URL validation, blocked patterns) |
| 318 | +2. **Bonne gestion des erreurs contextuelles** avec `anyhow::Context` |
| 319 | +3. **Architecture modulaire** claire avec séparation des commandes |
| 320 | +4. **Support multi-plateforme** bien pensé (Windows, macOS, Linux) |
| 321 | +5. **Tests unitaires** présents dans les modules critiques |
| 322 | +6. **Documentation inline** pour les commandes principales |
| 323 | +7. **Validation d'entrée** robuste dans `pr_cmd.rs` (branch names, refspecs) |
| 324 | +8. **Sécurité** bien pensée dans `uninstall_cmd.rs` (validate_path_safety) |
| 325 | + |
| 326 | +--- |
| 327 | + |
| 328 | +## 🛠️ Plan d'Action Recommandé |
| 329 | + |
| 330 | +### Phase 1 (Court terme - 1-2 semaines) |
| 331 | +1. ✅ Refactoriser les fonctions login pour retourner `Result` |
| 332 | +2. ✅ Extraire la logique session ID dans un module commun |
| 333 | +3. ✅ Ajouter tests pour `mcp_cmd.rs` |
| 334 | + |
| 335 | +### Phase 2 (Moyen terme - 1 mois) |
| 336 | +1. Migrer vers `tracing` pour le logging |
| 337 | +2. Réduire la complexité cyclomatique des grandes fonctions |
| 338 | +3. Compléter la documentation rustdoc |
| 339 | + |
| 340 | +### Phase 3 (Long terme) |
| 341 | +1. Rendre les constantes configurables |
| 342 | +2. Implémenter `McpServer` ou le supprimer |
| 343 | +3. Ajouter feature flags pour les dépendances optionnelles |
| 344 | + |
| 345 | +--- |
| 346 | + |
| 347 | +## Conclusion |
| 348 | + |
| 349 | +La CLI Cortex est une base solide avec une architecture bien pensée. Les améliorations identifiées sont principalement des optimisations et des standardisations qui amélioreront la maintenabilité et la testabilité du code sans nécessiter de refonte majeure. |
| 350 | + |
| 351 | +**Score global de qualité:** 7.5/10 |
| 352 | + |
| 353 | +Les points forts sont la sécurité, la modularité et la couverture fonctionnelle. Les points à améliorer sont la gestion des erreurs, la duplication de code et la couverture de tests. |
0 commit comments