Files
IdeA/.ideai/tickets/157/carnet.md
Blomios 5269315421 chore(tickets): sync miroir — #157/#171 + clôture #173 à #178
- counter.json : nextNumber 173 -> 179
- index.json : ajoute #173 à #178 (tous closed)
- dirs tickets/173-178 (carnet + issue)
- carnets/issues #157 #171 mis à jour

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 12:29:32 +02:00

197 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
issueRef: "#157"
version: 19
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedAt: 1786380032724
---
# Journal d'itération (le plus récent en haut)
## Itération 4 — 2026-08-10 — Correctif livré, QA verte ciblée, merge local sur `develop`, attente de validation AppImage live
### Diagnostic final du cycle
Le problème utilisateur n'était **pas** uniquement frontend.
- **Backend Codex** : un `agent_message` d'intention avant `idea_ask_agent` pouvait être traité comme faux candidat `Final` et ne pas être projeté live. De plus, le parser/session Codex émettait à la fois un `Progress` canonique et un `ToolActivity` de compatibilité pour certains événements tool/MCP (`conversation.item.added` / `conversation.item.done`), ce qui créait déjà une duplication en amont de l'UI.
- **Frontend custom CLI** : la réconciliation des cartes de progress ne dédupliquait pas au niveau de l'entité visuelle métier. Le même `idea_ask_agent` pouvait donc produire deux cartes distinctes (`Provider tool` puis `Délégation`) au lieu d'une seule carte `start` et d'une seule carte `done`.
### Correctifs réalisés
#### Backend (`#171` transverse, impact direct sur `#157`)
- Reclassification d'un `agent_message` pré-MCP en `Announcement` dès qu'un événement ultérieur prouve que le tour continue, au lieu de l'avaler comme candidat `Final`.
- Suppression de l'émission doublon `ToolActivity` quand un `ReplyEvent::Progress` canonique existe déjà pour l'événement Codex/MCP concerné.
- Fichiers: `crates/infrastructure/src/session/codex.rs`, `crates/infrastructure/src/session/mod.rs`.
#### Frontend (`#157`)
- Déduplication par entité visuelle métier: même délégation/tool + même bucket `started` ou `completed` = une seule carte.
- `idea_ask_agent` / `idea_ask_agents` toujours rendus comme **délégation**, même si le provider les remonte comme `providerNative/tool`.
- Le `Final` ne crée pas une deuxième carte `done`; il termine simplement l'état en cours quand approprié.
- Fichiers: `frontend/src/features/agents/CustomAgentChatView.tsx`, `frontend/src/features/agents/CustomAgentChatView.test.tsx`.
### Preuves de test / QA
QA a rejoué et validé les commandes suivantes:
- `CARGO_HOME=/tmp/idea-cargo-home cargo test -p infrastructure codex -- --nocapture` → **41 passed**
- `CARGO_HOME=/tmp/idea-cargo-home cargo test -p app-tauri --test chat_bridge -- --nocapture` → **25 passed**
- `cd frontend && npx vitest run src/features/agents/CustomAgentChatView.test.tsx` → **26 passed tests**
- `cd frontend && npx vitest run` → **1133 passed tests**
- `cd frontend && ./node_modules/.bin/tsc --noEmit --pretty false` → **exit 0**
Verdict QA: **vert sur le scope tickets `#157` + `#171`**.
### Git / intégration locale
- Commit backend: `d6306bb5` — `fix(codex): intention pré-MCP reclassée en Announcement + doublon ToolActivity supprimé (#157 #171)`
- Commit frontend: `9fe87a86` — `fix(cli): déduplication métier des cartes progress + délégations rendues une fois (#157 #171)`
- Commit miroir tickets: `1beeed8c` — `chore(tickets): sync miroir #157 #171 — QA verte ciblée (AppImage en attente)`
- Merge local vers `develop`: `fa613674` — `merge(codex/cli): cycle #157 #171 — dedup cartes tool/MCP + intention pré-MCP live`
### Réserve explicite avant fermeture définitive
- **Pas encore de preuve E2E/AppImage live** sur le binaire utilisateur final.
- Un rouge Rust global subsiste mais est **préexistant et hors scope**: `crates/infrastructure/tests/mcp_server.rs:777` attend 37 tools alors que le catalogue en expose 38 (`idea_context_update` en plus).
### Statut décidé
- Ticket laissé en **QA** et non fermé, dans l'attente d'une validation live AppImage par l'utilisateur.
- Si le live confirme: le ticket pourra être fermé sans nouveau cycle de correction.
---
## Itération 3 — 2026-08-10 — Régression CLI custom: doublons tool/MCP + progress potentiellement manquants avant le premier MCP
**Remontée user (capture live AppImage, 2026-08-10)** : sur la CLI custom, l'usage de `idea_ask_agent` affiche les événements tool/MCP en double (deux cartes `Delegation idea_ask_agent` et deux cartes `Provider tool: idea_ask_agent`) alors que l'attendu produit est de ne conserver qu'une première carte `start` et une première carte `done`. En parallèle, l'utilisateur suspecte que tous les messages de progression/intention ne sont pas surfacés, notamment possiblement avant le premier appel MCP (ex. "Je vais d'abord regarder la liste de tools MCP...").
### Arbitrage Main + Architect
- **#157 reste le ticket principal du rendu CLI custom** pour la hiérarchie visuelle et le dédoublonnage des cartes tool/MCP/delegation.
- **#171 porte la pipeline d'observabilité live** (`ReplyEvent::Progress -> UI`) pour les progress/messages d'intention qui ne doivent pas dépendre du `Final`.
- **#167 reste fermé** : le bug historique traité sur l'ordre `events after Final` n'est pas rouvert à ce stade ; si DevBackend démontre un nouveau défaut d'émission/ordering backend, il faudra alors créer un delta dédié ou rouvrir en second temps.
### Hypothèse de travail pour ce cycle
- Le backend expose déjà une part significative des progress live via la fondation #156 et le correctif OpenCode de l'itération 2.
- Le symptôme utilisateur courant est **probablement** un split :
1. problème frontend de réconciliation/rendu (dédoublonnage des cartes `start/done`), et/ou
2. défaut de projection live UI de certains `ReplyChunk::Progress` en amont du premier appel MCP.
### Cycle relancé
- Architect consulté pour arbitrage ports/contrats/tickets.
- Décision Git préparatoire récupérée : branche de cycle existante `fix/171-conversation-observability-pipeline` à privilégier, sauf preuve backend contraire.
- DevBackend mandaté pour vérifier si les progress pré-MCP existent bien dans le flux backend actuel et si les doublons tool/MCP naissent avant ou après transport UI.
- DevFrontend mandaté pour inspecter la logique de rendu/réconciliation des cartes progress/tool/MCP/delegation dans la custom CLI, corriger si nécessaire et préparer les tests.
- QA passera après implémentation réelle avec preuve de commandes/tests.
### Attendus de validation pour clôture
- Pour un appel `idea_ask_agent`, la CLI custom n'affiche qu'une carte `start` et une carte `done` pertinentes, sans doublons parasites.
- Les messages de progression/intention disponibles dans le flux sont visibles **avant** le premier MCP quand ils existent réellement côté provider/IdeA.
- Aucun faux streaming n'est simulé pour les profils qui n'exposent pas ce niveau de granularité.
---
## Itération 2 — 2026-08-09 — Régression profil OpenCode/GLM (pas de progress, pas de bulle MCP)
**Remontée user** : sur la CLI custom avec un profil OpenCode/GLM, aucun message de progress pendant le traitement de l'agent, et aucune bulle d'appel de tool MCP quand l'agent invoque un outil.
### Cause racine (vérifiée en source opencode v1.17.18)
J'ai lu `packages/opencode/src/cli/cmd/run.ts` (sst/opencode). `opencode run --format json` émet chaque événement JSONL **en temps réel** sur stdout (`{type, timestamp, sessionID, ...data}`). Types émis : `step_start`, `step_finish`, `text` (part textuelle finalisée, pas un delta token), `tool_use` (**seulement à** `part.state.status=completed|error`, pas de start), `reasoning`, `error`. Le parser IdeA `opencode.rs::parse_jsonl_record` reconnaît déjà ces types correctement — **le parser n'était pas cassé**.
Les deux vraies causes :
1. `OpenCodeSession` ne surchargeait **pas** `send_with_tap` (défaut `domain/ports.rs:1380` ignore le tap). Son `send` bufferisait TOUT le stdout jusqu'à l'EOF puis parsait en bloc → le tap live (`commands.rs:2301`) recevait zéro event pendant le tour (silence total), tout arrivait en burst à la fin.
2. La bulle `kind:Mcp`/`source:IdeaLocal` n'était émise que par `openai_compat.rs::apply_tool_calls` (où IdeA orchestre les outils). Pour OpenCode, les outils tournent **dans** opencode ; les `tool_use` étaient taggés `kind:Tool` générique.
### Correctif livré (backend-only)
Branche `fix/ticket157-opencode-progress-mcp-surfacing`, commit `836137a3` (base `develop` `a3d94d4d`). Fichier unique : `crates/infrastructure/src/session/opencode.rs` (+408/−69).
- **`send_with_tap` override** (pattern codex.rs/claude.rs) : lecture stdout ligne par ligne, projection live au tap des events non-terminaux (Progress/TextDelta/ToolActivity/Heartbeat), Final assemblé à la fin (jamais envoyé au tap). `send()` sans tap reste batch (inchangé).
- **Tagging MCP** : `tool_use` préfixé `idea_` → `ReplyProgress{source:IdeaLocal, kind:Mcp, stage:Completed, tool_name}` (remplace la Progress Tool provider-native, pas de double card).
- **Protection replay** : sur session continuée (`--session`), le premier messageID est tamponné puis supprimé si un nouveau messageID arrive (évite de projeter l'historique rejoué).
### Tests & QA
- 3 nouveaux tests : `parse_jsonl_turn_tags_idea_tools_as_mcp_progress`, `send_with_tap_emits_progress_live_before_final_and_tags_idea_tool_as_mcp`, `send_with_tap_does_not_replay_previous_message_into_live_stream`.
- `cargo test -p infrastructure session::opencode` → **20 passed**. `cargo check -p infrastructure -p application` → OK. `cargo fmt --check` → OK.
- QA verdict **VERT** : ciblé conforme au contrat, pas de régression. Les échecs larges (`mcp_server tools_list...` 38 vs 37 ; `orchestrator_service` 39 hangs/spawn) reproduisent **à l'identique sur la base `a3d94d4d`** → pré-existants, hors périmètre du fix.
### Restes / points pour les prochaines itérations
- **Réserve replay (tradeoff UX)** : sur une session continuée avec un **seul** messageID et aucun replay observable, le tap peut rester muet jusqu'à l'EOF (`hold_until_new_message`) pour éviter d'afficher un historique non rétractable. Cas frais = streaming immédiat. À retravailler si la reprise de session devient prioritaire.
- **`reasoning` non mappé** (dette) : opencode émet des events `reasoning` (thinking) que le parser ignore (`Ignored`). Hors périmètre de ce fix ; ticket dédié à créer si on veut afficher le thinking OpenCode.
- **Granularité honnête** : opencode JSON ne donne ni deltas de tokens ni tool-start — seulement step_start/step_finish + text(finalisé) + tool_use(completed). Le fix reste honnête (pas de faux stream simulé), conforme aux critères d'acceptation sur profils pauvres.
- **Vérif live en attente** : build AppImage lancé (artefact `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage`). Le user doit remplacer l'AppImage installée + relancer IdeA pour valider en live (⚠️ relance = tue l'orchestrateur courant). Branche non mergée dans `develop` en attente de vérif live verte (Git ferait le fast-forward ensuite).
- **Frontend** : aucun changement requis (`CustomAgentChatView`/`ProgressBubble` gèrent déjà `Progress{Tool|Mcp}` + délégations). Si le rendu live révèle un souci visuel (spinner qui ne s'arrête pas — cf. description initiale du ticket), ce sera un delta frontend ciblé.
---
# Objectif
Améliorer la CLI custom / chat agent pour afficher **un maximum de progress intermédiaires réellement disponibles** au lieu d'un silence jusqu'au `Final`, avec une UX différenciée pour :
- les messages/progress agent généraux
- les appels MCP / outils
- les délégations inter-agent
# Dépendance
- Dépend explicitement de #156, qui doit fournir le contrat d'événements canonique multi-profils.
# Attentes produit
- Afficher les événements intermédiaires au fil de l'eau quand ils existent.
- Montrer clairement quel agent parle à quel agent.
- Afficher un extrait court de la demande déléguée.
- Rendre les appels MCP/outils visuellement distincts du reste du flux.
- Fonctionner avec un maximum de profils IA, avec dégradation élégante quand un profil n'expose pas grand-chose.
# Périmètre UI/UX attendu
## Types visuels
- `AgentMessage` : message/progress principal d'un agent.
- `Delegation` : carte dédiée `Agent A -> Agent B` avec extrait court de la demande.
- `ToolCall` : carte secondaire/indentée pour les appels d'outil.
- `MCPEvent` : variante spécifique pour les appels MCP/méthodes MCP, distincte visuellement.
## États
- `started`
- `running`
- `done`
- `error`
## Hiérarchie visuelle
- Les délégations et appels MCP ne doivent pas se confondre avec un simple texte agent.
- Les appels MCP/outils doivent être lisibles mais plus discrets que le message principal.
- Prévoir la lecture d'une conversation longue sans transformer l'écran en log brut.
# Recommandations UX initiales (retour UX intégré)
- `Delegation` : carte avec flèche `From -> To`, extrait de demande tronqué (~80 chars), accès au détail sur expansion/hover.
- `ToolCall` : carte indentée avec badge outil, état spinner/check/error, args résumés/tronqués.
- `MCPEvent` : bordure latérale/coloration dédiée par serveur ou type de méthode.
- Timeline verticale légère pour relier visuellement les sous-événements au message/agent source.
- Les événements très courts doivent être lissés/batchés pour éviter le clignotement.
# Anti-bruit / garde-fous
- Ne pas afficher comme texte brut tous les micro-événements sans hiérarchie.
- Seuil temporel ou batching pour les événements trop fugitifs.
- Possibilité de collapse/groupement pour tool calls répétitifs.
- Limitation du nombre d'événements visibles avant expansion.
- Si un profil n'expose aucun delta ni événement intermédiaire, afficher au minimum l'état occupé/vivant sans simuler un faux stream.
# Critères d'acceptation
- Sur les profils riches, l'utilisateur voit les progress/events apparaître avant le `Final`.
- Sur les profils pauvres, l'UI reste honnête et utile (busy/progression minimale) sans faux "thinking".
- Les appels MCP apparaissent au fil de l'eau, pas seulement après le `Final`, si l'information est disponible côté IdeA.
- Les délégations inter-agent sont lisibles : on comprend qui parle à qui et à propos de quoi.
- La vue reste stable et lisible sur conversation longue.