# Archive — Phases Terminées

> Ce fichier contient les détails techniques des phases terminées de LintellO.
> Pour la roadmap active, voir `../Project_Status.md`.

---

## Phase 0b — Persistance Fichiers Conversation (TERMINÉE 27/01/2026)

### Objectif
Permettre à LintellO d'accéder aux fichiers uploadés pendant toute la conversation, pas seulement au moment de l'upload.

### Architecture : ConversationFile

```
┌─────────────────────────────────────────────────────────────────┐
│                     ConversationFile                             │
├─────────────────────────────────────────────────────────────────┤
│ id              : UUID (PK)                                      │
│ conversation    : ManyToOne → Conversation (CASCADE DELETE)     │
│ originalName    : string[255]                                    │
│ mimeType        : string[100]                                    │
│ size            : integer                                        │
│                                                                  │
│ extractedText   : encrypted_text  ← Contenu COMPLET (50k max)   │
│ summary         : encrypted_text  ← Résumé AUTO (~500-1000 ch.) │
│ ocrText         : encrypted_text  ← Images : OCR seulement      │
│ imageBase64     : encrypted_text  ← Images pour Pixtral         │
│                                                                  │
│ isActive        : boolean (default true)                         │
│ createdAt       : datetime_immutable                             │
└─────────────────────────────────────────────────────────────────┘
```

### Solution Implémentée

**Problème initial** : L'IA avait accès au fichier lors du premier message, mais le "perdait" lors des messages suivants.

**Cause** : Le contenu des fichiers n'était pas stocké dans l'historique des messages.

**Solution** :
- Le contenu complet des fichiers est maintenant attaché au message utilisateur (comme Claude/ChatGPT)
- Ajout de `findLastMessagesWithFiles()` pour toujours inclure les messages avec fichiers dans l'historique
- Ajout du champ `attachedFiles` (JSON) dans `Message` pour l'affichage UI

### Fichiers Modifiés
- `src/Entity/ConversationFile.php`
- `src/Repository/ConversationFileRepository.php`
- `src/Controller/Api/ConversationFileController.php`
- `src/Service/FileService.php` — `uploadConversationFile()` + `generateFileSummary()`
- `src/Service/MistralService.php` — Sauvegarde contenu fichier dans le message
- `src/Repository/MessageRepository.php` — `findLastMessagesWithFiles()`
- `src/Entity/Message.php` — Champ `attachedFiles`
- `frontend/src/components/chat/ChatMessage.tsx` — Affichage visuel fichiers

### Sécurité
| Aspect | Protection |
|--------|------------|
| Stockage BDD | Chiffré AES-256-GCM (`encrypted_text`) |
| Fichier physique | Supprimé après extraction |
| Suppression | CASCADE avec la conversation |
| Transit | HTTPS |

---

## Phase 0c — Nettoyage et Fusion File → ConversationFile (TERMINÉE 28/01/2026)

### Objectif
Simplifier l'architecture en supprimant l'entité `File` (ancien système) au profit de `ConversationFile` (nouveau système chiffré).

### Migration Effectuée
| Ancienne Entité | Nouvelle Entité |
|-----------------|-----------------|
| `File` (non chiffré) | `ConversationFile` (AES-256-GCM) |

### Système Hybride Images

| Cas | Stockage | Envoi à Mistral |
|-----|----------|-----------------|
| Image avec beaucoup de texte (OCR ≥ 250 car) | `ocrText` | Texte OCR seulement |
| Image avec peu/pas de texte | `imageBase64` | Pixtral (vision) |
| Image mixte | `ocrText` + `imageBase64` | OCR + Pixtral |
| Document (PDF, Word, etc.) | `extractedText` | Texte extrait |

### Fichiers Supprimés
- `src/Entity/File.php`
- `src/Repository/FileRepository.php`
- `src/Controller/Api/FileController.php` (routes déplacées vers ConversationFileController)

### Fix Affichage Fichiers (27-28/01/2026)
- Badge fichier utilisait `originalName` au lieu de `name`
- `attachedFiles` sauvegardé en JSON dans Message pour persistance au reload
- Flux "pending message" corrigé dans `ChatWindow.tsx`

---

## Migrations Corrigées (28/01/2026)

> **Contexte** : Après reconstruction Docker, des incohérences ont été détectées dans les migrations (VARCHAR(65535) non supporté par MySQL UTF8MB4, tables dupliquées). Ces corrections ont déjà été appliquées manuellement sur OVH.

### Liste des migrations modifiées

| Migration | Modification |
|-----------|--------------|
| `Version20251224052746` | `file.extracted_text` et `message.content` : VARCHAR(65535) → **LONGTEXT** |
| `Version20251224092031` | Idem — ALTER TABLE vers LONGTEXT |
| `Version20251225052545` | Idem — ALTER TABLE vers LONGTEXT |
| `Version20251225160000` | **Vidée** — `conversation_tag` déjà créée dans 20251224052746 |
| `Version20251226052142` | FK conversation_tag commentées (déjà OK) + LONGTEXT |
| `Version20251226065310` | LONGTEXT |
| `Version20251226070829` | LONGTEXT |
| `Version20251226073934` | LONGTEXT |
| `Version20251227125007` | LONGTEXT |
| `Version20251227141128` | LONGTEXT |
| `Version20251231010307` | LONGTEXT |
| `Version20260102072226` | LONGTEXT |
| `Version20260102075633` | LONGTEXT |
| `Version20260102084923` | LONGTEXT |
| `Version20260102153524` | LONGTEXT |
| `Version20260102162958` | LONGTEXT |

