docs(sprint-7.5): close FTD-44, track FTD-47, extend Golden Dataset
Some checks are pending
CI / quality (push) Waiting to run

- TECH_DEBT.md v1.31: FTD-44 resolved (audio hooks relocated to
  shared/lib/audio/, see d9160c4). New FTD-47 (T1 Live sessions
  untagged in historique, discovered during doc review). 14 -> 15
  active FTD, cap reached.
- CHANGELOG.md: new Sprint 7.5 Clean entry.
- GOLDEN_DATASET.md v1.1: Groupe D extended with D12-D16 (T1 Live
  manual test coverage), documenting the tache tag divergence
  (EO_T1 vs expected EO_T1_LIVE) and the probabilistic
  interruption caveat (cross-ref FTD-45/46).

No code changes.
This commit is contained in:
Hermann_Kitio 2026-07-02 05:11:04 +03:00
parent d9160c4493
commit 01f052dadc
3 changed files with 95 additions and 52 deletions

View file

@ -29,6 +29,27 @@ Chaque entrée suit ce format :
--- ---
## [Unreleased] — 2026-07-02 — Sprint 7.5 — Clean FTD-44
### Changed
- Hooks audio génériques `useAudioCapture`, `useAudioPlayback`, `useAudioRecording` (+ test) déplacés de `features/t2-live/hooks/` vers `shared/lib/audio/`. Imports mis à jour dans `useT2LiveSession.ts` et `useT1LiveSession.ts`. Résout FTD-44.
### Removed
- Marqueurs `// TODO(FTD-44)` retirés de `useT1LiveSession.ts`.
### Notes
- 4 fichiers déplacés (3 hooks + 1 test) + 2 fichiers d'imports édités. Aucun changement fonctionnel (pipeline audio « Voie A » intact).
- 301/301 tests verts, 0 erreur typecheck.
- Validation manuelle : T2 Live D2-D5 verts ; T1 Live parcours complet vert (préparation → dialogue → présentation → interruption → fin → téléchargement audio → rapport), navigation privée. D6 non rejoué (optionnel, état pré-existant partiel, sans lien avec cette refacto).
- Commit `d9160c4`.
- **TECH_DEBT.md v1.30 → v1.31** : FTD-44 résolue (fermée) ; ajout FTD-47 🟢 (sessions T1 Live non taguées dans l'historique — découverte pendant cette session, racine Sprint 7a backend). **14 → 15 FTD actives — cap de 15 atteint.**
- **GOLDEN_DATASET.md** : Groupe D étendu avec D12-D16 (T1 Live) — libellés vérifiés dans le code réel (`T1PreparationPage.tsx`, `T1DialoguePage.tsx`, `t1-machine.ts`).
---
## [Unreleased] — 2026-06-30 — Sprint 7b — Frontend T1 Live (monologue + interruption non déterministe) ## [Unreleased] — 2026-06-30 — Sprint 7b — Frontend T1 Live (monologue + interruption non déterministe)
### Added ### Added

View file

@ -90,7 +90,7 @@
> ⚠️ Certains items décrivent un état cible (sprints futurs), pas l'état implémenté actuel — voir marqueurs par ligne. > ⚠️ Certains items décrivent un état cible (sprints futurs), pas l'état implémenté actuel — voir marqueurs par ligne.
| # | Test | Compte | Résultat attendu | ✅/❌ | | # | Test | Compte | Résultat attendu | ✅/❌ |
| --- | ------------------------------------ | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----- | | --- | ------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- |
| D1 | Dashboard Premium après connexion | test.premium | Historique, bouton examen actif, T2 live accessible ; indice / patterns / profil ⏳ non implémenté (sprint ultérieur) | | | D1 | Dashboard Premium après connexion | test.premium | Historique, bouton examen actif, T2 live accessible ; indice / patterns / profil ⏳ non implémenté (sprint ultérieur) | |
| D2 | Accéder à EO T2 live | test.premium | Page préparation T2, bouton "Démarrer le dialogue" actif | | | D2 | Accéder à EO T2 live | test.premium | Page préparation T2, bouton "Démarrer le dialogue" actif | |
| D3 | Démarrer le dialogue T2 | test.premium | État "Connecting" puis "Listening" ; le candidat prend la parole en premier (le candidat initie l'interaction de service), l'IA répond ensuite | | | D3 | Démarrer le dialogue T2 | test.premium | État "Connecting" puis "Listening" ; le candidat prend la parole en premier (le candidat initie l'interaction de service), l'IA répond ensuite | |
@ -102,9 +102,18 @@
| D9 | Blocage à T=0 (Examen EE) | test.premium | Zone de texte figée, message "Temps écoulé", envoi auto — ⏳ Sprint 8 — non implémenté | | | D9 | Blocage à T=0 (Examen EE) | test.premium | Zone de texte figée, message "Temps écoulé", envoi auto — ⏳ Sprint 8 — non implémenté | |
| D10 | Lancer mode Examen EO | test.premium | Timer 12:00, enregistrement actif, tâches enchaînées — ⏳ Sprint 8 — non implémenté | | | D10 | Lancer mode Examen EO | test.premium | Timer 12:00, enregistrement actif, tâches enchaînées — ⏳ Sprint 8 — non implémenté | |
| D11 | Analyse patterns (5+ productions) | test.premium | Section "Mon profil" avec erreurs récurrentes classées — ⏳ non implémenté (sprint ultérieur) | | | D11 | Analyse patterns (5+ productions) | test.premium | Section "Mon profil" avec erreurs récurrentes classées — ⏳ non implémenté (sprint ultérieur) | |
| D12 | Accès à EO T1 Live → page préparation | test.premium | Carte « Tâche 1 — Live » débloquée sur `/simulation/eo` → clic → `/simulation/eo/t1/live/preparation` (titre « Préparation — Tâche 1 Live », bouton « Je suis prêt — démarrer la présentation ») | |
| D13 | Démarrer la présentation | test.premium | Passage à `/simulation/eo/t1/live/dialogue`, état `presenting` (« À vous — présentez-vous. ») ; le candidat parle en premier — monologue, pas de VAD micro | |
| D14 | Interruption examinateur (non déterministe) | test.premium | Si déclenchée par le backend : état `interrupted` (« L'examinateur vous interrompt — répondez-lui. »), reprise en `presenting` — ⚠️ non garantie à chaque essai (probabiliste, cf. note D12-D16) | |
| D15 | Fin → écran terminal | test.premium | Bouton « Terminer » → état `processing` (« Évaluation en cours… ») → écran « Session terminée » avec boutons « Télécharger l'audio » et « Voir le rapport » | |
| D16 | Rapport après T1 Live | test.premium | Rapport complet affiché (`/rapport/:id`) — ⚠️ aucun tag « T1 Live » visible (à la différence du tag « T2 Live »), cf. note D12-D16 | |
> **Note D6 (partiel)** : un drop WebSocket subi mène bien à l'état `error` avec un message utilisateur clair (`T2DialoguePage.tsx:165-184`, `useT2LiveSession.ts:336-380`). Mais l'« option de reprise » du critère cible n'est PAS implémentée : l'écran d'erreur n'offre qu'un bouton « Retour aux sujets » (`T2DialoguePage.tsx:176-180`), pas de bouton « Réessayer » / reconnexion. Item à reclasser ✅ une fois la reprise ajoutée. > **Note D6 (partiel)** : un drop WebSocket subi mène bien à l'état `error` avec un message utilisateur clair (`T2DialoguePage.tsx:165-184`, `useT2LiveSession.ts:336-380`). Mais l'« option de reprise » du critère cible n'est PAS implémentée : l'écran d'erreur n'offre qu'un bouton « Retour aux sujets » (`T2DialoguePage.tsx:176-180`), pas de bouton « Réessayer » / reconnexion. Item à reclasser ✅ une fois la reprise ajoutée.
> **Note D12-D16 (T1 Live)** : D14 dépend d'une décision probabiliste backend (P0=0.2 aucune interruption, P1=0.6 une, P2=0.2 deux, fenêtre 25-75 s) — un essai sans interruption est un résultat nominal, pas un échec de test. Deux dettes amont affectent le réalisme du dialogue sans bloquer ces tests : **FTD-45** (gelée, relances de l'examinateur parfois hors-sujet, extension TD-23) et **FTD-46** (gelée, transcription Gemini Live parfois imprécise) — toutes deux hors contrôle frontend.
>
> **D16 — divergence vérifiée dans le code** : contrairement à T2 Live (`tache='EO_T2_LIVE'`, libellé « EO · Tâche 2 Live » dans l'historique), le backend T1 Live persiste `tache='EO_T1'` / `mode='entrainement'` (`t1live.ts`) — identique à une simulation T1 batch classique. Vérifié dans `historique.ts` (`TACHE_NUMBER`) et `RapportPage.tsx` : **aucun tag « Live » n'existe** côté frontend pour T1. Tracé dans `TECH_DEBT.md` (**FTD-47**, nouvelle, 🟢 Mineur).
--- ---
## Groupe E — Paiements Stripe ## Groupe E — Paiements Stripe
@ -204,5 +213,6 @@ Test échoue
## Historique de ce document ## Historique de ce document
| Version | Date | Changements | | Version | Date | Changements |
| ------- | ---------- | ------------------------------------ | | ------- | ---------- | ------------------------------------------------------------------- |
| 1.0 | 2026-04-17 | Création initiale, 55 tests frontend | | 1.0 | 2026-04-17 | Création initiale, 55 tests frontend |
| 1.1 | 2026-07-02 | Ajout Groupe D étendu T1 Live (D12-D16) — Sprint 7.5 Clean (FTD-44) |

View file

@ -1,6 +1,6 @@
# TECH_DEBT.md — Expria Frontend # TECH_DEBT.md — Expria Frontend
> **Document de référence — Version 1.30** > **Document de référence — Version 1.31**
> Ce document recense les décisions techniques prises par pragmatisme qui devront être revisitées, les stubs temporaires, et les fonctionnalités reportées. > Ce document recense les décisions techniques prises par pragmatisme qui devront être revisitées, les stubs temporaires, et les fonctionnalités reportées.
> À mettre à jour après chaque session de développement. > À mettre à jour après chaque session de développement.
> >
@ -314,6 +314,25 @@ Risque : confusion pour un futur dev sur quel composant utiliser.
--- ---
### FTD-47 — Sessions T1 Live non taguées dans l'historique
**Priorité :** 🟢 Mineur
**Statut :** Ouvert — introduit Sprint 7a (backend), découvert Sprint 7.5
**Estimation de session :** à évaluer (cross-repo backend + frontend)
**Description :** Contrairement à T2 Live (`tache='EO_T2_LIVE'`, tag « T2 Live » visible dans l'historique), le backend T1 Live persiste `tache='EO_T1'` / `mode='entrainement'` (`t1live.ts`) — identique à une simulation T1 batch classique. Aucun champ ou tag ne permet de distinguer une session dialoguée en direct avec l'examinateur IA d'un simple enregistrement offline. Vérifié dans `historique.ts` (`TACHE_NUMBER`) et `RapportPage.tsx` : aucun tag « Live » n'existe côté frontend pour T1.
**Impact :** l'utilisateur ne peut pas retrouver ses sessions T1 Live dans son historique — confusion possible, et T1 Live (feature Premium différenciante) perd sa visibilité propre.
**À faire :** décision d'architecture — nouvelle valeur `tache` (ex. `EO_T1_LIVE`, migration cross-repo comme T2) ou champ booléen dédié (`is_live`). Nécessite une session backend + frontend coordonnée. Hors scope Sprint 7.5 (doc-only).
**Session concernée :** découverte Sprint 7.5, racine Sprint 7a.
**Note :** la racine du problème est backend (`t1live.ts`). Une entrée miroir dans `expria-backend/docs/TECH_DEBT-backend.md` serait pertinente mais n'a pas été créée (hors scope repo de cette session).
**Condition de résolution :** décision d'architecture prise + migration cross-repo implémentée.
---
## 3. Fonctionnalités reportées ## 3. Fonctionnalités reportées
### FTD-07 — Sentry non intégré ### FTD-07 — Sentry non intégré
@ -456,16 +475,7 @@ Frontend :
--- ---
### FTD-44 — Hooks audio génériques empruntés à `features/t2-live/` (T1 Live) > FTD-44 résolue au Sprint 7.5 (2026-07-02) — voir §5 Historique des résolutions.
**Priorité :** 🟡 Important
**Statut :** Gelé — réactivé au Sprint 7.5 (« factorisation Sprint 7 »)
**Estimation de session :** 0,5 jour
**Description :** Le flux T1 Live (Sprint 7b) importe directement les trois hooks audio génériques de `features/t2-live/hooks/` (`useAudioCapture`, `useAudioPlayback`, `useAudioRecording`) — une violation assumée de la frontière inter-features FSD (un feature ne devrait pas importer un sibling). Décision prise pour NE PAS toucher aux fichiers T2 (pipeline audio validé à l'oreille, intouchable jusqu'à factorisation). Sites d'import marqués `// TODO(FTD-44)` dans `features/t1-live/hooks/useT1LiveSession.ts`.
**À faire :** relocaliser les trois hooks (génériques par nature : aucune logique T2 spécifique) vers `shared/lib/audio/`, puis migrer les imports T2 ET T1 vers ce chemin partagé. Validation à l'oreille obligatoire après déplacement (T2 + T1).
**Condition de résolution :** Sprint 7.5 (factorisation Sprint 7), une fois les flux T1 et T2 Live stabilisés.
--- ---
@ -538,7 +548,7 @@ Frontend :
## 5. Historique des résolutions ## 5. Historique des résolutions
| ID | Description | Résolu le | Comment | | ID | Description | Résolu le | Comment |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FTD-11 | `@theme` Tailwind 4 non défini — palette et typographie absentes | 2026-04-18 | Résolu au Sprint 0.5 (design system). Palette Direction H complète (canvas/surface/ink/expria/deep/semantic) + typo Plus Jakarta Sans définis dans `src/index.css` via `@theme {}` et `.dark {}`. shadcn/ui remappé sur ces tokens. Règle L ajoutée dans `DEVELOPMENT_PRINCIPLES.md` pour garantir l'usage exclusif des tokens. | | FTD-11 | `@theme` Tailwind 4 non défini — palette et typographie absentes | 2026-04-18 | Résolu au Sprint 0.5 (design system). Palette Direction H complète (canvas/surface/ink/expria/deep/semantic) + typo Plus Jakarta Sans définis dans `src/index.css` via `@theme {}` et `.dark {}`. shadcn/ui remappé sur ces tokens. Règle L ajoutée dans `DEVELOPMENT_PRINCIPLES.md` pour garantir l'usage exclusif des tokens. |
| FTD-13 | Incompatibilité Vitest 3 / Vite 8 (conflit de types `Plugin<any>` entre le Vite 8 top-level avec Rolldown et le Vite 7 pinné de Vitest 3.2.4 ; `npm run build` cassé) | 2026-04-17 | Résolu par upgrade Vitest `3.2.4 → 4.1.4` (et `@vitest/coverage-v8` idem) à l'étape 12-bis du Sprint 0. Vitest 4.x supporte nativement Vite 8 Rolldown. Correctif complémentaire : script `typecheck` passé de `tsc --noEmit -p tsconfig.app.json` à `tsc -b --noEmit` pour couvrir aussi `tsconfig.node.json` (d'où `vite.config.ts`) et éviter qu'un bug similaire échappe à la CI. | | FTD-13 | Incompatibilité Vitest 3 / Vite 8 (conflit de types `Plugin<any>` entre le Vite 8 top-level avec Rolldown et le Vite 7 pinné de Vitest 3.2.4 ; `npm run build` cassé) | 2026-04-17 | Résolu par upgrade Vitest `3.2.4 → 4.1.4` (et `@vitest/coverage-v8` idem) à l'étape 12-bis du Sprint 0. Vitest 4.x supporte nativement Vite 8 Rolldown. Correctif complémentaire : script `typecheck` passé de `tsc --noEmit -p tsconfig.app.json` à `tsc -b --noEmit` pour couvrir aussi `tsconfig.node.json` (d'où `vite.config.ts`) et éviter qu'un bug similaire échappe à la CI. |
| FTD-16 | `VITE_MAINTENANCE_MODE` non lu dans le code — la variable d'env était dans `env.ts` mais jamais consommée | 2026-04-18 | Résolu au Sprint 1 étape 6. Ajout de `isMaintenanceMode` dans `src/shared/config/env.ts` et garde dans `src/app/main.tsx` : `isMaintenanceMode ? <MaintenancePage /> : <Providers />`. `MaintenancePage` est statique (aucun provider requis), tokens Direction H exclusivement. | | FTD-16 | `VITE_MAINTENANCE_MODE` non lu dans le code — la variable d'env était dans `env.ts` mais jamais consommée | 2026-04-18 | Résolu au Sprint 1 étape 6. Ajout de `isMaintenanceMode` dans `src/shared/config/env.ts` et garde dans `src/app/main.tsx` : `isMaintenanceMode ? <MaintenancePage /> : <Providers />`. `MaintenancePage` est statique (aucun provider requis), tokens Direction H exclusivement. |
@ -561,6 +571,7 @@ Frontend :
| FTD-35 | `PresentationGenereeT1Page` : refresh sans simulation active | 2026-04-26 | Sprint 5.5 — Subsumée par FTD-41 : la résolution de FTD-41 (persistance T1 en BDD) élimine le problème de FTD-35 (localStorage instable). Aucune action propre. | | FTD-35 | `PresentationGenereeT1Page` : refresh sans simulation active | 2026-04-26 | Sprint 5.5 — Subsumée par FTD-41 : la résolution de FTD-41 (persistance T1 en BDD) élimine le problème de FTD-35 (localStorage instable). Aucune action propre. |
| FTD-38 | `useAudioRecorder` : mise à jour de ref pendant le render | 2026-04-26 | Sprint 5.5 — Refactor `optionsRef.current = options` (assignation pendant render + eslint-disable) en `useEffect(() => { optionsRef.current = options })`. Sémantique préservée : effet sans deps run après chaque commit, donc avant le prochain render qui lit la ref. eslint-disable retiré. 195 lignes de tests `useAudioRecorder.test.ts` toujours vertes (219/219). | | FTD-38 | `useAudioRecorder` : mise à jour de ref pendant le render | 2026-04-26 | Sprint 5.5 — Refactor `optionsRef.current = options` (assignation pendant render + eslint-disable) en `useEffect(() => { optionsRef.current = options })`. Sémantique préservée : effet sans deps run après chaque commit, donc avant le prochain render qui lit la ref. eslint-disable retiré. 195 lignes de tests `useAudioRecorder.test.ts` toujours vertes (219/219). |
| FTD-39 | Règle D violée dans `StatCards.tsx` (`plan === 'free'` en dur) | 2026-04-26 | Sprint 5.5 — Remplacement de `{plan === 'free' && ...}` (ligne 90) par `{!hasAccess(plan, 'dashboard') && ...}`. Sémantique du gating : afficher « Renouvellement offert à l'upgrade » uniquement aux utilisateurs sans accès au dashboard complet (= Free). Import `hasAccess` ajouté depuis `@/entities/user/lib`. Tests Dashboard verts. | | FTD-39 | Règle D violée dans `StatCards.tsx` (`plan === 'free'` en dur) | 2026-04-26 | Sprint 5.5 — Remplacement de `{plan === 'free' && ...}` (ligne 90) par `{!hasAccess(plan, 'dashboard') && ...}`. Sémantique du gating : afficher « Renouvellement offert à l'upgrade » uniquement aux utilisateurs sans accès au dashboard complet (= Free). Import `hasAccess` ajouté depuis `@/entities/user/lib`. Tests Dashboard verts. |
| FTD-44 | Hooks audio génériques empruntés à `features/t2-live/` (T1 Live) | 2026-07-02 | Sprint 7.5 Clean — `useAudioCapture`, `useAudioPlayback`, `useAudioRecording` (+ test) déplacés de `features/t2-live/hooks/` vers `shared/lib/audio/`. Imports mis à jour dans `useT2LiveSession.ts` et `useT1LiveSession.ts`, marqueurs `TODO(FTD-44)` retirés. Dérogation Règle B assumée sur la vague `useAudioRecording` (hook + test déplacés ensemble pour préserver le chemin d'import relatif `../useAudioRecording`, condition nécessaire au respect de Règle C — jamais rouge entre étapes). Validation à l'oreille manuelle : T2 Live D2-D5 verts, T1 Live parcours complet vert. 301/301 tests, 0 erreur typecheck. Commit `d9160c4`. |
| FTD-19 | Token `--shadow-focus` absent de `src/index.css` | 2026-04-22 | Résolu au Sprint 3.5. Ajout de `--shadow-focus: 0 0 0 3px rgba(27, 79, 216, 0.18)` dans `@theme {}` (valeur conforme à `DESIGN_SYSTEM.md §2`) et `--shadow-focus: 0 0 0 3px rgba(91, 127, 255, 0.32)` dans `.dark {}` (recalculé sur la teinte expria dark `#5B7FFF`). Tailwind 4 génère automatiquement l'utility `shadow-focus`. Migration de 5 occurrences `ring-2 ring-expria/20``shadow-focus` dans `Button.tsx`, `Card.tsx`, `SimulationForm.tsx` (×3), `SpecialCharsKeyboard.tsx`. Factorisation bonus : className dupliquée des boutons secondaires de `SimulationForm` extraite en const `secondaryActionBtn`. | | FTD-19 | Token `--shadow-focus` absent de `src/index.css` | 2026-04-22 | Résolu au Sprint 3.5. Ajout de `--shadow-focus: 0 0 0 3px rgba(27, 79, 216, 0.18)` dans `@theme {}` (valeur conforme à `DESIGN_SYSTEM.md §2`) et `--shadow-focus: 0 0 0 3px rgba(91, 127, 255, 0.32)` dans `.dark {}` (recalculé sur la teinte expria dark `#5B7FFF`). Tailwind 4 génère automatiquement l'utility `shadow-focus`. Migration de 5 occurrences `ring-2 ring-expria/20``shadow-focus` dans `Button.tsx`, `Card.tsx`, `SimulationForm.tsx` (×3), `SpecialCharsKeyboard.tsx`. Factorisation bonus : className dupliquée des boutons secondaires de `SimulationForm` extraite en const `secondaryActionBtn`. |
--- ---
@ -600,3 +611,4 @@ Frontend :
| 1.28 | 2026-04-26 | Sprint 6c — FTD-09 et FTD-33 résolues (dégelées → fermées). **14 FTD actives** (inchangé — les gelées ne comptaient pas dans le cap). | | 1.28 | 2026-04-26 | Sprint 6c — FTD-09 et FTD-33 résolues (dégelées → fermées). **14 FTD actives** (inchangé — les gelées ne comptaient pas dans le cap). |
| 1.29 | 2026-06-30 | Sprint 7b (T1 Live) — Ajout FTD-44 🟡 **gelée** (hooks audio génériques empruntés à `features/t2-live/`, réactivée au Sprint 7.5). **14 FTD actives** (inchangé — entrée gelée, ne compte pas dans le cap, même mécanique que FTD-06). | | 1.29 | 2026-06-30 | Sprint 7b (T1 Live) — Ajout FTD-44 🟡 **gelée** (hooks audio génériques empruntés à `features/t2-live/`, réactivée au Sprint 7.5). **14 FTD actives** (inchangé — entrée gelée, ne compte pas dans le cap, même mécanique que FTD-06). |
| 1.30 | 2026-06-30 | Sprint 7b (T1 Live, finalisation) — Ajout FTD-45 🟡 **gelée** (relances Gemini hors-sujet, extension TD-23) et FTD-46 🟡 **gelée** (transcription Gemini Live hasardeuse). Bugs amont observés au test manuel, hors contrôle frontend. **14 FTD actives** (inchangé — entrées gelées, ne comptent pas dans le cap). | | 1.30 | 2026-06-30 | Sprint 7b (T1 Live, finalisation) — Ajout FTD-45 🟡 **gelée** (relances Gemini hors-sujet, extension TD-23) et FTD-46 🟡 **gelée** (transcription Gemini Live hasardeuse). Bugs amont observés au test manuel, hors contrôle frontend. **14 FTD actives** (inchangé — entrées gelées, ne comptent pas dans le cap). |
| 1.31 | 2026-07-02 | Sprint 7.5 Clean — FTD-44 résolue (hooks audio relocalisés vers `shared/lib/audio/`, dégelée → fermée ; ne libère pas de place, une entrée gelée ne comptait pas dans le cap). Ajout FTD-47 🟢 (sessions T1 Live non taguées dans l'historique — découverte Sprint 7.5, racine Sprint 7a backend). **14 → 15 FTD actives — cap de 15 atteint.** |