341 lines
11 KiB
Markdown
341 lines
11 KiB
Markdown
# AUDIT DE CONFORMITÉ GROVEENGINE - AISSIA
|
|
|
|
**Date** : 2025-11-26
|
|
**Auditeur** : Claude Code
|
|
**Version auditée** : Commit bc3b6cb
|
|
|
|
---
|
|
|
|
## RÉSUMÉ EXÉCUTIF
|
|
|
|
**Verdict : Le code contourne massivement les principes de GroveEngine.**
|
|
|
|
| Module | Lignes | Conformité Engine | Statut |
|
|
|--------|--------|-------------------|--------|
|
|
| AIModule | 306 | VIOLATION | Infrastructure dans module |
|
|
| MonitoringModule | 222 | VIOLATION | Appels OS dans module |
|
|
| StorageModule | 273 | VIOLATION | SQLite dans module |
|
|
| VoiceModule | 209 | VIOLATION | TTS/COM dans module |
|
|
| SchedulerModule | 179 | CONFORME | Logique métier pure |
|
|
| NotificationModule | 172 | CONFORME | Logique métier pure |
|
|
|
|
**Score global** : 2/6 modules conformes (33%)
|
|
|
|
---
|
|
|
|
## RAPPEL DES PRINCIPES GROVEENGINE
|
|
|
|
Selon `docs/GROVEENGINE_GUIDE.md` :
|
|
|
|
1. **Modules = Pure business logic** (200-300 lignes recommandées)
|
|
2. **No infrastructure code in modules** : threading, networking, persistence
|
|
3. **All data via IDataNode abstraction** (backend agnostic)
|
|
4. **Pull-based message processing** via IIO pub/sub
|
|
5. **Hot-reload ready** : sérialiser tout l'état dans `getState()`
|
|
|
|
---
|
|
|
|
## VIOLATIONS CRITIQUES
|
|
|
|
### 1. AIModule - Networking dans le module
|
|
|
|
**Fichier** : `src/modules/AIModule.cpp:146`
|
|
|
|
```cpp
|
|
nlohmann::json AIModule::agenticLoop(const std::string& userQuery) {
|
|
// ...
|
|
auto response = m_provider->chat(m_systemPrompt, messages, tools);
|
|
// Appel HTTP synchrone bloquant !
|
|
}
|
|
```
|
|
|
|
**Violation** : Appels HTTP synchrones directement dans `process()` via la boucle agentique.
|
|
|
|
**Impact** :
|
|
- Bloque la boucle principale pendant chaque requête LLM (timeout 60s)
|
|
- `isIdle()` retourne false pendant l'appel, mais le module reste bloquant
|
|
- Hot-reload impossible pendant une requête en cours
|
|
- Tous les autres modules sont bloqués
|
|
|
|
**Correction requise** : Déléguer les appels LLM à un service infrastructure externe, communication via IIO async.
|
|
|
|
---
|
|
|
|
### 2. StorageModule - Persistence dans le module
|
|
|
|
**Fichier** : `src/modules/StorageModule.cpp:78-91`
|
|
|
|
```cpp
|
|
bool StorageModule::openDatabase() {
|
|
int rc = sqlite3_open(m_dbPath.c_str(), &m_db);
|
|
// Handle SQLite directement dans le module
|
|
}
|
|
```
|
|
|
|
**Violation** : Gestion directe de SQLite. L'engine préconise `IDataNode` abstractions pour la persistence.
|
|
|
|
**Impact** :
|
|
- Hot-reload risqué (handle DB ouvert)
|
|
- Risque de corruption si reload pendant transaction
|
|
- Couplage fort avec SQLite
|
|
|
|
**Correction requise** : Service StorageService dans main.cpp, modules communiquent via topics `storage:*`.
|
|
|
|
---
|
|
|
|
### 3. MonitoringModule - Appels OS dans le module
|
|
|
|
**Fichier** : `src/modules/MonitoringModule.cpp:78-79`
|
|
|
|
```cpp
|
|
void MonitoringModule::checkCurrentApp(float currentTime) {
|
|
std::string newApp = m_tracker->getCurrentAppName();
|
|
// Appelle GetForegroundWindow(), OpenProcess(), etc.
|
|
}
|
|
```
|
|
|
|
**Violation** : Appels Win32 API dans `process()`. Même encapsulé dans `IWindowTracker`, c'est du code plateforme dans un module hot-reloadable.
|
|
|
|
**Impact** :
|
|
- Dépendance plateforme dans le module
|
|
- Handles système potentiellement orphelins au reload
|
|
|
|
**Correction requise** : Service PlatformService qui publie `monitoring:window_info` périodiquement.
|
|
|
|
---
|
|
|
|
### 4. VoiceModule - COM/SAPI dans le module
|
|
|
|
**Fichier** : `src/modules/VoiceModule.cpp:122`
|
|
|
|
```cpp
|
|
void VoiceModule::speak(const std::string& text) {
|
|
m_ttsEngine->speak(text, true);
|
|
// Appel ISpVoice::Speak via COM
|
|
}
|
|
```
|
|
|
|
**Fichier** : `src/shared/audio/SAPITTSEngine.hpp:26`
|
|
|
|
```cpp
|
|
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
|
```
|
|
|
|
**Violation** : Initialisation COM et appels SAPI dans le module.
|
|
|
|
**Impact** :
|
|
- `CoInitializeEx` par thread, hot-reload peut causer des fuites
|
|
- Appels asynchrones SAPI difficiles à gérer au shutdown
|
|
|
|
**Correction requise** : Service VoiceService dédié, modules envoient `voice:speak`.
|
|
|
|
---
|
|
|
|
## PROBLÈMES DE DESIGN
|
|
|
|
### 5. Topics incohérents
|
|
|
|
**SchedulerModule.h:26** utilise le format slash :
|
|
```cpp
|
|
// "scheduler/hyperfocus_alert"
|
|
```
|
|
|
|
**AIModule.cpp:52** utilise le format colon :
|
|
```cpp
|
|
m_io->subscribe("scheduler:hyperfocus_alert", subConfig);
|
|
```
|
|
|
|
**Standard GroveEngine** : Format `module:event` (colon)
|
|
|
|
**Impact** : Les messages ne seront jamais reçus si les formats ne correspondent pas.
|
|
|
|
---
|
|
|
|
### 6. SchedulerModule - IIO non utilisé
|
|
|
|
**Fichier** : `src/modules/SchedulerModule.cpp:66-68`
|
|
|
|
```cpp
|
|
void SchedulerModule::checkHyperfocus(float currentTime) {
|
|
// ...
|
|
// Publier l'alerte (si IO disponible)
|
|
// Note: Dans une version complète, on publierait via m_io
|
|
}
|
|
```
|
|
|
|
**Problème** : Le SchedulerModule a `m_io` mais ne publie JAMAIS rien. Les autres modules s'abonnent à `scheduler:*` mais ne recevront rien.
|
|
|
|
---
|
|
|
|
### 7. État non restaurable - StorageModule
|
|
|
|
**Fichier** : `src/modules/StorageModule.cpp:246-258`
|
|
|
|
```cpp
|
|
std::unique_ptr<grove::IDataNode> StorageModule::getState() {
|
|
state->setBool("isConnected", m_isConnected);
|
|
// ...
|
|
}
|
|
|
|
void StorageModule::setState(const grove::IDataNode& state) {
|
|
// NE ROUVRE PAS la connexion DB !
|
|
m_logger->info("Etat restore...");
|
|
}
|
|
```
|
|
|
|
**Problème** : `setState()` ne restaure pas la connexion SQLite. Après hot-reload, le module est dans un état incohérent.
|
|
|
|
---
|
|
|
|
### 8. Libraries statiques dans modules
|
|
|
|
**CMakeLists.txt:86-101** :
|
|
|
|
```cmake
|
|
add_library(AissiaLLM STATIC ...)
|
|
target_link_libraries(AIModule PRIVATE AissiaLLM)
|
|
```
|
|
|
|
**Problème** : Les libs `AissiaLLM`, `AissiaPlatform`, `AissiaAudio` sont compilées en STATIC et linkées dans chaque .so.
|
|
|
|
**Impact** :
|
|
- Code dupliqué dans chaque module
|
|
- Hot-reload ne rafraîchit pas ces libs
|
|
- Pas de partage d'état entre modules
|
|
|
|
---
|
|
|
|
### 9. Dépassement limite de lignes
|
|
|
|
| Module | Lignes | Limite recommandée |
|
|
|--------|--------|-------------------|
|
|
| AIModule | 306 | 200-300 |
|
|
|
|
Le dépassement est mineur mais symptomatique : le module fait trop de choses.
|
|
|
|
---
|
|
|
|
## CE QUI EST CONFORME
|
|
|
|
### SchedulerModule & NotificationModule
|
|
|
|
Ces deux modules respectent les principes :
|
|
- Logique métier pure
|
|
- Pas d'appels système
|
|
- État sérialisable
|
|
- Taille appropriée
|
|
|
|
### Structure IModule
|
|
|
|
Tous les modules implémentent correctement :
|
|
- `process()`
|
|
- `setConfiguration()`
|
|
- `getState()` / `setState()`
|
|
- `getHealthStatus()`
|
|
- `shutdown()`
|
|
- Exports C `createModule()` / `destroyModule()`
|
|
|
|
### main.cpp
|
|
|
|
La boucle principale est bien implémentée :
|
|
- FileWatcher pour hot-reload
|
|
- Frame timing à 10Hz
|
|
- Signal handling propre
|
|
- Chargement/déchargement correct
|
|
|
|
---
|
|
|
|
## ARCHITECTURE RECOMMANDÉE
|
|
|
|
### Actuelle (INCORRECTE)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ main.cpp │
|
|
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
│ │AIModule │ │Storage │ │Monitor │ │Voice │ │
|
|
│ │ +HTTP │ │ +SQLite │ │ +Win32 │ │ +COM │ │
|
|
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
Infrastructure DANS les modules = VIOLATION
|
|
```
|
|
|
|
### Corrigée (CONFORME)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ main.cpp │
|
|
│ │
|
|
│ ┌─────────────── INFRASTRUCTURE ──────────────────┐ │
|
|
│ │ LLMService │ StorageService │ PlatformService │ │ │
|
|
│ │ (async) │ (SQLite) │ (Win32) │ │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
│ ↑↓ IIO pub/sub (async, non-bloquant) │
|
|
│ ┌─────────────── MODULES (hot-reload) ────────────┐ │
|
|
│ │ AIModule │ StorageModule │ MonitoringModule │ │ │
|
|
│ │ (logic) │ (logic) │ (logic) │ │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
Infrastructure HORS modules = CONFORME
|
|
```
|
|
|
|
### Flux de données corrigé
|
|
|
|
```
|
|
User query → voice:transcription → AIModule
|
|
AIModule → ai:query_request → LLMService (async)
|
|
LLMService → ai:response → AIModule
|
|
AIModule → ai:response → VoiceModule → voice:speak
|
|
```
|
|
|
|
---
|
|
|
|
## ACTIONS REQUISES
|
|
|
|
### Priorité HAUTE
|
|
|
|
1. **Extraire LLM de AIModule**
|
|
- Créer `LLMService` dans main.cpp ou service dédié
|
|
- AIModule publie `ai:query_request`, reçoit `ai:response`
|
|
- Appels HTTP dans thread séparé
|
|
|
|
2. **Extraire SQLite de StorageModule**
|
|
- Créer `StorageService`
|
|
- Modules publient `storage:save_*`, reçoivent `storage:result`
|
|
|
|
3. **Extraire Win32 de MonitoringModule**
|
|
- Créer `PlatformService`
|
|
- Publie `platform:window_changed` périodiquement
|
|
|
|
4. **Extraire TTS de VoiceModule**
|
|
- Créer `VoiceService`
|
|
- Modules publient `voice:speak`
|
|
|
|
### Priorité MOYENNE
|
|
|
|
5. **Corriger format topics** : Tout en `module:event`
|
|
6. **Implémenter publish dans SchedulerModule**
|
|
7. **Corriger setState dans StorageModule**
|
|
|
|
### Priorité BASSE
|
|
|
|
8. **Refactorer libs STATIC en services**
|
|
9. **Réduire AIModule sous 300 lignes**
|
|
|
|
---
|
|
|
|
## CONCLUSION
|
|
|
|
Le code actuel **simule** l'utilisation de GroveEngine mais le **contourne** en plaçant l'infrastructure directement dans les modules.
|
|
|
|
Les modules ne sont **pas véritablement hot-reloadable** car ils :
|
|
1. Possèdent des ressources système (DB handles, COM objects)
|
|
2. Font des appels bloquants (HTTP 60s timeout, TTS)
|
|
3. Ne communiquent pas correctement via IIO
|
|
|
|
**Refactoring majeur requis** pour extraire l'infrastructure des modules vers des services dédiés dans main.cpp.
|
|
|
|
---
|
|
|
|
*Audit généré automatiquement par Claude Code*
|