--- issueRef: "#304" version: 5 updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} updatedAt: 1789024612607 --- # Carnet #304 - Navigation historique ArrowUp dans chat multiligne ## Demande - Date: 2026-09-10. - Problème: quand il y a plus de 2 lignes dans le champ chat, `ArrowUp` remonte le curseur dans le textarea au lieu de rappeler le message précédent. - Comportement souhaité: à la manière d'un terminal Linux, pouvoir remonter dans l'historique des messages quelle que soit la taille du message, tant que le curseur est à la fin de la dernière ligne. - Si le curseur n'est pas à la fin de la dernière ligne, conserver le comportement texte normal. ## Cadrage UX Règle de déclenchement `ArrowUp` historique uniquement si: - aucun modificateur (`Shift`, `Ctrl`, `Alt`, `Meta`); - aucune composition IME en cours (`isComposing`, et cas navigateur `keyCode 229`); - aucune sélection active; - curseur simple exactement à la fin du texte: `selectionStart === selectionEnd === value.length`; - historique contient une entrée précédente. Navigation: - Le premier `ArrowUp` mémorise intégralement le brouillon courant, puis affiche le dernier message envoyé. - Les `ArrowUp` suivants remontent l'historique. - Sur l'entrée la plus ancienne, conserver sans boucle. - `ArrowDown`, depuis une entrée rappelée et avec le curseur en fin de texte, avance vers l'entrée plus récente. - Après l'entrée la plus récente, `ArrowDown` restaure exactement le brouillon mémorisé, curseur en fin de texte. - Hors navigation historique, ou si le curseur n'est pas à la fin, `ArrowDown` reste natif. - Les messages déjà envoyés ne sont jamais modifiés. - L'envoi termine la navigation, efface le brouillon mémorisé et replace le champ dans son état normal. - Après injection/restauration, placer le curseur à la fin et rendre la dernière ligne visible. ## Cadrage Architect - Frontend pur, aucun contrat backend/DTO. - Cause technique probable: le handler actuel refuse `ArrowUp` dès qu'il y a un `\n` avant le curseur (`target.value.slice(0, target.selectionStart).includes("\n")`). - Remplacer par une règle fondée sur la position exacte du curseur à `value.length`, sans sélection ni modificateur/IME. - Slash menu ouvert reste prioritaire: navigation suggestions, pas historique. - `Enter`/`Shift+Enter`, tickets assistant, textareas génériques hors chat: inchangés. Fichiers probables: - `frontend/src/features/agents/CustomAgentChatView.tsx` - `frontend/src/features/agents/CustomAgentChatView.test.tsx` ## Critères QA - `ArrowUp` rappelle l'historique depuis la fin d'un brouillon vide, mono-, bi- et multiligne. - À toute autre position, déplacement natif du curseur. - Sélection, modificateur ou composition IME empêchent le rappel. - Plusieurs `ArrowUp` parcourent récent -> ancien sans boucle. - `ArrowDown` revient vers les messages récents puis restaure fidèlement le brouillon initial. - Sauts de ligne, espaces finaux et caractères Unicode du brouillon restaurés sans altération. - Modifier une entrée rappelée ne modifie jamais le message déjà envoyé. - Envoyer une entrée rappelée fonctionne et réinitialise la navigation. - Historique vide: pas de changement ni erreur. - Slash menu ouvert + `ArrowUp` continue de déplacer l'index des suggestions. ## Implémentation DevFrontend — 2026-09-10 ### Livré - Suppression de la règle fondée sur la présence d'un saut de ligne avant/après le curseur. - `ArrowUp` n'est intercepté que sans modificateur, hors composition IME (`isComposing` et `keyCode 229`), avec un caret simple exactement à `value.length` et un historique non vide. - `ArrowDown` n'est intercepté qu'avec les mêmes gardes de caret et lorsqu'une navigation d'historique est réellement active; sinon le textarea conserve son comportement natif. - La priorité du menu slash reste inchangée et son scénario `ArrowUp` est maintenant couvert explicitement. - Après rappel ou restauration du brouillon, un effet replace sélection et caret à la fin puis fixe `scrollTop` à `scrollHeight` pour rendre la dernière ligne visible. - Le brouillon mémorisé reste intégral: sauts de ligne, caractères Unicode et espaces finaux ne sont pas normalisés. - `Enter`, `Shift+Enter`, l'envoi, le stockage de l'historique et les textareas hors chat ne sont pas modifiés. ### Fichiers modifiés - `frontend/src/features/agents/CustomAgentChatView.tsx` - `frontend/src/features/agents/CustomAgentChatView.test.tsx` ### Commandes exécutées DevFrontend - `cd frontend && npm run typecheck` — vert. - `cd frontend && npm test -- src/features/agents/CustomAgentChatView.test.tsx` — vert, 1 fichier / 71 tests. - `cd frontend && npm run build` — vert, 515 modules transformés; seul l'avertissement Vite existant sur la taille du chunk principal subsiste. - `git diff --check` — vert. ## Validation QA — 2026-09-10 Verdict: VERT. Commandes exécutées: - `npm test -- src/features/agents/CustomAgentChatView.test.tsx` — OK, 71 tests. - `npm run typecheck` — OK. - `npm run build` — OK, avertissement Vite existant chunk > 500 kB. - `git diff --check` — OK. Conclusion QA: - `ArrowUp` rappelle l'historique depuis la fin exacte d'un brouillon multiligne et restaure le brouillon fidèlement via `ArrowDown`. - Les cas sélection, modificateurs, IME, curseur hors fin, historique vide et slash menu ouvert restent natifs/prioritaires. - Aucun finding bloquant. ## Blocage Topologie Git — 2026-09-10 - Branche courante: `fix/304-arrowup-chat-multiline-history`. - `git status` montre les deux fichiers #304 modifiés mais non committés: - `frontend/src/features/agents/CustomAgentChatView.tsx` - `frontend/src/features/agents/CustomAgentChatView.test.tsx` - Main a demandé à Git de committer/merger #304 après QA verte. Trois tentatives `idea_ask_agent` vers Git ont expiré au rendez-vous (600s), malgré un `idea_launch_agent` de rattachement. - Main ne réalise pas la topologie git à la place de l'agent Git selon la règle projet. #304 reste donc QA vert mais non committé/mergé. - #305 ne doit pas démarrer sur le même worktree tant que #304 n'est pas finalisé, pour éviter de mélanger les changements. ## Topologie Git — 2026-09-10 (reprise après expiration des délégations) - QA reconfirmée par Git: `npm test -- src/features/agents/CustomAgentChatView.test.tsx` 71/71, `npm run typecheck` OK, `git diff --check` OK. - Commit du correctif (2 fichiers uniquement): `db312bf` sur `fix/304-arrowup-chat-multiline-history` — `fix(frontend): ArrowUp rappelle l'historique chat même en multiligne — #304`. - Merge local: `develop` ← `--no-ff` → `ee5373e`. Branche `fix/304-arrowup-chat-multiline-history` conservée. - Exclus (worktree, non committés): `.ideai/*` (tickets/counter/index/attachments/chat-drafts), `scripts/`. - Aucun push. #305 peut démarrer: `feature/305-scheduled-project-tasks-mcp` sera resynchronisée sur `develop` par Git avant le début du travail.