Une demande idea_ask_agent vers UX échouait avec « finished without a structured Final response » alors qu'Architect répondait. Deux causes corrigées:
- session/process: un tour CLI terminé en code non nul SANS stdout (ex. erreur 401/auth) renvoyait une sortie vide au lieu du stderr réel; l'orchestrateur concluait alors à un « no Final ». On remonte désormais le stderr effectif (drain sync + async + helper process_exit_message + test dédié).
- orchestrator/service: la branche « ask waiting on background » masquait le premier Final structuré; la réponse synchrone redevient le premier Final (suppression de active_rendezvous_has_background_tasks / mark_rendezvous_task_waiting).
Nettoyage runtime corollaire (#204): arrêt du live runtime stale (PTY + structuré) d'un agent recréé afin que la délégation route vers l'agent courant (LiveSessions, stop_live_agent_runtime_in_project, wiring backend via DeleteAgent::with_runtime_cleanup, lifecycle, workstate cascade).
Corrige la perte de session à la navigation: le démontage du CustomAgentChatView
appelait close_agent_session (destructeur) au lieu de simplement détacher le
transport. Désormais:
- nouvelle commande Tauri detach_agent_chat (+ ChatBridge::detach) qui libère le
canal sans tuer la session ni le scrollback retenu; distinct de
close_agent_session qui reste le close destructeur explicite;
- le frontend appelle detachAgentChat à l'unmount puis restore sa vue depuis un
cache de session (turns + chunkCount) à la réattache;
- message « Reprise effectuée: N événements rattrapés… » quand la réattache
rejoue plus de chunks que le cache local n'en avait conservé.
Enrichit le rendu tools/MCP/progress:
- ProgressSettler (chat bridge) émet un progress completed synthétique quand un
spinner reste ouvert (nouvelle entité progress, chunk text/final/error): fini
les spinners fantômes;
- les adapters claude/codex/opencode/openai_compat extraient un aperçu du
payload (arguments/input/command/message/params) attaché au progress;
- bounded_reply_progress_preview (domain) garde les 4 premières lignes non
vides, normalisation CR/LF;
- previewText (frontend) multiligne whitespace-pre-wrap, source/nativeEvent
affichés sous le titre; suppression du flag settled et du Spinner inline
devenus redondants (l'état est porté par le stage + le settler).
Tests: detach_agent_chat gateway (Tauri + mock), ProgressSettler, bornage
reply_progress, item_preview/tool_preview par adapter, réattache avec cache et
notice de rattrapage.
Le Stop du CustomAgentChatView n'annulait que le tour courant sans libérer la
session ni toucher aux tâches enfants ou appels MCP en cours. Il appelle
désormais stop_live_agent sur l'agent vivant, qui:
- ajoute le port StopAgentExecutionCascade (best-effort, idempotent), implémenté
par OrchestratorService pour annuler les idea_run_in_background rattachés au
rendez-vous actif (via BackgroundTaskRunner.cancel);
- cascade l'arrêt aux wait-dépendances (stop_turn_watch + preempt) pour
interrompre les appels MCP et les attentes inter-agents;
- libère et supprime la session structurée.
UI: nouvel état "Arrêt en cours..." (bouton disabled + loading) pendant l'arrêt,
libération du sessionId, label expliquant la cascade demandée. La Tauri command
cancel_agent_chat est alignée sur stop_live_agent + stop_turn_watch agent et
dépendances.
Tests: SpyBackgroundRunner (cascade n'annule que les tâches rattachées),
workstate_actions cascade best-effort, CustomAgentChatView stop+cascade feedback
et fallback NOT_FOUND.
Le collage d'une image (ex. capture d'écran) échouait en environnement desktop : le presse-papier image n'est souvent pas exposé comme un File synchrone dans clipboardData.files, mais uniquement via l'Async Clipboard API. On ajoute donc un repli sur navigator.clipboard.read() (MIME image/*) quand l'événement de collage ne fournit aucun fichier. Le preventDefault() n'est émis que lorsqu'on a effectivement lu des fichiers issus de l'événement, afin de ne pas bloquer le collage texte quand le repli async ne remonte rien.
- refactor clipboardFiles(event) -> dataTransferFiles(DataTransfer) réutilisable
- dedupeKey robuste pour les images sans nom (mime + taille + contenu base64)
- ReplyChunk::UserPrompt porte désormais les labels d'attachments (DTO + accounting reply_chunk_bytes, skip_serializing_if Vec::is_empty)
- tests ciblés frontend (+219) et backend (chat_bridge/dto/attachments) verts
QA : tests ciblés verts. Réserve : environnement headless, pas de validation manuelle desktop — validation AppImage à confirmer en suivi.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Un agent_message d'intention arrivant avant un tool (ex idea_ask_agent) n'est plus avalé comme faux candidat Final: tamponné puis reclassé en Announcement dès qu'un événement le détrône (helper event_supersedes_pending_final), sur le tap live comme sur le flux autoritatif. Les items reasoning/command n'émettent plus de ToolActivity de compatibilité en doublon du Progress canonique Completed -> supprime les doubles cartes tool/MCP à la source. Tests mod.rs alignés + nouveau cas agent_message_before_tool_becomes_announcement_before_tool_progress.
L'adaptateur Codex n'émettait Progress/ToolActivity qu'à item.completed. On capte désormais conversation.item.added / item.started / response.output_item.added (stage Started), item.updated (Delta) et conversation.item.done / response.output_item.done (Completed), en préservant le nom réel de l'outil (name / function.name / function_call.name).
Les outils idea_* sont taggés ReplyProgressSource::IdeaLocal / Kind::Mcp pour les distinguer du tooling provider. Corrige #93 (l'activité MCP idea_ask_agent devient visible avant le Final, nom non corrompu) et #171 (pipeline progress -> UI temps réel) ; base du rendu live #58.
Tests : 3 unitaires (started live, tag IdeaLocal/Mcp, done avec nom) + assertion d'intégration (MCP started tapé avant le Final). QA : verte (live).
Override send_with_tap: progress/text/tool désormais projetés en live via LiveTurnProjector (au lieu d'un batch en EOF), en suivant le pattern de codex.rs.
Tagging des tool_use idea_* en Progress Mcp/IdeaLocal/Completed (tool_progress) pour faire apparaître la bulle MCP IdeA locale au moment de l'invocation.
Protection anti-replay de session continuée: hold_until_new_message + buffer pending n'émet que le message courant, jamais l'historique rejoué.
send() batch inchangé: stream_events ne filtre le Final que lorsqu'un tap est présent.
Permet à un plugin de contribuer des commandes slash adossées à une callback,
transitant par le registry/contrat unifié (#162) :
- sdk/IdeaSDK: manifeste contributes.slashCommands (déclaratif) — pointer bumpé.
- domain: source Plugin étendue + effet PluginCallback (la commande ne
s'exécute pas directement : elle renvoie une référence à la callback du plugin).
- application: registration des commandes plugin dans le registry + exécution
renvoyant l'effet PluginCallback ; métadonnées UI suffisantes pour l'autocomplete.
- backend + app-tauri: DTO + commandes Tauri listant/invoquant les commandes plugin.
- frontend (contrat): types adapters/domain/ports/mock pour pluginCallback et
l'invocation avec arguments.
L'exécution effective de la callback côté runtime UI est livrée par #166.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute /profile comme commande slash first-class dont la sémantique de reset
de session reste explicite et testable, séparée de la palette générique :
- domain + application: /profile est enregistrée et renvoie un effet
SlashCommandEffect::ProfileSwitch { session_id }. La commande ne reset pas
directement : elle délègue l'effet au frontend pour imposer une confirmation.
- frontend (CustomAgentChatView): à l'exécution de /profile, ouverture d'un
popup de sélection de profil informant que la validation reset la session,
avec confirmation explicite (confirmedReset) requise avant changeAgentProfile.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduit le contrat unifié des commandes slash consommable par le frontend,
indépendant de la source (native, puis plugin plus tard) :
- domain: modèle pur SlashCommand / SlashCommandSource / SlashCommandAvailability,
métadonnées UI (nom, description, disponibilité, confirmation requise) et
validation des noms/préfixes.
- application: registry + list/filter par préfixe + plan d'exécution natif ;
commandes natives /help et /clean (/clean = nettoyage de la vue de session
courante ; pas de /reset distinct tant qu'aucune utilité produit ne le justifie).
- backend + app-tauri: exposition du contrat via DTO/transport + tests DTO.
Source neutre : les commandes contribuées par plugins (#165) transiteront par
le même registry sans changer le contrat frontend.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- frontend: onPaste sur CustomAgentChatView, détection MIME image, chip/preview d'attachment, envoi via le contrat #154 (adapters/agent, ports)
- backend: import d'image par bytes dans le store attachments (commands, chat_attachments app+infra, dto, ports) + tests
- Ajoute le champ cell_kind dans LaunchAgentRequestDto pour distinguer les demandes chat (custom CLI) des lancements PTY historiques
- Convertit cellKind:Chat en require_structured:true dans commands.rs et web-server/src/lib.rs
- Implémente la logique de routing structuré dans LaunchAgent::execute :
- valide que require_structured implique un profil avec structured_adapter
- remplace une session PTY existante quand require_structured est vrai
- route vers structured seulement quand wants_structured est vrai
- Met à jour tous les appels historiques avec require_structured:false pour préserver le contrat PTY
- Ajoute les tests unitaires human_launcher_with_chat_intent_routes_structured_profile_to_chat_session et chat_intent_replaces_existing_pty_instead_of_returning_pty_session
- Wire les ports structured dans BackendCore pour le launcher humain
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implémente la vue chat structurée par cellule agent (toggle TUI/CLI custom,
préférence persistée `preferred_view`, reattach live, composer + pièces
jointes) avec le socle backend AgentSession/ChatBridge (UserPrompt,
cancel_current_turn, routage interrupt_agent, commande cancel_agent_chat).
Corrige le bug bloquant relevé par QA : le bouton Cancel de
CustomAgentChatView interrompait tout le tour via closeAgentChat au lieu
de n'annuler que le tour courant via cancelAgentChat, ce qui tuait la
session contrairement au contrat produit validé.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le store de tâches d'arrière-plan produisait un état incohérent lors de la
délégation multi-agent via idea_ask_agents. Tests ciblés ajoutés/étendus,
suite verte.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
La detection d'absence de reponse structuree finale (structured_no_reply_error)
ne couvrait pas AgentSessionError::Decode ni le message "aucun final textuel
exploitable" emis par l'adaptateur OpenCode, ce qui laissait idea_ask_agent
planter silencieusement sur les profils GLM/OpenCode au lieu de retomber sur
le chemin de secours prevu.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Étend le port/usecases window et layout.customPluginLayout pour ouvrir et
piloter des fenêtres OS hébergeant un layout plugin, en réutilisant
contributes.layouts plutôt qu'un système de fenêtres parallèle. Câble la
commande Tauri et l'état app-tauri correspondants.
Cargo test -p domain --test window : 5/5
Cargo test -p application --test window_usecases : 7/7
Cargo test -p infrastructure --test window_state_store : 1/1
Cargo test -p app-tauri view_window_tests : 8/8
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Étend le flux de création de layout backend (DTO, usecases, store) et le
frontend (sélecteur, adaptateurs, LayoutTabs/LayoutGrid) pour permettre
d'ouvrir un layout déclaré par un plugin installé (ex. Android Health),
sans passer par le message bloquant "extension backend pas encore livrée".
Ticket #141 — QA vert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
La lecture du contexte projet global via MCP (idea_context_read sans target)
lisait <root>/CLAUDE.md au lieu de la source de vérité canonique
<root>/.ideai/CONTEXT.md, désynchronisant la lecture MCP de
crates/application/src/project/context.rs. ReadContext, UpdateProjectContext
et ProposeContext partagent désormais project_context_path/project_context_dir,
avec création du dossier .ideai/ à l'écriture et lecture tolérante à l'absence
du fichier (FsError::NotFound -> contenu vide).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Plugins can now declare activationScope ("app" | "project") in their
manifest; loader/runtime honor it to defer activation of project-scoped
plugins until a project is focused instead of activating everything at
app bootstrap. Bumps sdk/IdeaSDK to the commit that adds the field.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
État d'intégration confiné à la branche batch. Les tickets #119 (skills →
capacités agent découvrables), #122 (override permissions par défaut), #131
(effort par agent/presets) et #132 (outil MCP d'édition du contexte projet)
sont verts en périmètre. Le sprint plugins multi-fichiers ESM / persistance
plugin-owned (#135/#136/#139) est co-implémenté dans les MÊMES fichiers de
câblage (frontend/src/ports/index.ts, backend/src/lib.rs, domain/ports.rs,
backend/dto.rs), inséparable sans staging interactif (indisponible ici).
Commit unique volontaire : préserve l'état vert QA sans découpe hunk risquée.
NON mergé vers develop tant que #137 (QA e2e plugins) n'est pas vert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implémente §22.1 : asset_allowed autorise tout chemin relatif dès lors que
les gardes déjà en place sont satisfaites (entrée registre active,
content_hash du package, confinement canonicalize en aval), au lieu de
restreindre au triplet main/icon/assets. Débloque les imports ESM
multi-fichiers (./constants.js, ./core/x.js) sans affaiblir le modèle de
menace fixé à l'install (#135).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- injecte model et model_reasoning_effort du profil via -c dans argv
- remplace le modèle TUI stale en config.toml
- aligne PTY/interactif sur le comportement déjà garanti par CodexExecSession
- test unitaire codex_pty_launch_forwards_profile_model_as_config_override
- Add model_reasoning_effort field to AgentProfile (domain layer)
- Remove model parameter from codex_config_toml, stop rewriting model in TOML
- Pass model and model_reasoning_effort via Codex CLI -c overrides on every exec
- Update CodexExecSession with new_with_policy_and_overrides factory
- Cover new conversation and resume flows with tests
- capability manifeste tooling supportée backend + transport runtime catalog
- ctx.services publique côté SDK/runtime, gated par tooling
- surface honnête: workspace, terminal, et tasks en observation/contrôle uniquement
- docs/exemple/tests mis à jour
- QA PASS sur feature/sdk-plugin-tooling-build-debug-surface
- plugin_install_load.rs: test uninstalls_then_reinstalls_sdk_hello_plugin_without_runtime_residue()
- application/src/plugin/mod.rs: refactor FakePackages pour supporter plusieurs staged packages et nettoyer les manifests sur uninstall
- Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
plugin_asset_response ne posait aucun header Access-Control-Allow-Origin,
ce qui bloquait l'import() dynamique du bundle plugin (origine distincte
du document) sous WebKitGTK — cause racine confirmee de la 4e rechute #120
(bandeau « Cross-origin script load denied »). Ajoute Access-Control-Allow-
Origin/-Methods sur toutes les reponses du protocole (succes et erreurs) et
un test backend dedie pour eviter une rechute silencieuse.
QA 2026-08-01 : PASS avec reserve — cargo test -p app-tauri (test CORS
cible + plugin_install_load) et tests frontend runtime/plugins verts,
mais pas de preuve visuelle e2e AppImage dans cet environnement (fuse
absent, AppImage non montable ici). Validation AppImage reelle a faire
avant cloture definitive du ticket #120.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Requalification Architect du 2026-08-01: le crash INTERFACE INTERROMPUE au
chargement d'un plugin (menu + item) remonte via ProjectsView -> usePluginMenus
-> MenuBar jusqu'à RootErrorBoundary, quel que soit le plugin (ancien ou
reconstruit via SDK).
- usePluginMenus isole la résolution/conversion des contributions plugin :
toute erreur retombe sur [] au lieu de propager.
- ProjectsView sépare les menus natifs des menus enrichis par plugin et rend
MenuBar derrière une error boundary locale (fallback menus natifs seuls).
- hello-plugin (SDK) et les tests d'installation associés durcis en cohérence.
Bookkeeping ticket #120 uniquement (issue.md, carnet.md) ; les fichiers
counter.json/index.json et le dossier tickets/122/ restent hors commit car
une collision de numérotation #122 existe entre cette base et
feature/ticket120-hello-plugin-install-path-audit (deux tickets différents
revendiquent #122) — à arbitrer avant de committer le bookkeeping global.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Écran noir hello-plugin (#120) récidivant après 3 fixes déjà mergés sans
capturer la cause réelle : on ne pouvait pas savoir si le crash venait de
l'install, du reconcile MCP ou d'un panic silencieux. Ajoute un panic hook
qui logge thread/location/backtrace, trace les étapes install/reconcile/
asset-protocol dans idea.log, et remplace les `.expect()` du superviseur MCP
plugin par une erreur typée au lieu d'un panic sur mutex empoisonné.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute SkillKind (Workflow/Reference) sur Skill, extrait le use case
ResolveAgentCapabilities à partir des SkillRef assignés, et enrichit
idea_list_agents d'un champ additif capabilities (name, description,
kind) — remplace l'exposition de SkillRef opaques par un inventaire de
capacités interrogeable, source commune avec le bloc « Skills
disponibles » injecté au lancement (#119).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Un bundle_url invalide ou un plugin dont l'asset n'est pas réellement
servable passe désormais en état Invalid isolé au lieu de faire
échouer globalement la réconciliation MCP au démarrage — cause racine
de la perte d'affichage à l'installation de hello-plugin (#116/#120).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Ajoute block_on_protocol_future() pour éviter l'erreur 'Cannot start a runtime from within a runtime'
- Ajoute test unitaire pour vérifier la compatibilité avec le runtime Tauri
- Ajoute test d'intégration pour le hello-plugin du SDK
Codex Code Mode pouvait appeler n'importe quel outil MCP directement,
contournant la médiation d'approbation. On force
[features.code_mode].direct_only_tool_namespaces = ["mcp__idea"] sur
chaque surface qui écrit le config.toml Codex (permission projector,
lifecycle, migration run-dir, assistant de ticket), et on ajoute
initialize.instructions côté serveur MCP pour orienter Codex vers le
bon outil idea_* dès la connexion, sans dépendre de la recherche
sémantique différée.
QA : domain 283/0, application 126/0 + agent_lifecycle 73/0 +
change_agent_profile 19/0 + ticket_assistant 5/0, infrastructure 339/0
dont mcp_server 37/0, backend 68/0 (7 ignored). Les échecs web-server
observés sur cargo test --workspace (Too many open files, cookies)
sont une contamination de ressources inter-tests ; les deux tests
concernés repassent isolément.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Les permissions déclarées ne reflétaient pas toujours les tools
effectivement exposés aux agents (contexte requester/projet lié après
coup). Ajoute ToolInvoker::tools_for_bound_context/tools_for_context
pour exposer la liste effective au moment de l'injection dans une
requête OpenAI-compatible, et propage le calcul dans la policy MCP,
le serveur, la factory de session et l'adapter openai_compat.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>