--- issueRef: "#101" version: 7 updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} updatedAt: 1785011116365 --- # Carnet #101 — défaut d'isolation multi-projet (cause racine figée) > Diagnostic Architect (2026-07-25). Source de vérité du fix. Mémoire durable : > `ticket101-cross-talk-multi-project-rootcause`. ## Cause racine Stores disque IdeA **correctement scoppés par projet** (mémoire, contexte, handoff, live-state lus depuis `input.project.root` ; agents persistés dans `.ideai/agents.json` par root projet, **sans re-mint des UUID à l'ouverture**). Mais plusieurs **registres mémoire runtime restent globaux, indexés par `AgentId` seul** → deux projets ouverts (surtout si l'un est une copie) peuvent porter les **mêmes `AgentId`** et le runtime les confond. ### 2 manifestations, même défaut - **A — contamination du contexte d'inférence** : conversation/session d'un projet réutilisée pour l'autre → contexte injecté à l'agent contaminé (preuve : pseudo-branche `wear-os-watch-sync` créée par l'agent Git avec un nom de l'autre projet). - **B — notification de tâche backend perdue / agent s'arrête** (sujet original) : complétion livrable/bloquée/réveillant la mauvaise session. ## Points précis (registres par `AgentId` seul à requalifier) - ConversationRegistry global + `ConversationId` dérivé des UUID agents seuls : `crates/domain/src/conversation.rs:71`, `crates/infrastructure/src/conversation/mod.rs:41`, orchestrateur `crates/application/src/orchestrator/service.rs:2192` (et `:2293`, `:2368`). - Sessions PTY/structured par `agent_id` seul : `crates/application/src/terminal/registry.rs:182,437`. - Verrous ask / busy-state / liveness / délégations différées : `crates/application/src/orchestrator/service.rs:418`, `crates/infrastructure/src/input/mod.rs:47`. - Inbox/mailbox par `AgentId` seul : `crates/domain/src/inbox.rs:68,156`, `crates/infrastructure/src/input/mod.rs:1052`, `crates/infrastructure/src/mailbox/mod.rs:44`. - Wake par `AgentId` seul : `crates/application/src/orchestrator/wake.rs:87`, provider `crates/backend/src/lib.rs:687`. ### Pour B — distinction runtime vs modèle La chaîne sink→`project_id`→wake est **correcte** jusqu'au bridge (`crates/infrastructure/src/background_task/sink.rs:23,142` ; `crates/backend/src/lib.rs:2228` recharge le projet par `project_id` puis `wake_agent`). Le défaut réapparaît juste après (inbox/mailbox/busy/session par AgentId seul). **Runtime IdeA suspecté en premier.** GLM 5.2 n'est l'hypothèse principale que si les logs prouvent enqueue+wake+`BackgroundTaskCompletionDelivered` sur le bon projet sans reprise. Traces : `lib.rs:2238`, `wake.rs:93`. ## Décision utilisateur **Lancer le fix structurel maintenant (lots 1-2).** La collision d'UUID et les logs B se vérifieront en parallèle. ## Périmètre DevBackend (lots 1-2 de ce fix) - **Lot 1** : introduire une clé runtime scellée `RuntimeAgentKey { project_id, agent_id }` ; interdire toute map app-wide indexée par `AgentId` seul. - **Lot 2** : propager la clé dans `AgentInbox`, `InputMediator`, `AgentMailbox`, busy/liveness/deferred, wake, session lookup, ask-locks. **Correctif structurel commun à A et B.** Lots suivants (3-6, hors premier passage) : qualifier ConversationId/registry par projet (lot 3) ; requalifier `TerminalSessions`/`StructuredSessions` par `(project_id, agent_id)` + `AppWakeSessionProvider` refuse l'autre projet (lot 4) ; audit `session_limit`/tables reprise (lot 5) ; télémétrie `project_id` sur logs diag wake/routage (lot 6). ## Invariants - Sources de contexte sur disque restent root-scopées (ne pas régresser). - Templates/profils globaux restent globaux produit (pas de vecteur de session/conversation partagée). - Un projet non-actif doit continuer à recevoir ses wakes et complétions. - Pas de régression OpenCode/Codex/Claude (correctif transverse runtime, pas moteur-spécifique). - Aucun nouveau DTO frontend pour la correction minimale. ## QA — critère de vérité Test d'intégration **non-cross-talk** : 2 projets ouverts avec **volontairement les mêmes `AgentId`** : - délégation projet A ne réutilise jamais session/conversation vivante de projet B ; - complétion `(projet A, agent X)` n'entre ni dans l'inbox ni dans la session de `(projet B, agent X)` ; - wake d'un projet non-actif fonctionne ; - collision d'ids qui échouait avant → verte sur PTY, structured et background wake. ## Clôture 2026-07-25 - Correctif livré sur `feature/ticket101-multi-project-isolation` puis mergé localement dans `develop`. - Commit feature : `6e98fd8 fix(runtime): isolate agent state by project (#101)`. - Merge local : `merge: integrate ticket 101 multi-project isolation`. - QA ciblée verte : - `cargo test -p application --test agent_wake --test orchestrator_service --test structured_registry_d1 --test structured_launch_d3 --test session_limit_service --test session_limit_t4 --test workstate --test workstate_actions` - `cargo test -p infrastructure --test agent_inbox --test mcp_server` - `cargo test -p app-tauri --test session_limit_wiring` - `cargo test -p application` - `cargo test -p app-tauri --tests` - Réserve connue : `cargo test -p infrastructure` complet reste rouge dans le sandbox QA sur tests `openai_compat` à cause du bind local interdit (`Operation not permitted`), sans signal de régression #101. ## Hors périmètre - #91 (popup de notification) : purement front, indépendant. - Remint systématique des AgentId à l'ouverture : non retenu (la clé runtime rend la collision inoffensive même sans remint). ## Lié - #91 (relatesTo). Mémoires : `background-tasks-first-class-design`, `b8-command-runner-pty-framing`, `mcp-bridge-and-delegation-runtime-notes` (règle rebuild AppImage).