# Changelog — ObsiGate Toutes les modifications notables d'ObsiGate sont documentées dans ce fichier. Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/), et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). > **En cours de développement** : les changements à venir sont listés dans la section > [Unreleased](#unreleased). La dernière version livrée est **2.27.0**. --- ## [Unreleased] --- ## [2.27.0] — 2026-09-25 ### Ajouté - **#152 — Viewer XLSX** : affichage des fichiers `.xlsx` en tableaux multi-feuilles (onglets, en-têtes A1), édition inline des cellules avec `PUT /api/file/{vault}/xlsx/save` (backup avant écriture, coercion numérique) et téléchargement du fichier d'origine. --- ## [2.25.1] — 2026-09-24 ### Corrigé - **`/api/diagnostics` — erreur 500 « dictionary changed size during iteration ».** Le calcul des statistiques d'index itérait `inv.word_index` et `index` en direct, pendant que l'indexeur les modifiait depuis un autre thread (build au démarrage, hooks incrémentaux) : l'itérateur de dict levait `RuntimeError` et l'endpoint renvoyait 500. Les deux dicts sont désormais **copiés avant itération** (copie atomique sous le GIL), ce qui supprime la course. --- ## [2.25.0] — 2026-09-24 ### Ajouté - **#115 — barre d'outils de lecture toujours visible.** La barre d'actions d'un document (pop-out, bookmark, Editer, Source, Copier, Partager…) est désormais **épinglée en haut** de la zone de lecture : elle reste accessible en permanence, même au bas d'un document long, au lieu de disparaître au défilement. Elle est rendue comme un enfant direct du conteneur de défilement (`.file-toolbar`), masquée en mode lecture, et alignée dans la fenêtre pop-out. - **#117 — avatars prédéfinis dans le profil.** La section **Profil** propose une galerie de **12 avatars** fournis avec l'application (`frontend/icons/avatar/`) : un clic charge l'image, la recadre au format carré 256 px (même pipeline que l'import) et l'enregistre sur le compte. L'avatar actif est surligné ; l'import d'une photo personnalisée et la suppression restent disponibles. ### Corrigé - **BUG-078 — coloration syntaxique des fichiers de code perdue.** Les feuilles de style highlight.js étaient basculées à partir de la **clé de thème** (`defaut-obsigate`, …) au lieu du **mode** (`dark`/`light`) : les deux feuilles se retrouvaient désactivées et les blocs de code (`.py`, `.sh`, `.ps1`, `.yml`, JSON, blocs Markdown…) s'affichaient en texte brut. Le basculement est désormais piloté par le mode, de façon déterministe, dans le moteur de thème (`themes.js`) comme au premier rendu (`ui.js`) ; sépia et contraste élevé réutilisent la palette claire. --- ## [2.24.0] — 2026-09-24 ### Ajouté - **BUG-077 — assistant IA : bouton « Stop ».** Pendant qu'une réponse se diffuse, le bouton d'envoi du composeur devient un bouton **Stop** (icône carrée, couleur d'alerte) : un clic interrompt immédiatement l'exécution de l'agent (abort de la requête SSE, annulation de la tâche côté serveur à la déconnexion) et la réponse partielle est conservée avec un marqueur « ⏹ Exécution arrêtée. ». Le bouton reste actif (il n'est plus désactivé) tant que l'agent travaille, y compris pendant la reprise d'une confirmation. ### Modifié - **BUG-075 — assistant IA : approbation globale des actions.** Une même réponse du modèle peut demander **plusieurs** mutations (créer un dossier et les fichiers qu'il contient…). Elles sont désormais **regroupées en une seule confirmation** (au lieu d'une action après l'autre) : la carte liste chaque action avec son libellé et son aperçu de diff, et un unique bouton « **Tout approuver (N)** » envoie `confirm_all` — les actions en attente sont appliquées d'un bloc, puis la suite de l'exécution est autorisée sans nouvelle carte. Les appels en lecture du même lot s'exécutent immédiatement (conversation valide). Côté backend, `pending.actions` remplace le report `deferred` des mutations d'un lot (`backend/agent/loop.py`) et `confirm_all` arme `ToolContext.confirmed` pour le reste du run (`backend/bookslm_routes.py`). ### Corrigé - **BUG-074 — assistant IA : bloc d'étapes sans titre et compteur figé à 1.** Le résumé replié affiche désormais un **titre** (le libellé de la première action, « N étapes — Fichier créé : notes/a.md ▶ »), le compteur ne compte plus les **réflexions** (seules les actions) et la reprise d'une confirmation continue de diffuser dans **le même message** au lieu de créer un nouveau message « 1 étape » par approbation : le bloc d'étapes s'accumule sur tout l'échange. - **BUG-076 — assistant IA : arborescence et document ouvert non rafraîchis.** Après une action mutatrice de l'agent (création/suppression/renommage de fichier ou dossier, écriture), l'arborescence est rafraîchie immédiatement (rafraîchissement débouncé sur les événements `tool` mutateurs, sans attendre le watcher) et le document affiché est rechargé depuis le disque ; les outils de création de documents (xlsx/docx/csv/pdf) notifient désormais aussi la visionneuse. --- ## [2.23.0] — 2026-09-24 ### Ajouté - **#114 — Configuration, refonte mobile-responsive.** La page « Configurations » est désormais pensée pour le tactile (≤ 768 px) : modale **plein écran** (`100dvh`, safe-area), sommaire en **drawer coulissant** gauche (`position: fixed`, largeur `min(320px, 88vw)`) avec fond assombri (`#config-modal.config-toc-open::before`) et bouton de fermeture `#config-toc-close` (tap sur le backdrop ou Échap ferme le drawer d'abord, puis la modale) ; formulaires sur **une colonne** ; tous les boutons (save/secondary/danger/add/sm/hamburger/fermer) et liens du sommaire en cibles **≥ 44 px** ; champs et selects en **16 px + min-height 44 px** (anti-zoom iOS) ; rangée « Sauvegarder / Réindexer / Réinitialiser » **sticky** en bas de sa section avec safe-area ; MFA (codes de secours en 1 colonne, champ de code full-width et wrap des rangées d'action) ; débordements webhook/token/share corrigés. Dettes HTML/i18n de l'audit incluses : `.config-actions-row` replacée dans `#cfg-backend-settings` (+ `` orphelin supprimé), id dupliqué `cfg-partages-publics` retiré du `

