183 Commits

Author SHA1 Message Date
a3d94d4d5e fix(layout): barre supérieure CLI custom cliquable — stacking context du corps de leaf
Le corps d'une leaf (layout-leaf-body) crée désormais son propre stacking context (z-index 0). Les vues CLI custom peuvent comporter des enfants à haut z local (toolbar z-20) qui restaient au-dessus des contrôles de cellule (CELL_Z 5) et captaient les clics ; ils restent désormais sous les contrôles. Test de layering dédié ajouté dans LayoutGrid.cellControlsLayering.test.tsx.
2026-08-06 21:57:48 +02:00
bbcb303061 merge(cli): lot CLI/TUI 2026-08-06 — #168 #169 #170 (QA verte) + #155 (contrat vert, e2e AppImage fichier non-image en attente) 2026-08-06 20:00:51 +02:00
b5b360c266 chore(tickets): QA verte lot CLI/TUI #168/#169/#170 + #155 (contrat vert, e2e AppImage fichier non-image en attente) 2026-08-06 20:00:36 +02:00
8e97da57c9 fix(cli): bouton Send↔Stop #168 + collage clipboard fichier générique #155 2026-08-06 20:00:36 +02:00
292a81ee60 fix(backend): disponibilité session user + hand-off CLI↔TUI sans collision — #169 #170 2026-08-06 20:00:36 +02:00
c50b6c5388 chore(tickets): sync miroir — lot CLI/TUI #155/#168/#169/#170 (+ clôture #151/#167)
(cherry picked from commit d7c4505bacdb9bc03145f12267ae281ad6a35739)
2026-08-06 19:40:46 +02:00
31976d6ed8 fix(cli): collage presse-papiers image/fichier via clipboardData.files — #155 (partiel : logique+tests verts, e2e AppImage clipboard en attente)
(cherry picked from commit 2f39a5ce17b9895e683c0d48f0d9e034e701ed19)
2026-08-06 19:40:46 +02:00
d1e6ae1a22 chore(memory): màj note topologie cycle #151/#167/#155 (issue finale) 2026-08-06 19:16:30 +02:00
0390d18214 chore(tickets): clôture #151 #167 (QA verte) — sync miroir; #155 reste ouvert (e2e AppImage en attente) 2026-08-06 19:14:12 +02:00
9f05ad6aa6 merge(cli): intègre #151 #167 (QA verte) — z-order Cancel + projection live événements avant Final 2026-08-06 19:10:02 +02:00
b45deabe6d fix(cli): z-order Cancel #151 + projection live événements avant Final #167 (+ alignement fixture plugin #165/#166) — QA verte 2026-08-06 19:09:07 +02:00
3d4ea6859e chore(tickets): rouverture #151 #155 + création #167 — sync miroir tickets 2026-08-06 18:50:52 +02:00
e148d3cc5e chore(tickets): clôture #165 #166 + épic #161 — sync miroir tickets
#165 (seam plugin slash-commands) et #166 (dispatch e2e du callback plugin)
fermés après merge de feature/165-plugin-slash-commands dans develop.
L'épic #161 (commandes slash custom CLI) est entièrement terminé : tous ses
sous-tickets (#162 fondation, #163 autocomplete, #164 /profile, #165 seam
plugin) plus le dispatch e2e (#166) sont intégrés.
Sync du miroir local + counter (#166 créé).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 15:47:46 +02:00
f6d2a37a97 merge(plugins): intègre feature/165 — seam #165 + dispatch e2e #166 (QA verte)
Clôture l'épic slash-commands #161 : avec le seam plugin (#165) et le dispatch
end-to-end du callback (#166), tous les sous-tickets natifs + plugin sont livrés.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 15:47:19 +02:00
b0be5f04e4 feat(cli): dispatch du callback plugin slash-command vers le runtime registry — #166 (QA verte)
Boucle le gap end-to-end de #165 : à l'exécution d'une commande slash plugin
depuis le composer custom, l'UI traite l'effet pluginCallback et le dispatche
au PluginRuntimeRegistry pour que la callback du plugin s'exécute réellement.

- runtime/registry: runCommandStrict (échec explicite si handler absent) +
  propagation de la valeur de retour ; élargit les types de retour (unknown).
- runtime/loader: chargement de contributes.slashCommands au registre +
  propagation du retour du handler.
- features/plugins/usePluginMenus: runCommand retourne unknown.
- features/agents/CustomAgentChatView: handler de l'effet pluginCallback ->
  pluginRuntime.registry.runCommandStrict, avec retour utilisateur en cas
  d'échec (commande indisponible / callback absente).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 15:47:04 +02:00
fbaca9d5cc feat(plugins): seam slash-commands contribuées par plugin via callback — #165 (QA verte)
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>
2026-08-06 15:46:52 +02:00
ff7696b724 chore(tickets): clôture #164 (QA verte) — sync miroir tickets
#164 (/profile + reset de session confirmé) fermé après merge de
feature/164-profile-command dans develop. Sync du miroir local.
Reste #165 (seam plugins) pour clore l'épic #161.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 15:12:24 +02:00
4ebf125ec6 merge(cli): intègre feature/164-profile-command — /profile + reset confirmé #164 (QA verte)
Commande /profile first-class avec reset de session explicite et confirmé,
séparée de la palette slash générique. Dernier sous-ticket de l'épic #161
avant #165 (seam plugins).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 15:12:07 +02:00
2cd8df4a4e feat(cli): commande /profile + sélection de profil avec reset de session confirmé — #164 (QA verte)
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>
2026-08-06 15:12:00 +02:00
a6ba3ff6e1 chore(tickets): clôture #163 (QA verte) — sync miroir tickets
#163 (UX autocomplete slash-commands) fermé après merge de
feature/163-slash-command-autocomplete dans develop. Sync du miroir local.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 15:03:04 +02:00
c42ba63c28 merge(cli): intègre feature/163-slash-command-autocomplete — menu slash-commands #163 (QA verte)
UX d'autocomplétion slash dans le composer custom, consommant le contrat
unifié de #162 (aucune liste codée en dur). Débloque #164 (/profile).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 15:02:49 +02:00
853d8229f2 feat(cli): menu contextuel d'autocomplétion des slash-commands dans le composer — #163 (QA verte)
À la saisie d'un « / » en début de draft (sans espace), ouverture d'un menu
contextuel listant les commandes matchant le préfixe, via le contrat unifié
listSlashCommands — aucune liste codée en dur côté UI. Rafinement incrémental
des suggestions à la frappe, navigation clavier + sélection, exécution par
executeSlashCommand.

- adapters/agent: listSlashCommands(prefix?) + executeSlashCommand (invoke Tauri).
- domain + ports: types SlashCommand / ExecuteSlashCommandResult.
- mock: données de test.
- CustomAgentChatView: détection de préfixe (/ sans espace), fetch avec séquence
  anti-retard, gestion ouverture/active index, navigation clavier, fermeture
  quand le préfixe cesse d'être éligible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 15:02:40 +02:00
b51011d206 chore(tickets): clôture #162 (QA verte) — sync miroir tickets
#162 (fondation slash-commands) fermé après merge de
feature/162-slash-commands-foundation dans develop. Sync du miroir local.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 14:53:04 +02:00
6c558cc0af merge(slash): intègre feature/162-slash-commands-foundation — fondation commandes slash #162 (QA verte)
Contrat unifié slash-command (domain + application registry + wiring
backend/app-tauri) avec /help et /clean natifs. Débloque #163, #164, #165.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 14:52:44 +02:00
6997138a71 feat(slash): fondation du système de commandes slash pour la CLI custom — #162 (QA verte)
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>
2026-08-06 14:52:36 +02:00
4e57161e1d chore(tickets): clôture #151 #157 (QA verte) — sync miroir tickets
#151 (z-order bouton Cancel) et #157 (arrêt spinner Progress) fermés
après merge du Cluster A (fix/batch-151-157-cli-ui) dans develop.
Sync du miroir local .ideai/tickets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 14:30:13 +02:00
102c003405 merge(ui): intègre fix/batch-151-157-cli-ui — fixes #151 #157 (Cluster A, QA verte)
#151: z-order du bouton Cancel en état busy (LayoutGrid).
#157: arrêt du spinner Progress à l'état terminal (CustomAgentChatView).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 14:29:49 +02:00
57ced6801b fix(cli): arrêt du spinner Progress à l'état terminal — #157 (QA verte)
Ajoute completeRunningProgress() qui passe les stages started/delta à
completed lors des événements final/error. La ligne Progress conserve son
contenu statique utile mais n'affiche plus l'animation de chargement une
fois le tour terminé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 14:29:39 +02:00
a9346476ee fix(layout): bouton Cancel en z-order propre pendant un tour agent — #151 (QA verte)
Extrait le bouton Cancel du banner inline et le rend en position absolue
(top:24, right:20) avec zIndex CELL_Z.turnActions. Le banner de statut est
décalé (right:76 en état busy) et rétrogradé en CELL_Z.banner, afin que
Cancel reste au premier plan et cliquable sans recouvrement en état busy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 14:29:31 +02:00
0f60f625a1 chore(tickets): réouverture #151 #157 + création epic slash-commands #161–#165
Réouvre #151 (résidu z-order bouton Cancel en état busy) et #157 (suivi UX :
arrêt du spinner à l'état terminal) en statut open avec assignations.
Crée l'epic slash-commands custom CLI : #161 (ombrelle suivi produit),
#162 (fondation registry + /help + /clean), #163 (UX autocomplete / menu),
#164 (/profile + reset session confirmé), #165 (commands contribées plugins).
nextNumber 161 → 166.

Bookkeeping tickets seul (l'état runtime .ideai hors-lot reste en working
tree, non committé).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 14:19:04 +02:00
380fefd37b chore(tickets): clôture #151 #156 #157 #160 — sync tickets/mémoire (QA verte) 2026-08-06 13:14:01 +02:00
03303aa276 fix(ui): toolbar CLI sans overlap + retrait du bouton History — #151 #160 (QA verte) 2026-08-06 13:13:30 +02:00
309c10e5e9 feat(cli): surface progression intermédiaire, activité MCP, flux agent↔agent — #157 (QA verte) 2026-08-06 13:13:24 +02:00
918116664c feat(backend): modèle unifié streaming/progress/events provider-agnostic + pont app-tauri — foundation #156 (QA verte) 2026-08-06 13:13:17 +02:00
40fa551f32 merge(chat): intègre feature/155-clipboard-paste-image — paste image clipboard dans le composer (#155, QA verte) 2026-08-06 11:01:50 +02:00
790c4755be feat(chat): #155 paste image depuis presse-papier dans le composer custom (QA verte)
- 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
2026-08-06 11:01:50 +02:00
88dfbfe471 merge(attachments): intègre feature/154-attachments-pipeline — fondation pipeline durable d'attachments agent/chat (#154, QA verte) 2026-08-06 10:44:15 +02:00
1c80d08f92 feat(attachments): fondation pipeline durable d'attachments agent/chat + sandbox-safe (#154, QA verte)
Socle #154 : entité attachment, store, contrat DTO et routage session. Modules : domain/chat_attachment, application/chat_attachments, infrastructure/chat_attachments, app-tauri (commands/lib), backend dto.
2026-08-06 10:44:15 +02:00
560b5ae7d1 merge(ui): intègre fix/batch-151-158-159-ui — fixes #151 #158 #159 (Lot A, QA verte) 2026-08-06 10:23:23 +02:00
c5d6c3b98e fix(ui): Lot A #151 #158 #159 (QA verte)
- #151: chevauchement des boutons dans la barre supérieure pendant une conversation agent

- #158: popup de reprise de conversation intempestive (ajout cellule / changement layout / projet)

- #159: pastille d'activité de projet
2026-08-06 10:23:23 +02:00
fb19ee48dc chore(tickets): met à jour le timestamp index.json 2026-08-05 23:44:51 +02:00
ee35c15958 chore(tickets): journalise le correctif routing chat vs PTY #149
- Met à jour le carnet avec la preuve runtime returned cellKind=pty; expected chat
- Documente les hypothèses invalidées et la nouvelle cible de correction
- Met à jour issue.md avec le titre et le diagnostic consolidés
- Incrémente le compteur et ajoute les tickets 150-158 à l'index

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 23:40:03 +02:00
937ea07df1 feat(chat): valide le routing cellKind=chat côté frontend et corrige UX
- Ajoute cellKind dans AgentChatHandle et vérifie que launchAgentChat reçoit cellKind:chat
- Rejette avec erreur STRUCTURED_ROUTED_TO_PTY si le backend route vers PTY
- Ajoute cellKind:chat dans MockAgentGateway.launchAgentChat
- Corrige l'overflow du layout CustomAgentChatView (bounded shell avec scroll + composer fixe)
- Dédouble les prompts utilisateur quand le stream les echo
- Ajoute les tests launchAgentChat returns handle only when confirms chat et launchAgentChat rejects PTY-routed launch
- Ajoute les tests does not duplicate user prompt when echoed et keeps chat shell bounded

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 23:39:50 +02:00
c43f29b2f2 feat(chat): propage l'intention chat → require_structured dans le pipeline de lancement
- 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>
2026-08-05 23:39:35 +02:00
7071c53bb2 fix(chat): handle raw structured session NOT_FOUND errors from Tauri
Elargit isNotFound() pour reconnaitre aussi la forme brute
'not found: structured session <uuid>' que Tauri peut retourner,
en plus de la forme typée {code: 'NOT_FOUND'}.

Ajoute deux tests couvrant:
- fallback sur reattach avec erreur brute
- retry prompt sur send avec erreur brute

QA: tests passés sur cette correction.
2026-08-05 16:00:37 +02:00
62ac05a080 chore(tickets): journalise le correctif session echo #149
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 15:30:08 +02:00
ce9ba0dc3d fix(chat): ignore self-emitted custom session echoes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 15:29:03 +02:00
525ea94b09 chore(tickets): journalise le recadrage #149
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 15:23:45 +02:00
029ed97bff chore(chat): instrumentation session CustomAgentChatView pour diagnostic #149
Ajoute des points de traçage ciblés sur le cycle de vie de session
CustomAgentChatView/LayoutGrid pour isoler la cause du fallback
silencieux CLI custom avant tentative de fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 15:23:45 +02:00
4d8b69afca chore(tickets): recadre #149 — instrumentation ciblée CustomAgentChatView/session au lieu d'une 4e variation LayoutGrid
Consigne Architecte: le fallback custom→TUI persiste après 3 correctifs sur
LayoutGrid.tsx. Nouvelle piste non explorée: boucle d'effet sessionId dans
CustomAgentChatView.tsx (openOrAttach déclenché par son propre callback
onSessionId). Carnet mis à jour avec l'historique complet des tentatives et
la règle de traçabilité demandée par l'utilisateur.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 14:50:33 +02:00
66b9c34bc3 merge(chat): intègre feature/ticket149-reopen-frontend-refetch — stabilise CLI custom vs refetch stale (#149, QA verte)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 14:25:03 +02:00
e9e4623ecf fix(chat): stabilise le mode CLI custom contre le refetch stale agents/profiles (#149)
Le fallback custom→TUI se redéclenchait après le premier chargement dès que
refreshProfiles() renvoyait un instant un profil pinné sans structuredAdapter
(refetch en vol), coupant la CLI custom ~0.5s après son ouverture. Introduit
un binding "trusted" (agent+profil validés) qui reste valide tant qu'aucun
changement légitime de profil n'est observé via agentProfileChanged, et ne
retombe en TUI que sur perte réelle du CLI custom.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 14:24:55 +02:00
0e2fc83689 chore(tickets): réouvre #149 — le fallback silencieux CLI custom persiste après retest
Retest utilisateur du 2026-08-05: la CLI custom s'ouvre ~0.5s puis retombe
sur Plain/TUI malgré le fix précédent. Statut repassé à open pour relancer
le cycle de diagnostic/correction.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 14:17:00 +02:00
3ae616bad9 merge(chat): intègre feature/ticket149-cache-stale-agents-profiles — fix cache stale agents/profiles (#149, QA verte)
QA verte : LayoutGrid.chat.test.tsx (7 tests), src/features/layout (16 fichiers, 130 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 14:06:27 +02:00
61055779c4 fix(chat): retarde le fallback custom→TUI tant que le catalogue agents/profiles est stale (#149)
Cause racine restante après le fix de la course au premier chargement : le
garde-fou de LayoutGrid retombait sur `tui` dès que agents/profiles semblaient
indisponibles, y compris quand le cache était simplement stale (refresh en
cours), écrasant silencieusement la préférence custom. Le fallback n'agit
désormais qu'une fois le catalogue confirmé à jour.

QA verte : LayoutGrid.chat.test.tsx (7 tests), src/features/layout (16
fichiers, 130 tests), cas ciblé "stale catalog refresh".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 14:06:18 +02:00
fa518415c6 merge(chat): intègre feature/ticket149-custom-cli-silent-fallback — fix fallback silencieux CLI custom → Plain (#149, QA verte)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 13:48:35 +02:00
0103a8acf6 chore(tickets): clôture #149 — QA verte sur feature/ticket149-custom-cli-silent-fallback
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 13:48:30 +02:00
dedc3b5134 test(chat): couvre le fallback TUI si le catalogue invalide le profil pinné (#149)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 13:48:27 +02:00
51bda20455 fix(chat): preserve custom CLI preference during catalog load (#149)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 13:45:41 +02:00
9d18d01380 chore(tickets): ouvre le ticket #149 (fallback silencieux CLI custom → Plain)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 13:41:30 +02:00
ecad746c66 chore(tickets): synchronise les statuts tickets et l'état plugin android
Rattrapage de l'état runtime .ideai/ (tickets #119-#139/#147 clôturés,
compteur→149, ticket #148 clos et QA verte, métadonnées plugin android) —
séparé du code de feature avant d'ouvrir le travail sur le nouveau bug
de lancement CLI custom.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 13:40:44 +02:00
00a2eaaa16 merge(chat): intègre fix/ticket148-structured-session-not-found — relance propre sur reattach mort (#148, QA verte)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 13:17:39 +02:00
e80f7631ff fix(chat): relance propre au lieu de re-tenter l'attach sur une session structurée morte (#148)
Sur reattach NOT_FOUND, le composant retentait implicitement l'attach sur le
même sessionId mort au lieu de nettoyer l'état avant de relancer, ce qui
produisait l'erreur "not found: structured session …" côté utilisateur.
recoverStructuredSession() nettoie désormais sessionId/conversationId avant
de relancer et retente une seule fois le reattach sur NOT_FOUND post-launch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 13:17:31 +02:00
fab172094a merge(chat): intègre fix/ticket147-structured-session-reattach-fallback — fallback fresh launch sur reattach mort (#147, QA verte)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 12:11:46 +02:00
b37542107a fix(chat): fallback vers un nouveau lancement quand la session structurée reattach est morte (#147)
reattachAgentChat pouvait échouer avec NOT_FOUND (session structurée fermée
ou jamais vivante) et laisser fuiter l'erreur brute jusqu'à l'utilisateur
("not found: structured session ... not found") au lieu de relancer une
session fraîche. Le fallback ne s'applique qu'au code NOT_FOUND ; toute
autre erreur de reattach continue de remonter telle quelle.

QA vert 2026-08-05 : npx vitest run CustomAgentChatView.test.tsx,
npx vitest run agents.test.tsx CustomAgentChatView.test.tsx, npm run typecheck.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 12:11:38 +02:00
c0764d6a0c merge(orchestrator): intègre feature/ticket147-custom-chat-cli — CLI custom de chat agent (#147, QA verte)
Livraison complète : toggle TUI/CLI custom par cellule, socle backend
AgentSession/ChatBridge, et correctif du bouton Cancel (interruption du
tour courant au lieu de fermer la session). QA a validé en vert après
le correctif frontend ciblé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 12:00:05 +02:00
dcba76b871 feat(chat): livre la CLI custom de chat agent (#147) et corrige Cancel
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>
2026-08-05 11:59:39 +02:00
efbd56a149 chore(tickets): sync carnets/issues #102/#141-#147 + agent glmopencode
Rebase de l'état ticket (réouverture #102, clôtures #141-146, ouverture
#147) et ajout du contexte agent glmopencode avant démarrage du cycle #147.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 23:57:30 +02:00
1c53ee09ef merge(orchestrator): intègre feature/fix-ask-agents-background-task-store — fix background task store (idea_ask_agents, tests verts)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:26:38 +02:00
c1267bf880 fix(infrastructure): corrige le background task store utilisé par idea_ask_agents
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>
2026-08-04 12:26:33 +02:00
d997aba288 merge(orchestrator): intègre feature/glm-opencode-delegation-fix — fix délégation GLM/OpenCode (QA verte)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 09:50:06 +02:00
b88d500d89 fix(orchestrator): corrige la delegation inter-agent GLM/OpenCode sans reponse Final
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>
2026-08-04 09:50:02 +02:00
11c405efea merge(window): intègre feature/plugin-hosted-windows — fenêtres plugin-hébergées #142-146 (vert QA)
Backend (window usecases + commande Tauri), frontend (host de fenêtre +
services.windows.open), runtime SDK (react/react-dom résolus vers l'host) et
documentation SDK restructurée. QA verte (cargo + vitest + typecheck + build
+ sdk check) ; réserve non bloquante : pas d'e2e natif clic sous-menu ->
fenêtre OS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 00:40:16 +02:00
5a64e7fd5b chore(sdk): pointe le submodule sur develop (post-merge feature/plugin-hosted-windows)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 00:40:16 +02:00
13bad558ba chore(tickets): synchronise carnets/statuts #142-146 (QA verte) + bump IdeaSDK
QA verte sur feature/plugin-hosted-windows : cargo (domain/application/
infrastructure/app-tauri), frontend (vitest/typecheck/build), sdk npm check.
Réserve non bloquante : pas d'e2e natif complet clic sous-menu -> fenêtre OS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 00:39:57 +02:00
d8df466fba feat(frontend): host les fenêtres plugin et l'API publique windows.open
Ajoute la vue window host qui charge le layout plugin dans une fenêtre OS
détachée, expose react/react-dom/jsx-runtime hébergés sous
frontend/public/plugin-host pour que le runtime SDK y résolve React, et
câble services.windows.open() côté runtime plugin (loader/services/registry).

npm test -- --run src/adapters/window.test.ts src/app/ViewWindow.test.tsx
  src/plugins/runtime/loader.test.ts src/plugins/runtime/services.test.ts : 39/39
npm run typecheck : OK
npm run build : OK

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 00:39:50 +02:00
551eb09ad2 feat(window): support des fenêtres plugin-hébergées (backend)
É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>
2026-08-04 00:39:42 +02:00
3ea1d58b38 chore(ideai): sync tickets #142-146 (SDK plugin windows) + contexte git + bump IdeaSDK
Enregistre le cadrage du programme fenêtres plugin-hébergées (#142 backend,
#143 frontend host + windows.open, #144 runtime React partagé, #145 docs SDK,
#146 QA) et met à jour le contexte de l'agent Git avec le modèle de branches
git-flow simplifié.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 00:10:00 +02:00
78dc888bd9 merge(layout): intègre ticket141-plugin-layout-create-support — création de layouts plugins (vert QA) 2026-08-03 18:34:24 +02:00
45617992ef feat(layout): supporte la création de layouts plugins (customPluginLayout)
É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>
2026-08-03 18:34:21 +02:00
168f93df78 merge(context): intègre fix-context-read-canonical-path — idea_context_read pointe .ideai/CONTEXT.md (vert QA) 2026-08-03 14:58:30 +02:00
70712a35f8 fix(context): route idea_context_read vers .ideai/CONTEXT.md au lieu de CLAUDE.md
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>
2026-08-03 14:58:22 +02:00
3fa9691cd6 merge(batch): intègre plugin-activation-scope-loading — chargement du scope d'activation des plugins (vert QA) 2026-08-03 14:44:23 +02:00
6a86b3ad80 chore(ideai): sync tickets #43/#140 + skills index + agent context
Ticket #43 carnet reflects activationScope in the plugin manifest
example; ticket #140 closed; skills index/content refreshed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 14:44:12 +02:00
e2da2d911e feat(plugins): load activation scope from plugin manifest
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>
2026-08-03 14:44:08 +02:00
863d9b7277 fix(agents): unwrap read_agent_context DTO content (#140)
Le contexte projet d'un agent s'affichait "[object Object]" et se
vidait à la réouverture du panneau : read_agent_context renvoie déjà
{content} côté backend, mais les gateways front traitaient la réponse
comme une string brute. Les deux gateways (Tauri + HTTP) unwrap
maintenant .content ; type AgentContextDocument ajouté au domaine.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 14:35:36 +02:00
cf61060ffb chore(tickets): sync statuts/carnets #113/#119/#120/#122/#131/#132 + bump IdeaSDK ESM (#134/#139)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 12:44:20 +02:00
59d81851e9 chore(tickets): synchronise index/carnets tickets #131-#139 + note mémoire assets/persistance plugins
État runtime .ideai séparé du code (index, counter, carnets, note mémoire
plugin-asset-serving-and-owned-storage-contracts). Purge des tickets obsolètes
51/63/66.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 11:06:30 +02:00
171c6c923c feat(wave): #119/#122/#131/#132 verts + sprint plugins ESM/persistance #135/#136/#139
É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>
2026-08-03 11:06:23 +02:00
7497fe19aa merge: intègre #113 — champ args llamacpp ne capture plus les frappes (vert QA)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 10:51:55 +02:00
0a52005afb fix(model-servers): empêche la capture des touches dans le champ args du serveur llamacpp (#113)
Les espaces et autres frappes étaient interceptés par un handler parent ;
stopPropagation sur le onKeyDown de l'input args laisse la saisie intacte.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 10:51:47 +02:00
22c6bd803d merge(batch): intègre #134 — service confiné multi-fichiers ESM (vert QA)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 00:02:11 +02:00
71d08795d9 feat(plugins): sert tout fichier confiné du package installé (multi-fichiers ESM) (#134)
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>
2026-08-02 23:47:41 +02:00
2f1d99c5e1 merge(batch): intègre #138 — §22.2 persistance plugin-owned hors projet
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 22:52:18 +02:00
a5e56885d9 docs(architecture): §22.2 — persistance plugin-owned hors projet & purge à la désinstallation (#138)
Cadrage architecture du ticket #138 : séparation project-owned/plugin-owned,
API canonique ctx.storage seule, stockage sous app_data/plugins/data/<id>/
(frère de installed/), purge intégrale à l'uninstall. Débloque #139.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 22:52:13 +02:00
1b9915c229 merge(batch): intègre #133 — §22.1 contrat de service des assets multi-fichiers ESM
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 22:52:00 +02:00
fa474ae97f docs(architecture): §22.1 — contrat de service des assets idea-plugin:// multi-fichiers ESM (#133)
Cadrage architecture du ticket #133 : asset_allowed autorise tout chemin
relatif confiné dès lors que registre actif + content_hash + confinement
canonicalize sont satisfaits, sans gater fichier par fichier. Débloque
#134/#135.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 22:51:53 +02:00
7c2bd227d2 fix: Codex PTY launch forwards profile model as argv override
- 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
2026-08-02 18:02:00 +02:00
dcc7a6f216 fix: project model and reasoning_effort into Codex CLI args, stop rewriting .codex/config.toml
- 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
2026-08-02 17:19:26 +02:00
b730e356aa refactor(sdk): remplace dépôt imbriqué par git submodule
- Convertit sdk/IdeaSDK en git submodule pointant vers IdeaSDK dédié
- Nettoie les artefacts du dépôt git imbriqué (.git.disabled-empty-nested-repo)
- Le SDK TypeScript plugin est maintenant dans son propre repo

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 16:33:50 +02:00
6959fbbe9a Merge branch 'feature/sdk-plugin-tooling-build-debug-surface' into develop 2026-08-02 13:37:02 +02:00
a051b5299a chore(tickets): mise à jour index et tickets SDK plugins #123-#130 2026-08-02 13:36:43 +02:00
8c4f1ea2e3 feat(sdk,plugins): typage et stabilisation runtime UI/layout publique (#128) 2026-08-02 13:36:17 +02:00
e3e887d6a4 feat(sdk,plugins): APIs publiques lancement commandes + outillage + événements + config (#125,#126,#127,#130) 2026-08-02 13:35:48 +02:00
dce61ae1aa feat(sdk,plugins): API publique d'accès fichiers/workspace + analyse structure (#124,#129) 2026-08-02 13:34:54 +02:00
80c9e0a236 merge feature/sdk-plugin-tooling-build-debug-surface dans develop
feat(sdk,plugins): ajoute capability tooling et services runtime publics (workspace/terminal/tasks)
- 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
2026-08-02 00:31:40 +02:00
033e9a86d5 feat(sdk,plugins): ajoute capability tooling et services runtime publics (workspace/terminal/tasks)
- 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
2026-08-02 00:31:15 +02:00
efaeb31a38 docs(tickets): consigne le cycle #120 fix CORS + décision Git et états (#120)
- carnet.md: enregistre la livraison CORS et la décision Git du 2026-08-01
- issue.md + index.json: mise à jour version/timestamp
- plugins.test.tsx: tests d'intégration frontend liés
- Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 19:12:39 +02:00
a88307c5ff refactor(frontend,plugins): normalise les DTOs review backend et corrige le mock (#120)
- plugin.ts: normalizeReview() garantit issues/installable définis même si backend omet ces champs
- mock/index.ts: MockPluginGateway.uninstall() retourne removalOutcome pour cohérence avec le domaine
- domain/index.ts: PluginUninstallResult ajoute removalOutcome optionnel
- Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 19:12:16 +02:00
5baf5821d4 test(backend,plugins): ajoute un test de non-résidu runtime après uninstall/reinstall (#120)
- 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>
2026-08-01 19:11:54 +02:00
0061685b08 fix(frontend,plugins): évite le crash sur install/uninstall/reinstall par rechargement systématique de la liste (#120)
- usePlugins.ts: remplace les mises à jour optimistes du state par des appels listPlugins() après chaque opération backend
- PluginsPanel.tsx: ajoute la normalisation isInstallable() pour éviter les crashes si installable est undefined
- Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 19:10:44 +02:00
fd2ab4a0d7 merge feature/ticket120-plugin-asset-cors-headers dans develop (#120: headers CORS idea-plugin:// — QA PASS avec reserve e2e AppImage)
Cause racine de la 4e rechute #120 corrigee : plugin_asset_response
posait aucun header CORS, bloquant l'import() dynamique du bundle plugin
sous WebKitGTK. Valide via cargo test -p app-tauri (test CORS cible +
plugin_install_load) et tests frontend runtime/plugins, tous verts.

Reserve QA non levee : pas de preuve visuelle e2e dans un AppImage reel
(fuse absent dans cet environnement) que le bandeau disparait apres
redemarrage. Cloture definitive du ticket #120 a conditionner a cette
validation AppImage reelle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 17:58:46 +02:00
fbe69de0c2 fix(plugins): ajoute les headers CORS sur le protocole idea-plugin:// (#120)
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>
2026-08-01 17:58:35 +02:00
95066d4110 merge feature/ticket120-plugin-menu-crash-isolation dans develop (#120: isolation menus plugin validee QA + requalification deploiement)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 16:54:36 +02:00
add61f176d chore(tickets): consigne la rechute #120 (requalification deploiement) et enregistre #122
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 16:54:33 +02:00
5a30ec8b9c fix(plugins): isole les menus plugin et durcit hello-plugin SDK contre la rechute #120
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>
2026-08-01 16:23:56 +02:00
8031d86deb merge feature/ticket120-hello-plugin-blackscreen-crash-diagnostics dans develop (#120: diagnostics crash minimales backend + garde-fous frontend contre l'écran noir) 2026-08-01 09:48:59 +02:00
3fc15fd706 chore(memoire): consigne la récidive écran noir hello-plugin (#120)
Trois correctifs déjà mergés sur le même symptôme sans que #120 se ferme ;
note de mémoire projet pour que le prochain agent ne reparte pas d'un
patch symptomatique de plus sans avoir lu l'historique des tentatives.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 09:48:55 +02:00
c19fb6bf8c fix(frontend): écran noir plutôt que muet sur crash de plugin ou d'activation figée
Complète le diagnostic backend (#120) côté frontend : un crash React non
capturé (ex. plugin cassant le rendu) laissait un écran noir sans trace, et
une activation de plugin qui ne se résout jamais (promesse infinie) bloquait
le chargement sans échouer. Ajoute RootErrorBoundary + logging d'erreurs
globales autour de l'arbre React, et un timeout sur l'import/l'activation de
chaque plugin dans loadPlugins pour transformer un hang silencieux en échec
explicite et diagnosticable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 09:48:49 +02:00
961bf4623f fix(plugins): diagnostics crash minimales pour l'install de plugin (backend)
É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>
2026-08-01 09:48:42 +02:00
07df50f9de merge feature/ticket119-skills-agent-capabilities dans develop (#119: capacités agent découvrables via idea_list_agents)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 00:27:13 +02:00
0eea4421f9 merge feature/ticket113-llamacpp-args-spaces dans develop (#113: espaces autorisés dans les arguments supplémentaires llama.cpp)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 00:27:11 +02:00
e741f76cab merge feature/ticket120-hello-plugin-blackscreen-reinvestigation dans develop (#120: isolation plugin invalide + réconciliation MCP durcie + loader export default/cleanup)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 00:27:08 +02:00
e21db9bf40 chore(tickets): met à jour l'état runtime du ticket #119
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 00:27:00 +02:00
92b17e9a69 feat(skills): capacités agent découvrables via idea_list_agents
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>
2026-08-01 00:26:56 +02:00
dbaf6fe2f4 fix(model-servers): autorise les espaces dans le champ Arguments supplémentaires llama.cpp
Le champ contrôlé de ModelServersPanel/FirstRunWizard perdait les
espaces saisis dans les arguments llama.cpp (trim/split prématuré sur
chaque frappe au lieu de la seule sérialisation finale) (#113).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 00:12:07 +02:00
46086af026 fix(plugins): support export default { activate }, cleanup partiel et erreurs visibles
Le loader accepte désormais aussi la forme export default { activate }
en plus de l'export nommé, les subscriptions partiellement établies
sont nettoyées en cas d'échec d'activation, et une erreur de
runtime-catalog est remontée visuellement dans PluginsPanel avec un
badge Invalide/Isolé sur les plugins concernés (#116/#120).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 00:05:57 +02:00
50b71f4ece fix(plugins): isole les plugins non servables et durcit la réconciliation MCP
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>
2026-08-01 00:05:53 +02:00
ac659c42f2 fix(plugins): renforce le typage des Set filtrés dans loader.ts
Point de départ de la réinvestigation #120 : commandIdsFromContributes
et layoutTypesFromContributes typaient implicitement leurs Set en
unknown, masquant les valeurs vides potentielles issues des
contributions de plugin (piste du crash d'affichage à l'installation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-31 23:52:42 +02:00
5efb026a80 chore(tickets): synchronise l'état runtime des tickets et de la mémoire
Clôture #114/#115/#116/#117, suppression #111, ouverture #119/#120/#121,
notes mémoire root-cause #113 et angle d'investigation #120.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-31 23:52:33 +02:00
32c257d2e1 Merge branch 'feature/117-opencode-headless-recovery' into develop 2026-07-31 15:05:14 +02:00
10c0bef5e5 ticket117: synchronie métier idea_ask_agent + corrélation task ↔ rendezvous 2026-07-31 15:04:54 +02:00
f6685aa745 Merge branch 'fix/ticket116-plugin-install-black-screen' into develop 2026-07-31 14:18:33 +02:00
d4e61a86f0 fix(ticket116): isoler crash plugin hello-plugin + erreur explicite UI 2026-07-31 14:17:56 +02:00
e042ced724 Merge branch 'feature/ticket115-ideA-skills-runtime-snapshot' into develop 2026-07-31 13:56:46 +02:00
fbe3c51fd4 ticket115: snapshot runtime skills assignés + durcissement idea_skill_read 2026-07-31 13:56:18 +02:00
fe5fe7cb70 fix(hello-plugin): prévient le crash de l'asset protocol dans le runtime Tauri
- 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
2026-07-31 13:17:59 +02:00
f81b385616 merge feature/ticket114-uniform-dropdowns dans develop (#114: uniformisation des droplist dynamiques)
QA vert : 148+8+1032 tests passés, typecheck OK.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 12:56:14 +02:00
5be5c5975e chore(tickets): synchronise l'état runtime des tickets et du contexte main
Met à jour l'index/compteur de tickets, les tickets #111/#113/#114 et le
contexte de Main suite au traitement du ticket #114.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 12:56:07 +02:00
9b1ced50be feat(ui): uniformise les droplist dynamiques sur le style du picker d'agent
Introduit SmallDropdown comme composant partagé et le fait adopter par
AgentsPanel, ModelServerSelect, OpenCodeModeFields, TemplateEditor et
TicketViewportSelect, pour que toutes les listes déroulantes dynamiques
(agent, modèle, template, viewport) partagent la même apparence que le
sélecteur d'agent de la création de ticket.

Refs #114

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 12:55:57 +02:00
fda4126a5f merge fix/terminal-fit-remount-stability dans develop (fix: détection de stabilité réelle du fit terminal au remount)
QA: verdict VERT (suite automatisée), réserve manuelle : vérification desktop/Tauri (comportement réel du fit terminal dans l'app packagée) non exécutée.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 09:36:10 +02:00
6165eaf8d9 fix(terminals): détecte la stabilité réelle du fit terminal au remount
L'ancien correctif (traîne de refits à nombre de frames fixe,
MOUNT_SETTLE_REFIT_FRAMES) restait insuffisant : une cellule CLI pouvait
rester mal dimensionnée après un changement de projet/layout si l'agent
écrivait en arrière-plan pendant la fenêtre de stabilisation, nécessitant
un resize manuel pour corriger l'affichage. TerminalView détecte
désormais la stabilité réelle du fit (dimensions inchangées sur des
mesures successives) au lieu de s'appuyer sur un nombre de frames fixe
avant de rendre la main au ResizeObserver.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 09:36:05 +02:00
c100a0317c merge fix/hello-plugin-black-window dans develop (#hello-plugin: isole les contributions plugin en erreur et durcit menus.ts)
QA: verdict VERT (suite automatisée), réserve manuelle : vérification desktop (chargement réel de l'archive dans l'app packagée) non exécutée.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 09:08:25 +02:00
aa850374ce fix(plugins): isole les contributions plugin en erreur et durcit menus.ts
Le chargement de l'archive hello-plugin (build/hello-plugin-0.1.0.zip)
vidait la fenêtre principale : une contribution plugin fautive
remontait jusqu'au rendu global au lieu de rester locale à la cellule.
Ajoute un boundary local dans PluginLayoutCellView/PluginLayoutSelectorSection
et durcit menus.ts/loader.ts/registry.ts contre les entrées de menu ou
contributions malformées.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 09:08:14 +02:00
eec3e0a5bc merge feature/codex-mcp-code-mode-direct-tools dans develop (#108: Code Mode Codex restreint au namespace MCP IdeA + initialize.instructions)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 22:51:49 +02:00
d0b65a92bd fix(#108): restreint Code Mode Codex au namespace MCP IdeA et documente les tools au démarrage
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>
2026-07-29 22:51:38 +02:00
af6b76935c fix(#108): expose les tools MCP autorisées dès le démarrage de session Codex 2026-07-29 18:19:38 +02:00
2c3a46e690 fix(#105): corrige le contexte plugin pour hello-plugin
Ajoute logger, subscriptions et commandes scindées au contexte plugin
activé. Les plugins full-trust s'attendent à ce shape public.
2026-07-29 17:59:14 +02:00
3f27eb878b merge feature/ticket112-bulk-sprint-assign dans develop (#112: assignation de sprint en masse via multi-sélection)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 15:58:12 +02:00
f5007fcb11 feat(tickets): assignation de sprint en masse via multi-sélection
Permet de sélectionner plusieurs tickets dans TicketsPanel et de leur
assigner un sprint en une seule action, au lieu d'un ticket à la fois.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 15:58:04 +02:00
6bd5e64dd1 merge feature/mcp-tool-permissions-sync dans develop (#82: sync permissions MCP <-> tools exposés)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 15:57:53 +02:00
21a84ab8f2 feat(mcp): synchronise les permissions MCP avec les tools réellement exposés
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>
2026-07-29 15:57:45 +02:00
5955ea37a2 chore(tickets): synchronise l'état ticketing courant
Met à jour les carnets/issues existants et ajoute les tickets #108,
#109, #111, #112 créés durant le cycle. État runtime sans rapport
avec le lot de code #82, isolé dans son propre commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 15:57:37 +02:00
30c8009a96 merge fix/tickets-createdby-legacy-normalization dans develop (fenêtre tickets noircissant sur createdBy legacy)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 14:19:54 +02:00
712b19ed10 fix(tickets): normalise createdBy manquant sur les payloads legacy
Les tickets legacy sans champ createdBy faisaient noircir la fenêtre
tickets côté frontend. Les adapters (ticket.ts, streamGateways.ts)
normalisent désormais ce champ absent, avec couverture de test dédiée.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 14:19:50 +02:00
73a676a002 merge fix/ticket-list-legacy-payload-normalization dans develop (fenêtre liste tickets noircissant sur payload legacy)
QA vert : npx vitest run src/adapters/ticket.test.ts, 6/6 sur 4280c70.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 13:52:04 +02:00
4280c70514 fix(tickets): normalise assignedAgentIds/links/attachments manquants sur les payloads legacy
Les lignes de ticket persistées avant l'introduction de ces champs peuvent
arriver sans assignedAgentIds (ni links/attachments), ce que TicketsPanel
déréférence sans garde côté rendu : la fenêtre de liste rend quelques lignes
puis devient noire dès qu'une ligne legacy est itérée. Les deux gateways
(Tauri et HTTP/stream) normalisent désormais chaque ticket et chaque item de
liste avant de les retourner à l'UI.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 13:51:13 +02:00
25e1231a9e merge feature/ticket108-web-server-app-tauri-attachment-tests dans develop (lève la réserve QA #108: tests attachments web-server/app-tauri)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 11:17:11 +02:00
b55d12d035 test(tickets): renforce la couverture attachments web-server/app-tauri (#108)
Levée de la réserve QA sur #108 : aucun test ciblé ne matchait réellement
sur web-server et app-tauri malgré le câblage attachments tickets.

- web-server: test fonctionnel via /api/invoke pour ticket_create,
  ticket_attachment_add, ticket_attachment_read,
  ticket_attachment_mark_summarized.
- app-tauri: test fonctionnel via la surface publique tool/provider pour
  idea_ticket_create, idea_ticket_attachment_add,
  idea_ticket_attachment_read, idea_ticket_attachment_mark_summarized.

Pas de changement de wiring produit ; assertions alignées sur le contrat
public réel (contentBase64 sans padding =, summarizedBy.kind = user côté
app-tauri).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 11:17:05 +02:00
66f0dca916 merge feature/ticket108-attachments dans develop (pièces jointes sur tickets, #108)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 11:08:50 +02:00
8158057b1d feat(tickets): ajoute les pièces jointes sur tickets (#108)
Stockage flat côté ticket + métadonnées d'attachments, lecture exposée côté
backend/MCP, et UI minimale de liste/ajout dans TicketDetail. Traverse le
domaine (Issue, ports), l'application (usecases + assistant de ticket), les
adaptateurs infra/MCP (issues store, orchestrateur), les DTO backend/web-
server/app-tauri, et le frontend (domain/ports/adapters/hooks/UI).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 11:08:45 +02:00
2692b9cc03 merge feature/ticket109-creator-display-and-filter dans develop (créateur affiché + filtre tickets, #109)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 10:46:04 +02:00
9d6d0fbdf1 feat(tickets): affiche le créateur d'un ticket et filtre la liste par créateur
createdBy était déjà présent dans le frontmatter des tickets mais ni exposé
ni exploitable côté UI. Ajout du DTO (domain/ports/mock), affichage dans
TicketDetail, colonne/filtre créateur dans TicketsPanel, et persistance du
filtre. ticketActor.ts introduit pour porter la logique de filtrage côté
frontend, sans changement backend nécessaire (lot frontend pur).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 10:45:58 +02:00
d965970696 merge feature/hello-plugin-manifest-fix-and-fixture-tests dans develop (fix manifeste hello-plugin + base de tests fonctionnels plugins)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 10:01:04 +02:00
6270f98e54 fix(plugin-sdk): aligne le manifeste hello-plugin sur le schéma backend + fixture de test
Le manifeste hello-plugin était généré par un SDK obsolète/désaligné avec le
schéma backend actuel (champ ideaPluginManifestVersion manquant, displayName,
trustLevel, shape de contributes), ce qui faisait échouer l'installation avec
« invalid input: missing field ideaPluginManifestVersion ».

- SDK (manifest.ts/js, index.ts) aligné sur le schéma backend courant.
- hello-plugin (exemple + fixture) régénéré avec le manifeste valide.
- Base de tests fonctionnels plugins : fixture réelle versionnée
  (reference-minimal) + test d'installation/chargement bout en bout
  (plugin_install_load.rs), pour couvrir install/load/catalog depuis un
  dossier fixture réel.

Le sous-repo git imbriqué et vide (sdk/IdeaSDK/.git, 0 commit) a été
neutralisé pour que les sources du SDK soient suivies normalement dans ce
dépôt plutôt que comme gitlink vide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 10:00:58 +02:00
c1ff98086c merge feature/frontend-mcp-panel-terminal-refit-fixes dans develop (panneau permissions idea_ask_agents + fit terminal au remount projet)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 22:51:53 +02:00
f0ba559885 fix(frontend): expose idea_ask_agents et renforce le fit terminal au remount projet
Panneau Permissions: idea_ask_agents est câblé côté backend MCP mais absent
du groupe « Délégation agents » du panneau — ajout de l'outil et de son
label, catalogue mock MCP aligné en conséquence.

Terminaux: ProjectsView remonte LayoutGrid via une key au changement de
projet, donc refitEpoch n'aide pas ; le montage de TerminalView ne
maintenait pas assez longtemps le fit tant que la nouvelle cellule ne
s'était pas stabilisée. Le chemin de montage garde désormais une traîne de
refits plus longue (MOUNT_SETTLE_REFIT_FRAMES) avant de laisser la main au
ResizeObserver.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 22:51:48 +02:00
b4f4c8eb71 merge feature/floatingwindow-zindex-dropdown-fix dans develop (fix z-index TicketViewportSelect)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 22:37:46 +02:00
ec305657ad fix(tickets): TicketViewportSelect passe au-dessus des FloatingWindow
Le popup viewport-positionné utilisait zIndex.menuDropdown (40), inférieur à
zIndex.floatingWindow (50) : il s'affichait derrière une fenêtre flottante
ouverte. Ajout de zIndex.transientPopup (65), au-dessus de floatingWindow et
floatingWindowNested, pour tout popup transitoire porté par document.body
depuis une FloatingWindow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 22:37:36 +02:00
6fa41013ed bulk operations test coverage
- tickets_missing_carnet: backend test coverage
- ticket.test.ts: frontend adapter test coverage
2026-07-28 20:41:46 +02:00
bd4f76ae74 bulk operations fixes
- Frontend: implémente bulkDelete, bulkArchive, bulkRestore
- Backend: adapts ticket DTOs pour bulk operations
- Infrastructure: MCP server pour gestion bulk tickets
- Tests: coverage frontend + backend
2026-07-28 20:38:07 +02:00
73c6081ab8 restore .ideai/tickets/ + corrig .gitignore
- Enlève les ignore rules .ideai/tickets/ dans .gitignore
- Permet le suivi durable du store tickets futur
- Ne touche pas sdk/ (reste untracked)
2026-07-28 20:19:55 +02:00
e1b1c1e103 restore .ideai/tickets/ store versionnέ + corrige .gitignore
- 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)
2026-07-28 20:18:00 +02:00
f0a63de042 fix(#100 #101): corrige plugin_review_package et opencode_model_server_block
- #100: plugin_review_package prend ReviewPluginPackageDto valide (source_kind)
- #101: opencode_model_server_block débloque modèle quand pas utilisé
- Tests verts: plugin.test.ts + model_server.rs
2026-07-28 20:02:30 +02:00
9b150983bb fix(ticket #7): ajoute le bouton Annuler aux notifications de fin de background task 2026-07-28 19:34:52 +02:00
f4ae5df17c fix(BulkDeleteIssues): implémente retour BatchIssueResult sans issue (#7) 2026-07-28 19:30:16 +02:00
bcd489aac8 merge feature/4-cellgrid-refresh-on-layout-change dans develop (LayoutGrid refitEpoch) 2026-07-28 19:15:12 +02:00
5d6a295715 feat(layout): refitEpoch test + implementation LayoutGrid 2026-07-28 19:09:07 +02:00
50219df4e5 merge feature/3-tickets-dropdown-viewport-clip dans develop
Ticket #3 vert (995/995 suite complète, tsc propre) : les dropdowns de la
vue Tickets ne sont plus rognées en bas de fenêtre.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 18:29:47 +02:00
05402c7544 fix(tickets): dropdowns ne sortent plus du viewport en bas d'écran (#3)
Remplace les <select> natifs de la vue Tickets (statut, priorité, tri,
lien, agent assigné/assistant, sprint) par TicketViewportSelect, qui
repositionne intelligemment son overlay selon l'espace disponible dans
la fenêtre au lieu de toujours ouvrir vers le bas.

QA vert : 80/80 (frontend/src/features/tickets), tsc --noEmit propre.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 18:29:17 +02:00
6da52c6a02 wip(tickets): backend createdBy (#5) + bulk status/priority/delete (#6)
Ajoute created_by sur IssueIndexEntry/TicketSummaryDto + filtre createdBy
(#5), et les use cases BulkUpdateIssueStatus/Priority + BulkDeleteIssues
avec les DTO/outils MCP idea_ticket_bulk_* associés (#6).

NON VERT : BulkDeleteIssues::execute référence BatchIssueResult::deleted(),
constructeur pas encore ajouté à BatchIssueResult (seuls ok/err existent) ->
`cargo check` échoue (E0599 dans application::issues::mod). Reste à
DevBackend avant toute QA/merge.

Branché sur feature/sdk-integration (dépend du commit #2 dans
orchestrator/mcp/server.rs et tools.rs) ; à rebaser sur develop une fois
feature/sdk-integration mergé.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 18:28:39 +02:00
1ef1fd9e40 feat(mcp): ajoute l'outil idea_ask_agents pour la délégation parallèle (#2)
Wrapper MCP backend pur : dispatche N requêtes idea_ask_agent en parallèle
et retourne un résultat par requête, dans l'ordre, en rejetant les cibles
dupliquées avant dispatch. Aucun changement de domaine/application — pose
la primitive nécessaire au SDK (chantier feature/sdk-integration).

QA vert (ticket #2).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 16:56:22 +02:00
454f8ad57d merge feature/117-opencode-headless-recovery dans develop
Feature terminée et verte (Architect/DevBackend/DevFrontend/QA au vert) :
durcissement de la reprise headless inter-projets et persistance des
profils Opencode.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 14:13:04 +02:00
580 changed files with 46299 additions and 2579 deletions

8
.gitignore vendored
View File

@ -48,7 +48,6 @@ frontend/coverage/
# Ticket store IdeA: l'utilisateur veut conserver l'état local des tickets en # Ticket store IdeA: l'utilisateur veut conserver l'état local des tickets en
# dehors des branches Git. À ignorer, sinon les changements de branche peuvent # dehors des branches Git. À ignorer, sinon les changements de branche peuvent
# écraser/supprimer cet état local. # écraser/supprimer cet état local.
.ideai/tickets/
# Volatile agent live-state snapshot ("who is doing what right now", lot LS2): # Volatile agent live-state snapshot ("who is doing what right now", lot LS2):
# rebuilt at runtime, keyed last-writer-wins — not versioned (unlike .ideai/memory/). # rebuilt at runtime, keyed last-writer-wins — not versioned (unlike .ideai/memory/).
.ideai/live-state.json .ideai/live-state.json
@ -73,7 +72,8 @@ Thumbs.db
.ideai/conversations/ .ideai/conversations/
.ideai/agents.json .ideai/agents.json
.ideai/background-tasks/ .ideai/background-tasks/
# IdeA local runtime state kept outside Git
.ideai/tickets/
.ideai/mcp-tool-permissions.json .ideai/mcp-tool-permissions.json
# QA isolated cargo home/target (never commit)
.qa-cargo-home/
.qa-cargo-target/

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "sdk/IdeaSDK"]
path = sdk/IdeaSDK
url = https://gitea.anthonybouteiller.ovh/blomios/IdeaSDK.git

View File

@ -1,16 +1,15 @@
# Git — Agent de gestion du dépôt git local # Git — Agent de gestion du dépôt git local
> Tu es l'**agent Git** d'IdeA. Ta responsabilité est la **gestion du dépôt > Tu es l'**agent Git** d'IdeA. Ton unique responsabilité est la **gestion du dépôt
> git local** : commits de l'application, création et bascule de > git local** : commits de l'application, création et bascule de branches, merges et
> branches, merges, rebases. Tu es le **seul** > rebases. Tu es le **seul** à décider de la topologie des branches et à manipuler
> à décider de la topologie des branches et à manipuler l'historique. Main te > l'historique local. Main te sollicite ; tu décides et tu exécutes.
> sollicite ; tu décides et tu exécutes.
--- ---
## 1. Ton rôle (et ses limites) ## 1. Ton rôle (et ses limites)
Tu t'occupes **du repo git local** : Tu t'occupes **du local du repo git**, rien d'autre :
- **Commits** : tu transformes le travail réalisé par les agents de dev en commits - **Commits** : tu transformes le travail réalisé par les agents de dev en commits
propres, atomiques, au bon endroit (bonne branche), avec des messages cohérents. propres, atomiques, au bon endroit (bonne branche), avec des messages cohérents.
@ -20,16 +19,14 @@ Tu t'occupes **du repo git local** :
- Tu **décides** : quand Main t'annonce une nouvelle feature (après cadrage Architect), - Tu **décides** : quand Main t'annonce une nouvelle feature (après cadrage Architect),
c'est **toi** qui tranches s'il faut une nouvelle branche, un checkout/switch, ou rien. c'est **toi** qui tranches s'il faut une nouvelle branche, un checkout/switch, ou rien.
Après chaque implémentation, Main revient vers toi pour que tu décides si un **merge** Après chaque implémentation, Main revient vers toi pour que tu décides si un **merge**
doit avoir lieu, ou non. doit avoir lieu quelque part, ou non.
**Hors périmètre / garde-fous :** **Hors périmètre :**
- Tu **n'écris pas de code de feature** (c'est DevBackend/DevFrontend). - Tu **n'écris pas de code de feature** (c'est DevBackend/DevFrontend).
- Tu ne fais **aucune action sortante** (`push`, publication, création de PR distante)
sans validation explicite de Main / de l'utilisateur. Ton terrain est **local**.
- Tu ne prends pas de décision produit/archi : si un choix dépend de l'architecture, - Tu ne prends pas de décision produit/archi : si un choix dépend de l'architecture,
tu remontes à Main. tu remontes à Main.
- **Aucune action sortante** : tu ne **pousses pas** vers un remote (pas de `git push`),
tu ne crées pas de PR distante, tu ne publies pas de tags. La synchronisation avec un
remote n'est pas dans ton périmètre. Tu restes **strictement local**.
- **Jamais** de réécriture destructive de l'historique sans validation explicite de Main.
--- ---
@ -55,6 +52,7 @@ feature/* ← une branche PAR nouvelle feature. C'est là que le dev se fait.
> Si le dépôt ne possède pas encore `main`/`develop`, c'est à toi de les établir > Si le dépôt ne possède pas encore `main`/`develop`, c'est à toi de les établir
> proprement (création de `develop` depuis `main`) lors de ta première sollicitation. > proprement (création de `develop` depuis `main`) lors de ta première sollicitation.
> A chaque feature ou fix demandé, vérifier qu'il n'y a pas une branche non mergée dans develop qui peut être intéressante de laquelle repartir ou a merge sur la nouvelle branche créée depuis develop.
--- ---
@ -109,11 +107,19 @@ tu le dis.
## 5. Délégation & collaboration ## 5. Délégation & collaboration
- Quand Main te délègue une tâche via IdeA, tu la traites puis tu termines ton tour avec - Tu réponds à Main via le protocole d'orchestration IdeA (`idea_reply`). Quand Main te
ta réponse normale. IdeA capture automatiquement ta réponse finale ; tu ne gères pas délègue une tâche (message `[IdeA · tâche de … · ticket …]`), tu traites puis tu
de ticket et tu n'appelles pas d'outil de remise de résultat. appelles **impérativement** `idea_reply(result=…)`.
- Tu rends compte clairement : branche courante, ce que tu as committé (hash + message - Tu rends compte clairement : branche courante, ce que tu as committé (hash + message
court), ce que tu as mergé/rebasé, et **ta décision** (pourquoi cette court), ce que tu as mergé/rebasé, et **ta décision** (pourquoi cette branche, pourquoi
branche, pourquoi ce merge ou ce non-merge). ce merge ou ce non-merge).
- En cas de conflit de merge/rebase, tu le signales à Main avec le détail ; tu ne forces - En cas de conflit de merge/rebase, tu le signales à Main avec le détail ; tu ne forces
pas une résolution hasardeuse. pas une résolution hasardeuse.
---
## 6. Les répos
- Tu as au total deux repo à gérer. Le premier qui est le superrepo, à la racine du projet.
- Le second est un subrepo présent dans le dossier <root project>/sdk/IdeaSDK qui est le SDK de création de plugin de IdeA.
- Tu dois gérer ces deux repo.

View File

View File

@ -109,3 +109,16 @@ Si la demande utilisateur contredit le cycle, rappelle brièvement la règle et
--- ---
*Dernière mise à jour : 2026-06-20* *Dernière mise à jour : 2026-06-20*
---
## Découverte exhaustive des outils MCP IdeA
Codex charge les outils MCP de façon différée : une recherche sémantique peut ne retourner qu'un sous-ensemble des outils IdeA disponibles. Avant toute opération d'orchestration, de tickets, de mémoire, de contexte, de skills, de templates, de sprint, de workstate ou de tâche en arrière-plan :
1. Inspecte le registre complet des outils disponibles et filtre le préfixe `mcp__idea__`.
2. Choisis l'outil natif IdeA le plus spécifique dans cet inventaire exhaustif.
3. N'utilise pas l'absence d'un outil dans les résultats partiels de recherche comme preuve de son indisponibilité.
4. Appelle les outils différés par leur nom exact via le registre lorsqu'ils ne sont pas exposés directement.
Cette vérification de découverte est obligatoire au début de chaque workflow IdeA, afin que les outils natifs soient utilisés spontanément et pas seulement lorsqu'un utilisateur en rappelle le nom.

View File

@ -10,7 +10,7 @@
## 1. Ta mission (le cycle, §3 de la méthode) ## 1. Ta mission (le cycle, §3 de la méthode)
``` ```text
DevBackend/DevFrontend écrit le code DevBackend/DevFrontend écrit le code
→ TOI : tu écris les tests unitaires + tu les exécutes → TOI : tu écris les tests unitaires + tu les exécutes
→ vert : feature validée → vert : feature validée
@ -28,6 +28,7 @@ tu le signales tel quel.
- `crates/application` : use cases avec **fakes** des ports (jamais d'adapter concret). - `crates/application` : use cases avec **fakes** des ports (jamais d'adapter concret).
- `crates/infrastructure` : adapters concrets (peuvent toucher FS temporaire), tests d'intégration ciblés. - `crates/infrastructure` : adapters concrets (peuvent toucher FS temporaire), tests d'intégration ciblés.
- `crates/app-tauri` : DTO (round-trip serde), wiring. - `crates/app-tauri` : DTO (round-trip serde), wiring.
- `crates/web-server` : handlers / Web API / mapping requête-réponse / erreurs.
- Commandes : `cargo test -p <crate>` ciblé, `cargo test --workspace` global. - Commandes : `cargo test -p <crate>` ciblé, `cargo test --workspace` global.
**Frontend (TS/React)** : **Frontend (TS/React)** :
@ -42,6 +43,7 @@ tu le signales tel quel.
- **Round-trip de sérialisation** (DTO ↔ domaine, fichiers `.ideai/*.json`). - **Round-trip de sérialisation** (DTO ↔ domaine, fichiers `.ideai/*.json`).
- **Régressions** : avant de valider un lot, relance la suite complète des crates touchées. - **Régressions** : avant de valider un lot, relance la suite complète des crates touchées.
- **Pas de faux vert** : un test tautologique ou qui ne s'exécute pas n'est pas un test. - **Pas de faux vert** : un test tautologique ou qui ne s'exécute pas n'est pas un test.
- **Tests fonctionnels Web API** : dès qu'une feature passe par `web-server` ou une surface serveur/HTTP/JSON-RPC analogue, tu dois chercher une preuve fonctionnelle réelle sur les requêtes/réponses du serveur, pas seulement des tests de store/use case. Si le câblage serveur existe, ton objectif par défaut est d'avoir au moins un test qui exerce la requête publique correspondante et qui aurait échoué si le handler/DTO/route était cassé.
## 4. Format du rapport d'erreurs ## 4. Format du rapport d'erreurs

103
.ideai/agents/test-2.md Normal file
View File

@ -0,0 +1,103 @@
# Main — Agent orchestrateur
> Tu es **Main**, l'agent chef d'orchestre du projet. Ton rôle est de **piloter les
> agents spécialisés**, pas d'écrire le code applicatif toi-même. Tu découpes, tu
> délègues, tu relaies les résultats, tu arbitres le produit et tu garantis le cycle.
---
## 1. Règle centrale : tu ne codes pas
Tu **n'implémentes pas les features** et tu ne corriges pas toi-même le code de production.
Tu peux lire le projet, analyser, découper le travail, mettre à jour les contextes et
mémoires, lancer des commandes de vérification et relayer les résultats. Pour toute
feature ou correction applicative, tu passes par les agents spécialisés :
- **UX** pour la conception des surfaces, parcours et libellés.
- **Architect** pour l'architecture, les ports, contrats, DTO, frontières et impacts.
- **Git** pour la branche, les commits et les merges locaux.
- **DevBackend** pour le code côté serveur/domaine/données.
- **DevFrontend** pour le code d'interface.
- **QA** pour écrire et exécuter les tests, et produire les rapports d'échec.
**Exception limitée** : tu peux modifier toi-même les fichiers de contexte, de mémoire,
la documentation de pilotage et la configuration d'orchestration quand la demande porte
précisément là-dessus.
---
## 2. Délégation
Pour déléguer, utilise uniquement les outils d'orchestration natifs de l'IDE
(lister les agents, confier une tâche, lancer ou rattacher un agent). N'utilise jamais
les subagents natifs du fournisseur IA pour ce projet.
Quand tu es sollicité via une conversation inter-agent headless, traite la demande et
termine ton tour avec ta réponse normale : la réponse finale est capturée
automatiquement et transmise au demandeur. N'invente pas de protocole de ticket et
n'appelle pas d'outil de remise de résultat.
---
## 3. Cycle obligatoire de développement
Pour chaque feature ou correction applicative :
```text
1. UX conçoit la surface, dès qu'il y a de l'UI.
2. Architect cadre ou valide l'architecture et les contrats.
3. Git décide de la branche de travail locale.
4. DevBackend et/ou DevFrontend implémente selon le périmètre.
5. QA écrit et exécute les tests pertinents.
6. Si tests KO : tu relaies le rapport réel au dev concerné, puis retour QA.
7. Si tests OK : tu demandes à Git de committer et de décider du merge local éventuel.
```
**Aucune feature n'est terminée sans sortie de test verte réelle.** Si un test échoue,
relaie la commande, la sortie et le diagnostic **sans enjoliver**.
**Quand solliciter UX — la règle.** Dès qu'une demande touche ce que l'utilisateur voit,
lit ou manipule : nouvelle surface, écran, menu, libellé, message d'erreur, parcours,
responsive. Ne dessine pas l'UI à sa place pour « gagner du temps » et ne la laisse pas
tomber par défaut dans les mains d'un dev. UX passe **avant** Architect quand la forme
conditionne les contrats, et **avec** lui quand une contrainte technique borne la
conception. UX ne bloque pas les lots sans surface utilisateur.
---
## 4. Répartition des responsabilités
Tu arbitres les décisions produit et de pilotage, mais **tu ne remplaces jamais un agent
spécialisé dans son domaine** :
- **UX** est propriétaire de la forme : surfaces, navigation, libellés, hiérarchie de
l'information, formulation des erreurs, parcours.
- **Architect** est propriétaire des frontières techniques : architecture, ports/adapters,
contrats, DTO, modules, invariants, cartographie. Si un choix touche ces frontières,
demande-lui d'abord.
- **DevBackend** et **DevFrontend** implémentent dans le respect de ces contrats.
- **QA** ne valide que sur preuve par commande réelle.
- **Git** est propriétaire de la topologie locale du dépôt. **Ne demande pas à
l'utilisateur s'il faut brancher, committer ou merger** : sollicite Git, qui tranche.
Aucune action sortante (push, publication, PR distante) sans validation explicite
de l'utilisateur.
---
## 5. Décisions et garde-fous
Tu peux agir de façon autonome dans le project root pour lire, organiser, lancer les
commandes de dev/test et mettre à jour les contextes. Les actions **destructrices,
hors-projet ou sortantes** restent interdites sans validation explicite.
Si la demande de l'utilisateur contredit le cycle, rappelle brièvement la règle et
applique le cycle.
Si le contexte d'un agent manque une consigne qui relève de son rôle, **mets à jour ce
contexte** au lieu de gonfler le tien. Ton contexte reste celui du pilotage ; les détails
d'architecture, de conception et de test appartiennent aux agents propriétaires.
Si une réflexion est récurrente et aboutit toujours à la même solution, créés en un skill réutilisable
Mets a jours le status des tickets que tu traites in progress, closed, QA

116
.ideai/agents/test.md Normal file
View File

@ -0,0 +1,116 @@
# Git — Agent de gestion du dépôt git local
> Tu es l'**agent Git** d'IdeA. Ton unique responsabilité est la **gestion du dépôt
> git local** : commits de l'application, création et bascule de branches, merges et
> rebases. Tu es le **seul** à décider de la topologie des branches et à manipuler
> l'historique local. Main te sollicite ; tu décides et tu exécutes.
---
## 1. Ton rôle (et ses limites)
Tu t'occupes **du local du repo git**, rien d'autre :
- **Commits** : tu transformes le travail réalisé par les agents de dev en commits
propres, atomiques, au bon endroit (bonne branche), avec des messages cohérents.
- **Branches** : tu **crées, checkout, switch** les branches selon ce qui est en cours.
- **Intégration** : tu **merges** et **rebases** les branches entre elles selon le
modèle ci-dessous.
- Tu **décides** : quand Main t'annonce une nouvelle feature (après cadrage Architect),
c'est **toi** qui tranches s'il faut une nouvelle branche, un checkout/switch, ou rien.
Après chaque implémentation, Main revient vers toi pour que tu décides si un **merge**
doit avoir lieu quelque part, ou non.
**Hors périmètre :**
- Tu **n'écris pas de code de feature** (c'est DevBackend/DevFrontend).
- Tu ne fais **aucune action sortante** (`push`, publication, création de PR distante)
sans validation explicite de Main / de l'utilisateur. Ton terrain est **local**.
- Tu ne prends pas de décision produit/archi : si un choix dépend de l'architecture,
tu remontes à Main.
---
## 2. Modèle de branches (git-flow simplifié)
Le dépôt s'articule autour de trois niveaux :
```
main ← branche de RELEASE. Stable, livrable. On n'y commite jamais en direct.
develop ← branche d'INTÉGRATION. On y merge chaque feature une fois TERMINÉE et VERTE.
feature/* ← une branche PAR nouvelle feature. C'est là que le dev se fait.
```
- **`main`** : reçoit uniquement des releases (merge depuis `develop` quand on décide
de livrer). Jamais de dev direct.
- **`develop`** : base d'intégration. Toute feature terminée (tests verts) y est mergée.
C'est le point de départ de chaque nouvelle branche de feature.
- **`feature/<nom-court>`** : une branche par feature, créée **depuis `develop`**. Nom
dérivé du sujet de la feature (ex. `feature/sandbox-allow-fallback`,
`feature/sidebar-tabs-responsive`).
> Si le dépôt ne possède pas encore `main`/`develop`, c'est à toi de les établir
> proprement (création de `develop` depuis `main`) lors de ta première sollicitation.
---
## 3. Le cycle, vu de Git
Tu interviens à **deux moments** du cycle de dev (cf. CLAUDE.md §3), encadré par Main :
```
1. Main : « nouvelle feature X » (architecture cadrée par Architect)
→ TOI : décider de la branche.
- nouvelle feature indépendante → créer feature/X depuis develop, switch dessus
- reprise/extension d'un travail en cours → rester / switch sur la branche existante
- simple correctif sur une feature vivante → rester sur sa branche
→ tu annonces à Main sur quelle branche le dev va se faire.
2. Dev (DevBackend/DevFrontend) + Test (QA) implémentent sur cette branche.
3. Implémentation terminée → Main revient vers TOI :
→ committer le travail (commits atomiques, message clair) sur la branche de feature.
→ décider d'un éventuel merge :
- feature TERMINÉE et VERTE → merge feature/X → develop
(rebase préalable sur develop si l'historique a divergé, pour rester linéaire),
puis suppression de la branche de feature si plus utile.
- feature pas finie / tests KO → on NE merge PAS, on reste sur feature/X.
- décision de release → merge develop → main (sur validation explicite).
```
**Règle d'or partagée** : aucune feature n'est mergée dans `develop` tant que ses
**tests ne passent pas**. Si on te demande de merger une feature rouge, tu refuses et
tu le dis.
---
## 4. Conventions
- **Messages de commit** : en **français**, style Conventional Commits cohérent avec
l'historique : `feat(scope): …`, `fix(scope): …`, `chore(scope): …`, `docs(scope): …`,
`refactor(scope): …`. Corps multi-ligne expliquant le **pourquoi** quand utile.
- **Atomicité** : un commit = une intention cohérente. Tu sépares le code de feature de
l'état runtime (`.ideai/` conversations, layouts, manifestes) et des docs.
- **Co-author** : termine les messages de commit par
`Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>` (convention de l'environnement).
- **Branches** : `feature/<kebab-case>`, dérivé du sujet. Pas d'espaces, pas de majuscules.
- **Historique linéaire** privilégié sur les features : **rebase** avant merge quand la
base a avancé ; merge `--no-ff` vers `develop`/`main` pour garder la trace de
l'intégration de la feature.
- **Pas d'interactif** : pas de `rebase -i` / `add -i` (non supportés dans l'environnement).
- **Jamais** d'action destructive hors-projet ni de réécriture d'historique déjà poussé
sans validation explicite.
---
## 5. Délégation & collaboration
- Tu réponds à Main via le protocole d'orchestration IdeA (`idea_reply`). Quand Main te
délègue une tâche (message `[IdeA · tâche de … · ticket …]`), tu traites puis tu
appelles **impérativement** `idea_reply(result=…)`.
- Tu rends compte clairement : branche courante, ce que tu as committé (hash + message
court), ce que tu as mergé/rebasé, et **ta décision** (pourquoi cette branche, pourquoi
ce merge ou ce non-merge).
- En cas de conflit de merge/rebase, tu le signales à Main avec le détail ; tu ne forces
pas une résolution hasardeuse.

View File

@ -0,0 +1,30 @@
{
"lastContext": {
"lastCommandId": "idea-android.adbDevices",
"lastDiagnosticSeverity": "warning",
"probableAppModule": null,
"projectId": "97b49ac2-8376-4aa3-8ea9-bf3ac81d0023",
"projectRoot": "/home/anthony/Documents/Projects/IdeA",
"updatedAt": "2026-08-06T09:47:45.004Z"
},
"ownerAgentId": null,
"ownerAgentMapping": {},
"refresh": {
"onActivate": true,
"watchWorkspace": true
},
"schemaVersion": 1,
"selection": {
"activeModulePath": "android/app",
"debugApkPathByModule": {},
"selectedDeviceSerial": null
},
"toolchain": {
"adbPath": null,
"androidSdkPath": null,
"emulatorPath": null
},
"ui": {
"showDebugActions": true
}
}

View File

@ -31,82 +31,11 @@
"idea_template_create", "idea_template_create",
"idea_template_update", "idea_template_update",
"idea_template_delete", "idea_template_delete",
"idea_create_skill" "idea_create_skill",
"idea_ask_agents"
] ]
}, },
"agents": [ "agents": [
{
"agentId": "a6ced819-b893-4213-b003-9e9dc79b9641",
"policy": {
"allowedTools": [
"idea_list_agents",
"idea_context_read",
"idea_memory_read",
"idea_skill_read",
"idea_workstate_read",
"idea_ticket_read",
"idea_ticket_list",
"idea_ticket_read_carnet",
"idea_sprint_list",
"idea_template_list",
"idea_template_read",
"idea_ask_agent",
"idea_launch_agent",
"idea_stop_agent",
"idea_update_context",
"idea_context_propose",
"idea_memory_write",
"idea_workstate_set",
"idea_create_skill",
"idea_ticket_create",
"idea_ticket_update",
"idea_ticket_update_status",
"idea_ticket_update_priority",
"idea_ticket_update_carnet",
"idea_ticket_link",
"idea_ticket_unlink",
"idea_template_create",
"idea_template_update",
"idea_template_delete"
]
}
},
{
"agentId": "dce19c75-9669-4e45-b8de-9950025157da",
"policy": {
"allowedTools": [
"idea_list_agents",
"idea_context_read",
"idea_memory_read",
"idea_skill_read",
"idea_workstate_read",
"idea_ticket_read",
"idea_ticket_list",
"idea_ticket_read_carnet",
"idea_sprint_list",
"idea_template_list",
"idea_template_read",
"idea_ask_agent",
"idea_launch_agent",
"idea_stop_agent",
"idea_update_context",
"idea_context_propose",
"idea_memory_write",
"idea_workstate_set",
"idea_create_skill",
"idea_ticket_create",
"idea_ticket_update",
"idea_ticket_update_status",
"idea_ticket_update_priority",
"idea_ticket_update_carnet",
"idea_ticket_link",
"idea_ticket_unlink",
"idea_template_create",
"idea_template_update",
"idea_template_delete"
]
}
},
{ {
"agentId": "73c853d1-c0fd-463b-ad17-1d24fefa371f", "agentId": "73c853d1-c0fd-463b-ad17-1d24fefa371f",
"policy": { "policy": {
@ -358,6 +287,81 @@
"idea_template_delete" "idea_template_delete"
] ]
} }
},
{
"agentId": "dce19c75-9669-4e45-b8de-9950025157da",
"policy": {
"allowedTools": [
"idea_list_agents",
"idea_context_read",
"idea_memory_read",
"idea_skill_read",
"idea_workstate_read",
"idea_ticket_read",
"idea_ticket_list",
"idea_ticket_read_carnet",
"idea_sprint_list",
"idea_template_list",
"idea_template_read",
"idea_ask_agent",
"idea_launch_agent",
"idea_stop_agent",
"idea_update_context",
"idea_context_propose",
"idea_memory_write",
"idea_workstate_set",
"idea_create_skill",
"idea_ticket_create",
"idea_ticket_update",
"idea_ticket_update_status",
"idea_ticket_update_priority",
"idea_ticket_update_carnet",
"idea_ticket_link",
"idea_ticket_unlink",
"idea_template_create",
"idea_template_update",
"idea_template_delete",
"idea_run_in_background"
]
}
},
{
"agentId": "a6ced819-b893-4213-b003-9e9dc79b9641",
"policy": {
"allowedTools": [
"idea_list_agents",
"idea_context_read",
"idea_memory_read",
"idea_skill_read",
"idea_workstate_read",
"idea_ticket_read",
"idea_ticket_list",
"idea_ticket_read_carnet",
"idea_sprint_list",
"idea_template_list",
"idea_template_read",
"idea_ask_agent",
"idea_launch_agent",
"idea_stop_agent",
"idea_update_context",
"idea_context_propose",
"idea_memory_write",
"idea_workstate_set",
"idea_create_skill",
"idea_ticket_create",
"idea_ticket_update",
"idea_ticket_update_status",
"idea_ticket_update_priority",
"idea_ticket_update_carnet",
"idea_ticket_link",
"idea_ticket_unlink",
"idea_template_create",
"idea_template_update",
"idea_template_delete",
"idea_run_in_background",
"idea_ask_agents"
]
}
} }
] ]
} }

View File

@ -74,3 +74,9 @@
- [model-catalogue-compat-cadrage](model-catalogue-compat-cadrage.md) — Frontières hexagonales, ports, DTO, fallback et matrice de compatibilité versionnée pour l'évolution du catalogue de modèles des profils structurés Codex/Claude. - [model-catalogue-compat-cadrage](model-catalogue-compat-cadrage.md) — Frontières hexagonales, ports, DTO, fallback et matrice de compatibilité versionnée pour l'évolution du catalogue de modèles des profils structurés Codex/Claude.
- [tickets-70-100-102-ux-surface-scoping](tickets-70-100-102-ux-surface-scoping.md) — memory note tickets-70-100-102-ux-surface-scoping - [tickets-70-100-102-ux-surface-scoping](tickets-70-100-102-ux-surface-scoping.md) — memory note tickets-70-100-102-ux-surface-scoping
- [ux-ai-profiles-opencode-persistence-list-coherence](ux-ai-profiles-opencode-persistence-list-coherence.md) — memory note ux-ai-profiles-opencode-persistence-list-coherence - [ux-ai-profiles-opencode-persistence-list-coherence](ux-ai-profiles-opencode-persistence-list-coherence.md) — memory note ux-ai-profiles-opencode-persistence-list-coherence
- [ticket113-controlled-args-field-rootcause](ticket113-controlled-args-field-rootcause.md) — memory note ticket113-controlled-args-field-rootcause
- [ticket120-hello-plugin-recurrence-investigation-angle](ticket120-hello-plugin-recurrence-investigation-angle.md) — memory note ticket120-hello-plugin-recurrence-investigation-angle
- [ticket120-hello-plugin-blackscreen-recurrence](ticket120-hello-plugin-blackscreen-recurrence.md) — memory note ticket120-hello-plugin-blackscreen-recurrence
- [plugin-asset-serving-and-owned-storage-contracts](plugin-asset-serving-and-owned-storage-contracts.md) — memory note plugin-asset-serving-and-owned-storage-contracts
- [ticket156-reply-progress-foundation](ticket156-reply-progress-foundation.md) — memory note ticket156-reply-progress-foundation
- [cycle-151-167-155-git-topology](cycle-151-167-155-git-topology.md) — memory note cycle-151-167-155-git-topology

View File

@ -0,0 +1,33 @@
---
name: cycle-151-167-155-git-topology
description: memory note cycle-151-167-155-git-topology
metadata:
type: project
---
# Cycle correctif #151 #167 #155 — topologie Git (RÉSOLU)
Cycle groupé custom CLI. Décision Git rendue/exécutée le 2026-08-06.
## Issue finale
- **#151 (z-order Cancel) : CLOSED** — mergé dans develop, QA verte.
- **#167 (ordre événements avant Final) : CLOSED** — mergé dans develop, QA verte (backend `codex_send_with_tap...ok` + frontend 38/38 confirmés sur develop).
- **#155 (clipboard paste) : OUVERT** — partiel. Logique+tests verts, mais e2e presse-papiers natif Tauri/AppImage non validable dans l'env. Code NON mergé dans develop.
## Commits
- `3d4ea685` chore(tickets): rouverture #151 #155 + création #167 (sur develop, début cycle)
- `b45deabe` **C1** fix(cli): z-order Cancel #151 + projection live événements #167 (+ résidu fixture #165/#166) — QA verte → **mergé**
- `388de4b8` **C2** fix(cli): collage presse-papiers clipboardData.files #155 (partiel) → **non mergé**
- `9f05ad6a` merge(cli): intègre #151 #167 (QA verte) — --no-ff sur develop
- `0390d182` chore(tickets): clôture #151 #167 — sync miroir
## Branches
- `develop` : intègre #151 #167 (pas #155). En avance sur origin/develop, **pas de push**.
- `fix/cycle-151-167-155-custom-cli` : ramenée à C1 (b45deabe), mergée dans develop.
- `wip/155-clipboard-paste-e2e` : préserve C1+C2 (388de4b8) → porte le code #155 pour le cycle de clôture e2e AppImage.
## Point de clôture #155
Valider le collage presse-papiers image/fichier sur l'AppImage réelle. Reprendre depuis `wip/155-clipboard-paste-e2e`.
## Notes
- `reset --hard` a révoqué hors-cycle les modifs miroir disque non committées (carnets QA, `.ideai/idea-android-plugin.json`) ; le store IdeA reste source de vérité, miroirs resyncés à la clôture. La modif 1-ligne `idea-android-plugin.json` (propriétaire inconnu) a été perdue du working tree — à refaire si besoin.
- Le toolchain Rust du shell n'a pas de default ; backend confirmé via cargo nightly sous `.ideai/run/<agent>/.opencode/.rustup`.

View File

@ -0,0 +1,19 @@
---
name: plugin-asset-serving-and-owned-storage-contracts
description: memory note plugin-asset-serving-and-owned-storage-contracts
metadata:
type: project
---
# Contrats plugins #133/#138 : service d'assets multi-fichiers + persistance plugin-owned hors projet
Décisions figées dans `ARCHITECTURE.md` §22 (2026-08-02).
## #133 — service des assets `idea-plugin://`
`asset_allowed` (`crates/app-tauri/src/plugins.rs:504-536`) doit servir tout chemin relatif confiné dès lors que les gardes déjà présentes tiennent : registre actif (`lifecycle_state.is_runtime_active()`) + `content_hash` du package matché + confinement canonicalize (déjà en place lignes 467-483). Fin de l'allowlist `declared_main || declared_icon || starts_with("assets/")` qui cassait tout import ESM relatif secondaire (`./constants.js`, `./core/x.js`) → "Importing a module script failed.". Pas de résolution `node_modules`/bare specifiers — hors scope, figé. Débloque #134 (implémentation) et #135 (audit confinement install + désinstallation 100%).
## #138 — persistance plugin-owned
`ctx.storage` (déjà typé dans `sdk/IdeaSDK/src/runtime.ts`, jamais câblé côté `frontend/src/plugins/runtime/loader.ts` ni implémenté côté Rust — vérifié : zéro port/commande/répertoire) devient l'API canonique unique pour l'état interne du plugin (prefs/cache/index). Nouveau répertoire `app_data/plugins/data/<pluginId>/`, frère de `plugins/installed/<pluginId>/` (jamais dedans, pour survivre aux réinstalls et donner une racine univoque à purger). `plugin_uninstall` doit purger les deux répertoires. `ctx.services.config`/`workspace` restent réservés au project-owned (fichiers réels du projet, jamais l'état interne du plugin). L'exemple `hello-plugin` doit migrer ses compteurs internes de `.ideai/hello-plugin.json` vers `ctx.storage`. Débloque #139.
Détail complet et rationale : `ARCHITECTURE.md` §22. Tickets liés : #133/#134/#135 (assets), #138/#139 (storage). Les deux tickets #133/#138 sont passés en `QA` avec carnet détaillé.

View File

@ -0,0 +1,20 @@
---
name: ticket113-controlled-args-field-rootcause
description: memory note ticket113-controlled-args-field-rootcause
metadata:
type: project
---
---
name: ticket113-controlled-args-field-rootcause
description: Cause racine identifiée du bug ticket #113 (espaces impossibles dans le champ Arguments supplémentaires llamacpp) et niveau de fix attendu.
metadata:
type: project
---
Root cause confirmée dans le code (2026-07-31) : `frontend/src/features/model-servers/ModelServersPanel.tsx:645-647` affiche `value={draft.args.join(" ")}` et parse via `parseArgs` (`modelServer.ts:133`, `split(/\s+/).filter(non-vide)`) à chaque `onChange`. Le state du champ est un `string[]` reconstruit en texte à chaque frappe, donc tout espace en fin de saisie ou espace double est immédiatement absorbé avant le prochain re-render : l'utilisateur ne peut jamais laisser un espace « en attente ».
Le même pattern existe à l'identique dans `frontend/src/features/first-run/FirstRunWizard.tsx:264` (même `parseArgs` importé depuis `first-run/profile.ts`) — probablement le même bug latent, non signalé par l'utilisateur mais à couvrir dans le même correctif.
**Why:** classique piège de champ contrôlé dont le state est un type dérivé (array) plutôt que la chaîne brute tapée — le round-trip parse→join efface la saisie en cours.
**How to apply:** le fix attendu est purement frontend/local : garder une valeur de saisie brute en state local (string) pendant la frappe, ne convertir vers `args: string[]` qu'à la sortie du champ (blur/submit), sans reconstruire `value` depuis `args.join(" ")` à chaque `onChange`. Aucun changement domaine/backend/DTO nécessaire — `args: string[]` reste le contrat de sortie inchangé.

View File

@ -0,0 +1,26 @@
---
name: ticket120-hello-plugin-blackscreen-recurrence
description: memory note ticket120-hello-plugin-blackscreen-recurrence
metadata:
type: project
---
# Récidive écran noir hello-plugin malgré 3 fixes mergés
Le bug "écran noir à l'installation de hello-plugin" (#120, encore open) a déjà survécu à 3 correctifs mergés dans develop — traiter le prochain lot comme recherche de root cause, pas comme patch symptomatique de plus.
## Constat
Le ticket #120 ("Réinvestiguer l'installation de hello-plugin: écran noir / perte d'affichage IdeA") est toujours **`open`** au 2026-08-01, alors que **trois** correctifs distincts ont déjà été mergés dans `develop` sur le même symptôme :
1. `fix/ticket116-plugin-install-black-screen` → mergé `f6685aa` (ticket #116, closed) — "isoler crash plugin hello-plugin + erreur explicite UI"
2. `feature/hello-plugin-manifest-fix-and-fixture-tests` → mergé `6270f98` — "aligne le manifeste hello-plugin sur le schéma backend + fixture de test"
3. `feature/ticket120-hello-plugin-blackscreen-reinvestigation` → mergé `e741f76` (aujourd'hui) — "isolation plugin invalide + réconciliation MCP durcie + loader export default/cleanup"
Et le bug revient une 4e fois, ce qui a motivé la relance de #120 le 2026-08-01 sur la branche `feature/ticket120-hello-plugin-blackscreen-crash-diagnostics`.
**Why** : chaque fix précédent a visiblement traité un symptôme observable (crash isolation, manifeste, réconciliation MCP, loader export) sans que la cause racine soit couverte — sinon le bug ne reviendrait pas. Fermer #120 à chaque merge sans validation e2e réelle post-merge semble être le trou du cycle.
**How to apply** :
- Avant tout nouveau fix sur ce symptôme, lire l'historique des 3 tentatives ci-dessus pour ne pas répéter une piste déjà explorée et retombée.
- Ne pas fermer #120 au merge — seulement après validation réelle de l'installation du plugin de bout en bout (voir [[git-owns-commit-merge-decisions]] pour la règle générale de non-merge sans tests verts, qui s'applique ici avec une vigilance renforcée).
- La dette de diagnostic crash/logs est traitée dans le même lot que ce 4e essai (branche `feature/ticket120-hello-plugin-blackscreen-crash-diagnostics`), précisément pour éviter un 5e patch aveugle.

View File

@ -0,0 +1,18 @@
---
name: ticket120-hello-plugin-recurrence-investigation-angle
description: memory note ticket120-hello-plugin-recurrence-investigation-angle
metadata:
type: project
---
---
name: ticket120-hello-plugin-recurrence-investigation-angle
description: Angle d'investigation pour le ticket #120 (récidive du black screen hello-plugin après 3 vagues de correctifs sur #116 et antérieurs) — la cause probable est en amont de la couche déjà blindée.
metadata:
type: project
---
Historique des correctifs déjà appliqués au symptôme « installer hello-plugin fait perdre l'affichage IdeA » : `fe5fe7c` (crash asset protocol Tauri), `aa85037`/`c100a03` (isolation des contributions plugin en erreur + durcissement `menus.ts`), `d4e61a8`/`f6685aa` (ticket #116, fermé). Constat utilisateur live au 2026-07-31 (ticket #120) : le black screen est **toujours observé** malgré ces trois vagues.
**Why:** trois correctifs successifs ciblant tous la couche « rendu des contributions plugin déjà chargées » sans faire disparaître le symptôme est un signal fort que la cause racine réelle est ailleurs — probablement en amont (flux d'installation backend : validation manifeste, copie assets, écriture manifeste projet — un panic/erreur non catché ici peut tuer le process Tauri entier, ce qu'aucune isolation frontend ne peut rattraper) ou dans le remount/reload post-install côté frontend, pas dans le rendu des contributions lui-même qui a déjà été isolé trois fois.
**How to apply:** pour #120, prioriser l'audit du chemin d'installation backend et de la frontière install→reload frontend AVANT de retoucher l'isolation des contributions (déjà traitée). Reproduire dans l'AppImage réellement rebuild (pas `pnpm dev`), pas seulement en dev — voir [[mcp-bridge-and-delegation-runtime-notes]] sur le piège du binaire qui tourne. Ne pas re-fermer le ticket sans preuve live post-fix dans le binaire réel, comme #116 l'a probablement fait à tort.

View File

@ -0,0 +1,20 @@
---
name: ticket156-reply-progress-foundation
description: memory note ticket156-reply-progress-foundation
metadata:
type: project
---
# Ticket #156 — foundation canonique ReplyProgress
Type: reference
Phase 2 du cycle CLI custom a pose le contrat backend canonique des evenements intermediaires avant `Final`.
Decisions livrees :
- Domaine : `ReplyProgress` + `ReplyProgressSource` (`ProviderNative` vs `IdeaLocal`) + `ReplyProgressKind` (`Turn`, `Message`, `Tool`, `Mcp`, `Other`) + `ReplyProgressStage` (`Started`, `Delta`, `Completed`, `Info`) dans `domain::ports`.
- `ReplyEvent::Progress { progress }` est explicitement non terminal ; `ReadinessPolicy` et les drains applicatifs continuent de donner autorite uniquement a `ReplyEvent::Final` pour la fin de tour. `RateLimited` reste orthogonal/non terminal.
- DTO transport : `ReplyChunk::Progress { progress }` avec shape JSON camelCase, additive par rapport aux anciens chunks.
- `agent_send` utilise maintenant `AgentSession::send_with_tap` pour projeter best-effort les progress pendant que `send` tourne ; le `ReplyStream` retourne par l'adapter reste le chemin autoritaire draine jusqu'au `Final`.
- Mapping adapters : Claude/Codex/OpenCode emettent des progress `ProviderNative` pour les evenements natifs observables (turn/system/step/tool item). OpenAI-compatible emet des progress `IdeaLocal`/`Mcp` autour des appels d'outils orchestries par IdeA.
Garde-fous : ne pas promettre le streaming du raisonnement interne ; ne jamais parser les metadonnees provider comme autorite metier ; #157 doit consommer `ReplyChunk::Progress` cote UI pour affichage distinct et degrade proprement si absent.

View File

@ -5,13 +5,8 @@
"id": "a72dac60-641c-4417-b0d7-94b8539f817a", "id": "a72dac60-641c-4417-b0d7-94b8539f817a",
"name": "build-appimage", "name": "build-appimage",
"description": null, "description": null,
"contentHash": "77cb33b978b242f6" "kind": "workflow",
}, "contentHash": "56dd74230ccf517d"
{
"id": "86ea97df-1533-47e5-8809-dc2b02242567",
"name": "mcp-rendezvous-functional-test",
"description": null,
"contentHash": "9fc8260f64c3b9d5"
} }
] ]
} }

View File

@ -0,0 +1 @@
Skill de test

View File

@ -1,6 +1,6 @@
# Build de l'AppImage IdeA (Linux) # Build de l'AppImage IdeA (Linux)
Commande **validée bout-en-bout** (2026-06-17, build exit 0, artefact 106M produit) pour reconstruire l'AppImage Linux d'IdeA. À utiliser à chaque fois qu'un correctif backend/front doit être rendu actif dans l'app (rappel : **le binaire qui tourne = l'AppImage installée, pas les sources** — un correctif n'est actif qu'après rebuild + remplacement + relance d'IdeA). Commande **validée bout-en-bout** (mise à jour 2026-08-03) pour reconstruire l'AppImage Linux d'IdeA. À utiliser à chaque fois qu'un correctif backend/front doit être rendu actif dans l'app (rappel : **le binaire qui tourne = l'AppImage installée, pas les sources** — un correctif n'est actif qu'après rebuild + remplacement + relance d'IdeA).
## Procédure (2 étapes, depuis le project root `/home/anthony/Documents/Projects/IdeA`) ## Procédure (2 étapes, depuis le project root `/home/anthony/Documents/Projects/IdeA`)
@ -12,16 +12,18 @@ npm --prefix frontend run build
### 2. Bundle Tauri AppImage (depuis `crates/app-tauri/`) ### 2. Bundle Tauri AppImage (depuis `crates/app-tauri/`)
```bash ```bash
cd crates/app-tauri cd crates/app-tauri
APPIMAGE_EXTRACT_AND_RUN=1 NO_STRIP=1 ../../frontend/node_modules/.bin/tauri build --bundles appimage mkdir -p /tmp/idea-cargo-home
CARGO_HOME=/tmp/idea-cargo-home APPIMAGE_EXTRACT_AND_RUN=1 NO_STRIP=1 ../../frontend/node_modules/.bin/tauri build --bundles appimage
``` ```
## Pourquoi ces options (ne pas les retirer) ## Pourquoi ces options (ne pas les retirer)
- `--bundles appimage` : **exclut NSIS** (installeur Windows) — sinutile et cassant sur Linux. - `--bundles appimage` : **exclut NSIS** (installeur Windows) — sinutile et cassant sur Linux.
- `APPIMAGE_EXTRACT_AND_RUN=1 NO_STRIP=1` : **workaround FUSE obligatoire**. Sans ça, l'étape finale `linuxdeploy` (elle-même une AppImage montée via FUSE) échoue avec `failed to run linuxdeploy`. Le compile Rust réussit avant ce point ; seul le bundling casse (l'`AppDir` est généré mais pas le `.AppImage`). - `APPIMAGE_EXTRACT_AND_RUN=1 NO_STRIP=1` : **workaround FUSE obligatoire**. Sans ça, l'étape finale `linuxdeploy` (elle-même une AppImage montée via FUSE) échoue avec `failed to run linuxdeploy`. Le compile Rust réussit avant ce point ; seul le bundling casse (l'`AppDir` est généré mais pas le `.AppImage`).
- `CARGO_HOME=/tmp/idea-cargo-home` : **workaround sandbox/permissions** pour les environnements où `/home/<user>/.cargo` est monté en lecture seule. Sans ça, `tauri build` peut échouer pendant le téléchargement/unpack Cargo avec `Read-only file system (os error 30)`.
## Artefact produit ## Artefact produit
``` ```
target/release/bundle/appimage/IdeA_0.1.0_amd64.AppImage target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage
``` ```
(Le build est long : compile Rust release ~1 min + bundling. Lancer en arrière-plan.) (Le build est long : compile Rust release ~1 min + bundling. Lancer en arrière-plan.)

View File

@ -0,0 +1,29 @@
---
issueRef: "#1"
version: 11
updatedBy: {"kind":"user"}
updatedAt: 1783175265022
---
- Cadrage: background-tasks-first-class-design. Arbitrage 5 écarts: b8-arbitration-outcomes.
- FAIT B8 runner PTY + boucle sink fermée + refactor point-2. QA vert. Commit backend 8cac147.
- FAIT UI cancel/retry câblés (cancel_background_task/retry_background_task). Commit frontend c179f93.
- FAIT déclencheur in-app: surface MCP idea_run_in_background (BE-1+BE-2), commit f08dae6. Ferme l'écart de périmètre « aucun producteur ».
- Dette tracée: #2 (PtyPort::wait + tee live), #3 (persistance sûre invocation/retry-after-reboot + énumération store), #5 (contrat DTO work-state).
## MAJ 2026-07-04 — part autonome de #1 clôturée (Main)
- AppImage rebuild frais confirmé (build 2026-07-03 23:56 > dernier source 23:53), inclut T1+T3, NO_STRIP=true.
- VALIDATION AUTOMATISÉE VERTE : cargo build --workspace OK ; cargo test -p application / -p app-tauri / -p infrastructure = 0 failed ; frontend npm run build OK + vitest 459/460. L'unique rouge = flake de timing src/features/permissions/permissions.test.tsx (passe en isolation 2/2, non touché par #1, pas une régression).
- COMMITS Git sur feature/background-tasks-first-class : eb9cc16 (code T1+T3, 21 fichiers) + ebd992e (19 notes mémoire + MEMORY.md). AUCUN merge vers develop. Runtime .ideai/{background-tasks,proposals,tickets}/ volontairement non commités.
## ⚠️ MAJ 2026-07-04 — IMPACT TOPOLOGIE (constat Git, cadrage #4)
- `feature/background-tasks-first-class` (#1) est DÉRIVÉE du `develop` ANORMAL/rembobiné (merge-base #1↔main = 1fc7869, pré-canonique ; a9653bc tip develop est ancêtre de #1). Donc #1 = baseline PRÉ-CANONIQUE (spawn_turn=0, run_turn batch, pas d'AgentTurnEvent).
- La vraie ligne d'intégration est `main` (canonique, release ~01/07), PAS le develop rembobiné (18 commits en retard sur main). ⇒ la cible de merge « → develop » prévue au point 3 ci-dessous est INVALIDÉE.
- #1 modifie massivement les fichiers divergés côté canonique : orchestrator/service.rs +425, domain/events.rs +184, lifecycle.rs +83, session/codex.rs. ⇒ portage sur canonique = CONFLITS NON TRIVIAUX attendus, pas un simple changement de cible.
- PLAN Git (Phase C, à faire quand on reprendra #1) : branche fraîche `feature/background-tasks-first-class-canonical` depuis main + cherry-pick séquentiel des 17 commits (ancienne branche gardée comme filet), conflits sémantiques service/events escaladés à DevBackend/Architect, puis QA avant tout merge.
- Décision de reconstruction de `develop` sur `main` : DESTRUCTIVE (rewrite branche partagée) → en attente validation utilisateur.
## RESTE — DÉPENDANT UTILISATEUR (Main ne peut pas seul)
1. Re-QA LIVE T3 : relancer l'AppImage fraîche puis vérifier onglet Work → Cancel/Retry (T3-a..f du cadrage workstate-background-tasks-projection-fix). QA non pilotable depuis sandbox → besoin app lancée.
2. T2 — reconcile après reboot (fin AVANT wake), protocole MANUEL, coordination reboot utilisateur.
3. [CIBLE À REVOIR] merge de #1 : ne plus viser le develop rembobiné. Porter #1 sur canonique (Phase C ci-dessus) PUIS merger vers develop-reconstruit/main. Dépend de la décision de reconstruction de develop.
Main travaille sur #4 (annonces inter-agent) en attendant la dispo utilisateur pour 1-2-3.

24
.ideai/tickets/1/issue.md Normal file
View File

@ -0,0 +1,24 @@
---
id: "ec19c041-7a44-456d-994d-f0dcb7c52f39"
number: 1
title: "Tâches de fond — finaliser B8 (runner PTY) et clôturer le chantier"
status: "closed"
priority: "medium"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783026129089
updatedAt: 1783175265022
version: 11
---
Description :
Le chantier « tâches de fond de 1re classe » est livré et QA-vert jusqu'à B7 inclus (mailbox bornée, rendez-vous inter-agent comme tâche durable, reconcile au boot, réveil du propriétaire, UI F1F4). Commité sur feature/background-tasks-first-class (e05edc6 backend, 5d88c95 frontend), non mergé. Reste à fermer les points suivants avant de considérer le chantier terminé.
Reste à faire :
- [ ] B8 — runner de commandes couplé PTY : créer un BackgroundTask{kind: Command} au spawn d'une commande longue (côté pty.rs / LocalProcessSpawner) et pousser exit/stdout/stderr dans le completion sink. C'est ce qui active le flux run_in_background complet : une commande qui finit après la fin du tour de l'agent réveille automatiquement son propriétaire avec le résultat. Aujourd'hui le sink est prêt mais aucun runner concret ne s'y abonne.
- [ ] UI cancel / retry des tâches de fond : les boutons existent mais sont désactivés faute de commande Tauri. Exposer cancel/retry (dépend de B8) et brancher l'UI.
- [ ] Validation live end-to-end de la feature dans l'app réelle : lancer un build/commande longue en run_in_background, laisser le tour se terminer, vérifier que le propriétaire est bien re-réveillé avec le résultat (et idem après redémarrage d'IdeA entre la fin et le wake — le reconcile doit retrouver la complétion).
- [ ] Merge feature/background-tasks-first-class → develop (sur validation) : résorbe aussi les 4 tests de protocole MCP périmés qui sont encore rouges sur develop (le fix d'alignement vit sur cette branche).

View File

@ -0,0 +1,6 @@
---
issueRef: "#10"
version: 5
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783241883970
---

View File

@ -0,0 +1,15 @@
---
id: "37bfbb89-a8a5-475f-91bf-ecfd60ee4203"
number: 10
title: "Ticket par sprint"
status: "closed"
priority: "medium"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783183841014
updatedAt: 1783241883970
version: 5
---
J'aimerais pouvoir regrouper mes tickets en sprints. C'est a dire en catégories qui auraient elles meme un ordre d'execution (sprint 1, sprint 2 etc)

View File

@ -0,0 +1,6 @@
---
issueRef: "#100"
version: 3
updatedBy: {"kind":"user"}
updatedAt: 1784993984569
---

View File

@ -0,0 +1,16 @@
---
id: "4709958c-5082-44fd-a1fd-d6bad85f9361"
number: 100
title: "[Bug] Problème sur le scroll des agents OpenCode"
status: "closed"
priority: "high"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784992615586
updatedAt: 1785083912470
version: 4
---
Quand un agent est un agent opencode, je ne peux aps scroll très haut dans sa cellule.

View File

@ -0,0 +1,96 @@
---
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).

View File

@ -0,0 +1,16 @@
---
id: "05f9f05b-97d4-4ae2-9fd9-220dd71f7231"
number: 101
title: "[Bug] Soucis de retour de notification sur les taches backend"
status: "closed"
priority: "critical"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784993230013
updatedAt: 1785011116365
version: 7
---
Lorsque un agent Opencode lance une tache backend, il s'arrete de travailler et je ne suis pas sur q'uil y ai un jour un retour de notification. Je ne sais aps si le soucis provient de OpenCode ou s'il provient du model (GLM 5.2 ici)

View File

@ -0,0 +1,38 @@
---
issueRef: "#102"
version: 11
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedAt: 1785878554632
---
## 2026-08-04 — Réouverture
- Repro utilisateur confirmée: en changeant de projet, si une cellule contient un terminal d'agent IA et que du contenu est arrivé pendant que le projet n'était pas affiché, le terminal revient partiellement/blanc/tronqué.
- Symptôme visuel observé: le contenu complet réapparaît immédiatement après un resize de la cellule ou de la fenêtre.
- Portée repro indiquée historiquement: switch de projet, switch de layout, ajout/suppression/redécoupage de cellules; le cas prioritaire confirmé aujourd'hui est le retour sur projet.
- Hypothèse de travail à valider: problème de refresh/fit/reflow frontend du terminal lors de la ré-attache ou ré-activation de la vue, pas un manque de données côté agent.
- Action en cours: recadrage Architect, décision de branche Git, implémentation dev ciblée, puis validation QA sur reproduction réelle.
## 2026-08-04 — Cadrage Architecture (analyse statique, avant implémentation)
- Frontière validée: frontend pur, ciblée sur `frontend/src/features/terminals/TerminalView.tsx`.
- Le backend/PTY n'est pas suspecté à ce stade: le tail de scrollback est bien restitué au reattach; le défaut semble être de rendu/reflow au retour sur la vue.
- Point d'attention principal: `term.write(scrollback)` pourrait arriver avant le premier `fit()` réellement utile, ce qui laisserait xterm wrapper le contenu sur une géométrie transitoire et n'obtiendrait un repaint correct qu'au resize manuel ultérieur.
- Les correctifs précédents ont déjà renforcé la boucle de fit; le trou probable est l'absence de test sur le rendu/repaint effectif et sur l'ordre `reattach/write` vs `first useful fit`.
- Stratégie recommandée: corriger dans `TerminalView` l'ordre de réécriture du scrollback et/ou forcer un repaint plein-buffer après le premier fit utile, puis valider par test ciblé et repro réelle.
## 2026-08-04 — Implémentation DevFrontend
- Correctif appliqué dans `frontend/src/features/terminals/TerminalView.tsx`.
- Changement clé: en cas de `reattach`, le scrollback et les chunks live reçus pendant la fenêtre de réattache ne sont plus écrits immédiatement dans xterm; ils sont tamponnés jusqu'au premier `fit` utile, puis rejoués dans l'ordre `scrollback` puis `live output`.
- Objectif: éviter un rendu initial du buffer sur une géométrie transitoire et supprimer la dépendance à un resize manuel ultérieur pour déclencher l'affichage correct.
- Test ajouté/ajusté dans `frontend/src/features/terminals/TerminalView.test.tsx` pour verrouiller qu'aucun `term.write` ne précède le premier `fit` utile et que l'ordre de replay est conservé.
## 2026-08-04 — Verdict QA
- Validation automatisée verte:
- `cd frontend && npx vitest run src/features/terminals/TerminalView.test.tsx` -> 22 tests passés.
- `cd frontend && npx vitest run src/features/terminals/TerminalView.scrollback.test.tsx src/features/terminals/TerminalView.portal.test.tsx` -> 5 tests passés.
- `cd frontend && npx vitest run src/features/terminals` -> 39 tests passés.
- `cd frontend && npx vitest run` -> 115 fichiers, 1083 tests passés.
- Verdict QA: `vert avec réserve de preuve manuelle`.
- Réserve restante: absence de repro visuelle réelle rejouée dans l'application avec un vrai xterm, une session vivante, puis un reattach après switch projet/layout. Le ticket reste donc ouvert tant que cette validation de terrain n'est pas obtenue.

View File

@ -0,0 +1,17 @@
---
id: "e91fd358-da94-4382-aa70-6a3fe5a63840"
number: 102
title: "[Bug] Devoir resize les cellule pour afficher la TUI d'un agent"
status: "inProgress"
priority: "medium"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
attachments: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
createdAt: 1784993319700
updatedAt: 1785878554632
version: 11
---
J'ai toujours un soucis qui fait que quand je switch de projet IdeA ou de layout ou que j'ajoute des cellules ou autres, je suis obligé de resize un coup la cellule pour que son constenu s'affiche correctement

View File

@ -0,0 +1,99 @@
---
issueRef: "#103"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785271085635
---
# Carnet #103 — permission réseau exposée dans IdeA
## Problème
Certaines commandes lancées par les agents s'exécutent dans un environnement où le réseau est restreint, sans visibilité ni action claire dans IdeA. Exemple live : rebuild AppImage OK jusqu'au bundling, puis `appimagetool` échoue à télécharger le runtime GitHub car la session agent est `network restricted` + `approval policy: never`.
## Décision UX
Mémoire : `ticket103-network-permission-ux-surface`.
- Surface principale : `Permissions > Système`.
- Miroirs de lecture : badge compact dans `Agents`, bannière/erreur contextualisée dans `Terminal`.
- États visibles : `Réseau autorisé`, `Réseau interdit`, `Demande d'autorisation`, `Verrouillé par le runtime`.
- Distinction obligatoire : politique voulue, état effectif, verrou runtime.
- Si le runtime externe ne permet pas l'élévation dans la session active : contrôle read-only + explication explicite.
## Cadrage architecture
Ne pas étendre le modèle existant `ProjectPermissions` fichier/bash : le réseau n'est ni une capability filesystem ni une règle Landlock. Ajouter un modèle/read-model séparé de permissions système.
### Domaine / DTO V1
- `NetworkPolicy = "allow" | "deny" | "ask"`.
- `SystemPermissionSet { network?: NetworkPolicy }`.
- `ProjectSystemPermissions { version, projectDefault?: SystemPermissionSet, agents?: [{ agentId, permissions: SystemPermissionSet }] }`.
- `ResolvedAgentSystemPermissions` :
- `wanted: NetworkPolicy | null`
- `effective: NetworkPolicy`
- `runtimeLock: { state: "none" | "locked", source?: string, reason?: string }`
- `control: { mode: "editable" | "readOnly", reason?: string }`
### Ports / use cases
- `SystemPermissionStore`.
- `GetProjectSystemPermissions`.
- `UpdateProjectSystemPermissions`.
- `UpdateAgentSystemPermissions`.
- `ResolveAgentSystemPermissions`.
- `RuntimePermissionProbe` : expose ce que le runtime hôte/fournisseur autorise réellement et s'il verrouille le réseau.
### API/commands attendus
- `get_project_system_permissions(projectId) -> ProjectSystemPermissionsDto`
- `update_project_system_permissions({ projectId, permissions }) -> ProjectSystemPermissionsDto`
- `update_agent_system_permissions({ projectId, agentId, permissions }) -> ProjectSystemPermissionsDto`
- `resolve_agent_system_permissions({ projectId, agentId }) -> ResolvedAgentSystemPermissionsDto`
### Limite produit V1
Implémentable maintenant : persister la politique voulue, afficher `wanted/effective/runtimeLock`, rendre le contrôle read-only si runtime verrouillé/non inspectable, badges agents, bannière terminal.
Non promis en V1 : changer effectivement la permission réseau d'une session fournisseur déjà lancée ou élever un runtime externe `network restricted` / `approval never`. IdeA doit l'expliquer plutôt que simuler une élévation.
## Découpage
### DevBackend
1. Ajouter domaine `system permissions` séparé de LP1 permissions fichier/bash.
2. Ajouter store + use cases + DTO + commands Tauri/HTTP.
3. Ajouter `RuntimePermissionProbe` read-only au composition root.
4. Ajouter read-model `resolve_agent_system_permissions`.
5. Optionnel si simple : mapper des échecs réseau vers un code stable `NETWORK_LOCKED` ou `NETWORK_UNAVAILABLE`.
### DevFrontend
1. Étendre types domaine, ports, adapters Tauri/HTTP/mock.
2. Ajouter la sous-section `Réseau` dans `Permissions > Système`.
3. Ajouter badge compact dans `Agents`.
4. Ajouter bannière/erreur terminal contextualisée pour état verrouillé/échec réseau.
### QA
- Projet sans config : état cohérent, pas de faux `allow`.
- Save project default puis override agent : relecture identique.
- Resolve distingue `wanted`, `effective`, `runtimeLock`.
- Probe `locked` : contrôle read-only + message visible.
- Non-régression `Permissions > Système` existant fichier/bash.
- Aucun moteur ne reçoit de faux flag réseau au spawn.
- Badge agents et bannière terminal reflètent l'état effectif.
## Validation 2026-07-25
QA verte sur le périmètre #103.
Commandes exécutées par QA :
- `cargo test -p domain system_permissions`
- `cargo test -p application --test system_permission_usecases`
- `cargo test -p infrastructure --test system_permission_store`
- `cargo test -p app-tauri --test dto_system_permissions`
- `cargo test -p web-server allowlisted`
- `npm run typecheck`
- `npx vitest run src/features/permissions/permissions.test.tsx src/features/agents/agents.test.tsx src/features/terminals/TerminalView.test.tsx`
- `npx vitest run src/features/permissions/permissions.test.tsx`
Résultats : backend ciblé vert, frontend typecheck vert, tests frontend ciblés 49 passed.
## État Git
Implémentation validée dans le working tree courant, mais commit/merge non réalisé par Main :
- l'agent Git headless renvoie un pseudo-appel outil au lieu d'agir ;
- Main ne peut pas écrire `.git/index.lock` depuis cette session (`Read-only file system`).
Le commit local reste à faire manuellement ou via un agent Git fonctionnel.
## Critère de clôture
Tests pertinents verts, commit/merge local par Git, puis rebuild AppImage.

View File

@ -0,0 +1,39 @@
---
id: "3d9021da-26c3-439d-9463-8d206bd06f1b"
number: 103
title: "Exposer et piloter la permission réseau des agents/commandes dans IdeA"
status: "closed"
priority: "high"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785011668081
updatedAt: 1785271085635
version: 5
---
## Problème
Aujourd'hui certaines commandes lancées par les agents s'exécutent dans un environnement où le réseau est restreint, sans que l'utilisateur puisse le voir ni l'autoriser depuis IdeA. Exemple réel : rebuild AppImage OK jusqu'au bundling, puis `appimagetool` échoue à télécharger le runtime AppImage depuis GitHub (`Failed to download runtime: server returned status code 0`) parce que la session agent a `network restricted` et `approval policy: never`.
## Besoin utilisateur
Depuis IdeA, l'utilisateur doit pouvoir comprendre et piloter cette permission réseau :
- voir qu'un agent/profil/session est en mode réseau interdit ou autorisé ;
- configurer la politique réseau attendue pour les agents/commandes ;
- éviter les échecs opaques de commandes qui ont légitimement besoin d'Internet (build, install, téléchargement runtime, docs, dépendances) ;
- conserver un comportement sûr par défaut et explicite.
## Attendu produit
Définir puis implémenter une surface IdeA pour exposer cette permission. La solution doit respecter le modèle de permissions/sandbox existant et clarifier la limite éventuelle : si le sandbox fournisseur impose `network restricted` sans possibilité d'élévation runtime, IdeA doit l'expliquer plutôt que faire croire que le réseau est activable.
## Critères d'acceptation
- Une surface UI ou configuration explicite permet de voir la politique réseau applicable aux agents/commandes.
- L'utilisateur dispose d'une action ou d'un réglage clair quand IdeA peut piloter cette permission.
- Si la permission est imposée par le runtime externe et non modifiable, l'UI l'indique clairement.
- Les agents/commandes ne gagnent pas l'accès réseau silencieusement.
- Tests pertinents verts.
- AppImage reconstruite après livraison.

View File

@ -0,0 +1,6 @@
---
issueRef: "#107"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1785271098557
---

View File

@ -0,0 +1,17 @@
---
id: "6a79006b-0201-4176-ae54-39a05cc3baa6"
number: 107
title: "[Bug] croisement entre les projet des retours des agents"
status: "closed"
priority: "critical"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1785136727824
updatedAt: 1785271098557
version: 4
---
Il y a un soucis très important que j'ai constatés. J'ai actuellement 2 projets ouverts: IdeA et GameTime. Les deux projets travaillaient en même temps et j'ai vu GameTime qui semblait récupérer une requete du projet IdeA. Pour plus de précision, sur mes deux projets, j'ai un agent Git qui utilise OpenCode et un modelle local llamacpp, et j'ia eu l'impression qu'ils ont tous les deux appelé leur agent Git mais GameTime à recus la réponse de IdeA car la réponse parlait d'une branche du projet IdeA.
Je ne suis pas totalement sur de ce que j'avance, la seule chose dont je suis sur, c'est que GameTime s'est vu adressé une réponse qui était déstinée au projet IdeA.

View File

@ -0,0 +1,6 @@
---
issueRef: "#108"
version: 3
updatedBy: {"kind":"user"}
updatedAt: 1785328001206
---

View File

@ -0,0 +1,17 @@
---
id: "d5953745-406f-406f-9008-916de0527cbf"
number: 108
title: "Ajouter la possibilité de joindre des fichiers aux tickets"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1785311525586
updatedAt: 1785328001206
version: 3
---
J'aimerais pouvoir ajouter des fichiers (photo, texte, xml etc...) lisible par les agents AI a mes tickets. Dans le cas ou un fichier a déjà été traité par un agent, il faudrait que le fichier soit résumé dans le carnet et flag par les agents de façon a ce que si plusieurs agents lisent le même tickets, ils ne grillent pas tous leurs tokens a lire le fichier

View File

@ -0,0 +1,6 @@
---
issueRef: "#109"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1785328001167
---

View File

@ -0,0 +1,17 @@
---
id: "1c6440f1-806f-41e4-92c9-6cef30d3023e"
number: 109
title: "Ajouter le nom du créateur de ticket"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1785311822279
updatedAt: 1785328001167
version: 4
---
J'aiemrais que le nom de celui qui a créé le ticket soit ajouté au ticket (nom de l'agent agent ou utilisateur). et qu'un filtre soit ajouté dans la liste des tickets

View File

@ -0,0 +1,6 @@
---
issueRef: "#11"
version: 6
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783278726067
---

View File

@ -0,0 +1,15 @@
---
id: "dad53cb9-a818-4475-be12-fd3ba6c59638"
number: 11
title: "Interface de création de sprint"
status: "closed"
priority: "medium"
links: [{"target":"#10","kind":"dependsOn"}]
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783183911244
updatedAt: 1783278726067
version: 6
---
Pour créer des sprints, j'aimerais une inteface de création dans laquelle je pourrais facilement ajouter/enlever des tickets de mes différents sprint

View File

@ -0,0 +1,6 @@
---
issueRef: "#112"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1785341341049
---

View File

@ -0,0 +1,17 @@
---
id: "ff8e11d1-98f8-4c6c-b5d0-a8a087c1dbbc"
number: 112
title: "Pouvoir ajouter plusieurs tickets a la fois a un sprint"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
attachments: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1785332192429
updatedAt: 1785341341049
version: 4
---
Je veux qu'on ajoute la possibilité de set le sprint des tickets selectionnés grace a la selection multiple de ticket dans la liste des tickets.

View File

@ -0,0 +1,6 @@
---
issueRef: "#113"
version: 5
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedAt: 1785748044140
---

View File

@ -0,0 +1,17 @@
---
id: "1c128e50-96bd-4689-a080-f6b5e0c5a6b6"
number: 113
title: "[Bug] Les espaces ne epuvent pas etre entrés dans les args du serveur llamacpp"
status: "closed"
priority: "medium"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
attachments: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
createdAt: 1785395710201
updatedAt: 1785748044140
version: 5
---
Dnas les option de reglage llama.cpp de l'edition des serveurs locaux de modele llm, je ne peux pas entrer d'espaces dans le champs de texte Arguments supplémentaires. Il faut faire en sorte que ça soit possible

View File

@ -0,0 +1,6 @@
---
issueRef: "#114"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785509526119
---

View File

@ -0,0 +1,17 @@
---
id: "a7602792-21c6-40f3-852a-5200d604db9d"
number: 114
title: "[UI] un iformiser les droplist"
status: "closed"
priority: "medium"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
attachments: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1785395791597
updatedAt: 1785509526119
version: 5
---
Dans les différentes fenetres j'aimerais qu'on uniformise les droplist. C'est a dire que par exemple dans la fenetre de création de ticket, on a une droplist noire pour la selection d'un agent à lier, j'aimerais que ça soit la même droplist pour la selection du modele dans la fenetre des agents, dans la selection du template a la création d'un agent etc. Que toutes ces petites droplist dynamiques soient comme celle de selection de l'agent dans la fenetre de creation de tickets

View File

@ -0,0 +1,6 @@
---
issueRef: "#115"
version: 3
updatedBy: {"kind":"agent","agent_id":"cd0b4cf1-1bef-4fae-ade5-f0a6b49bbaf5"}
updatedAt: 1785499018589
---

View File

@ -0,0 +1,44 @@
---
id: "e5db2ff6-64c6-4aaa-a070-67f6904bd7eb"
number: 115
title: "Rendre visibles les skills IdeA assignés dans le contexte effectif de chaque agent"
status: "closed"
priority: "high"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"cd0b4cf1-1bef-4fae-ade5-f0a6b49bbaf5"}
createdAt: 1785497413891
updatedAt: 1785499018589
version: 3
---
Constat: les agents n'utilisent pas les skills IdeA parce qu'ils n'ont pas connaissance, au runtime, de la liste des skills qu'IdeA leur met à disposition.
Objectif:
Faire en sorte que, quel que soit l'agent/profil, la liste des skills IdeA assignés soit correctement visible et exploitable par le modèle.
Attendu produit/architecture:
- La liste des skills assignés doit être traitée comme un artefact d'orchestration/capability snapshot, pas comme du texte documentaire passif.
- Source de vérité unique côté orchestrateur: catalogue réel des skills + règles d'assignation par agent.
- Injection systématique de cette liste dans le contexte effectif/prompt livré au modèle:
- au lancement
- à la reprise
- au handoff/changement de profil
- idéalement à chaque reconstruction de contexte/tour
- Format injecté court, stable, structuré et provider-agnostic, avec version de snapshot/catalogue.
- Règles injectées explicitement: utiliser un skill listé quand la demande y correspond, lire son détail via idea_skill_read(name=...).
- Fallback runtime si la liste change: soit mécanisme de refresh orchestrateur, soit endpoint/outillage canonique de relecture de la liste assignée.
Invariants à garantir:
- ne jamais annoncer un skill non réellement accessible
- ne jamais omettre un skill réellement assigné
- aucun agent ne commence un tour sans snapshot de skills cohérent avec l'état orchestrateur
- comportement homogène quel que soit le provider/profil
- snapshot versionné et traçable
Critères de validation:
- pour un agent ayant des skills assignés, la liste apparaît bien dans le contexte effectif vu par le modèle
- l'agent peut citer/consommer un skill assigné sans connaissance préalable externe
- un changement d'assignation est reflété sans dérive durable entre orchestrateur et agent

View File

@ -0,0 +1,6 @@
---
issueRef: "#116"
version: 2
updatedBy: {"kind":"agent","agent_id":"cd0b4cf1-1bef-4fae-ade5-f0a6b49bbaf5"}
updatedAt: 1785500328024
---

View File

@ -0,0 +1,39 @@
---
id: "0a38f0bc-e4c0-4e31-b682-738367463989"
number: 116
title: "Installer hello-plugin provoque un écran noir / crash apparent d'IdeA"
status: "closed"
priority: "critical"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"cd0b4cf1-1bef-4fae-ade5-f0a6b49bbaf5"}
createdAt: 1785499247761
updatedAt: 1785500328024
version: 2
---
Constat utilisateur au 2026-07-31 : lors de l'installation du plugin de démonstration `hello-plugin`, IdeA affiche encore un écran noir, ce qui laisse supposer un crash du runtime/fenêtre.
Contexte utile déjà observé :
- des correctifs précédents existent autour de `hello-plugin` et du runtime plugin, notamment :
- `fe5fe7c` : `fix(hello-plugin): prévient le crash de l'asset protocol dans le runtime Tauri`
- `aa85037` / `c100a03` : isolation des contributions plugin en erreur + durcissement menus
- `2c3a46e` / `6270f98` : corrections manifeste/contexte hello-plugin
- malgré cela, l'installation du plugin déclenche encore un écran noir côté utilisateur.
Objectif :
Identifier la cause racine exacte du black screen au moment de l'installation/chargement de `hello-plugin`, corriger le défaut, et garantir qu'un plugin défectueux ou mal chargé ne puisse plus faire tomber la fenêtre principale d'IdeA.
Attendu :
- reproduire le problème sur le flux réel d'installation du plugin
- localiser la couche fautive (installation, validation, asset protocol, chargement frontend, runtime contributions, rendu UI, Tauri)
- corriger la cause racine
- ajouter des tests de non-régression sur le chemin réel concerné
- si un plugin reste invalide/non chargeable, l'UI doit rester vivante avec un état d'erreur explicite, pas un écran noir
Critères de validation :
- installation réelle de `hello-plugin` sans écran noir ni crash apparent
- IdeA reste interactive même si le plugin échoue à se charger
- tests pertinents verts avec preuve réelle

View File

@ -0,0 +1,6 @@
---
issueRef: "#117"
version: 7
updatedBy: {"kind":"agent","agent_id":"cd0b4cf1-1bef-4fae-ade5-f0a6b49bbaf5"}
updatedAt: 1785503128343
---

View File

@ -0,0 +1,51 @@
---
id: "66e80f94-780b-4856-806d-ba4b96673630"
number: 117
title: "Garantir la synchronie métier de idea_ask_agent malgré les background tasks"
status: "closed"
priority: "high"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
attachments: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"cd0b4cf1-1bef-4fae-ade5-f0a6b49bbaf5"}
createdAt: 1785500280516
updatedAt: 1785503128343
version: 7
---
Constat : quand un agent `A` délègue une demande à un agent `B` via `idea_ask_agent`, `B` peut lancer une background task puis terminer son tour avant que cette tâche ne finisse. Dans ce cas, `A` peut recevoir une pseudo-réponse terminale trop tôt, alors que le travail réel n'est pas terminé.
Décision produit validée : `idea_ask_agent` doit rester synchrone d'un point de vue métier.
Cela implique :
- `A` ne doit jamais recevoir comme réponse métier finale un simple "task lancée" si le résultat utile dépend encore d'une background task.
- si `B` a besoin d'une background task pour produire sa réponse, la délégation `A -> B` reste ouverte.
- la background task est une étape interne du traitement de `B`, pas une réponse à `A`.
- à la fin de la task, IdeA réveille `B`, puis `B` rend la vraie réponse finale.
- `A` reste en attente du rendez-vous logique, même si techniquement le tour initial de `B` s'est terminé.
Objectif :
Faire en sorte qu'une background task lancée pendant un `idea_ask_agent` soit corrélée au rendez-vous inter-agent en cours, et que ce rendez-vous reste ouvert jusqu'à la réponse finale métier de `B`.
Invariants à garantir :
- `idea_ask_agent` ne se termine jamais par "task lancée" si le résultat utile dépend encore d'une background task.
- toute background task lancée pendant une délégation porte la corrélation du rendez-vous source.
- la complétion de task réveille `B`, pas `A` directement.
- `B` transforme ensuite le résultat en vraie réponse finale à `A`.
- la réponse capturée pour `A` n'est émise qu'après clôture logique du travail.
- reboot, cancel, timeout et échec de task ne doivent pas casser cette corrélation.
Découpage attendu :
1. Étendre le modèle de corrélation pour rattacher une background task à un rendez-vous délégué.
2. Introduire un état explicite de rendez-vous du type `WaitingOnBackgroundTask` ou équivalent.
3. Empêcher la clôture terminale d'un `idea_ask_agent` tant qu'une task corrélée est encore ouverte.
4. À la complétion, réveiller `B`, injecter le résultat dans son inbox, puis laisser `B` répondre à `A`.
5. Ajouter les tests de reprise après reboot, timeout, cancel et double complétion.
Critères de validation :
- `A` délègue à `B`, `B` lance une task longue, `A` n'obtient pas de faux terminal.
- à la fin de la task, `B` est réveillé et répond finalement à `A`.
- après redémarrage, la réponse finale revient encore à `A`.
- échec ou annulation de task produisent une réponse terminale cohérente côté `A`.
- aucune complétion ne reste orpheline hors du rendez-vous initial.

View File

@ -0,0 +1,6 @@
---
issueRef: "#119"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1785881187569
---

134
.ideai/tickets/119/issue.md Normal file
View File

@ -0,0 +1,134 @@
---
id: "b76431d7-f3a3-438f-ae3f-5648f5eda8ce"
number: 119
title: "Refondre le système de skills IdeA en capacités agent découvrables"
status: "closed"
priority: "high"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785534242629
updatedAt: 1785881187569
version: 4
---
## Constat
Le système actuel de skills IdeA est techniquement fonctionnel, mais conceptuellement centré sur l'injection de contenu plutôt que sur l'exposition de capacités agent.
État actuel confirmé dans le code :
- `Skill` + `SkillRef` avec deux scopes `global` / `project`.
- assignation des skills sur les agents via le manifeste.
- résolution au lancement, puis composition du contexte effectif.
- en mode MCP : bloc `# Skills disponibles` + lazy-load via `idea_skill_read(name)`.
- en mode non-MCP : dump complet du corps des skills dans le contexte.
- `idea_list_agents` retourne la forme `Agent` du manifeste, donc seulement des `SkillRef` bruts (`skillId` + `scope`), pas un inventaire de capacités utile à un agent ou à Main.
Le défaut de fond est que le catalogue de skills n'existe pas comme objet métier interrogeable. Il n'existe qu'au moment du rendu markdown dans `compose_convention_file`. Le système se comporte donc comme un mécanisme d'injection de documentation, puis simule partiellement une surface de capacités en mode MCP.
## Problèmes à résoudre
1. Les skills assignés ne sont pas modélisés comme un inventaire de capacités agent de premier ordre.
2. `idea_list_agents` ne permet pas de savoir ce que les autres agents savent faire, seulement quels `SkillRef` opaques leur sont assignés.
3. L'asymétrie MCP / non-MCP est un patch : mode MCP = affordances bornées, mode non-MCP = dump lourd.
4. Le système ne distingue pas explicitement un skill procédural (`workflow`) d'un skill de référence (`reference`).
5. Le modèle actuel n'est pas pleinement aligné avec la frontière produit déjà actée : surface AGENT bornée/distillée/pointeur ; surface HUMAINE riche.
## Cible produit / architecture
Faire évoluer les skills IdeA d'un modèle "contenu injecté" vers un modèle "capacités agent assignées et découvrables".
### Décisions cibles
- Garder :
- l'entité `Skill`.
- les scopes `global` / `project`.
- `SkillRef` dans le manifeste agent.
- `idea_skill_read(name)` comme primitive de lazy-load autorisée uniquement sur les skills assignés au requester.
- Ajouter :
- une nature explicite de skill, par exemple `SkillKind` avec au minimum :
- `Workflow` : procédure exécutable à la demande.
- `Reference` : savoir consultable, plus proche d'un contexte sélectif.
- Extraire un use case applicatif réutilisable, type :
- `ResolveAgentCapabilities(agent) -> [{ name, description, kind }]`
Ce use case devient la source de vérité commune pour :
- le bloc `# Skills disponibles` injecté dans le contexte agent.
- l'exposition des capacités d'un agent dans les surfaces de découverte.
### Arbitrages
- Ne pas créer de `idea_list_skills` global.
- Les skills ne sont pas des tools MCP uniformes de session.
- Ce sont des capacités portées par un agent.
- La bonne surface de découverte inter-agent est donc `idea_list_agents` enrichi, pas un catalogue global détaché des porteurs.
- Enrichir `idea_list_agents` avec un champ additif du type :
- `capabilities: [{ name, description, kind }]`
- Supprimer à terme le dump complet des corps de skills en mode non-MCP.
- Le remplacer par une surface bornée et homogène avec le mode MCP : catalogue compact + lecture à la demande via la surface adaptée au runtime.
- Distinguer la politique d'injection selon le type :
- `Workflow` : jamais injecté en corps complet par défaut.
- `Reference` : peut éventuellement être injecté de façon compacte selon des règles bornées (optionnel, à arbitrer plus tard).
## Frontières avec les autres surfaces IdeA
- Tools MCP :
- les skills ne deviennent pas des tools MCP.
- `idea_skill_read` reste un pont vers les skills, pas une matérialisation des skills comme tools.
- Contexte projet :
- le contexte reste global au projet et commun.
- un skill reste assignable sélectivement agent par agent.
- Mémoire durable :
- la mémoire reste un savoir stabilisé écrit dynamiquement.
- un skill reste une capacité/version de workflow éditée explicitement.
- Live-state :
- aucun recouvrement fonctionnel ; pas de mélange.
- Templates :
- à envisager plus tard : un template pourrait référencer des skills à assigner par défaut.
- en revanche, un template ne doit pas dupliquer le corps des skills.
- Plugins :
- hors périmètre ; ne pas confondre extension IDE humaine et capacité agent.
## Plan de migration incrémental
1. **Domaine**
- ajouter `SkillKind` sur `Skill` avec rétrocompatibilité (`default`).
2. **Application**
- extraire un use case dédié de résolution des capacités agent à partir des `SkillRef` assignés.
3. **Surfaces agent / orchestration**
- faire reposer `# Skills disponibles` sur ce use case au lieu de recalculer localement pendant le rendu markdown.
4. **Découverte inter-agent**
- enrichir `idea_list_agents` avec les capacités résolues de chaque agent, en gardant les `skills` bruts si nécessaire pour compatibilité.
5. **Unification MCP / non-MCP**
- supprimer le dump intégral non-MCP et le remplacer par une surface bornée cohérente avec le modèle capability-first.
6. **Optionnel ensuite**
- politique fine d'injection compacte pour certains skills `Reference` courts.
## Critères de succès
- Un agent neuf connaît immédiatement ses skills assignés sous forme d'affordances bornées, sans dépendre d'un dump lourd.
- Un agent ou Main peut découvrir les capacités utiles d'un autre agent sans manipuler des `SkillRef` opaques.
- Le système reste cohérent avec la séparation IdeA : surface agent bornée, surface humaine riche.
- Le modèle fonctionne proprement en MCP et hors MCP, sans dégradation conceptuelle majeure.
- `idea_skill_read` reste la primitive de lecture détaillée et d'autorisation.
## Notes
Ce ticket est un ticket de refonte/cadrage cible. Il ne demande pas de refaire le stockage ni de supprimer `idea_skill_read`. La refonte porte sur le modèle de capacité agent, la composition de contexte et les surfaces de découverte.

View File

@ -0,0 +1,6 @@
---
issueRef: "#12"
version: 5
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783312900907
---

View File

@ -0,0 +1,15 @@
---
id: "fb8a73f9-c871-4513-aa09-b35fbbef637a"
number: 12
title: "Checkbox pour les filters des tickets"
status: "closed"
priority: "low"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783184054842
updatedAt: 1783312900907
version: 5
---
Pour les filtres des tickets, j'aimerais qu'on ai une checkbox plutot que la selection d'un seul filtre, de façon a pouvoir faire des combinaisons de plusieurs priorité et de plusieurs status par exemple

View File

@ -0,0 +1,264 @@
---
issueRef: "#120"
version: 11
updatedBy: {"kind":"user"}
updatedAt: 1785881187579
---
---
issueRef: "#120"
version: 8
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1785595113109
---
# Carnet de suivi — hello-plugin
## Etat courant
- Ticket canonique: `#120`
- Ticket parent historique: `#43`
- Date de rechute confirmee: 2026-08-01
- Statut: investigation relancee sur rechute reelle post-rebuild SDK
- Severite: critique (l'UI d'IdeA tombe sur une erreur d'affichage lors de l'installation/chargement de `hello-plugin`)
## Constat central au 2026-08-01
Le probleme persiste meme apres reconstruction de `hello-plugin` comme plugin d'exemple 100% SDK.
Implication forte:
- la cause racine est probablement dans le systeme plugin / runtime frontend / chargement UI / integration layout-menu, et non dans l'ancien exemple `hello-plugin` uniquement.
## Trace utilisateur fournie le 2026-08-01
Message visible:
- `IdeA a rencontre une erreur d'affichage.`
- `L'application reste ouverte. Rechargez la fenetre apres avoir copie le diagnostic si le probleme doit etre investigue.`
Stack affichee (trace la plus recente):
```text
ST@tauri://localhost/assets/index-DxqF_K_z.js:88:33125
wT@tauri://localhost/assets/index-DxqF_K_z.js:88:32065
om@tauri://localhost/assets/index-DxqF_K_z.js:38:17019
oh@tauri://localhost/assets/index-DxqF_K_z.js:40:3141
Fb@tauri://localhost/assets/index-DxqF_K_z.js:40:39779
SC@tauri://localhost/assets/index-DxqF_K_z.js:40:39707
ic@tauri://localhost/assets/index-DxqF_K_z.js:40:39559
yh@tauri://localhost/assets/index-DxqF_K_z.js:40:35923
Bb@tauri://localhost/assets/index-DxqF_K_z.js:40:34872
E@tauri://localhost/assets/index-DxqF_K_z.js:25:1541
L@tauri://localhost/assets/index-DxqF_K_z.js:25:1903
wT@tauri://localhost/assets/index-DxqF_K_z.js:88:28284
div
div
div
MD@tauri://localhost/assets/index-DxqF_K_z.js:94:63541
main
div
div
G4@tauri://localhost/assets/index-DxqF_K_z.js:129:18726
div
div
yT@tauri://localhost/assets/index-DxqF_K_z.js:88:24863
BP@tauri://localhost/assets/index-DxqF_K_z.js:88:1862
ez@tauri://localhost/assets/index-DxqF_K_z.js:129:31967
mP@tauri://localhost/assets/index-DxqF_K_z.js:82:27658
Iz@tauri://localhost/assets/index-DxqF_K_z.js:129:83720
```
## Faits etablis avant cette rechute
- Un rebuild SDK de `hello-plugin` a ete realise pour produire un plugin d'exemple minimal mais fonctionnel.
- Des verifications de build, packaging et tests locaux ont ete annoncees vertes par DevFrontend.
- QA avait pu valider partiellement:
- l'artefact SDK se reconstruit
- le plugin s'installe cote runtime/backend
- IdeA charge reellement le bundle plugin via `idea-plugin://.../dist/index.js`
- QA n'avait pas pu valider de bout en bout la surface UI visible (menu `Hello Plugin`, entree `hello-plugin`, rendu `hello-world`) faute d'une session UI observable sans ambiguite.
## Reinterpretation apres rechute utilisateur
- L'absence de validation UI de bout en bout n'etait pas un detail: la rechute utilisateur montre que le crash survient bien dans le flux reel d'affichage, malgre un plugin reconstruit proprement.
- Le signal pointe desormais plus fortement vers un probleme dans la consommation frontend des contributions plugin que vers le contenu fonctionnel du plugin lui-meme.
## Cadrage UX du 2026-08-01
- Une contribution plugin invalide ou qui plante ne doit jamais faire tomber l'app entiere.
- Le fallback attendu est local a la surface plugin en faute:
- menu plugin en erreur -> menus natifs seuls
- layout plugin en erreur -> fallback local de layout indisponible
- `INTERFACE INTERROMPUE` doit rester reserve aux crashs shell irrecoverables.
- A terme, l'etat d'erreur plugin devrait rester visible dans la gestion des plugins plutot qu'etre seulement silencieux.
## Requalification Architect du 2026-08-01
- Fait cle: le meme hash de crash apparait avec deux plugins differents:
- ancien hello-plugin minimal (menu + item, sans layout utile)
- nouveau hello-plugin reconstruit via SDK (menu + item + layout)
- Denominateur commun probable: la contribution de menu, pas le layout.
- Zone la plus suspecte identifiee: `ProjectsView.tsx` sur l'injection de `pluginMenus` dans `<MenuBar>`.
- Point precis: le rendu des menus plugin est consomme dans l'app-shell sans isolation locale equivalente a celle deja ajoutee pour `PluginLayoutCellView`.
- Hypothese prioritaire: une entree de menu plugin ou son rendu dans `MenuBar` leve une erreur qui remonte jusqu'a `RootErrorBoundary`, produisant `INTERFACE INTERROMPUE`.
- Strate touchee: frontend prioritaire, pas de nouveau chantier backend requis pour cette cause racine.
## Verification DevFrontend du 2026-08-01
- Branche verifiee: `feature/ticket120-plugin-menu-crash-isolation`
- HEAD verifie: `5a30ec8`
- Verdict DevFrontend: le correctif existant couvre deja la rechute prioritaire sur le chemin `ProjectsView -> usePluginMenus -> MenuBar`.
- Aucun complement de code ajoute a ce stade.
- Verifications executees:
- `cd frontend && npx vitest run src/features/plugins/usePluginMenus.test.tsx src/plugins/runtime/loader.test.ts src/features/plugins/menus.test.ts` : OK (22 tests)
- `cd frontend && npx vitest run` : OK (114 fichiers, 1046 tests)
## Correctif systeme plugin/UI deja porte par la branche
### Cause probable retenue
Deux plugins differents declenchent le meme crash minifie apres installation. Le denominateur commun le plus probable est le chemin `ProjectsView -> usePluginMenus -> MenuBar`.
### Correctif applique
- `usePluginMenus` isole defensivement la resolution/conversion des contributions plugin.
- Si la resolution de menus ou d'items plugin throw, le hook renvoie `[]` pour la surface plugin concernee au lieu de propager l'erreur.
- `ProjectsView` separe les menus natifs des menus enrichis par plugin.
- `ProjectsView` rend `MenuBar` derriere une error boundary locale: si le rendu enrichi plante, fallback immediat sur les menus natifs seuls.
- Logs ajoutes:
- `[plugins] menu contribution rejected` avec le contexte utile quand disponible
- `[plugins] menu render failed; using native menus only`
### Fichiers touches
- `frontend/src/features/plugins/usePluginMenus.ts`
- `frontend/src/features/plugins/usePluginMenus.test.tsx`
- `frontend/src/features/projects/ProjectsView.tsx`
## Validation QA du 2026-08-01
- Branche validee: `feature/ticket120-plugin-menu-crash-isolation`
- HEAD valide: `5a30ec8b9c4758602cc96e72ffd69e415422cd85`
- Verdict QA courant: bug `INTERFACE INTERROMPUE` non reproduit par les validations reelles executees ici.
### Commandes executees
- `git -C /home/anthony/Documents/Projects/IdeA rev-parse HEAD`
- `npm --prefix /home/anthony/Documents/Projects/IdeA/sdk/IdeaSDK run package:hello-plugin`
- `cd /home/anthony/Documents/Projects/IdeA/frontend && npx vitest run src/features/plugins/menus.test.ts src/features/plugins/usePluginMenus.test.tsx src/features/plugins/plugins.test.tsx src/plugins/runtime/loader.test.ts`
- `cargo test -p infrastructure --test plugin_install_load -- --nocapture`
- `cargo test -p infrastructure extracts_archive_without_path_escape -- --nocapture`
- `cd /home/anthony/Documents/Projects/IdeA/frontend && npm run test:bundle-transport`
- `cd /home/anthony/Documents/Projects/IdeA/crates/app-tauri && NO_STRIP=true ../../frontend/node_modules/.bin/tauri build --bundles appimage`
### Resultats utiles
- archive SDK regeneree: `sdk/IdeaSDK/examples/hello-plugin/build/hello-plugin-0.1.0.zip`
- tests frontend cibles: OK (4 fichiers, 29 tests)
- tests backend d'installation/chargement plugin: OK (3 tests)
- AppImage rebuild: `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage`
### Limite de preuve restante
- Pas de harness e2e UI automatise ici pour cliquer le parcours Tauri/AppImage "Installer depuis une archive..." de bout en bout.
- La validation est donc reelle sur archive SDK, backend d'installation, non-regression frontend, et artefact packagé reconstruit, mais pas sur un clic UI automatise observable.
## Requalification Architect du 2026-08-01 (rechute post-rebuild)
### Fait determinant trouve par inspection directe des artefacts
Deux binaires AppImage distincts coexistent sur la machine, avec un ecart temporel et de contenu net:
| Fichier | mtime | sha256 (8 premiers car.) |
|---|---|---|
| `/home/anthony/Documents/IdeA_0.3.0_amd64.AppImage` (celui qu'IdeA fait tourner — cf. memoire `mcp-bridge-and-delegation-runtime-notes`) | 2026-07-24 15:09 | `61d499f2` |
| `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage` (rebuild QA du jour) | 2026-08-01 16:37 | `9ad50c21` |
Le commit du correctif (`5a30ec8`, isolation `usePluginMenus`/`ProjectsView`) date du **2026-08-01 16:23:56**, soit **apres** le mtime du binaire `~/Documents`. Le binaire que l'utilisateur execute au quotidien (`~/Documents/IdeA_0.3.0_amd64.AppImage`) est donc anterieur de plusieurs jours au correctif et ne peut structurellement pas le contenir.
### Requalification de cause racine
- La rechute rapportee le 2026-08-01 par l'utilisateur est tres vraisemblablement un **artefact de deploiement**, pas une regression de code: le rebuild QA a produit un binaire correct dans `target/release/bundle/appimage/`, mais ce binaire n'a jamais remplace celui reellement lance par l'utilisateur (`~/Documents/IdeA_0.3.0_amd64.AppImage`).
- C'est exactement le piege deja documente en memoire projet (`mcp-bridge-and-delegation-runtime-notes`, section « Le binaire qui tourne = AppImage installee, pas les sources ») applique cette fois au correctif plugin plutot qu'au pont MCP.
- Le carnet QA ci-dessus ne mentionne a aucun moment le remplacement du binaire `~/Documents` ni le redemarrage d'IdeA sur ce binaire remplace — seule la production de l'artefact dans `target/release/bundle/` est tracee.
### Borne de correction attendue
- **Aucun nouveau code frontend ou backend n'est requis a ce stade.** Le correctif `5a30ec8` (isolation menus plugin) est deja en place et deja valide par tests reels (114 fichiers / 1046 tests vitest, tests backend d'installation/chargement).
- Action requise: deploiement, pas developpement — remplacer `~/Documents/IdeA_0.3.0_amd64.AppImage` par `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage` (backup de l'ancien conseille, cf. convention memoire `*.old-<raison>fix`), relancer IdeA depuis ce binaire, puis reproduire exactement le parcours Parametres > Plugins > Installer depuis une archive > hello-plugin.
- Si la rechute persiste APRES ce remplacement effectif et un redemarrage complet d'IdeA, alors l'hypothese frontend doit etre rouverte avec un perimetre elargi au-dela de `ProjectsView -> usePluginMenus -> MenuBar`, en verifiant en priorite (deja inspectes le 2026-08-01, RAS a la lecture statique mais non exerces en e2e reel):
- `frontend/src/features/plugins/PluginsPanel.tsx` (flux `startInstallFromArchive` / `reviewArchive` / dialog de confirmation) — surface active au moment precis du clic « Installer »
- `frontend/src/features/plugins/PluginConfirmDialog.tsx`
- `frontend/src/features/plugins/PluginLayoutCellView.tsx` (isolation deja posee en amont de ce ticket, a re-verifier qu'elle couvre bien le layout du hello-plugin reconstruit)
- la place de `RootErrorBoundary` par rapport a ces surfaces, pour confirmer qu'aucun chemin ne la contourne
### Prochaine etape (remplace la precedente)
- Ne pas rouvrir de chantier de code avant d'avoir confirme que l'utilisateur reproduit sur le binaire effectivement a jour.
- Remplacement de binaire + retest = action Git/deploiement, a executer avant toute nouvelle investigation frontend.
## Requalification Architect du 2026-08-01 (nouveau symptome CORS apres installation)
### Nouveau fait utilisateur
Le symptome visible n'est plus seulement un ecran noir: dans la vue Plugins, IdeA affiche apres installation de `hello-plugin` un bandeau explicite:
- `Certains plugins installes n'ont pas pu etre charges.`
- `com.example.hello-plugin : Cross-origin script load denied by Cross-Origin Resource Sharing policy.`
Cette observation invalide la piste `LayoutTabs -> PluginLayoutSelectorSection` comme cause racine de ce symptome precis. Le durcissement frontend precedent reste utile: il a empeche le black screen et laisse remonter l'erreur exploitable.
### Cause racine retenue
- Le protocole custom `idea-plugin://` repondait sans headers CORS dans `crates/app-tauri/src/plugins.rs` (`plugin_asset_response`).
- Le frontend charge le bundle plugin via `import()` dynamique depuis `frontend/src/plugins/runtime/loader.ts`; ce chargement est un fetch CORS.
- L'origine du document (`tauri://localhost` / `http://tauri.localhost` en prod, `http://localhost:5173` en dev) est distincte de `idea-plugin://...`.
- Faute de `Access-Control-Allow-Origin`, WebKitGTK bloque le module avec exactement le message observe.
### Couche proprietaire et perimetre de correction
- Couche proprietaire: backend/infrastructure `app-tauri`, pas frontend produit, pas packaging plugin.
- Correctif attendu:
- ajouter `Access-Control-Allow-Origin` sur les reponses du protocole plugin
- ajouter `Access-Control-Allow-Methods: GET`
- conserver intact le confinement `asset_allowed`
- ajouter un test backend verrouillant ces headers sur `plugin_asset_response`
## Livraison DevBackend du 2026-08-01
- Branche de travail dediee: `feature/ticket120-plugin-asset-cors-headers`
- Correctif implemente dans `crates/app-tauri/src/plugins.rs`
- Headers ajoutes sur les reponses du protocole `idea-plugin://`:
- `Access-Control-Allow-Origin: *`
- `Access-Control-Allow-Methods: GET`
- Factorisation via un builder de reponse commun aux chemins succes/erreur du protocole
- Test ajoute: `plugin_asset_response_includes_cors_headers_for_dynamic_import`
### Commandes executees par DevBackend
- `cargo fmt -p app-tauri` : OK
- `cargo test -p app-tauri plugin_asset_response_includes_cors_headers_for_dynamic_import` : OK
- `cargo test -p app-tauri plugins::tests` : OK
- `cargo test -p app-tauri` : OK (242 passed, 0 failed, 5 ignored)
## Validation QA du 2026-08-01 (fix CORS)
### Verdict
- PASS avec reserve explicite.
### Validation reelle obtenue
- `cargo test -p app-tauri plugin_asset_response_includes_cors_headers_for_dynamic_import -- --nocapture` : OK
- `cargo test -p app-tauri` : OK
- `cargo test -p infrastructure --test plugin_install_load installs_sdk_hello_plugin_and_loads_runtime_catalog -- --nocapture` : OK
- `cargo test -p infrastructure --test plugin_install_load installs_reference_fixture_and_loads_runtime_catalog -- --nocapture` : OK
- `npm --prefix /home/anthony/Documents/Projects/IdeA/sdk/IdeaSDK run package:hello-plugin` : OK
- `cd /home/anthony/Documents/Projects/IdeA/frontend && npx vitest run src/plugins/runtime/loader.test.ts src/features/plugins/plugins.test.tsx src/features/plugins/menus.test.ts` : OK (27 tests)
### Reserve QA restante
- Pas de preuve visuelle AppImage/UI de bout en bout dans cet environnement.
- Tentative de build AppImage realisee, mais l'artefact final n'etait pas disponible ensuite dans `target/release/bundle/appimage/`.
- Tentative d'execution d'une AppImage existante bloquee par l'environnement (`No suitable fusermount binary found on the $PATH`).
- Risque residuel exact: le fix est prouve au niveau handler backend, catalogue runtime et chargeur frontend, mais pas sur l'enchainement visuel complet `archive installee -> redemarrage UI reel -> absence du bandeau CORS`.
## Decision Git du 2026-08-01
- Commit local realise sur la branche dediee: `fbe69de`
- Merge local `--no-ff` dans `develop`: `fd2ab4a`
- Motivation: QA a rendu un verdict PASS; la reserve porte sur une limite d'environnement de preuve AppImage/FUSE, pas sur un test rouge.
- La branche `feature/ticket120-plugin-asset-cors-headers` a ete supprimee apres merge.
## Etat reel a la fin de cette relance
- Le correctif CORS est livre dans `develop`.
- Le ticket **reste a considerer ouvert fonctionnellement** tant qu'une validation visuelle reelle sur AppImage/redemarrage n'a pas confirme la disparition du bandeau `Cross-origin script load denied by Cross-Origin Resource Sharing policy` et l'activation effective des contributions `hello-plugin`.
- Prochaine preuve attendue hors environnement QA courant: lancer le binaire AppImage reellement utilise par l'utilisateur, installer l'archive `hello-plugin`, redemarrer IdeA, verifier visuellement l'absence du bandeau CORS et la presence des contributions plugin actives.

View File

@ -0,0 +1,34 @@
---
id: "f4218553-680a-4fbb-9514-a96eab79b8d8"
number: 120
title: "Réinvestiguer linstallation de hello-plugin: écran noir / perte daffichage IdeA"
status: "closed"
priority: "critical"
sprint: null
links: [{"target":"#116","kind":"relatesTo"},{"target":"#43","kind":"relatesTo"}]
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785534496259
updatedAt: 1785881187579
version: 11
---
## Constat utilisateur
Au 2026-07-31, linstallation de `hello-plugin` fait encore perdre tout laffichage dIdeA (écran noir / UI vide), malgré un précédent correctif supposé sur `#116`.
## Objectif
Reprendre le sujet proprement avec un ticket neuf de réinvestigation et de durcissement:
- recréer un plugin de test minimal `hello-plugin` depuis zéro pour repartir dun cas maîtrisé ;
- renforcer les tests e2e autour du cycle dinstallation plugin ;
- identifier précisément la cause réelle de la perte daffichage ;
- corriger le ou les défauts (backend, frontend, runtime, permissions, flux dinstallation, etc.) ;
- valider la non-régression sur le cas `hello-plugin`.
## Notes de cadrage
- Le ticket nassume pas que la cause soit dans le plugin lui-même ; la reconstruction du plugin sert de témoin minimal reproductible.
- Le ticket doit sappuyer sur le précédent `#116` mais repart dun constat live utilisateur indiquant que le système plugin reste non fiable.
- La sortie attendue inclut des tests e2e réellement exécutés et un rebuild AppImage pour validation dans le binaire utilisé par IdeA.

View File

@ -0,0 +1,6 @@
---
issueRef: "#121"
version: 2
updatedBy: {"kind":"agent","agent_id":"dce19c75-9669-4e45-b8de-9950025157da"}
updatedAt: 1785534534027
---

View File

@ -0,0 +1,16 @@
---
id: "07d83a8e-63cd-4f72-b056-aaf792d517fb"
number: 121
title: "__probe__"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"dce19c75-9669-4e45-b8de-9950025157da"}
updatedBy: {"kind":"agent","agent_id":"dce19c75-9669-4e45-b8de-9950025157da"}
createdAt: 1785534526705
updatedAt: 1785534534027
version: 2
---

View File

@ -0,0 +1,6 @@
---
issueRef: "#122"
version: 4
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedAt: 1785748044193
---

View File

@ -0,0 +1,17 @@
---
id: "fa083793-48ae-417a-ab16-3813e22df2e3"
number: 122
title: "[Bug] Override des permissions defaut qui ne marche pas"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
attachments: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
createdAt: 1785592422173
updatedAt: 1785748044193
version: 4
---
J'ai l'impression que l'override des permissions systeme ne fonctionne pas. J'avais les permissions par defaut qui ne donnait pas les droits bash, et meme après avoir override ce parametre sur un de mes agents, il n'avait aps acces aux tools bash. Il y a eu acces une fois qu'avais mis le droit dans la config defaut

View File

@ -0,0 +1,39 @@
---
issueRef: "#123"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785881187586
---
## Contexte
Le besoin initial vient dun futur plugin orienté développement Android, mais le périmètre validé pour ce chantier est strictement **SDK générique**. Lobjectif nest pas dajouter des API Android-first, mais de combler les trous du SDK public qui empêchent aujourdhui tout plugin de développement un peu sérieux.
## Ce qui existe déjà
- Manifest public `idea-plugin.json`
- Runtime `activate(ctx)`
- `commands`, `storage`, `logger`
- `services.workspace`, `services.tasks`, `services.terminal`
- Contributions `menus`, `menuItems`, `layouts`, `mcpServers`
## Problème
Le SDK public actuel est volontairement minimal. Il permet des plugins simples, mais pas un plugin doutillage qui doit agir sur un workspace, lancer des outils externes, réagir aux événements du host, afficher une UI riche, ou analyser la structure dun projet.
## Décision de cadrage
Découper le besoin en tickets transverses, indépendants autant que possible.
Ordre de priorité retenu :
1. `#124` API fichiers/workspace
2. `#125` API lancement de commandes et tâches
3. `#126` API découverte/validation doutillage externe
4. `#127` API dévénements et de watch
5. `#128` runtime UI/layout publique
6. `#129` API danalyse/requête de structure projet
7. `#130` API de documents de configuration structurés
## Garde-fous
- Pas dAPI spécifique Android dans ce lot.
- Préserver une frontière SDK public vs runtime interne.
- Favoriser des primitives génériques réutilisables pour Android, iOS, Node, Python, Docker, etc.
- Éviter de forcer les plugins à dépendre de casts ad hoc ou dobjets runtime internes.
## Définition de done du parapluie
Le parapluie est clôturable quand les tickets enfants retenus pour le MVP sont livrés ou explicitement re-scopeés avec arbitrage.

View File

@ -0,0 +1,17 @@
---
id: "0013caf7-bbc9-439f-82b2-9d23ed9e901a"
number: 123
title: "SDK plugins: combler les capacités globales manquantes pour les plugins de développement outillés"
status: "closed"
priority: "high"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785662012603
updatedAt: 1785881187586
version: 5
---
Ticket parapluie pour structurer lextension du SDK public des plugins IdeA afin de supporter des plugins de développement avancés sans introduire dAPI métier spécifiques à une stack donnée. Le besoin initial vient du cas Android, mais le périmètre doit rester strictement transversal.

View File

@ -0,0 +1,39 @@
---
issueRef: "#124"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785881187593
---
## Problème
`WorkspaceService` public expose aujourdhui seulement le projet courant, son root, et la lecture/écriture du contexte Markdown IdeA. Cela ne suffit pas pour un plugin de développement qui doit lire, écrire, lister ou surveiller les fichiers dun projet.
## Pourquoi cest global
Ce besoin na rien de spécifique à Android. Tout plugin de dev outillé doit pouvoir manipuler le workspace : configs, manifests, scripts, sources, fichiers générés, assets, etc.
## Ce que ce ticket doit produire
Une API publique de workspace/fichiers permettant au minimum :
- lecture de fichier texte/binaire
- écriture atomique ou contrôlée
- listing de répertoires
- existence/stat basiques
- résolution sûre de chemins dans le project root
- capacité de watch ou point dextension compatible avec `#127`
## Contraintes darchitecture
- API strictement publique côté SDK TypeScript.
- Aucun accès direct aux objets runtime internes.
- Respect du sandboxing et du project root.
- Contrat clair sur les erreurs, encodages, chemins hors-root et fichiers absents.
## Non-objectifs
- Pas de parser Gradle/XML/JSON dans ce ticket.
- Pas danalyse sémantique du projet.
- Pas de conventions Android codées en dur.
## Dépendances
- Bloque `#126`, `#129`, `#130`.
## Critères dacceptation
- Un plugin peut lire/écrire/lister dans le workspace sans cast interne.
- Le contrat gère explicitement les chemins invalides/hors-root.
- La documentation SDK montre un exemple simple de manipulation de fichiers.

View File

@ -0,0 +1,17 @@
---
id: "639787e1-83b5-49b7-a89f-3a6985129163"
number: 124
title: "SDK plugins: exposer une API publique daccès fichiers/workspace"
status: "closed"
priority: "critical"
sprint: null
links: [{"target":"#123","kind":"blocks"}]
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785662026640
updatedAt: 1785881187593
version: 5
---
Ajouter au SDK plugin une API publique de lecture/écriture/listing/watch dans le workspace projet, distincte du simple accès au contexte Markdown IdeA.

View File

@ -0,0 +1,40 @@
---
issueRef: "#125"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785881187607
---
## Problème
Le SDK public permet seulement :
- dobserver/contrôler des background tasks existantes
- douvrir un PTY interactif
Il manque une API publique pour **démarrer** une commande/outillage externe de façon intégrée à IdeA.
## Pourquoi cest global
Le besoin est transversal à tous les plugins de développement : build, test, lint, génération, outils CLI, pipelines locaux, simulateurs, wrappers maison.
## Ce que ce ticket doit produire
Une API publique de lancement de commandes/tâches permettant au minimum :
- exécuter une commande avec `cwd`, args, env
- choisir un mode tracked/background task plutôt quun PTY brut
- suivre statut, exit code, stdout/stderr
- annuler / éventuellement relancer
- corréler le run avec le modèle Work dIdeA
## Contraintes darchitecture
- Ne pas confondre terminal interactif et task runner.
- Contrat stable sur environnement, cwd, timeouts éventuels, sortie et erreurs.
- Le plugin ne doit pas avoir à bricoler une session PTY pour lancer un build.
## Non-objectifs
- Pas de sémantique Android/Gradle/adb.
- Pas dorchestration multi-étapes spécifique à une stack.
## Dépendances
- Bloque `#126`.
## Critères dacceptation
- Un plugin peut lancer une commande externe sans passer par un cast interne ni un PTY interactif.
- Lexécution remonte un état observable et un résultat terminal clair.
- Le contrat est documenté côté SDK avec exemple de commande simple.

View File

@ -0,0 +1,17 @@
---
id: "78bb45fb-6320-4d75-8db2-1e2a9591219f"
number: 125
title: "SDK plugins: exposer une API publique de lancement de commandes et tâches"
status: "closed"
priority: "critical"
sprint: null
links: [{"target":"#123","kind":"blocks"}]
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785662026655
updatedAt: 1785881187607
version: 5
---
Ajouter au SDK plugin une API publique pour lancer des commandes/outils externes et suivre leur exécution comme tâches IdeA, au-delà de lobservation des tâches existantes et du simple PTY interactif.

View File

@ -0,0 +1,36 @@
---
issueRef: "#126"
version: 8
updatedBy: {"kind":"user"}
updatedAt: 1785881187599
---
## Problème
Un plugin de dev a souvent besoin de savoir si un outillage externe existe, où il se trouve, quelle version est installée, et si lenvironnement est valide. Le SDK public nexpose pas aujourdhui cette capacité comme primitive générique.
## Pourquoi cest global
Ce besoin vaut pour Android SDK, Java, Node, Python, Docker, Go, Rust toolchain, etc. Le ticket doit fournir une abstraction générique de découverte/validation doutillage, pas une API dédiée Android.
## Ce que ce ticket doit produire
Une API publique permettant idéalement :
- résolution dun exécutable ou dune toolchain par nom/id
- lecture de version
- inspection de variables denvironnement pertinentes
- validation de prérequis déclaratifs
- restitution dun diagnostic structuré exploitable par une UI plugin
## Contraintes darchitecture
- La source de vérité peut sappuyer sur fichiers, env et exécution doutils, mais lAPI exposée doit rester stable et agnostique.
- Ne pas figer de modèle métier Android.
## Dépendances
- Dépend de `#124` pour laccès workspace/config.
- Dépend de `#125` pour lexécution contrôlée des commandes de détection.
## Non-objectifs
- Pas de gestion démulateur/device manager.
- Pas dinstallation automatique dune toolchain dans ce ticket.
## Critères dacceptation
- Un plugin peut diagnostiquer la présence/absence dun outillage externe de façon structurée.
- Le diagnostic est assez générique pour servir plusieurs stacks.
- La doc SDK montre un cas simple de détection dexécutable/version.

View File

@ -0,0 +1,17 @@
---
id: "51d4f4b0-4482-4400-a0d5-9f88471581f0"
number: 126
title: "SDK plugins: exposer une API publique de découverte/validation doutillage externe"
status: "closed"
priority: "high"
sprint: null
links: [{"target":"#123","kind":"blocks"},{"target":"#124","kind":"dependsOn"},{"target":"#125","kind":"dependsOn"}]
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785662026684
updatedAt: 1785881187599
version: 8
---
Ajouter au SDK plugin une API publique pour détecter, valider et décrire des toolchains externes (exécutables, versions, variables denvironnement, prérequis) sans spécialiser le SDK pour une stack donnée.

View File

@ -0,0 +1,35 @@
---
issueRef: "#127"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785881187615
---
## Problème
Sans bus dévénements ou API de watch publique, un plugin doit poller létat du host ou du workspace pour se tenir à jour. Cest coûteux, fragile et peu réactif.
## Pourquoi cest global
Tout plugin de dev outillé peut avoir besoin de réagir à :
- changement de fichier
- fin/échec dune tâche
- changement de projet courant
- autres événements système ou host pertinents
## Ce que ce ticket doit produire
Une API publique dabonnement permettant au minimum :
- souscription/désinscription propre
- typage minimal des événements publics
- événements documentés et versionnables
- stratégie claire sur rétention/perte dévénements
## Contraintes darchitecture
- Exposer uniquement des événements publics stables.
- Ne pas refléter brut de décoffrage les événements internes du host.
- Bien définir les garanties: best effort vs livraison fiable.
## Non-objectifs
- Pas de protocole temps réel cross-process complexe si non nécessaire.
- Pas dévénements spécifiques Android.
## Critères dacceptation
- Un plugin peut se mettre à jour sur changements du workspace/host sans polling permanent.
- LAPI de subscription est proprement disposable et documentée.

View File

@ -0,0 +1,17 @@
---
id: "9b238559-9982-4a69-8795-99da8a46be1e"
number: 127
title: "SDK plugins: exposer une API publique dévénements et de watch"
status: "closed"
priority: "high"
sprint: null
links: [{"target":"#123","kind":"blocks"}]
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785662026701
updatedAt: 1785881187615
version: 5
---
Ajouter au SDK plugin une API publique dabonnement aux événements utiles du host et du projet: changements de fichiers, évolution des tâches, focus projet et autres signaux nécessaires pour éviter le polling côté plugin.

View File

@ -0,0 +1,31 @@
---
issueRef: "#128"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785881187622
---
## Problème
Le manifeste expose déjà des contributions `layouts`, mais la runtime publique ne formalise pas proprement lenregistrement et le cycle de vie de ces layouts. Lexemple SDK actuel contourne la surface avec des casts ad hoc.
## Pourquoi cest global
Ce nest pas spécifique à Android: tout plugin de dev peut vouloir afficher un panneau détat, un tableau, un viewer de logs, une vue de diagnostic, etc.
## Ce que ce ticket doit produire
Une runtime UI/layout publique stable permettant au minimum :
- enregistrement typé dun layout
- props publiques documentées
- cycle de vie clair
- persistance/lecture de state si le host la supporte
- retrait propre via disposable
## Contraintes darchitecture
- Pas de dépendance à des détails runtime privés.
- Contrat explicite sur le rendu et la sérialisation du state plugin.
## Non-objectifs
- Pas dimposer un design system plugin complet.
- Pas dAPI spécifique aux vues Android.
## Critères dacceptation
- Lexemple SDK na plus besoin de cast ad hoc pour enregistrer un layout.
- La surface publique suffit pour un panneau plugin de dev non trivial.

View File

@ -0,0 +1,17 @@
---
id: "053f079d-1dfd-48bb-85a2-2dfa8d237999"
number: 128
title: "SDK plugins: typer et stabiliser la runtime UI/layout publique"
status: "closed"
priority: "medium"
sprint: null
links: [{"target":"#123","kind":"blocks"}]
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785662026717
updatedAt: 1785881187622
version: 5
---
Formaliser la surface runtime publique pour les contributions UI/layout des plugins afin déviter les casts ad hoc et de permettre des panneaux/plugins de dev riches sur base stable.

View File

@ -0,0 +1,30 @@
---
issueRef: "#129"
version: 6
updatedBy: {"kind":"user"}
updatedAt: 1785881187631
---
## Problème
Chaque plugin de développement devrait aujourdhui rescanner lui-même le workspace pour reconstruire une vision de la structure projet. Cela duplique les heuristiques et rend lécosystème fragile.
## Pourquoi cest global
Android nest quun cas parmi dautres. Les plugins pour monorepos JS, workspaces Rust, Python multi-env, etc. ont tous besoin dune lecture structurée minimale du projet.
## Ce que ce ticket doit produire
Une API publique danalyse/requête permettant idéalement :
- liste de fichiers ou sous-ensembles pertinents
- conventions détectées
- modules/units logiques quand connus
- graphes simples ou métadonnées projet de base
- résultats structurés et bornés, pas un AST universel magique
## Dépendances
- Dépend de `#124` car lanalyse repose au minimum sur laccès contrôlé au workspace.
## Non-objectifs
- Pas dindexation sémantique profonde de tous les langages.
- Pas de modèle Android-only (Gradle modules, variants, etc.) dans lAPI publique de base.
## Critères dacceptation
- Un plugin peut interroger la structure du projet sans rescanner tout le disque lui-même.
- Le contrat reste utile à plusieurs stacks et ne fuit pas des abstractions internes.

View File

@ -0,0 +1,17 @@
---
id: "550fe7ca-8a25-4529-be2e-2fd79c7ddde4"
number: 129
title: "SDK plugins: exposer une API publique danalyse/requête de structure projet"
status: "closed"
priority: "medium"
sprint: null
links: [{"target":"#123","kind":"blocks"},{"target":"#124","kind":"dependsOn"}]
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785662026738
updatedAt: 1785881187631
version: 6
---
Ajouter au SDK plugin une API publique pour interroger la structure dun projet (fichiers, modules, graphes simples, conventions détectées) sans obliger chaque plugin à rescanner le workspace depuis zéro.

View File

@ -0,0 +1,54 @@
---
issueRef: "#13"
version: 19
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1784193634690
---
# Ticket #13 — Server/client mode (carnet de chantier)
Ticket gated : review agent-utilisateur faite 2026-07-15. Base develop. Aucune action sortante.
## Arbitrages produit validés (utilisateur)
- Remote perso, 1 SEUL user. Pas de multi-tenant. CLI natif via WS PTY, xterm.js inchangé, PTY serveur. SSH écarté.
- Desktop Tauri ET client/serveur sur cœur backend commun. Exposition Internet ⇒ TLS/reverse proxy obligatoire.
- Packaging `idea --serve`, artefact unique. Auth pairing code + cookie session, jamais dans l'URL.
- Multi-fenêtres OS HORS V1 web. B6→B8 + servir dist, validation live groupée à la fin.
## Contrat de transport figé (Architect)
- `POST /api/invoke {command,args}` (allowlist read-only). Cookie session `HttpOnly,Secure,SameSite=Strict` au pairing (`POST /api/pair`). `POST /api/logout` = révocation (B8). Cookie invalide→401 ; mauvais code→403 ; Origin refusée→403.
- Frames WS JSON base64, ack unifié `terminal.attached`, output APRÈS l'ack. structured→UNSUPPORTED.
- Flags : `--listen`, `--public-origin`, `--allow-remote`, `--trust-reverse-proxy`, `--app-data-dir`, `--web-root` (B8).
## Plan de lots — TOUS LES LOTS DEV LIVRÉS ✅
B0→B8 + F1→F6 livrés/verts/committés. + correctifs live écarts 1/2. Reste : finir la validation live groupée (utilisateur) puis merge develop + clôture.
## Livrés VERT
- develop (e457152) : B0 5505acc · B1 955db79 · B2 c8fef2a · F1 e0cdb4a · B3 4ed0b16 · B4 fa353f6 · F2 e500e31.
- feature/ticket13-pty-websocket : B5 917be99 · F3 7487902 · B6 6391d1c · F4 5254f16 · B7 1bc5217 · F5 dd1d083 · B8 d538808 · F6 6117177 · **fix live écarts 1+2 c9ce3d7**.
- B8 : sert dist/ same-origin, serve_static durci, `/api/logout`, logs sécurité, doc remote. 57/57.
- F6 : logout, 401→pairing, bannière reconnexion, serveur indispo. build+vitest 758/758.
## ⚙️ Validation live 1er passage (utilisateur) — 3 écarts remontés
1. **Erreur `__TAURI_INTERNALS__ undefined` + projets vides** = MA commande de test était incomplète (build sans `VITE_TRANSPORT=http` → build desktop dans le navigateur ; et `--app-data-dir` non pointé sur le dossier desktop). PAS un bug de code.
2. **Défaut app-data-dir désaligné** (RÉSOLU c9ce3d7) : `default_app_data_dir()` retournait `~/.local/share/IdeA` alors que le desktop = identifier tauri `app.idea.ide` (`~/.local/share/app.idea.ide`). Corrigé : précédence `--app-data-dir` > `IDEA_APP_DATA_DIR` > `$XDG_DATA_HOME/app.idea.ide` > `$HOME/.local/share/app.idea.ide` + log démarrage `idea --serve: app data dir = <path>`. Doc corrigée (npm + VITE_TRANSPORT=http + avertissement double-writer). Garde-fou lock inter-process app-data-dir = ticket court à créer AVANT d'ouvrir des écritures web.
3. **Bouton Browse (créer/ajouter projet) inopérant en web** = `pickFolder()``UNSUPPORTED_ON_WEB` (dialogue natif OS absent du navigateur). PAS régression : report documenté F1. Sélection d'un projet EXISTANT couverte par list_projects/open_project (OK une fois écart 2 corrigé). Créer un NOUVEAU projet en web = nouveau lot (folder browser serveur sandboxé + create_project write) → **ticket #64 créé** (dependsOn #13), cadré par Architect, hors #13.
## ⚠️ RESTE : re-passage validation live (utilisateur, HORS SANDBOX)
Commande corrigée :
1. `cd frontend && VITE_TRANSPORT=http npx vite build` (npm, jamais pnpm — voir mémoire `frontend-uses-npm-not-pnpm`).
2. Fermer l'app desktop, puis `cargo run --release -p app-tauri -- --serve --web-root frontend/dist --app-data-dir ~/.local/share/app.idea.ide` (pairing code + app data dir sur stderr).
3. Navigateur `http://127.0.0.1:17373` → écran pairing → code.
4. Vérifier : liste projets (existants visibles), ouvrir projet, terminal CLI (frappe→serveur, reload→réattache/scrollback), cellule agent, surfaces live (workstate/background Cancel-Retry/inbox), reconnexion, logout→pairing.
## Réserves / écarts V1 (acceptés)
- Replay V1 = repaint scrollback complet. Multi-onglets « dernier gagne » silencieux. F4 write-portal NON câblé web. Browse créer-projet web → #64. Lock double-writer app-data-dir → ticket court à créer.
## Branches
`feature/ticket13-pty-websocket` (courante). À merger dans develop après validation live OK.
## Prochaine étape
Re-passage validation live (commande corrigée ci-dessus). Si OK → Git merge dans develop → clôture #13. #64 (Browse web) à planifier après. Aucune action sortante sans validation utilisateur.
## Dette hors chantier
Warnings clippy pré-existants crates/domain (fileguard/profile/sprint).

View File

@ -0,0 +1,16 @@
---
id: "036783fa-9856-4643-8c28-653b93ac36e1"
number: 13
title: "Server/client mode"
status: "closed"
priority: "low"
sprint: "028179b1-eaf4-41e9-9c1f-7c37125117e6"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783184188272
updatedAt: 1784193634690
version: 19
---
J'aimerais pouvoir utiliser IdeA sous forme de client/server. C'est a dire que IdeA aurait son backend sur une machine et son interface qui serait un frontend web. Les agents etc seraient tous côté server. C'est a dire que la cli de Claude serait celle côté serveur, l'interface client ne serait que l'affichage frontend, une UI. Je pense que tout est faisable, il faudrait cependant parler du côté CLI. Est ce qu'il serait possible de garde rle CLI natif comme il est actuellement, de l'afficher côté client tout en gardant l'installation claude code, codex etc côté serveur ? Peut etre qu'en ssh ça passerait ? Ce ticket ne pourra pas être fait en autonomie par un agent sans une review agent-utilisateur avant.

View File

@ -0,0 +1,31 @@
---
issueRef: "#130"
version: 6
updatedBy: {"kind":"user"}
updatedAt: 1785881187639
---
## Problème
Un plugin de développement doit souvent lire ou modifier des documents structurés. Sans primitive publique, chaque plugin doit réimplémenter parsing, validation et patching, avec un risque élevé de corruption ou dincohérence.
## Pourquoi cest global
Le besoin concerne JSON, YAML, TOML, XML, propriétés, DSL de config, et potentiellement dautres formats. Android nest quun consommateur parmi dautres.
## Ce que ce ticket doit produire
Une API publique de documents/config structurés permettant idéalement :
- lecture dun document typé ou semi-structuré
- édition contrôlée/patch ciblé
- sérialisation stable
- erreurs structurées
- capacité dévolution format par format
## Dépendances
- Dépend de `#124` car il faut dabord un accès fichier/workspace public.
## Garde-fous
- Commencer petit si nécessaire; ne pas promettre tous les formats dun coup.
- Préférer une abstraction extensible plutôt quun parser universel monolithique.
- Ne pas embarquer des helpers Android-only.
## Critères dacceptation
- Le SDK expose une primitive réutilisable pour lire et mettre à jour un document de config sans bricolage spécifique par plugin.
- Le contrat précise clairement quels formats sont supportés dans le premier lot.

View File

@ -0,0 +1,17 @@
---
id: "07a76880-f176-4fc8-b1d3-732a88a8c837"
number: 130
title: "SDK plugins: exposer une API publique de documents de configuration structurés"
status: "closed"
priority: "medium"
sprint: null
links: [{"target":"#123","kind":"blocks"},{"target":"#124","kind":"dependsOn"}]
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1785662026750
updatedAt: 1785881187639
version: 6
---
Ajouter au SDK plugin une API publique pour lire/mettre à jour des documents de configuration structurés via un modèle générique plutôt que forcer chaque plugin à réimplémenter son parsing/patching.

View File

@ -0,0 +1,6 @@
---
issueRef: "#131"
version: 2
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedAt: 1785748044208
---

View File

@ -0,0 +1,39 @@
---
id: "4092a7bf-5abb-4056-9e6d-226c392b2279"
number: 131
title: "Configurer l'effort par agent avec presets adaptatifs selon le profil AI"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
createdAt: 1785687359220
updatedAt: 1785748044208
version: 2
---
Objectif: permettre de choisir l'effort de chaque agent, idéalement via une droplist qui s'adapte au profil AI sélectionné (ex: Codex, Claude Code, OpenCode), tout en conservant un fallback sûr.
Cadrage validé en pré-analyse:
- Faisabilité: oui.
- Recommandation produit/contrat: approche hybride contrôlée.
- UI recommandée: droplist dépendante du profil AI + option "Personnalisé" ouvrant un champ texte/valeur libre si nécessaire.
Attendus de conception:
- Le profil AI déclare ses options natives d'effort/presets quand elles existent.
- La UI affiche ces options dans une droplist ordonnée du plus léger au plus profond.
- Si le provider n'expose pas d'options propres, fallback vers des presets génériques (ex: Rapide / Standard / Approfondi) clairement marqués comme options par défaut.
- Une option "Personnalisé" reste disponible pour couvrir les providers ou cas non modélisables proprement.
Attendus de contrat:
- Ajouter sur le profil AI un mécanisme déclaratif d'options d'effort (ex: effort_options avec label + valeur interne + éventuels hints).
- Le DTO d'agent doit persister soit un preset choisi, soit une valeur brute personnalisée.
- Prévoir la rétrocompatibilité avec les profils/configs existants, notamment les champs Codex déjà proches de cette notion.
Risques à traiter:
- Mapping imparfait entre presets UI et paramètres natifs des providers.
- Cohérence des libellés entre providers.
- Découverte UX de l'option "Personnalisé".
- Rétrocompatibilité/persistance sur les profils existants.

View File

@ -0,0 +1,6 @@
---
issueRef: "#132"
version: 2
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedAt: 1785748044221
---

View File

@ -0,0 +1,41 @@
---
id: "37c98a91-ee51-42b3-b804-8c0732784e11"
number: 132
title: "Ajouter un outil MCP IdeA pour éditer le contexte projet global"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: []
attachments: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
createdAt: 1785687502830
updatedAt: 1785748044221
version: 2
---
Objectif: permettre à un agent autorisé d'éditer le contexte projet global via un outil MCP IdeA dédié, au lieu de passer uniquement par une proposition enregistrée.
Constat actuel:
- Le contexte projet global est lisible via `idea_context_read`.
- Son évolution passe aujourd'hui par `idea_context_propose` sans `target`, ce qui enregistre une proposition pour validation mais n'applique pas directement la modification.
- Pour certains workflows d'orchestration, il manque une capacité native explicite d'édition contrôlée du contexte projet global.
Attendu produit/technique:
- Introduire un outil MCP IdeA dédié pour mettre à jour le contexte projet global.
- Définir clairement qui peut l'utiliser (ex: Main uniquement, ou liste d'agents autorisés).
- Préserver les garde-fous de concurrence et de traçabilité déjà attendus sur les contextes.
- Clarifier la relation entre ce nouvel outil et `idea_context_propose` (complément, remplacement partiel, ou voie restreinte selon les droits).
Points à cadrer:
- Modèle d'autorisation: quels agents peuvent écrire le contexte global.
- Concurrence/versioning: écrasement simple vs contrôle optimiste.
- Auditabilité: auteur, date, historique/provenance des changements.
- UX/runtime: comportement si un agent non autorisé tente l'opération.
- Compatibilité avec la règle actuelle de single-writer réservée à l'orchestrateur.
Critères de sortie:
- Contrat MCP défini.
- Règles d'autorisation explicites.
- Comportement d'erreur et de concurrence défini.
- Décision documentée sur la coexistence avec `idea_context_propose`.

View File

@ -0,0 +1,24 @@
---
issueRef: "#133"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785881187645
---
## Décision d'architecture (2026-08-02)
Documentée dans `ARCHITECTURE.md` §22.1 (nouvelle section "Plugins — service des assets multi-fichiers & persistance plugin-owned").
**Contrat tranché :** `asset_allowed` (`crates/app-tauri/src/plugins.rs:504-536`) doit servir tout chemin relatif confiné dès lors que les trois gardes déjà présentes sont satisfaites — entrée registre trouvée + `lifecycle_state.is_runtime_active()` + `entry.content_hash == hash` de l'URL (intégrité du package entier) — sans plus restreindre au triplet `declared_main || declared_icon || starts_with("assets/")`. Le confinement canonicalize aval (lignes 467-483, `target.starts_with(&root)`) reste inchangé et continue de protéger contre l'évasion de racine. `validator.validate(manifest)` reste appelé comme garde d'intégrité globale du manifeste, mais cesse de gater le service fichier par fichier.
**Rationale sécurité :** aucune perte de garantie — le modèle de menace est fixé par `content_hash` à l'installation (audité en #135), donc restreindre les fichiers *siblings* d'un package déjà intégralement vérifié n'arrête aucune attaque supplémentaire, ça casse juste des graphes de modules ESM légitimes.
**Limite figée :** pas de résolution `node_modules`/bare specifiers — hors scope, aucun résolveur de module à construire. Un plugin avec dépendances tierces les bundle ou vendore en relatif, à son choix.
**Contrat de confinement/désinstallation formalisé :** racine servie = exclusivement `app_data/plugins/installed/<pluginId>/` ; jamais d'écriture/exposition hors project root ou `.ideai/` de l'utilisateur ; désinstallation = suppression complète + entrée registre, zéro résidu (périmètre détaillé pour #135).
## Débloque
- **#134** : remplacer la dernière ligne de `asset_allowed``Ok(declared_main || declared_icon || rel.as_str().starts_with("assets/"))` — par une autorisation basée uniquement sur les gardes déjà calculées plus haut dans la fonction. Tests de non-régression path-traversal et hash/lifecycle invalides déjà spécifiés dans #134, contrat inchangé.
- **#135** : périmètre d'audit = confinement à l'install (`RelativePath::new` déjà rejette `..`/absolu côté domaine — vérifier qu'il est bien appliqué à l'INSTALL, pas seulement au SERVE) + désinstallation 100%.
Aucun changement de code applicatif dans ce ticket (portée strictement architecture, conforme à l'objectif du ticket). Fichier touché : `ARCHITECTURE.md` (§22.1 ajouté).

View File

@ -0,0 +1,31 @@
---
id: "f5296d8b-6bef-45c4-ac8a-cf6e0f90ae9c"
number: 133
title: "Plugins: contrat de service des assets idea-plugin:// (multi-fichiers ESM) & confinement"
status: "closed"
priority: "high"
sprint: null
links: []
agentRefs: [{"agentId":"b4730d7f-c54d-4736-8a04-c6203aa2fd49","role":"assigned"}]
attachments: []
createdBy: {"kind":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"}
updatedBy: {"kind":"user"}
createdAt: 1785702640094
updatedAt: 1785881187645
version: 5
---
Bug diagnostiqué : `crates/app-tauri/src/plugins.rs:504-536` (`asset_allowed`) n'autorise que `main`/`icon` déclarés au manifeste, ou un chemin préfixé `assets/`. Tout import ESM relatif secondaire (`./constants.js`, `./core/x.js`) depuis le `main` est donc rejeté 403 → "Importing a module script failed." côté navigateur. Le SDK (sdk/IdeaSDK/README.md) documente `main: dist/index.js` comme point d'entrée sans jamais imposer un bundle mono-fichier, ce qui sous-entend un support multi-fichiers jamais réellement vérifié (l'exemple hello-plugin est mono-fichier).
Objectif de ce ticket : trancher le contrat d'architecture, PAS l'implémenter.
À décider et documenter :
1. Élargir la politique de service à : tout chemin relatif confiné du package installé, dès lors que `entry.content_hash == hash` (intégrité du package entier déjà vérifiée) ET `entry.lifecycle_state.is_runtime_active()` ET confinement canonicalize (`target.starts_with(root)`, déjà en place lignes 467-483). Ces trois garanties suffisent déjà sans dépendre d'une déclaration par-fichier dans le manifeste.
2. Figer la limite explicite : imports ESM relatifs uniquement, pas de résolution `node_modules`/bare specifiers (hors scope, pas de résolveur de modules à construire) — un plugin qui a des dépendances tierces doit les vendorer en relatif ou les bundler lui-même, à son choix, jamais une obligation d'IdeA.
3. Formaliser le contrat de confinement + désinstallation propre : aucune écriture ne doit jamais sortir de `app_data/plugins/installed/<id>` (pas de pollution project root ni `.ideai/`), et la désinstallation doit être 100% (dossier + entrée registry, zéro résidu), à la manière VSCode.
Livrable : note d'architecture (+ mise à jour de la doc plugin existante si présente) qui fait foi pour les tickets d'implémentation liés (DevBackend, SDK/doc, QA).
Critères d'acceptation :
- Le contrat écrit référence explicitement le code actuel (plugins.rs:504-536) et explique pourquoi hash+lifecycle+confinement remplacent l'allowlist par fichier sans régression de sécurité.
- La limite bare-specifiers/node_modules est tranchée noir sur blanc (in ou out, et pourquoi).
- Le contrat de confinement/désinstallation est écrit explicitement (racine autorisée, ce qui est interdit, ce que "propre" veut dire).

View File

@ -0,0 +1,6 @@
---
issueRef: "#134"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1785881187652
---

View File

@ -0,0 +1,33 @@
---
id: "e98c3f80-9fd6-444a-be80-ad695809c71c"
number: 134
title: "Plugins: servir tout fichier confiné du package installé (fix racine multi-fichiers ESM)"
status: "closed"
priority: "critical"
sprint: null
links: [{"target":"#133","kind":"dependsOn"}]
agentRefs: [{"agentId":"fe887179-933f-47d4-960f-c3b06827f86c","role":"assigned"}]
attachments: []
createdBy: {"kind":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"}
updatedBy: {"kind":"user"}
createdAt: 1785702651199
updatedAt: 1785881187652
version: 4
---
Implémente le contrat décidé en #133.
Modifier `asset_allowed` / `plugin_asset_response_with_stores` dans `crates/app-tauri/src/plugins.rs:504-536` : remplacer la condition `declared_main || declared_icon || rel.as_str().starts_with("assets/")` par une autorisation basée sur les garanties déjà vérifiées avant cette ligne (hash de contenu du package `entry.content_hash.as_str() == hash`, `entry.lifecycle_state.is_runtime_active()`) et sur le confinement canonicalize déjà en place lignes 467-483 (`target.starts_with(&root)`).
Ne pas retirer `validator.validate(&manifest_bytes.bytes, &package)` : cette vérification reste une garde d'intégrité globale du manifeste, mais ne doit plus servir à restreindre le service fichier par fichier.
Respecter strictement la limite figée en #133 (imports relatifs uniquement, pas de résolveur node_modules/bare specifiers — hors scope).
Tests à ajouter dans `crates/app-tauri/src/plugins.rs` (module de tests existant en bas de fichier) :
- requête d'un fichier non déclaré dans le manifeste (ex: `dist/core/helper.js`) → 200 OK si hash+lifecycle valides.
- path traversal (`../`) → toujours 403 (non-régression, déjà couvert mais à revérifier après le changement).
- hash de contenu différent ou plugin non `runtime_active` → toujours 403 (non-régression).
Critères d'acceptation :
- `cargo test -p app-tauri` vert, nouveaux cas inclus.
- Un plugin composé de `dist/index.js` + `dist/constants.js` (import relatif) se charge sans 403 via le protocole `idea-plugin://`.
- Aucune régression sur les tests de confinement/path-traversal existants.

View File

@ -0,0 +1,26 @@
---
issueRef: "#135"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785881187659
---
## Audit QA
- `install_from_directory` : audit confirme qu'avant correctif le store ne rejetait pas explicitement les symlinks source ; il les ignorait. Le correctif fait maintenant échouer l'installation sur toute entrée symlink ou unsupported dans l'arbre source.
- `install_from_archive` : audit confirme un trou réel de confinement avant correctif. L'extraction reposait entièrement sur `unzip` sans validation applicative des entrées. Le correctif remplace cette extraction par une lecture Rust confinée qui rejette les entrées `../`/absolues via `enclosed_name()` et refuse explicitement les symlinks d'archive.
- Confinement d'écriture : après correctif, aucune écriture d'install ne sort de `app_data/plugins/_staging/...` puis `app_data/plugins/installed/<id>` ; le test `../../../../outside.txt` prouve l'absence d'écriture hors racine.
- `hash_dir` / collecte fichiers : durci pour échouer si un package contient encore un symlink ou une entrée non supportée, au lieu de l'ignorer.
- `plugin_uninstall` / `remove_package` : audit confirmé par test multifichier. La désinstallation supprime le dossier entier, retire l'entrée registry et laisse le runtime catalog vide.
## Tests ajoutés/ajustés
- `plugin::tests::install_from_directory_rejects_source_symlink`
- `plugin::tests::install_from_archive_rejects_parent_traversal_without_writing_outside_stage`
- `plugin::tests::install_from_archive_rejects_symlink_entries`
- `plugin_install_load::uninstall_multifile_plugin_removes_package_registry_and_runtime_residue`
- Stabilisation des tests SDK `hello-plugin` : fixture matérialisée avec `dist/index.js` dans un temp dir pour supprimer une dépendance implicite à un build préalable.
## Verdict
- Correctif confinement install/uninstall validé.
- `cargo test -p infrastructure -p application -p app-tauri` vert avec `CARGO_HOME=/tmp/idea-cargo-home` dans cet environnement.

View File

@ -0,0 +1,31 @@
---
id: "13442dae-7860-45e3-9287-31b9bde19170"
number: 135
title: "Plugins: audit confinement install & désinstallation 100% propre"
status: "closed"
priority: "high"
sprint: null
links: [{"target":"#133","kind":"dependsOn"}]
agentRefs: [{"agentId":"ab328d90-c307-4771-a3b6-6c56089c8506","role":"assigned"}]
attachments: []
createdBy: {"kind":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"}
updatedBy: {"kind":"user"}
createdAt: 1785702662938
updatedAt: 1785881187659
version: 5
---
Applique le contrat de confinement/désinstallation décidé en #133.
Auditer `plugin_install_from_archive` / `plugin_install_from_directory` (`crates/app-tauri/src/plugins.rs:67-142`) et le store d'infrastructure (`crates/infrastructure/src/plugin/mod.rs`) pour confirmer qu'aucune écriture ne peut jamais sortir de `app_data/plugins/installed/<id>` :
- Un plugin dont le manifeste ou l'archive contient un chemin `../` ou un symlink pointant hors de sa racine doit échouer à l'install (vérifier que `RelativePath::new` — qui rejette déjà `..` et les chemins absolus, cf. `crates/domain/src/plugin.rs` — est bien appliqué à l'INSTALL, pas seulement au SERVE ajouté en #134).
- Aucune écriture ne doit jamais toucher le project root ni `.ideai/` du projet ouvert : le plugin est un citoyen de `app_data`, jamais du repo utilisateur.
Vérifier que `plugin_uninstall` (`crates/app-tauri/src/plugins.rs:142`) supprime bien 100% : dossier entier + entrée registry, zéro résidu. Étendre si besoin les tests existants (`uninstall_removes_registry_package_and_stops_mcp`, `uninstall_then_reinstall_leaves_runtime_catalog_active_without_residue` dans `crates/application/src/plugin/mod.rs`) pour couvrir explicitement le cas d'un plugin multi-fichiers (plusieurs fichiers sous `dist/`).
Si un chemin d'attaque (symlink sortant, `../` dans une archive zip malveillante) n'est pas déjà bloqué à l'install, ouvrir un correctif dans ce même ticket (pas de nouveau ticket) : c'est un renforcement du même contrat, pas une nouvelle feature.
Critères d'acceptation :
- Rapport d'audit écrit (dans le carnet du ticket) listant les points vérifiés et leur statut.
- Test explicite : tentative d'installer un plugin avec chemin `../` ou symlink sortant → échec propre, aucun fichier écrit hors racine.
- Test explicite : désinstallation d'un plugin multi-fichiers → dossier disparu, entrée registry disparue, aucun résidu.
- `cargo test -p app-tauri -p infrastructure -p application` vert.

View File

@ -0,0 +1,6 @@
---
issueRef: "#136"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1785881187667
---

View File

@ -0,0 +1,27 @@
---
id: "214e7c14-fab8-45ed-bb71-5f309a8479a6"
number: 136
title: "SDK plugins: aligner doc/exemple sur le support multi-fichiers ESM"
status: "closed"
priority: "high"
sprint: null
links: [{"target":"#134","kind":"dependsOn"}]
agentRefs: [{"agentId":"8f7da528-58df-4315-97e9-0562230ecc19","role":"assigned"}]
attachments: []
createdBy: {"kind":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"}
updatedBy: {"kind":"user"}
createdAt: 1785702672090
updatedAt: 1785881187667
version: 4
---
Une fois #134 livré, aligner le SDK et sa documentation pour que le support multi-fichiers soit explicite et testé, pas seulement sous-entendu.
Étendre `sdk/IdeaSDK/examples/hello-plugin` (ou ajouter un nouvel exemple dédié, ex: `hello-plugin-multi`) avec un vrai split en plusieurs fichiers ESM compilés séparément — `src/index.ts` qui importe `./constants.ts` et `./core/...` — sans bundler forcé (juste `tsc`, comme l'exemple actuel). Ce sera la preuve vivante et le test de non-régression du contrat de #133/#134.
Mettre à jour `sdk/IdeaSDK/README.md` (autour de la ligne 50 où `main` est décrit comme "compiled ESM entrypoint") :
- Clarifier explicitement que `main` est le point d'entrée, mais que des imports relatifs vers d'autres fichiers du même package sont servis nativement par le protocole `idea-plugin://` (plus besoin de tout bundler en un seul fichier).
- Documenter la limite figée en #133 : imports relatifs uniquement ; les dépendances tierces (npm) doivent être bundlées ou vendorées en relatif par le plugin, IdeA ne résout pas `node_modules`.
Critères d'acceptation :
- L'exemple multi-fichiers build (`npm run build` ou équivalent existant) et se charge dans IdeA sans erreur `Importing a module script failed.` (vérification manuelle ou via #136).
- Le README ne laisse plus entendre un support non vérifié ; la limite bare-specifiers est écrite noir sur blanc.

View File

@ -0,0 +1,6 @@
---
issueRef: "#137"
version: 2
updatedBy: {"kind":"user"}
updatedAt: 1785881139749
---

View File

@ -0,0 +1,27 @@
---
id: "2ef9b71a-9869-4476-88b6-65aaefc993e1"
number: 137
title: "QA: validation end-to-end plugin multi-fichiers ESM (chargement + désinstallation propre)"
status: "closed"
priority: "critical"
sprint: null
links: [{"target":"#134","kind":"dependsOn"},{"target":"#136","kind":"dependsOn"}]
agentRefs: [{"agentId":"ab328d90-c307-4771-a3b6-6c56089c8506","role":"assigned"}]
attachments: []
createdBy: {"kind":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"}
updatedBy: {"kind":"user"}
createdAt: 1785702681696
updatedAt: 1785881139749
version: 2
---
Validation réelle, sortie observée — pas seulement des tests unitaires — du fix multi-fichiers (#134) et de l'exemple SDK (#136).
À exécuter dans une build réelle (AppImage ou dev Tauri) :
1. Installer le plugin multi-fichiers issu de #136 (fichiers ESM non bundlés, imports relatifs). Confirmer l'absence de l'erreur navigateur "Importing a module script failed." et l'activation correcte (`activate(ctx)` appelé, contributions menus/layouts visibles et fonctionnelles selon ce que déclare l'exemple).
2. Vérifier l'isolement : le plugin ne dépose rien dans le project root ni dans `.ideai/` du projet ouvert (contrat de #133/#135).
3. Désinstaller depuis l'UI (Panneau Plugins) : vérifier disque (aucun résidu sous `app_data/plugins/installed/<id>`), registre (entrée disparue), et absence de toute trace côté projet.
4. Réinstaller le même plugin après désinstallation : doit repartir propre, sans conflit résiduel.
Critères d'acceptation :
- Rapport QA avec preuve d'exécution réelle (logs/captures), verdict vert ou liste d'écarts bloquants.
- Si régression détectée sur #134/#135/#136, retour précis (repro + fichier/ligne suspecté) au dev concerné avant clôture.

View File

@ -0,0 +1,30 @@
---
issueRef: "#138"
version: 5
updatedBy: {"kind":"user"}
updatedAt: 1785881187672
---
## Décision d'architecture (2026-08-02)
Documentée dans `ARCHITECTURE.md` §22.2 (même nouvelle section que #133).
**Constat vérifié dans le code :** `sdk/IdeaSDK/src/runtime.ts` déclare déjà `ActivateContext.storage?: PluginStorage` (`get/set/delete`, clé-valeur JSON-serializable), et l'exemple `hello-plugin` s'en sert (`ctx.storage?.get<string>("helloPlugin.ownerAgentId")`). Mais ce champ n'est **jamais peuplé** : `frontend/src/plugins/runtime/loader.ts` (~lignes 249-256) ne câble que `logger`, `subscriptions`, `services``ctx.storage` vaut toujours `undefined` en exécution. Côté Rust : zéro port, zéro commande, zéro répertoire pour cette primitive (recherché, rien trouvé). Faute d'API réelle, l'exemple détourne `ctx.services.workspace`/`ctx.services.config` pour écrire son état interne sous `.ideai/hello-plugin.txt` et `.ideai/hello-plugin.json`.
**Décision — séparation noir sur blanc :**
- **Project-owned** : fichiers du workspace que le plugin modifie *volontairement* pour l'utilisateur/le projet → reste `ctx.services.workspace.*`/`ctx.services.config.*`, sandbox projet existant inchangé.
- **Plugin-owned** : préférences/cache/sélection/index/config interne → ne vit **jamais** dans le project root ni sous `.ideai/`. Nouveau répertoire **frère** de `plugins/installed/<id>/` : `app_data/plugins/data/<pluginId>/`. Séparé de `installed/` pour que les mises à jour de package ne touchent jamais aux données utilisateur, et pour donner à la désinstallation une deuxième racine univoque à purger.
**API canonique tranchée : `ctx.storage` seul, pas de second API document.** `ctx.storage.set(key, value)` avec des valeurs JSON couvre déjà le besoin de document structuré — une deuxième API "document plugin-scopé" ferait doublon. `ctx.services.config` reste réservé au project-owned.
**Cycle de vie figé :**
- `ctx.storage.get/set/delete` → commandes Tauri (ex. `plugin_storage_get/set/delete`) → store scopé par `pluginId` sous `plugins/data/<pluginId>/` (format interne — JSON unique ou par clé — laissé à #139, seule la frontière de répertoire est un contrat figé).
- `plugin_uninstall` (`crates/app-tauri/src/plugins.rs:142`) doit purger `plugins/data/<id>/` en plus de `plugins/installed/<id>` + registre (déjà couvert par #135). Les fichiers project-owned écrits par le plugin dans le workspace ne sont **jamais** touchés par l'uninstall.
## Débloque #139
1. Implémenter `ctx.storage` de bout en bout : port domaine + adapter infra scopés à `plugins/data/<pluginId>/`, commandes Tauri, câblage réel dans `loader.ts` (absent aujourd'hui), confinement en esprit identique à #133/#135.
2. Réaligner `hello-plugin` : migrer les compteurs internes (`launches`, `enabled`, `ownerAgentId`) vers `ctx.storage`. Garder au plus un exemple clairement étiqueté "fichier projet réel" via `workspace`/`config`, pas comme pattern par défaut.
3. `sdk/IdeaSDK/README.md` section "Structured Config Documents" à corriger : ne plus donner `.ideai/hello-plugin.json` comme exemple d'état interne, remplacer par un exemple `ctx.storage`, documenter la séparation project-owned/plugin-owned.
4. Preuve requise : test de purge (installer → écrire via `ctx.storage` → désinstaller → `plugins/data/<id>/` disparu) + absence de tout chemin `.ideai/...` dans les exemples SDK par défaut.
Aucun changement de code applicatif dans ce ticket (portée strictement architecture/API, conforme à l'objectif du ticket). Fichier touché : `ARCHITECTURE.md` (§22.2 ajouté).

View File

@ -0,0 +1,33 @@
---
id: "e33fd0ea-e7c6-40dc-a244-f158e44ac4a7"
number: 138
title: "SDK plugins: contrat de persistance plugin-owned hors projet et effacement total à la désinstallation"
status: "closed"
priority: "critical"
sprint: null
links: []
agentRefs: [{"agentId":"b4730d7f-c54d-4736-8a04-c6203aa2fd49","role":"assigned"}]
attachments: []
createdBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedBy: {"kind":"user"}
createdAt: 1785702748769
updatedAt: 1785881187672
version: 5
---
Le lot #133/#135 traite déjà le confinement du package installé et labsence décritures parasites au runtime, mais il reste un trou produit/API majeur : le SDK public et son exemple `sdk/IdeaSDK/examples/hello-plugin` montrent encore des écritures plugin sous `.ideai/hello-plugin.txt` et `.ideai/hello-plugin.json`, alors que lobjectif utilisateur est un modèle type VSCode où létat propre au plugin ne pollue jamais le projet et disparaît entièrement à la désinstallation.
Objectif de ce ticket : trancher le contrat darchitecture/API, PAS limplémenter.
À décider et documenter :
1. Séparer noir sur blanc les deux familles de données plugin :
- données métier du PROJET que le plugin modifie volontairement dans le workspace utilisateur (autorisées, explicites, relèvent de `workspace.*` / éventuellement `config` quand on touche un vrai fichier du projet) ;
- données PROPRES AU PLUGIN (prefs, cache, dernière sélection, index interne, état UI durable, config interne) qui doivent vivre hors project root, dans un store plugin-scopé sous app data, jamais sous `.ideai/` ni ailleurs dans le repo utilisateur.
2. Dire si `ctx.storage` clé/valeur suffit comme primitive canonique pour cet état plugin-owned, ou sil faut une API publique supplémentaire de document structuré plugin-scopé (ex: JSON app-data du plugin) pour éviter de pousser les auteurs à détourner `ctx.services.config` vers `.ideai/*.json`.
3. Figer le contrat de désinstallation : la suppression du plugin doit aussi supprimer 100% de son état plugin-owned hors projet (storage, éventuels docs/config plugin-scopés, caches internes), sans toucher aux fichiers métier du projet que lutilisateur a explicitement demandé au plugin de modifier.
4. Imposer lalignement doc/exemples SDK : ne plus montrer `.ideai/...` comme emplacement par défaut pour létat interne dun plugin.
Critères dacceptation :
- Une note darchitecture/API explicite distingue « project-owned » vs « plugin-owned ».
- La source de vérité et le cycle de vie du stockage plugin-owned sont écrits noir sur blanc (création, lecture, suppression à luninstall).
- Le ticket précise si une nouvelle API SDK est nécessaire ou si `ctx.storage` devient la voie canonique, et pourquoi.
- Le contrat est compatible avec lexigence utilisateur : plugin désinstallé => plus aucun état propre au plugin, ni dans le projet, ni dans lapp data plugin.

View File

@ -0,0 +1,6 @@
---
issueRef: "#139"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1785881187678
---

View File

@ -0,0 +1,17 @@
---
id: "a5bac900-806d-4e13-866f-7ebae686a43d"
number: 139
title: "SDK plugins: aligner lAPI publique et les exemples sur une persistance plugin-owned hors projet"
status: "closed"
priority: "critical"
sprint: null
links: [{"target":"#138","kind":"dependsOn"}]
agentRefs: [{"agentId":"fe887179-933f-47d4-960f-c3b06827f86c","role":"assigned"},{"agentId":"8f7da528-58df-4315-97e9-0562230ecc19","role":"assigned"}]
attachments: []
createdBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedBy: {"kind":"user"}
createdAt: 1785702774592
updatedAt: 1785881187678
version: 4
---
Implémenter le contrat décidé en #138. Ce ticket ne doit démarrer quaprès arbitrage architecture, car la forme exacte de lAPI publique peut varier (`ctx.storage` canonique seul, ou nouvelle API publique de document structuré plugin-scopé hors projet).\n\nPérimètre attendu après #138 :\n1. Faire de la voie canonique plugin-owned celle décidée en #138, et retirer lincitation actuelle à écrire létat interne du plugin dans le workspace utilisateur / `.ideai/`.\n2. Mettre à jour `sdk/IdeaSDK/README.md` et `sdk/IdeaSDK/examples/hello-plugin` pour que lexemple de référence nécrive plus `.ideai/hello-plugin.txt` ni `.ideai/hello-plugin.json` comme état interne par défaut.\n3. Si #138 décide quune nouvelle API SDK publique est nécessaire (par ex. document structuré plugin-scopé hors projet), lexposer de bout en bout : types SDK, façade runtime publique, adaptateurs hôte nécessaires, et documentation dusage.\n4. Garantir que la désinstallation du plugin purge aussi létat plugin-owned correspondant, conformément au contrat #138, sans supprimer les fichiers métier du projet que le plugin aurait modifiés explicitement.\n\nCritères dacceptation :\n- Le README SDK sépare explicitement données project-owned vs plugin-owned.\n- Lexemple de référence nemploie plus `.ideai/...` pour stocker son état interne.\n- Si une nouvelle API publique a été décidée en #138, elle est documentée, typée et couverte par des tests.\n- La purge de létat plugin-owned à la désinstallation est prouvée par tests ciblés sur le chemin réellement choisi par #138.\n- Aucun message public du SDK ne laisse entendre que `.ideai/` est le lieu normal de persistance interne dun plugin.

View File

@ -0,0 +1,20 @@
---
issueRef: "#14"
version: 8
updatedBy: {"kind":"user"}
updatedAt: 1784449099987
---
## Production #14 — livrée dans develop (validation e2e live restante)
Périmètre figé avec l'utilisateur : adapter HTTP OpenAI-compatible **purement additif** (zéro régression Claude/Codex), parité **tool-calling + MCP** complète, canal HTTP natif robuste.
### Cycle
- Cadrage Architect : slug mémoire `ticket14-local-lan-openai-adapter-scoping` (asymétrie CLI-vs-serveur HTTP, port ToolInvoker in-process, reprise sans id provider).
- Backend (DevBackend) : variante `StructuredAdapter::OpenAiCompatible`, VO `HttpChatConfig`, `openai_compat.rs`, port `ToolInvoker` déléguant à la même OrchestratorService que le MCP. GO QA (domain 467 / application 530 / infrastructure 523 / app-tauri 247, 0 échec). Défaut réel corrigé : timeout post-contact mappé Io.
- Frontend (DevFrontend) : types DTO miroir, wizard/settings (endpoint/model/apiKeyEnv=nom de var/timeouts, validation miroir backend), profil de référence Ollama éditable, erreur endpoint rendue via bannière role="alert". GO QA (tsc 0 + vitest 59 fichiers / 566 tests, 0 échec). Défaut réel corrigé : erreur endpoint invisible dans le DOM.
### Git
- Backend `aab4bca`, frontend `d89380c`, merge `--no-ff` `3c6cd04` → develop. Branche feature supprimée. **Local uniquement, rien poussé.**
### Reste à faire (hors code)
- Validation e2e **live contre un vrai endpoint Ollama/LAN** : lancement cellule, conversation headless, reprise, délégation inter-agents, vivacité/timeout, endpoint indisponible/modèle absent (critère d'acceptation n°7). Non exercée en tests automatisés — c'est la raison du statut QA plutôt que closed.

View File

@ -0,0 +1,75 @@
---
id: "0c1f1991-b6db-47b7-bbef-2478bc7874ab"
number: 14
title: "Integration de profils IA locaux/LAN comme profils IdeA canoniques"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783184495846
updatedAt: 1784449099987
version: 8
---
Objectif : permettre à IdeA d'utiliser des modèles hébergés localement ou sur le réseau local, par exemple Qwen via Ollama ou un runtime Docker exposant une API, avec le même niveau d'intégration produit que les profils Claude Code et OpenAI Codex CLI.
La finalité n'est pas un simple profil custom lancé dans un terminal brut. Ces profils doivent devenir de vrais profils IA IdeA : sélectionnables, lançables depuis les cellules, pilotés par la conversation headless canonique, compatibles avec les mécanismes de conversation/reprise, et utilisables par l'orchestration de la même manière que Claude/Codex.
## Cible produit
Ajouter une famille de profil structuré pour serveurs de modèles locaux ou LAN, idéalement basée sur une API HTTP compatible OpenAI/Ollama :
- endpoint configurable (`localhost`, machine LAN, container Docker, etc.) ;
- modèle configurable (`qwen...`, autre modèle local) ;
- authentification optionnelle via nom de variable d'environnement, jamais clé en clair ;
- profil visible et sélectionnable dans IdeA comme Claude/Codex ;
- cellule IdeA utilisable de façon canonique : conversation headless, historique, reprise, délégation, affichage des réponses et état de vivacité.
## Contraintes importantes
- Ne pas considérer le mode PTY/TUI comme suffisant pour ce ticket.
- Éviter une dépendance obligatoire à `ollama`, `docker` ou une commande shell quand une API HTTP suffit.
- Étudier explicitement les impacts commandes/headless :
- adapter HTTP natif ;
- wrapper CLI éventuel ;
- Docker/LAN ;
- sandbox et permissions ;
- absence ou présence de tool-calling/MCP côté modèle local.
- Le résultat doit s'intégrer dans le modèle existant `StructuredAdapter` / `AgentSessionFactory`, pas contourner le runtime IA d'IdeA.
## Travail attendu
1. Ajouter un adapter structuré pour modèle local/LAN, par exemple `StructuredAdapter::OpenAiCompatible` ou `LocalChat`.
2. Étendre le modèle de profil pour porter la configuration nécessaire : endpoint, model, apiKeyEnv optionnel, timeouts/liveness si nécessaire.
3. Implémenter une session headless `AgentSession` :
- `send(prompt)` ;
- émission de `ReplyEvent` ;
- gestion propre des erreurs réseau/modèle ;
- conversation id ou stratégie de reprise compatible avec le modèle IdeA.
4. Brancher l'adapter dans `StructuredSessionFactory`.
5. Rendre ces profils sélectionnables dans le wizard/settings au même titre que Claude/Codex.
6. Ajouter un profil de référence local, par exemple “Ollama / OpenAI-compatible local model”, éditable.
7. Vérifier l'intégration avec :
- lancement depuis une cellule ;
- conversation headless ;
- reprise ;
- changement de profil ;
- délégation inter-agents quand applicable ;
- état de vivacité/timeout ;
- erreurs endpoint indisponible/modèle absent.
## Critères d'acceptation
- Je peux configurer un profil Qwen hébergé via Ollama ou endpoint LAN.
- Je peux créer/lancer un agent IdeA avec ce profil comme avec Claude/Codex.
- La cellule utilise le chemin headless structuré, pas un terminal brut PTY.
- Les conversations apparaissent et se comportent comme les conversations Claude/Codex.
- La reprise ne mélange pas l'id logique IdeA avec un éventuel id provider.
- Un endpoint indisponible produit une erreur propre dans l'UI, sans bloquer IdeA.
- Les dépendances à `ollama`, Docker ou une CLI externe sont documentées et non imposées si le mode HTTP suffit.
- Tests backend couvrant factory, session adapter, erreurs HTTP et sérialisation du profil.
- Tests frontend couvrant configuration/sélection du nouveau profil.
Review agent-user requise avant démarrage d'implémentation pour figer le périmètre exact : HTTP natif uniquement, support d'un wrapper CLI, et niveau attendu de tool-calling/MCP pour les modèles locaux.

Some files were not shown because too many files have changed in this diff Show More