{"id":"44bc8d1d-93e9-46b3-94a8-8d11ab72ae82","conversation":"08336578-5b47-09d2-2f41-5cc483f101f4","atMs":1781369145058,"source":{"kind":"agent","agentId":"a6ced819-b893-4213-b003-9e9dc79b9641"},"role":"prompt","text":"Tâche : ajouter UN test fonctionnel anti-régression de la communication inter-agent (round-trip question/réponse) au plus haut niveau de fidélité possible SANS lancer de vrai CLI IA (zéro token). Contexte précis ci-dessous, suis-le à la lettre.\n\n## Où\nFichier : crates/app-tauri/src/state.rs, dans le module de test existant `#[cfg(test)] mod mcp_serve_peer_tests` (commence vers la ligne 1893). Ce module pilote déjà la fn privée `serve_peer` sur un `tokio::io::duplex` (pas de socket, pas de process). Réutilise au maximum ses helpers existants : `build_service`, `spawn_peer`, `handshake_line`, `tools_call_line`, `read_one_response`, `project()`, `project_id_arg`, `McpServer::new`.\n\n## Le trou à combler\nLe module couvre handshake+tools/list, propagation du requester, mismatch projet, pairs concurrents — MAIS PAS le round-trip `idea_ask_agent` → `idea_reply` à travers `serve_peer`. C'est la glue critique : l'identité de l'agent répondeur vient de la ligne de handshake (`requester`), et c'est elle qui permet à `idea_reply` de corréler la réponse au ticket en attente. Référence du comportement attendu : `crates/infrastructure/tests/mcp_server.rs::ask_agent_returns_target_reply_inline` (qui, lui, court-circuite le transport via handle_raw/for_requester ; ton test doit passer par serve_peer + handshake réel).\n\n## Problème à régler d'abord\nLe `build_service` actuel du module construit l'`OrchestratorService` via `OrchestratorService::new(...)` SANS câbler le médiateur d'entrée ni le mailbox ni le registre de conversations. Or `ask_agent` exige `with_input_mediator(...)` + (idéalement) `with_conversations(...)`, sinon il renvoie « la messagerie inter-agents n'est pas disponible ». \n=> Ajoute dans le module un `build_service_with_mailbox(contexts) -> (Arc, Arc, Arc)` en PORTANT les fakes déjà éprouvés depuis `crates/application/tests/orchestrator_service.rs` (sections après la ligne ~806) : `TestMailbox` (impl `domain::mailbox::AgentMailbox`), `TestMediator` (impl `domain::input::InputMediator`, écrit le tour dans le PTY lié + délègue l'enqueue au TestMailbox), `TestConversations` (impl `domain::conversation::ConversationRegistry`). Câble : `.with_input_mediator(mediator, mailbox).with_conversations(conversations)`. Garde le profil Claude complet déjà présent dans `build_service` (adaptateur structuré + capacité MCP) pour passer la garde F2. Tu peux factoriser le profil pour éviter la duplication. Ajoute aussi un helper `seed_live_pty(sessions, agent_id, session_id)` (copie de celui d'orchestrator_service.rs) pour que la cible soit déjà vivante en PTY et qu'`ask_agent` la réutilise sans lancer de process.\n\n## Le test à écrire (un seul, simple)\n`async fn ask_reply_round_trips_over_serve_peer_via_handshake_requester()` :\n1. `let proj = project();` ; `let contexts = FakeContexts::new();` ; `let target_id = contexts.seed_agent(\"architect\");`\n2. `let (service, mailbox, sessions) = build_service_with_mailbox(contexts);`\n3. `seed_live_pty(&sessions, target_id, );` (cible vivante → pas de spawn)\n4. `let server = Arc::new(McpServer::new(service, proj.clone()));`\n5. Peer A (le demandeur = humain) : `spawn_peer(Arc::clone(&server), project_id_arg(&proj))`. Écris `handshake_line(&project_id_arg(&proj), \"\")` (requester vide ⇒ ask d'origine humaine, le plus simple : évite la garde de cycle et le besoin que le demandeur soit un agent enregistré), puis `tools_call_line(7, \"idea_ask_agent\", json!({\"target\":\"architect\",\"task\":\"What is the answer?\"}))`. NE bloque pas le test : lis la réponse de A dans une task spawnée OU lis-la après avoir débloqué via B (voir étape 7).\n6. Attends (borné par TIMEOUT, via boucle `mailbox.pending(&target_id) == 1` + `tokio::task::yield_now().await`) que A ait enqueué son ticket et soit en attente.\n7. Peer B (la cible qui répond) : `spawn_peer(Arc::clone(&server), project_id_arg(&proj))`. Écris `handshake_line(&project_id_arg(&proj), &target_id.to_string())` (CRUCIAL : le requester du handshake = l'id de la cible, c'est ce qui fait que `idea_reply` corrèle au mailbox de la cible), puis `tools_call_line(8, \"idea_reply\", json!({\"result\":\"the answer is 42\"}))`. Lis la réponse de B : `isError == false`.\n8. Lis la réponse de A : `isError == false` et le texte inline == \"the answer is 42\" (le texte est dans result[\"content\"][0][\"text\"], cf. `result_text` dans mcp_server.rs — réplique ce petit helper si besoin).\nGARDE-FOU obligatoire : borne chaque attente/lecture par `tokio::time::timeout(TIMEOUT, …)` (TIMEOUT existe déjà dans le module) pour qu'une régression échoue vite au lieu de hang.\n\n## Contraintes\n- Respecte l'archi hexagonale : les fakes implémentent les ports du domaine, aucune dépendance nouvelle.\n- Code lisible, commenté dans le style du module (doc-comments expliquant POURQUOI le handshake requester est le point testé).\n- Lance le test et rends-moi la SORTIE RÉELLE de `cargo test -p app-tauri-lib mcp_serve_peer_tests` (ou le nom de crate exact). Si ça ne compile pas / échoue, débogue jusqu'au vert et rends le diagnostic.\n\nRends ton résultat via idea_reply : (a) le diff/chemin du test ajouté, (b) la sortie cargo test réelle (vert ou rouge avec détail), (c) toute difficulté rencontrée."}