From 59d81851e993af80e85f732461a0699679ac67db Mon Sep 17 00:00:00 2001 From: Blomios Date: Mon, 3 Aug 2026 11:06:30 +0200 Subject: [PATCH] =?UTF-8?q?chore(tickets):=20synchronise=20index/carnets?= =?UTF-8?q?=20tickets=20#131-#139=20+=20note=20m=C3=A9moire=20assets/persi?= =?UTF-8?q?stance=20plugins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit É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 --- .ideai/memory/MEMORY.md | 1 + ...set-serving-and-owned-storage-contracts.md | 19 ++ .ideai/tickets/131/carnet.md | 6 + .ideai/tickets/131/issue.md | 39 ++++ .ideai/tickets/132/carnet.md | 6 + .ideai/tickets/132/issue.md | 41 ++++ .ideai/tickets/133/carnet.md | 24 +++ .ideai/tickets/133/issue.md | 31 +++ .ideai/tickets/134/carnet.md | 6 + .ideai/tickets/134/issue.md | 33 ++++ .ideai/tickets/135/carnet.md | 26 +++ .ideai/tickets/135/issue.md | 31 +++ .ideai/tickets/136/carnet.md | 6 + .ideai/tickets/136/issue.md | 27 +++ .ideai/tickets/137/carnet.md | 6 + .ideai/tickets/137/issue.md | 27 +++ .ideai/tickets/138/carnet.md | 30 +++ .ideai/tickets/138/issue.md | 33 ++++ .ideai/tickets/139/carnet.md | 6 + .ideai/tickets/139/issue.md | 17 ++ .ideai/tickets/51/carnet.md | 6 - .ideai/tickets/51/issue.md | 15 -- .ideai/tickets/63/carnet.md | 6 - .ideai/tickets/63/issue.md | 15 -- .ideai/tickets/66/carnet.md | 6 - .ideai/tickets/66/issue.md | 27 --- .ideai/tickets/counter.json | 2 +- .ideai/tickets/index.json | 181 ++++++++++++++---- 28 files changed, 557 insertions(+), 116 deletions(-) create mode 100644 .ideai/memory/plugin-asset-serving-and-owned-storage-contracts.md create mode 100644 .ideai/tickets/131/carnet.md create mode 100644 .ideai/tickets/131/issue.md create mode 100644 .ideai/tickets/132/carnet.md create mode 100644 .ideai/tickets/132/issue.md create mode 100644 .ideai/tickets/133/carnet.md create mode 100644 .ideai/tickets/133/issue.md create mode 100644 .ideai/tickets/134/carnet.md create mode 100644 .ideai/tickets/134/issue.md create mode 100644 .ideai/tickets/135/carnet.md create mode 100644 .ideai/tickets/135/issue.md create mode 100644 .ideai/tickets/136/carnet.md create mode 100644 .ideai/tickets/136/issue.md create mode 100644 .ideai/tickets/137/carnet.md create mode 100644 .ideai/tickets/137/issue.md create mode 100644 .ideai/tickets/138/carnet.md create mode 100644 .ideai/tickets/138/issue.md create mode 100644 .ideai/tickets/139/carnet.md create mode 100644 .ideai/tickets/139/issue.md delete mode 100644 .ideai/tickets/51/carnet.md delete mode 100644 .ideai/tickets/51/issue.md delete mode 100644 .ideai/tickets/63/carnet.md delete mode 100644 .ideai/tickets/63/issue.md delete mode 100644 .ideai/tickets/66/carnet.md delete mode 100644 .ideai/tickets/66/issue.md diff --git a/.ideai/memory/MEMORY.md b/.ideai/memory/MEMORY.md index 5a8ac04..e414774 100644 --- a/.ideai/memory/MEMORY.md +++ b/.ideai/memory/MEMORY.md @@ -77,3 +77,4 @@ - [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 diff --git a/.ideai/memory/plugin-asset-serving-and-owned-storage-contracts.md b/.ideai/memory/plugin-asset-serving-and-owned-storage-contracts.md new file mode 100644 index 0000000..51e7226 --- /dev/null +++ b/.ideai/memory/plugin-asset-serving-and-owned-storage-contracts.md @@ -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//`, frère de `plugins/installed//` (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é. \ No newline at end of file diff --git a/.ideai/tickets/131/carnet.md b/.ideai/tickets/131/carnet.md new file mode 100644 index 0000000..3a5d57b --- /dev/null +++ b/.ideai/tickets/131/carnet.md @@ -0,0 +1,6 @@ +--- +issueRef: "#131" +version: 1 +updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} +updatedAt: 1785687359220 +--- diff --git a/.ideai/tickets/131/issue.md b/.ideai/tickets/131/issue.md new file mode 100644 index 0000000..03efd75 --- /dev/null +++ b/.ideai/tickets/131/issue.md @@ -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: "open" +priority: "medium" +sprint: null +links: [] +agentRefs: [] +attachments: [] +createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} +updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} +createdAt: 1785687359220 +updatedAt: 1785687359220 +version: 1 +--- +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. \ No newline at end of file diff --git a/.ideai/tickets/132/carnet.md b/.ideai/tickets/132/carnet.md new file mode 100644 index 0000000..1c55ae6 --- /dev/null +++ b/.ideai/tickets/132/carnet.md @@ -0,0 +1,6 @@ +--- +issueRef: "#132" +version: 1 +updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} +updatedAt: 1785687502830 +--- diff --git a/.ideai/tickets/132/issue.md b/.ideai/tickets/132/issue.md new file mode 100644 index 0000000..d444cf9 --- /dev/null +++ b/.ideai/tickets/132/issue.md @@ -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: "open" +priority: "medium" +sprint: null +links: [] +agentRefs: [] +attachments: [] +createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} +updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} +createdAt: 1785687502830 +updatedAt: 1785687502830 +version: 1 +--- +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`. \ No newline at end of file diff --git a/.ideai/tickets/133/carnet.md b/.ideai/tickets/133/carnet.md new file mode 100644 index 0000000..1ddec84 --- /dev/null +++ b/.ideai/tickets/133/carnet.md @@ -0,0 +1,24 @@ +--- +issueRef: "#133" +version: 4 +updatedBy: {"kind":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"} +updatedAt: 1785703664966 +--- +## 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//` ; 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é). \ No newline at end of file diff --git a/.ideai/tickets/133/issue.md b/.ideai/tickets/133/issue.md new file mode 100644 index 0000000..c55ce4f --- /dev/null +++ b/.ideai/tickets/133/issue.md @@ -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: "qa" +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":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"} +createdAt: 1785702640094 +updatedAt: 1785703664966 +version: 4 +--- +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/` (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). \ No newline at end of file diff --git a/.ideai/tickets/134/carnet.md b/.ideai/tickets/134/carnet.md new file mode 100644 index 0000000..bf40c02 --- /dev/null +++ b/.ideai/tickets/134/carnet.md @@ -0,0 +1,6 @@ +--- +issueRef: "#134" +version: 3 +updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +updatedAt: 1785707290184 +--- diff --git a/.ideai/tickets/134/issue.md b/.ideai/tickets/134/issue.md new file mode 100644 index 0000000..af57132 --- /dev/null +++ b/.ideai/tickets/134/issue.md @@ -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: "qa" +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":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +createdAt: 1785702651199 +updatedAt: 1785707290184 +version: 3 +--- +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. \ No newline at end of file diff --git a/.ideai/tickets/135/carnet.md b/.ideai/tickets/135/carnet.md new file mode 100644 index 0000000..12eda3d --- /dev/null +++ b/.ideai/tickets/135/carnet.md @@ -0,0 +1,26 @@ +--- +issueRef: "#135" +version: 4 +updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +updatedAt: 1785708498776 +--- +## 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/` ; 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. \ No newline at end of file diff --git a/.ideai/tickets/135/issue.md b/.ideai/tickets/135/issue.md new file mode 100644 index 0000000..2591504 --- /dev/null +++ b/.ideai/tickets/135/issue.md @@ -0,0 +1,31 @@ +--- +id: "13442dae-7860-45e3-9287-31b9bde19170" +number: 135 +title: "Plugins: audit confinement install & désinstallation 100% propre" +status: "qa" +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":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +createdAt: 1785702662938 +updatedAt: 1785708498776 +version: 4 +--- +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/` : +- 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. \ No newline at end of file diff --git a/.ideai/tickets/136/carnet.md b/.ideai/tickets/136/carnet.md new file mode 100644 index 0000000..c7631bb --- /dev/null +++ b/.ideai/tickets/136/carnet.md @@ -0,0 +1,6 @@ +--- +issueRef: "#136" +version: 3 +updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +updatedAt: 1785708478849 +--- diff --git a/.ideai/tickets/136/issue.md b/.ideai/tickets/136/issue.md new file mode 100644 index 0000000..d5068a0 --- /dev/null +++ b/.ideai/tickets/136/issue.md @@ -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: "qa" +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":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +createdAt: 1785702672090 +updatedAt: 1785708478849 +version: 3 +--- +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. \ No newline at end of file diff --git a/.ideai/tickets/137/carnet.md b/.ideai/tickets/137/carnet.md new file mode 100644 index 0000000..94413ef --- /dev/null +++ b/.ideai/tickets/137/carnet.md @@ -0,0 +1,6 @@ +--- +issueRef: "#137" +version: 1 +updatedBy: {"kind":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"} +updatedAt: 1785702681696 +--- diff --git a/.ideai/tickets/137/issue.md b/.ideai/tickets/137/issue.md new file mode 100644 index 0000000..d0cdfef --- /dev/null +++ b/.ideai/tickets/137/issue.md @@ -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: "open" +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":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"} +createdAt: 1785702681696 +updatedAt: 1785702681696 +version: 1 +--- +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/`), 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. \ No newline at end of file diff --git a/.ideai/tickets/138/carnet.md b/.ideai/tickets/138/carnet.md new file mode 100644 index 0000000..aaec342 --- /dev/null +++ b/.ideai/tickets/138/carnet.md @@ -0,0 +1,30 @@ +--- +issueRef: "#138" +version: 4 +updatedBy: {"kind":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"} +updatedAt: 1785703680849 +--- +## 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("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//` : `app_data/plugins/data//`. 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//` (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//` en plus de `plugins/installed/` + 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//`, 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//` 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é). \ No newline at end of file diff --git a/.ideai/tickets/138/issue.md b/.ideai/tickets/138/issue.md new file mode 100644 index 0000000..784f0fe --- /dev/null +++ b/.ideai/tickets/138/issue.md @@ -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: "qa" +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":"agent","agent_id":"b4730d7f-c54d-4736-8a04-c6203aa2fd49"} +createdAt: 1785702748769 +updatedAt: 1785703680849 +version: 4 +--- +Le lot #133/#135 traite déjà le confinement du package installé et l’absence 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 l’objectif 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 d’architecture/API, PAS l’implé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 s’il 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 l’utilisateur a explicitement demandé au plugin de modifier. +4. Imposer l’alignement doc/exemples SDK : ne plus montrer `.ideai/...` comme emplacement par défaut pour l’état interne d’un plugin. + +Critères d’acceptation : +- Une note d’architecture/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 à l’uninstall). +- 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 l’exigence utilisateur : plugin désinstallé => plus aucun état propre au plugin, ni dans le projet, ni dans l’app data plugin. \ No newline at end of file diff --git a/.ideai/tickets/139/carnet.md b/.ideai/tickets/139/carnet.md new file mode 100644 index 0000000..1b307f9 --- /dev/null +++ b/.ideai/tickets/139/carnet.md @@ -0,0 +1,6 @@ +--- +issueRef: "#139" +version: 3 +updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +updatedAt: 1785709504027 +--- diff --git a/.ideai/tickets/139/issue.md b/.ideai/tickets/139/issue.md new file mode 100644 index 0000000..687126a --- /dev/null +++ b/.ideai/tickets/139/issue.md @@ -0,0 +1,17 @@ +--- +id: "a5bac900-806d-4e13-866f-7ebae686a43d" +number: 139 +title: "SDK plugins: aligner l’API publique et les exemples sur une persistance plugin-owned hors projet" +status: "qa" +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":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +createdAt: 1785702774592 +updatedAt: 1785709504027 +version: 3 +--- +Implémenter le contrat décidé en #138. Ce ticket ne doit démarrer qu’après arbitrage architecture, car la forme exacte de l’API 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 l’incitation 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 l’exemple 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 qu’une nouvelle API SDK publique est nécessaire (par ex. document structuré plugin-scopé hors projet), l’exposer de bout en bout : types SDK, façade runtime publique, adaptateurs hôte nécessaires, et documentation d’usage.\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 d’acceptation :\n- Le README SDK sépare explicitement données project-owned vs plugin-owned.\n- L’exemple de référence n’emploie 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 d’un plugin. \ No newline at end of file diff --git a/.ideai/tickets/51/carnet.md b/.ideai/tickets/51/carnet.md deleted file mode 100644 index f8dd171..0000000 --- a/.ideai/tickets/51/carnet.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -issueRef: "#51" -version: 1 -updatedBy: {"kind":"user"} -updatedAt: 1783941336721 ---- diff --git a/.ideai/tickets/51/issue.md b/.ideai/tickets/51/issue.md deleted file mode 100644 index 0e8426f..0000000 --- a/.ideai/tickets/51/issue.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: "6b74084c-0323-4f87-83f0-d9f944c364dc" -number: 51 -title: "Clean des session headless" -status: "open" -priority: "medium" -sprint: null -links: [] -agentRefs: [] -createdBy: {"kind":"user"} -updatedBy: {"kind":"user"} -createdAt: 1783941336721 -updatedAt: 1783941336721 -version: 1 ---- diff --git a/.ideai/tickets/63/carnet.md b/.ideai/tickets/63/carnet.md deleted file mode 100644 index eea29b6..0000000 --- a/.ideai/tickets/63/carnet.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -issueRef: "#63" -version: 1 -updatedBy: {"kind":"user"} -updatedAt: 1784098438671 ---- diff --git a/.ideai/tickets/63/issue.md b/.ideai/tickets/63/issue.md deleted file mode 100644 index e0b9508..0000000 --- a/.ideai/tickets/63/issue.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: "b5753734-1474-48d5-af6c-4a41b78005dc" -number: 63 -title: "Systeme de test de l'UI" -status: "open" -priority: "medium" -sprint: null -links: [] -agentRefs: [] -createdBy: {"kind":"user"} -updatedBy: {"kind":"user"} -createdAt: 1784098438671 -updatedAt: 1784098438671 -version: 1 ---- diff --git a/.ideai/tickets/66/carnet.md b/.ideai/tickets/66/carnet.md deleted file mode 100644 index a9e8413..0000000 --- a/.ideai/tickets/66/carnet.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -issueRef: "#66" -version: 2 -updatedBy: {"kind":"user"} -updatedAt: 1784193460805 ---- diff --git a/.ideai/tickets/66/issue.md b/.ideai/tickets/66/issue.md deleted file mode 100644 index ce6e6c3..0000000 --- a/.ideai/tickets/66/issue.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -id: "f805cd9b-8ecd-401a-8f03-665a27fe73cb" -number: 66 -title: "Image Docker serveur/client IdeA" -status: "open" -priority: "medium" -sprint: "028179b1-eaf4-41e9-9c1f-7c37125117e6" -links: [{"target":"#65","kind":"dependsOn"}] -agentRefs: [] -createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} -updatedBy: {"kind":"user"} -createdAt: 1784187597004 -updatedAt: 1784193460805 -version: 2 ---- -Objectif : livrer une image Docker exécutant le mode serveur/client d'IdeA, bâtie sur le binaire headless `idea-serve` (#65), pas sur le binaire Tauri. Cadré par Architect (suite #13). - -Plan de lots (Architect) : -- **L4 — Build web transport HTTP** : produire les assets client Vite en `VITE_TRANSPORT=http` (npm, jamais pnpm), vérifier qu'aucun import Tauri ne fuit dans ce mode, packager dans `/usr/share/idea/web`. -- **L5 — Docker runtime** : Dockerfile multi-stage (build Rust headless + build frontend + runtime minimal Debian/Ubuntu selon deps PTY/process). Défauts : `IDEA_APP_DATA_DIR=/data`, `--listen 0.0.0.0:17373`, `--web-root /usr/share/idea/web`. Volumes `/data` (app-data : projects/profiles/templates/tasks/logs) et `/workspace` (projets manipulés par les agents). Entrypoint `idea-serve`. Healthcheck HTTP local. Conteneur reste HTTP interne ; reverse proxy TLS externe obligatoire en prod distante (`--allow-remote`/`--public-origin https`/`--trust-reverse-proxy`, doc B8). Pas de TLS applicatif V1. -- **L6 — Agents CLI en conteneur** : décider image minimale (profils détectés au runtime, exécutables attendus dans PATH) vs image `idea-server-agents` (CLIs redistribuables installées si licence OK). Seed profils compatibles conteneur. Documenter env (OPENAI_API_KEY, ANTHROPIC_API_KEY, vars opencode) et montages de credentials. Tester au moins un agent bout en bout. Hors périmètre : installer automatiquement des CLIs propriétaires sans validation licence. - -Lock app-data-dir : peu critique en Docker mono-conteneur mono-writer ; multi-conteneurs sur le même /data explicitement hors support sans lock distribué. - -Hors périmètre V1 : Kubernetes, multi-tenant, auth externe, TLS intégré. - -Dépend de #65 (binaire headless). \ No newline at end of file diff --git a/.ideai/tickets/counter.json b/.ideai/tickets/counter.json index 14e53ba..03e32ab 100644 --- a/.ideai/tickets/counter.json +++ b/.ideai/tickets/counter.json @@ -1,3 +1,3 @@ { - "nextNumber": 131 + "nextNumber": 140 } \ No newline at end of file diff --git a/.ideai/tickets/index.json b/.ideai/tickets/index.json index 150ab17..1da344b 100644 --- a/.ideai/tickets/index.json +++ b/.ideai/tickets/index.json @@ -713,19 +713,6 @@ }, "updatedAt": 1783959345112 }, - { - "issueRef": "#51", - "path": "51", - "title": "Clean des session headless", - "status": "open", - "priority": "medium", - "sprint": null, - "assignedAgentIds": [], - "createdBy": { - "kind": "user" - }, - "updatedAt": 1783941336721 - }, { "issueRef": "#52", "path": "52", @@ -841,19 +828,6 @@ }, "updatedAt": 1784406936659 }, - { - "issueRef": "#63", - "path": "63", - "title": "Systeme de test de l'UI", - "status": "open", - "priority": "medium", - "sprint": null, - "assignedAgentIds": [], - "createdBy": { - "kind": "user" - }, - "updatedAt": 1784098438671 - }, { "issueRef": "#64", "path": "64", @@ -882,20 +856,6 @@ }, "updatedAt": 1784210420516 }, - { - "issueRef": "#66", - "path": "66", - "title": "Image Docker serveur/client IdeA", - "status": "open", - "priority": "medium", - "sprint": "028179b1-eaf4-41e9-9c1f-7c37125117e6", - "assignedAgentIds": [], - "createdBy": { - "kind": "agent", - "agent_id": "a6ced819-b893-4213-b003-9e9dc79b9641" - }, - "updatedAt": 1784193460805 - }, { "issueRef": "#67", "path": "67", @@ -1706,6 +1666,147 @@ "agent_id": "a6ced819-b893-4213-b003-9e9dc79b9641" }, "updatedAt": 1785669830933 + }, + { + "issueRef": "#131", + "path": "131", + "title": "Configurer l'effort par agent avec presets adaptatifs selon le profil AI", + "status": "open", + "priority": "medium", + "sprint": null, + "assignedAgentIds": [], + "createdBy": { + "kind": "agent", + "agent_id": "a6ced819-b893-4213-b003-9e9dc79b9641" + }, + "updatedAt": 1785687359220 + }, + { + "issueRef": "#132", + "path": "132", + "title": "Ajouter un outil MCP IdeA pour éditer le contexte projet global", + "status": "open", + "priority": "medium", + "sprint": null, + "assignedAgentIds": [], + "createdBy": { + "kind": "agent", + "agent_id": "a6ced819-b893-4213-b003-9e9dc79b9641" + }, + "updatedAt": 1785687502830 + }, + { + "issueRef": "#133", + "path": "133", + "title": "Plugins: contrat de service des assets idea-plugin:// (multi-fichiers ESM) & confinement", + "status": "qa", + "priority": "high", + "sprint": null, + "assignedAgentIds": [ + "b4730d7f-c54d-4736-8a04-c6203aa2fd49" + ], + "createdBy": { + "kind": "agent", + "agent_id": "b4730d7f-c54d-4736-8a04-c6203aa2fd49" + }, + "updatedAt": 1785703664966 + }, + { + "issueRef": "#134", + "path": "134", + "title": "Plugins: servir tout fichier confiné du package installé (fix racine multi-fichiers ESM)", + "status": "qa", + "priority": "critical", + "sprint": null, + "assignedAgentIds": [ + "fe887179-933f-47d4-960f-c3b06827f86c" + ], + "createdBy": { + "kind": "agent", + "agent_id": "b4730d7f-c54d-4736-8a04-c6203aa2fd49" + }, + "updatedAt": 1785707290184 + }, + { + "issueRef": "#135", + "path": "135", + "title": "Plugins: audit confinement install & désinstallation 100% propre", + "status": "qa", + "priority": "high", + "sprint": null, + "assignedAgentIds": [ + "ab328d90-c307-4771-a3b6-6c56089c8506" + ], + "createdBy": { + "kind": "agent", + "agent_id": "b4730d7f-c54d-4736-8a04-c6203aa2fd49" + }, + "updatedAt": 1785708498776 + }, + { + "issueRef": "#136", + "path": "136", + "title": "SDK plugins: aligner doc/exemple sur le support multi-fichiers ESM", + "status": "qa", + "priority": "high", + "sprint": null, + "assignedAgentIds": [ + "8f7da528-58df-4315-97e9-0562230ecc19" + ], + "createdBy": { + "kind": "agent", + "agent_id": "b4730d7f-c54d-4736-8a04-c6203aa2fd49" + }, + "updatedAt": 1785708478849 + }, + { + "issueRef": "#137", + "path": "137", + "title": "QA: validation end-to-end plugin multi-fichiers ESM (chargement + désinstallation propre)", + "status": "open", + "priority": "critical", + "sprint": null, + "assignedAgentIds": [ + "ab328d90-c307-4771-a3b6-6c56089c8506" + ], + "createdBy": { + "kind": "agent", + "agent_id": "b4730d7f-c54d-4736-8a04-c6203aa2fd49" + }, + "updatedAt": 1785702681696 + }, + { + "issueRef": "#138", + "path": "138", + "title": "SDK plugins: contrat de persistance plugin-owned hors projet et effacement total à la désinstallation", + "status": "qa", + "priority": "critical", + "sprint": null, + "assignedAgentIds": [ + "b4730d7f-c54d-4736-8a04-c6203aa2fd49" + ], + "createdBy": { + "kind": "agent", + "agent_id": "a6c6ea12-bfc6-4bdc-8031-324102dfa34d" + }, + "updatedAt": 1785703680849 + }, + { + "issueRef": "#139", + "path": "139", + "title": "SDK plugins: aligner l’API publique et les exemples sur une persistance plugin-owned hors projet", + "status": "qa", + "priority": "critical", + "sprint": null, + "assignedAgentIds": [ + "fe887179-933f-47d4-960f-c3b06827f86c", + "8f7da528-58df-4315-97e9-0562230ecc19" + ], + "createdBy": { + "kind": "agent", + "agent_id": "a6c6ea12-bfc6-4bdc-8031-324102dfa34d" + }, + "updatedAt": 1785709504027 } ] } \ No newline at end of file