- Restaure .ideai/tickets/ depuis 851f1f8^ (167 tickets + index.json + counter.json) - Enlève les ignore rules .ideai/tickets/ dans .gitignore (ligne 51 et 75) - Permet le suivi durable du store tickets futur - Ne touche pas sdk/ (reste untracked)
96 lines
5.7 KiB
Markdown
96 lines
5.7 KiB
Markdown
---
|
|
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). |