`, conteneur mort `#plugins-settings-container` supprimé, libellé `#mt-explorer` i18n (`settings.explorer`), doublons `.config-btn-add` et règle morte `.mfa-recovery-input` purgés ; i18n : clés mortes `settings.backend`, `settings.backend_hint`, `settings.restart_badge`, `settings.save`, `settings.plugins` supprimées, `config.toc_close` ajoutée, `settings.tabs` FR corrigé (« Onglets »). Tests : `config-mobile.test.mjs` étendu (27, au CI) + E2E `config-mobile.spec.js` (5, projet `chromium-mobile`). Fiche : [docs/features/settings-mobile-114.md](./docs/features/settings-mobile-114.md). --- ## [2.22.1] — 2026-09-23 ### Corrigé - **BUG-073 — mobile, fin de contenu masquée.** La barre de navigation fixe du bas (`#mobile-toolbar`, 64 px + safe-area) recouvrait le bas de tous les documents et pages en vue mobile (≤ 768 px) : les dernières lignes restaient définitivement sous la barre. Cause : la règle de clearance du bloc mobile ciblait `.main-layout`, classe absente de `index.html` (le vrai conteneur est `.main-body`) — sélecteur mort, aucun dégagement réservé. Correctif : cible `.main-body` (`padding-bottom: calc(64px + env(safe-area-inset-bottom, 0))`), suppression de la règle sœur morte `.editor-modal.active ~ .main-layout`, reset du dégagement en mode lecture (barre masquée) et `body.np-active .content-area` ramené à `76 px` (le dégagement dock, sans double comptage avec `.main-body`). Tests : `tests/frontend/mobile-toolbar.test.mjs` (7, au CI) et E2E `tests/e2e/mobile-toolbar.spec.js` (2, projet `chromium-mobile`). --- ## [2.22.0] — 2026-09-23 ### Ajouté - **#113 — avatar utilisateur.** La section « Profil » des Configurations permet de **choisir / importer une image** (PNG, JPG, WEBP, 8 Mo max) : elle est recadrée en carré 256 px côté client, validée côté serveur (data-URL + octets magiques, sans SVG) et persistée sur le compte (`avatar` dans `data/users.json`, exposé par `GET/PATCH /api/auth/me` et la réponse de login). L'image s'affiche dans le **cercle du profil en bas de la sidebar** (initiales en repli) et peut être supprimée. UI : aperçu circulaire avec overlay caméra au survol, boutons Choisir / Supprimer, erreurs en ligne. Clés i18n FR/EN. ### Modifié - **#113 — ordre des sections Configurations.** La TOC et la page sont réorganisées dans un ordre naturel et **parfaitement synchronisées** : **Profil en premier**, puis Sécurité, Thèmes, Recherche, Historique récent, Tags, Fichiers cachés, Synchronisation, Backend, Diagnostics, IA, Sources connectées, Clés API & MCP, Push, Webhooks, Partages publics, Plugins et **À propos en dernier**. Les ancres `cfg-tags` et `cfg-partages-publics` sont désormais portées par leur `
` (cible de défilement = haut de section). Garde-fous : test statique `tests/frontend/settings-order-avatar.test.mjs` (ordre TOC = page, pas d'ancre morte). --- ## [2.21.0] — 2026-09-23 ### Ajouté - **#112 — section compte en bas de la sidebar.** L'identité (avatar avec initiales, nom, rôle) et la **déconnexion** sont regroupées dans un bloc épinglé au bas de la barre latérale, comme sur les sites professionnels ; un clic sur l'identité ouvre le Profil. Nouvelle clef i18n FR/EN pour le rôle. - **#112 — pellicule d'images défilable.** La molette de la souris fait défiler horizontalement la bande de miniatures et deux **flèches translucides** sur les côtés (révélées au survol) remplissent la même fonction. ### Modifié - **#112 — en-tête allégé.** La **version** quitte le header pour le menu **Options** (ligne « Version ») ; le **bouton de déconnexion** et le **nom de l'utilisateur** sont retirés du header au profit de la section compte de la sidebar. Le header droit ne conserve que l'indicateur hors-ligne, le contexte vault et le bouton Options. --- ## [2.20.0] — 2026-09-23 ### Ajouté - **#111 — visionneuse d'images : flèches latérales translucides.** Deux boutons superposés le long des bords du cadre passent à l'image précédente/suivante ; quasi invisibles au repos, ils se révèlent au survol (et restent visibles sur les appareils tactiles). Un compteur `n / total` complète la barre d'outils. ### Modifié - **#111 — navigation d'images fluide.** Changer d'image se fait désormais **en place** (`showSibling` remplace le `src` du ``) : plus de rechargement de la vue ni de nouvel appel `/api/browse` à chaque flèche, **même dans un dossier contenant beaucoup d'images**. La liste du dossier est mise en cache (TTL court) et les images voisines sont préchargées ; la **pellicule de miniatures reste visible** et la vignette active est simplement re-marquée. - **#111 — image toujours ajustée au cadre.** La visionneuse occupe tout l'espace disponible (zone de contenu en flex, sans défilement de page) et l'image est systématiquement redimensionnée dans son cadre, y compris panneau « Métadonnées » ouvert. --- ## [2.19.2] — 2026-09-23 ### Ajouté - **Lanceur E2E Windows/PowerShell** : `scripts/run-e2e-local.ps1` (+ script npm `test:e2e:ps`) reproduit localement le job CI `e2e` (uvicorn natif, auth désactivée, fixtures TestVault/TestDir, port 2029, projet `chromium-desktop`) sans dépendre de `bash` — indispensable sur les postes Windows où WSL ne démarre pas et où git-bash est bloqué par une politique de contrôle d'application. Le script `bash` reste la référence pour la CI/Linux. ### Corrigé - **BUG-072 — visionneuse d'images** : le plein écran (lightbox) et le panneau « Métadonnées » sont désormais **conservés lors de la navigation** entre images (flèches ←/→ et clic sur la pellicule) ; auparavant chaque changement d'image recréait la visionneuse et perdait ces états. Le panneau de métadonnées s'affiche maintenant en **barre latérale à droite de l'image** (au lieu d'une bande sous la pellicule) et reste visible en plein écran. --- ## [2.19.1] — 2026-09-23 ### Corrigé - **#110 — lisibilité et positionnement du lecteur média** : en mode mobile, la barre audio passe en grille (barre de progression pleine largeur sur sa propre ligne) et les actions secondaires (précédent/suivant/agrandir/volume) sont masquées pour éviter tout chevauchement ; le volume est aussi masqué sur les écrans intermédiaires en desktop, et `overflow: hidden` empêche le débordement hors de la pilule. La mini-fenêtre vidéo n'est plus ré-aimantée sur les bords : elle se déplace et se redimensionne **librement** (position absolue mémorisée, centre autorisé), le glisser fonctionnant désormais depuis n'importe quel point de la fenêtre (boutons/curseurs/poignée exclus, seuil de 4 px pour préserver les contrôles natifs de la vidéo). --- ## [2.19.0] — 2026-09-23 ### Ajouté - **#110 — Lecteur média persistant « Now Playing »** : les fichiers audio et vidéo continuent de jouer pendant la navigation grâce à un contrôleur global `frontend/js/now-playing.js` qui possède **un seul** élément `