# Architecture ## Flux de bout en bout ``` USER ──TASK_SUBMISSION──▶ KERNEL ──ROUTE_REQUEST──▶ ROUTER ──ROUTE_DECISION──▶ KERNEL │ └──CODE_PROPOSAL──▶ VERIFIER ──TOOL_CALL × n──▶ SKILL_EXECUTOR ▲ │ └────────TOOL_RESULT × n───────┘ VERIFIER ──VERIFICATION_RESULT──▶ CORRECTOR certifié ? ──oui──▶ FINAL_ANSWER ──▶ USER (certificat) └─non──▶ CORRECTION_REQUEST ──▶ KERNEL ──(CODE_PROPOSAL, tentative+1) └─budget épuisé──▶ SESSION_ABORT ──▶ USER (aucune sortie) ``` Chaque flèche est un `JevMessage` validé par le `JevBus` (schéma strict, aucun champ inconnu) puis journalisé dans le registre d'audit. Les composants n'ont aucune référence directe les uns vers les autres : ils ne communiquent que par abonnement `(type, destinataire)`. `mouh/verification/loop.py` est l'unique endroit où ce câblage est déclaré. ## Noyau séquentiel hybride (`mouh/model/layers.py`) - 24 blocs pour le défaut : motif `SSSSSA` × 4 (5 blocs Gated-SSM pour 1 bloc d'attention, imposé par validation de config). - **Gated-SSM** : `in_proj` → convolution causale depthwise → récurrence d'espace d'état sélective (dt, B, C dépendants de l'entrée) évaluée par l'algorithme **SSD par blocs** (complexité linéaire en longueur) → porte `silu(z)·y` + RMSNorm → `out_proj`. Au décodage, un pas de récurrence met à jour un état de taille constante (`ssm_step`). Les deux chemins sont équivalents à 1e-4 près (tests). - **Attention** : multi-têtes causale, RoPE (avec mise à l'échelle NTK optionnelle `rope_scaling_factor`), cache KV. - **Pré-normalisation** `LayerNorm` avant chaque transformation ; activations SiLU (Swish). - **Portes de rétroaction** : `g = 2·σ(W2·silu(W1·h))` (bas rang) module la sortie du mélangeur avant l'ajout résiduel ; `g ≈ 1` à l'initialisation. - **Initialisation SSM** : `A ∈ [1,16]` (log), `dt` log-uniforme dans [1e-3, 0,1] (softplus inverse), sorties résiduelles mises à l'échelle `1/√(2L)`. - **Noyaux Triton** (`triton_kernels.py`) : porte `silu(a)·b` fusionnée (avant et arrière) pour les experts et la porte SSM. Les projections linéaires restent sur cuBLAS. Repli PyTorch automatique hors GPU. ## MoE déterministe (`mouh/model/moe.py`) - 8 experts SwiGLU par couche (`syntax_repair`, `formal_logic`, `code_generation`, `data_schema`, `refactor_optimize`, `docs_formatting`, `test_diagnostics`, `arbiter`), correspondant aux experts n°1 à n°8 de la spécification. - **Score** = routeur linéaire + **prior du type de message** (table JEV précompilée) + biais d'équilibrage. **Sélection** : tri stable décroissant (égalité → plus petit indice), 4 premiers. **Coefficients** : σ(score) renormalisé sur les experts retenus. Aucun softmax, aucun bruit, aucun aléa : même entrée, même routage (testé bit à bit). - **Contrôle de charge** : capacité par expert `⌈capacity_factor·N·k/E⌉` appliquée dans l'ordre des tokens (causal) en entraînement ; perte auxiliaire `E·Σ fᵢPᵢ` ; règle d'équilibrage sans perte (`step_routing_bias`) qui abaisse le biais des experts sur-chargés. L'historique de charge est un tampon persistant (`load_ema`). En inférence, le routage est sans abandon par défaut pour que préremplissage et décodage incrémental donnent les mêmes logits (`enforce_capacity_at_inference`). - **Experts déchargeables** : `offload_experts` / `load_experts`. - **Sortie validée** : aucune valeur non finie ne quitte la couche ; la trace discrète du routage est exportable sur le bus (`routing_messages`). ## Têtes de contrôle typées `type_head` et `tool_head` produisent des logits sur `JevMessageType` et sur les skills. `MouhForCausalLM.decide()` renvoie des `JevChoice` (alternatives bornées, `JevScore` normalisé, argmax déterministe). Elles se supervisent avec `type_labels` / `tool_labels`. ## Boucle de vérification (`mouh/verification`) Score = moyenne pondérée de composantes (analyse statique 1, exécution 2, tests 4, preuves 3). Un certificat est délivré si et seulement si **score ≥ 0,85 et toutes les barrières dures valent 1** (syntaxe/politique, exécution sans erreur, tous les tests, toutes les obligations prouvées) **et** au moins un oracle (tests ou preuves) existe. Sinon : demande de correction, routée vers les experts de refactoring en tête (n°5, 1, 7, 3), avec les diagnostics typés et les indices tirés des corrections déjà réussies (`CorrectionStore`, exportables en JSONL d'affinage). La boucle s'arrête sur certificat, épuisement du budget, absence de progrès (même code proposé deux fois) ou renoncement du générateur.