11 KiB
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 :
- Modules = Pure business logic (200-300 lignes recommandées)
- No infrastructure code in modules : threading, networking, persistence
- All data via IDataNode abstraction (backend agnostic)
- Pull-based message processing via IIO pub/sub
- Hot-reload ready : sérialiser tout l'état dans
getState()
VIOLATIONS CRITIQUES
1. AIModule - Networking dans le module
Fichier : src/modules/AIModule.cpp:146
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
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
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
void VoiceModule::speak(const std::string& text) {
m_ttsEngine->speak(text, true);
// Appel ISpVoice::Speak via COM
}
Fichier : src/shared/audio/SAPITTSEngine.hpp:26
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
Violation : Initialisation COM et appels SAPI dans le module.
Impact :
CoInitializeExpar 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 :
// "scheduler/hyperfocus_alert"
AIModule.cpp:52 utilise le format colon :
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
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
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 :
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
-
Extraire LLM de AIModule
- Créer
LLMServicedans main.cpp ou service dédié - AIModule publie
ai:query_request, reçoitai:response - Appels HTTP dans thread séparé
- Créer
-
Extraire SQLite de StorageModule
- Créer
StorageService - Modules publient
storage:save_*, reçoiventstorage:result
- Créer
-
Extraire Win32 de MonitoringModule
- Créer
PlatformService - Publie
platform:window_changedpériodiquement
- Créer
-
Extraire TTS de VoiceModule
- Créer
VoiceService - Modules publient
voice:speak
- Créer
Priorité MOYENNE
- Corriger format topics : Tout en
module:event - Implémenter publish dans SchedulerModule
- Corriger setState dans StorageModule
Priorité BASSE
- Refactorer libs STATIC en services
- 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 :
- Possèdent des ressources système (DB handles, COM objects)
- Font des appels bloquants (HTTP 60s timeout, TTS)
- 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