### Pourquoi ces modifications ?

1. **VARCHAR(65535) impossible** : MySQL UTF8MB4 limite VARCHAR à 16383 caractères. Les champs chiffrés (AES-256-GCM + base64) dépassent facilement cette limite → **LONGTEXT obligatoire**.

2. **Table conversation_tag dupliquée** : Créée dans `Version20251224052746`, puis re-créée dans `Version20251225160000` → erreur "table already exists". La 2ème migration a été vidée.

### Impact sur les déploiements

| Environnement | Impact |
|---------------|--------|
| **Docker local** | Migrations exécutées de zéro → OK |
| **dev.lintello.ai** | Migrations déjà marquées "migrées" → **Aucun impact** |
| **www.lintello.ai** | Migrations exécutées de zéro → OK |

> **Note** : Si une migration est déjà dans `doctrine_migration_versions`, elle ne sera pas ré-exécutée même si le fichier PHP a changé.

---

## Phase 2 — Développement Bêta (TERMINÉE)

### Exports Retravaillés
- Word (.docx), PDF, Markdown
- RGPD compliant
- Fichiers : `ExportService.php`, `ExportController.php`

### Sélection Auto Modèle V2.1
| Condition | Modèle |
|-----------|--------|
| Images présentes | Pixtral (Artiste) |
| Code détecté (score ≥ seuil) | Codestral (Ingénieur) |
| Tâche complexe (score ≥ seuil) | Large (Savant) |
| Question simple | Small (Curieux) |

Fichiers : `ModelDetectorService.php`, `ModelDetectionConfig.php`, `ModelBadge.tsx`

### L'dicO (SearXNG Self-Hosted)
- VPS OVH Strasbourg (51.210.4.32)
- URL : search.lintello.ai
- Stack : SearXNG + PostgreSQL
- Tables : `search_query`, `search_result`

### OCR Tesseract
- Extraction texte images scannées
- Combiné avec Pixtral pour meilleure précision
- Format stockage : `[OCR]...[FIN_OCR]` + `[IMAGE_BASE64]`
- Fichiers : `OcrService.php`, `FileService.php`

### Changelog Public
- Entity `Changelog` + CRUD admin
- API `/changelog/grouped`
- Page frontend `/nouveautes`

### Aide/FAQ In-App
1. **Onboarding** : Modal 4 slides au 1er login (champ `hasSeenIntro`)
2. **HelpModal** : FAQ dynamique avec Entity `HelpArticle` (14 articles)
3. **ChangelogModal** : Timeline par version

---

## Fine-Tuning Mistral (REPORTÉ — À EXPLORER)

### Concept
Entraîner un modèle Mistral personnalisé "à la manière LintellO" pour des réponses naturellement cohérentes.

### Format Données
```jsonl
{"messages": [{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]}
```

Volume recommandé : 500 à 5000 exemples de conversations idéales.

### Coûts Estimés
| Élément | Coût |
|---------|------|
| Entraînement (1000 exemples) | ~50-100€ |
| Entraînement (5000 exemples) | ~200-500€ |
| Inférence | Même prix que le modèle de base |

### Prérequis
- [ ] 500+ conversations de qualité (feedback 👍)
- [ ] Script export : `app:export-training-data --min-rating=1 --format=jsonl`
- [ ] Compte Mistral Fine-tuning

### Cycle de Vie
Un modèle fine-tuné est lié à une version spécifique de Mistral. Re-training nécessaire si migration (~100-300€/an).

**Bonnes Pratiques** :
- Versionner les données : `training_data_v1.jsonl`, `v2.jsonl`
- Documenter le modèle de base utilisé
- Backup JSONL hors serveur (Git, S3)

---

## Refonte UX Chat & Sidebar — Phase 2.1 (TERMINÉE)

### Nouvelle UX Accueil (WelcomeHome)
- Input centré proéminent
- Message bienvenue personnalisé
- 4-5 modes suggérés en chips
- Modal "Voir tous les modes"
- Bouton "+" pour fichiers/images

### Nouvelle Sidebar
```
┌─────────────────────────────────┐
│  LintellO                    ☰  │
├─────────────────────────────────┤
│  [+ Nouvelle conversation]      │
│  [Découvrir les modes]          │
│  [Rechercher...]                │
├─────────────────────────────────┤
│  PROJETS                        │
│  ├─ Projet 1                    │
│  └─ Projet 2                    │
├─────────────────────────────────┤
│  RÉCENTS                        │
│  ├─ Conversation 1...           │
│  └─ Conversation 2...           │
├─────────────────────────────────┤
│  Nouveautés   Aide/FAQ          │
│  Profil                   Plan  │
└─────────────────────────────────┘
```

### Tags Désactivés
Les beta testeurs ne les utilisent pas. Code commenté pour réactivation future.

### ProjectHome
Page d'accueil projet avec mode forcé, instructions, input, modes suggérés, liste conversations.

### Fichiers Principaux
- `WelcomeHome.tsx/css`
- `Sidebar.tsx`
- `ProjectHome.tsx/css`
- `SearchModal.tsx`
- `ModesModal.tsx/css`
- `ModeIcon.tsx` (icônes lucide-react)
