--- issueRef: "#245" version: 8 updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} updatedAt: 1787484920086 --- 2026-08-23 - Signalement utilisateur avec capture: dans la conversation agent / CLI custom, après le premier appel à l’agent, les appels suivants n’affichent plus correctement progress ni usage des tools; la chatbox reste éditable; l’agent ciblé par l’utilisateur (ex Main) n’apparaît pas busy alors qu’un agent peut être actif dans Work state. - Tickets antérieurs liés relus: #236 (collisions de clés progress/tools + store annonces borné par projectId), #238 (désalignement conversation vs activité réelle), #241 (reconnect web ne réattachait pas `chatSinks` après reconnexion). - UX: la source visuelle de vérité du tour utilisateur reste l’agent ciblé (`Main`) jusqu’au terminal; chatbox disabled du submit au `final`/erreur/annulation/timeout terminal; si délégation, afficher sous-état `Main attend Architect`; l’absence de progress détaillé ne doit jamais réactiver l’input. - Architect: suspicion principale sur un désalignement entre flux structuré de conversation (`ChatBridge`/`ReplyChunk`), état busy canonique du tour structuré/rendez-vous, et projection UI de cellule. Correctif minimal sûr proposé: verrouillage chatbox + badge busy pilotés par l’état busy canonique de l’agent, pas par la présence d’événements `progress/tools`; corriger ensuite le relay live des non-terminaux si nécessaire. - Git: branche locale créée depuis `develop` = `fix/245-custom-cli-busy-progress-chatbox`. - DevBackend: backend impliqué. Cause 1: `agent_send` (desktop) et `ws_send_chat` (web) appellent la session structurée directement (`send` / `send_with_tap`) sans passer par `InputMediator::enqueue_silent`; résultat: pas de `AgentBusyChanged`, `GetProjectWorkState` voit l’agent idle, et la cellule/chatbox ne peuvent pas s’aligner sur un busy canonique. Cause 2: côté web, `ws_send_chat` n’utilise pas `send_with_tap`, donc peut rater des progress/tools live non terminaux. Fix implémenté: ajout d’un `StructuredHumanTurnGuard` partagé sur le backend; `agent_send` et `ws_send_chat` démarrent désormais un tour humain médié, marquent alive sur activité, clearent idle sur terminal/erreur/drop, et le web passe aussi par `send_with_tap`. Tests backend/web ciblés ajoutés; commandes exécutées par DevBackend: `cargo fmt`, `cargo test -p web-server websocket_chat_send -- --nocapture`, `cargo check -p app-tauri --lib`. - DevFrontend: source actuelle du verrouillage = `busy` local de `CustomAgentChatView`, remis à false seulement sur `final/error`; la cellule Layout lit déjà un busy canonique Work state mais ne le propage pas à la vue de chat. De plus, `progressIndex` vit à travers les tours et peut fusionner à tort des progress/tools legacy récurrents sur les tours suivants. Fix implémenté: `effectiveBusy = localBusy || canonicalBusy || requesterDelegation.active`; textarea/Joindre/Envoyer restent verrouillés tant que le tour canonique est ouvert; fallback de délégation `Main attend Architect`; `agentBusyChanged(false)` du même agent peut relâcher le busy local si le terminal stream n’est pas arrivé; namespace/index des progress legacy reset par tour via `progressScope`. Tests frontend ciblés ajoutés; commandes exécutées par DevFrontend: `npm run test -- src/features/agents/CustomAgentChatView.test.tsx`, `npm run typecheck`, `git diff --check`. - Étape suivante: validation QA complète backend + frontend sur le scénario multi-demandes/busy/délégation.