97 Commits

Author SHA1 Message Date
045e0984cc chantier: durcissement reprise headless inter-projets + persistance profils Opencode
- Implémentation reprise de session Opencode headless (conversational_recovery)
- Persistance des profils IA Opencode dans .ideai/memory avec JSON Schema
- Gestion des permissions MCP pour agents externes
- Tests QA verts : structured_launch_d3, conversation_log, tickets_missing_carnet, agents, ProfilesSettings
2026-07-28 12:23:34 +02:00
78f7c8fe2d merge develop into feature/85-fix-flaky-setcellagent-test 2026-07-27 17:24:40 +02:00
851f1f8f2c chore(gitignore): stop tracking local IdeA tickets state 2026-07-27 17:23:19 +02:00
41aa2789a7 merge feature/fix-opencode-final-capture dans develop 2026-07-27 17:15:51 +02:00
f4895208d7 merge feature/91-rendezvous-toast-label dans develop
Ticket #91 — libellé explicite « Appel X -> Y terminé/en échec/annulé »
pour les notifications de fin de background task issues d'un rendez-vous
inter-agent. Frontend pur, tests annoncés verts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 16:49:26 +02:00
88a5256a1e feat(rendezvous): libellé explicite des notifications de fin de background task (#91)
Le toast de fin de tâche de fond liée à un rendez-vous inter-agent passe
de « Main -> DevBackend completed » à « Appel Main -> DevBackend terminé »
(idem en échec / annulé), pour nommer explicitement l'appel plutôt qu'un
état brut. Fallback générique conservé quand requester/target sont absents.

Validations obtenues avant commit : tests frontend annoncés verts pour #91.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 16:49:22 +02:00
efbd084b7d merge feature/58-background-task-live-subscriber dans develop
Ticket #58 — rendu live des tâches de fond (subscriber UI + canal IPC
attachable au task output). Validations vertes : tests infrastructure,
cargo check backend/app-tauri, vitest workstate, typecheck, QA.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 16:48:33 +02:00
b734c237d3 feat(background-task): rendu live des tâches de fond — subscriber UI + canal IPC (#58)
Câble un canal attachable au flux de sortie d'une tâche de fond (runner
infrastructure + commande app-tauri + port/adaptateurs frontend) et le
panneau ProjectWorkStatePanel s'y abonne pour un rendu live au lieu d'un
état figé au dernier snapshot.

Validations obtenues avant commit :
- cargo test -p infrastructure --test background_task_runner : vert
- cargo check -p backend -p app-tauri : vert
- npx vitest run src/features/workstate/workstate.test.tsx : vert
- npm run typecheck : vert
- verdict QA #58 : vert

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 16:48:29 +02:00
e1d8f5885f fix(opencode): capture Final trop stricte et ordre parse/status
Un tour OpenCode sans texte mais terminé proprement (step_finish, ex.
tool-call-only) échouait en Decode alors qu'aucune erreur réelle ne
s'était produite : parse_jsonl_turn émet désormais un Final vide dans
ce cas au lieu d'un hard-fail, réservé aux flux vraiment vides,
ignorés ou seulement démarrés.

send() inversait aussi l'ordre de décision : un statut de sortie non
nul faisait échouer la délégation même quand stdout contenait un
événement terminal structuré exploitable (Final/Error). Le parse est
maintenant tenté avant l'évaluation du statut, et un événement
terminal structuré prévaut sur un exit code non nul.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 14:30:03 +02:00
6f532d7434 merge feature/ticket96-effective-permissions-assistants-ticket dans develop 2026-07-27 14:18:59 +02:00
ce375c3e70 merge feature/67-correct-repository-branch dans develop 2026-07-27 14:18:57 +02:00
0b83b5bbd2 feat(lock): implémentation lock inter-process app-data-dir V1 — acquisition non-bloquante avec RAII 2026-07-27 13:57:58 +02:00
e74a9703f9 feat: livrable ticket #96 — effective permissions pour assistants de ticket 2026-07-27 13:37:08 +02:00
865f90eafd merge feature/multi-profiles-codex-clarification-toast-notices dans develop
Résout le conflit d'imports/helpers de tests dans
crates/application/tests/model_server.rs par union des deux côtés
(imports application/domain + helpers aid/nid/sess).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 13:06:35 +02:00
d7b6038f23 merge feature/ticket107-multi-project-isolation dans develop
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 13:04:51 +02:00
cf074a7d61 fix(runtime): isolation d'usage multi-projet #107
Implémentation du garde ModelServerProjectUseGuard pour séparer
les retours des agents entre projets concurrents.

- Garde RAII par LocalModelServerId partagé entre projets
- Refus inter-projets concurrent via model_server_in_use
- Partage intra-projet conservé avec refcount
- Libération automatique à la fermeture/erreur de session

Tests de validation: rejet projet distinct, compteur refs, libération retrait
2026-07-27 09:47:23 +02:00
038e90ecec feat: livrable ticket #91 — notification fin BackgroundTask enrichie
- Backend: enrichissement HeadlessRendezvous avec requester/target/conversationId
- Frontend: toast 'Requester -> Target completed/...' explicite
- Clic ouvrant viewer de conversation pour visualiser l'échange
2026-07-27 09:05:34 +02:00
02603441c1 fix: livrable tickets #70 #100 #102 — UX surface scoping
- #70: implémentation suppression modèles locaux téléchargés
- #100: correction scroll OpenCode
- #102: correction fit TUI après switch/layout
- memory note scoping UX
2026-07-26 19:42:06 +02:00
4321d048ac fix: correction de régression UI wizard first-run 2026-07-26 16:52:23 +02:00
ca70ec75f4 feat: catalogue dynamique modèles Codex/Claude avec compatibilité CLI locale
Ajout du catalogue enrichi pour les modèles Codex et Claude avec:
- Compatibilité estimée avec la version CLI locale détectée
- Source d'origine (catalogue/Provider) pour chaque entrée
- Support du catalogue Provider API externe
- Matrice de compatibilité embarquée dans l'application

Frontend:
- UI de configuration des modèles avec affichage des états de compatibilité
- Suggestions dynamiques avec badges de compatibilité
- Messages d'aide contextuels (compatible/unknown/likelyTooRecent)
- Alertes non-bloquantes pour les modèles trop récents
- Gestion des échecs de catalogue avec saisie manuelle conservée

Backend:
- Ports CliVersionReader, ProviderModelCatalogue, CompatibilityMatrixSource
- Implémentations: ProcessCliVersionReader, HttpProviderModelCatalogue, EmbeddedCompatibilityMatrix
- Enrichissement des DTOs avec compatibility, cli_version, warnings
- Tests unitaires complets pour le resolver de catalogue
2026-07-26 16:09:10 +02:00
e7bf1d3666 frontend: suppress network banner params unneeded after runtime lock refactor 2026-07-26 15:12:14 +02:00
e5bafc30e7 Merge branch 'main' into feature/multi-profiles-codex-claude-model-catalogue 2026-07-26 14:57:31 +02:00
ea7ea71230 feat: finalise multi-profil Codex/Claude avec catalogue de modèles
- Backend : clone_profile_from_seed généralisé (non OpenCode)
- Backend : catalogue static Claude/Codex (3 modèles chacun, 1 recommandé)
- Backend : commandes Tauri list_claude_models/list_codex_models
- Frontend : ProfilesSettings refonte en onglets Codex/Claude + create/duplicate/edit/delete
- Frontend : ModelSelect searchable partagé + fallback saisie manuelle
- Frontend : assignation agent nom · modèle
- Tests QA : 4 profils modèles distincts (2 Claude, 2 Codex) assignés à agents
2026-07-26 14:56:26 +02:00
c807a70fea Remove all target/ files from index (should be .gitignore'd) 2026-07-26 14:22:52 +02:00
d741035c47 Remove tracked files from target/release/bundle/appimage after AppImage rebuild
- Remove app-tauri binary (should be in source, not target)
2026-07-26 14:21:17 +02:00
455eba3f91 Fix git index: remove target/artefact .gitignore, keep runtime JSON in index 2026-07-26 14:16:45 +02:00
13ff1a4f51 ignore .ideai/background-tasks/ (runtime tasks sensibles, issue b8-arbitration-outcomes) 2026-07-26 14:15:26 +02:00
480cdc41ac ignore .ideai/background-tasks/ (runtime tasks sensibles) 2026-07-26 14:14:50 +02:00
0821739924 feat: finalise ticket99 - implémentation agent model configuration v2
- agent/lifecycle.rs: lifecycle management per profile
- agent/provider_catalogue.rs: provider registration with model support
- agent/usecases.rs: usecases for profile-based agent invocation
- agent/mod.rs: expose agent capabilities via AgentManager
- backend/dto.rs: AgentModelConfig, AgentProviderConfig DTOs
- domain/profile.rs: extend Profile avec agent capabilities
- domain/permission.rs: permission checks pour agent access
- infrastructure/assistant/mod.rs: agent integration
- infrastructure/permission/{claude,codex}.rs: permission handlers
- web-server/lib.rs: agent endpoints
- commands.rs: agent commands
- frontend/adapters/{http,profile,mock,domain}.ts: adapters
- frontend/first-run/FirstRunWizard.{test.tsx,tsx}: first-run flow
2026-07-26 13:38:18 +02:00
b5d7e16501 feat: correction provider/API key - removal Codex/Claude provider configs 2026-07-26 13:23:04 +02:00
dae07d35bb feat: implémentation et QA ticket99 - agent model configuration v2
- backend A-C: VO Codex/Claude, renderers/projecteurs modèle, SecretRef/env, catalogues/use cases/Tauri commands
- frontend D: profils Codex/Claude provider->model->secret, validations, conservation SecretRef
- fix: app-tauri embedded_server isolant IDEA_WEB_ROOT

QA: backend 57/57 tests, frontend 74/74 tests OK
2026-07-26 11:56:25 +02:00
13fb538880 fix(permissions): validate network access flow 2026-07-26 10:52:46 +02:00
3047dc9195 feat(permissions): expose network permission state (#103) 2026-07-25 23:06:50 +02:00
e8731834f4 merge: integrate ticket 101 multi-project isolation 2026-07-25 22:14:19 +02:00
6e98fd89f7 fix(runtime): isolate agent state by project (#101) 2026-07-25 22:14:02 +02:00
da907b880e Fix terminal resize bug
Fix resize handling in TerminalView component and update related tests
2026-07-25 14:54:57 +02:00
6a87c4635f merge: integrate ticket 98 OpenCode provider fix 2026-07-25 14:27:10 +02:00
ad491e765f fix(opencode): make models.dev providers cache-independent 2026-07-25 14:26:15 +02:00
69e5878679 fix(backend): clone du seed OpenCode tolère un seed persisté converti en cloud
CloneOpenCodeProfileFromSeed::execute rejetait auparavant tout profil persisté squattant l'UUID déterministe du seed canonique opencode-llamacpp avec « internal error: canonical OpenCode seed is not an OpenCode profile ».

Root cause: un profil persisté converti en backend cloud GLM5.2 (ticket #92, opencodeProvider) conserve l'UUID du seed ; le find le matchait et le garde-fou seed.opencode.is_none() — non mis à jour pour le backend cloud — déclenchait une erreur Internal bloquante.

Correctif:

- Le find exige désormais un seed OpenCode valide (structured_adapter OpenCode + au moins un backend opencode local OU opencode_provider cloud), et retombe sur le seed catalogue sinon au lieu d'errer sur un état de store inattendu.

- L'override opencode local remet opencode_provider = None pour honorer l'invariant #97 opencode_backend_is_consistent (miroir de AgentProfile::with_opencode).

- 2 tests de régression (fallback catalogue, seed cloud accepté) + 1 test de symétrie save ajoutés.

Vérification: cargo test -p application --test profile_usecases -> 25 passed.
2026-07-25 01:47:58 +02:00
55330732dd Merge feature/ticket97-opencode-provider-mutual-exclusion into develop 2026-07-24 19:52:49 +02:00
0f0a76d806 fix(backend): exclusion mutuelle des backends OpenCode (llamacpp vs cloud) (#97)
Les builders `with_opencode` / `with_opencode_provider` s'évacuent
réciproquement (dernier appel gagnant) pour honorer l'invariant
`opencode_backend_is_consistent`. Le use case SaveOpenCodeProviderProfile
route désormais via le builder au lieu de muter le champ directement — c'est
ce qui dupliquait `opencode` + `opencodeProvider` et forçait un repli sur
llamacpp même quand l'utilisateur choisissait un provider cloud.

Défense en profondeur côté store :
- `read_doc` répare les profils corrompus sur disque (drop du stale `opencode`)
- `save` refuse de persister un profil violant l'invariant via le nouveau
  variant `StoreError::Invalid` (mappé vers `AppError::Invalid`)

Tests verts : builders last-wins (domain), save rejets + read repair
(infra, profile_store 10/10).

Refs #97
2026-07-24 19:52:34 +02:00
7fee56acf5 Merge feature/ticket95-opencode-mcp-timeout into develop 2026-07-24 15:18:13 +02:00
6e9a3ff657 fix(agent): timeout MCP OpenCode aligné sur le plafond du rendez-vous (#95)
Le timeout hardcoded 15000ms (15s) dans le bloc mcp.idea de l'opencode.json
généré par IdeA était far too short pour idea_ask_agent, qui bloque pendant
que l'agent cible travaille. OpenCode tuait la requête à 15s avec l'erreur
-32001 « Request timed out », même si la cible répondait correctement
(visible dans le workstate). Claude/Codex n'étaient pas affectés car leur
config MCP n'a pas de champ timeout.

Désormais le timeout est résolu par resolve_opencode_mcp_timeout_ms() :
- défaut 4h (14_400_000 ms), aligné sur DEFAULT_RENDEZVOUS_CEILING ;
- overridable via IDEA_OPENCODE_MCP_TIMEOUT_MS ;
- fallback sûr sur 0/parse-error (jamais d'expiration instantanée).

Les 4 occurrences (lifecycle.rs x2 + assistant/mod.rs x2) utilisent la même
fonction exportée depuis application::agent. Aucune modification des configs
MCP Claude/Codex.
2026-07-24 15:00:53 +02:00
7d3e74a114 Merge feature/opencode-permissions-projection into develop
Fix backend isolé, tests unitaires verts (ticket #94).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 18:14:27 +02:00
56631bd3c8 fix(backend): projeter les EffectivePermissions dans le bloc permission d'opencode.json
Les 4 générateurs opencode.json/opencode_provider.json codaient en dur
{"bash":"ask","edit":"ask"}, ignorant les permissions configurées côté
IdeA pour l'agent. Claude et Codex appliquaient déjà PermissionProjector,
seul OpenCode passait à côté.

Ajoute domain::opencode_permission_block(eff: Option<&EffectivePermissions>)
qui mappe bash ← posture bash effective, edit ← posture Write effective
(Read/Delete non exprimables dans le schéma OpenCode, déjà enforcées par
le sandbox Landlock). eff == None omet la clé permission entièrement,
préservant le prompting natif OpenCode — même invariant que Claude/Codex.

Câble eff jusqu'aux 4 sites d'appel (lifecycle.rs + assistant/mod.rs,
variantes llamacpp et provider cloud). Le chemin ticket-assistant
(assistant/mod.rs) n'a pas de PermissionStore par agent pour l'instant,
donc eff y reste None (comportement inchangé, pas de régression).

Réf ticket #94.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 18:14:20 +02:00
c9fffd7c47 Merge feature/fix-opencode-jsonl-parsing into develop
Fix confiné à l'adaptateur OpenCode (parsing JSONL text.part.text +
gestion événements error), validé par QA (cargo test -p infrastructure
309 passed, 0 failed).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 16:23:59 +02:00
0f57e7323a fix(backend): lecture du texte JSONL OpenCode niché sous part.text
Le parseur lisait value.text/value.content à la racine alors que
`opencode run --format json` niche le texte réel sous value.part.text
(cf. packages/opencode/src/cli/cmd/run.ts). Conséquence : idea_ask_agent
vers un profil OpenCode échouait systématiquement avec « OpenCode n'a
produit aucun final textuel » malgré une réponse CLI normale.

Ajoute aussi la gestion des événements type "error" (ParsedEvent::Error,
ReplyEvent::Error) pour distinguer un échec explicite d'un final vide,
et des tests de conformité sur le format JSONL réel confirmé.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 16:23:50 +02:00
4ac2dd1568 Merge feature/fix-gguf-shard-selection into develop
Fix backend de sélection GGUF (fichier fusionné prioritaire sur les
shards partiels) — QA vert : cargo test -p infrastructure/application,
cargo check --workspace, 3 nouveaux tests unitaires.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:23:59 +02:00
557d1c3f24 fix(backend): sélection GGUF prioritaire au fichier fusionné sur les shards
Quand un repo HuggingFace héberge à la fois le fichier GGUF fusionné et
ses shards pour une même quantisation, select_gguf_file (tri alphabétique
naïf) pouvait retenir un shard partiel plutôt que le fichier fusionné ou
l'ensemble complet des shards, causant un échec immédiat au démarrage du
serveur llama.cpp (agent Context).

select_gguf_files renvoie désormais soit le fichier fusionné seul (priorité),
soit tous les shards correspondants triés par index — jamais un shard isolé.
Le téléchargement, le cache et la reprise gèrent le cas multi-fichiers
(manifest de shards, chemins locaux préservant le nom distant pour
l'autoload de llama.cpp).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:23:55 +02:00
e8f6e9eded Merge feature/ticket92-opencode-provider-dynamic-catalog into develop
Complément post-livraison du ticket #92 : catalogue de providers
OpenCode dynamique (cache ~/.cache/opencode/models.json, repli
statique garanti) + option provider personnalisé en saisie libre.
QA verte : backend cargo build+test workspace, frontend tsc/build,
vitest 958/958.
2026-07-23 12:44:17 +02:00
ef747cd156 chore(ideai): état runtime — permissions et tâche de fond
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 12:44:10 +02:00
1784027f5d feat(frontend): provider OpenCode dynamique + saisie provider personnalisé (#92)
Le picker de provider OpenCode du first-run wizard consomme le
catalogue dynamique exposé par le backend et propose une option
« provider personnalisé » avec un formulaire de saisie libre
(id + clé API) quand le provider souhaité n'y figure pas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 12:44:02 +02:00
e943a0efed feat(backend): catalogue de providers OpenCode dynamique + provider personnalisé (#92)
Le catalogue de providers OpenCode lit désormais le cache local
~/.cache/opencode/models.json pour refléter les providers réellement
disponibles, avec repli garanti sur le catalogue statique en cas
d'absence ou d'erreur de lecture du cache. Ajout d'un champ additif
`custom` sur OpenCodeProviderConfig pour permettre à l'utilisateur de
déclarer un provider hors catalogue (id + clé API en saisie libre).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 12:43:59 +02:00
162e3ae641 chore(ideai): état runtime — tickets, mémoire, tâches de fond
Ticket #92 rouvert, mises à jour de carnets/tâches de fond.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 08:57:15 +02:00
12c7d103d0 Merge feature/ticket92-opencode-provider-cloud into develop
Ticket #92 — support des providers OpenCode cloud, backend + frontend,
QA vert des deux côtés (cargo test workspace + 952 tests frontend).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 08:18:09 +02:00
c181b43d04 feat(frontend): support des providers OpenCode cloud (#92)
Ajoute l'UI de configuration des providers OpenCode cloud dans le wizard
first-run (sélection, édition, sauvegarde, suppression), le domaine et
les ports associés, ainsi que les adapters HTTP/mock correspondants.

Build + 952 tests verts, comportements clés vérifiés en exécution réelle,
y compris un test de couverture ajouté pour le parcours d'édition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 08:18:02 +02:00
23a3c2788f feat(backend): support des providers OpenCode cloud (#92)
Ajoute le catalogue statique de providers OpenCode (lot B3), le stockage
sécurisé des secrets (SecretStore + adapter infrastructure), et les
use cases SaveOpenCodeProviderProfile/DeleteProfile câblés en composition
root. Couvre le fix B1 et les tests de régression demandés par QA.

cargo build --workspace propre, cargo test --workspace -- --test-threads=1
intégralement vert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 08:03:03 +02:00
bece7c92c5 Merge feature/ticket43-plugin-system into develop
Système de plugins (#43) : backend (domaine/application/infrastructure,
lots B1-B4) + frontend (runtime, menus, layouts custom, lots F1-F4).
Validé vert par QA (cargo test + npm typecheck/test 947/947).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 07:37:28 +02:00
98fb05447d chore(ideai): état runtime — tickets, mémoire, tâches de fond
État d'exécution accumulé (tickets créés/mis à jour hors #43, notes de
mémoire, tâche de fond) capturé au moment du commit de la feature.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 07:37:19 +02:00
ac726d075e feat(frontend): système de plugins — runtime, menus, layouts custom (#43)
Lots F1-F4 : runtime de chargement/registre plugin, extension des menus
existants, panneau de gestion des plugins, types de layout custom
(sélecteur, fallback, cellule dédiée) branchés sur le port plugin.
Suite npm typecheck/test verte (947/947).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 07:37:11 +02:00
bb35641715 feat(backend): système de plugins — domaine, application, infrastructure (#43)
Lots B1-B4 : modèle de domaine des plugins (manifeste, capacités menus/layouts/MCP),
port et registre applicatif, chargement/validation en infrastructure, exposition DTO
et commandes Tauri. Tests cargo verts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 07:37:03 +02:00
47aacc6da9 Merge feature/ticket61-cells-refit-web-regression into develop
Corrige la régression persistante en version web du refit des
cellules terminal (#61 rouvert) : le rafraîchissement du scaling
CLI après ajout/suppression de cellule ne se déclenchait pas dans
le workspace web, forçant un redimensionnement manuel.

QA : tsc propre, 909/909 tests vitest, aucune régression desktop
(LayoutGrid/useLayout/TerminalView).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 21:23:34 +02:00
3a18556ffa fix(frontend): refit web agent cells after opening a new one (#61 web regression)
The web shell never adopted the desktop's #61 fix: WebAgentCell/WebWorkspace
didn't pass any refitSignal to TerminalView, so a cell opened after another
kept a stale xterm scaling — desktop "fixed" it via an incidental window
resize, but mobile has no such escape hatch.

- TerminalView: a refit landing on a transient 0x0 container now reschedules
  on the next few frames instead of giving up for good (bounded retries),
  closing the independent timing gap Architect identified. refitSignal stays
  the single explicit-refit mechanism; the terminal/PTY is never recreated,
  and resize is still pushed to the PTY only when rows/cols actually change.
- WebAgentCell: new optional refitSignal prop, forwarded to TerminalView
  as-is (no key change, no remount).
- WebWorkspace/LiveProjectPanel: new cellLayoutVersion counter, the web
  equivalent of desktop useLayout.layoutVersion, bumped on every cell
  open/close and forwarded as refitSignal to the visible WebAgentCell.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 21:21:52 +02:00
a197197a90 Merge feature/ticket89-server-autostart into develop
Ajoute l'option de lancement automatique du serveur web au démarrage
d'IdeA (#89) : déclenchement backend Tauri au boot selon la
préférence utilisateur persistée, réglage frontend dans les
paramètres de déploiement avec erreur port occupé actionnable.

QA : 57 tests backend app-tauri verts (embedded_server/auto_start
compris), 895/895 tests frontend, tsc propre.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 21:16:59 +02:00
4fd339c047 Merge feature/ticket90-web-missing-menus into develop
Ajoute les menus Panneaux/Paramètres manquants à la version web
(#90), avec élargissement de l'allowlist /api/invoke côté
web-server pour router les commandes correspondantes.

QA : 895/895 tests frontend, tsc propre, tests backend
web_invoke_routes verts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 21:16:55 +02:00
e9b01795d1 feat(frontend): démarrage auto du serveur + erreur port occupé actionnable (#89)
Étend ServerExposureSettings avec autoStart (défaut false, mock aligné sur le
backend). useDeployment expose setAutoStart, qui persiste immédiatement le
draft sans jamais appeler start() ni toucher le comportement de stop(), et ne
met à jour l'état local qu'après confirmation de la sauvegarde (même piste de
validation que start/save). DeploymentSettings ajoute la case à cocher sous
le panneau Serveur, et des actions « Modifier le port »/« Réessayer » quand le
statut échoue avec le code PORT_IN_USE stabilisé côté backend.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:38:40 +02:00
30f6415d51 feat(frontend): ajoute les menus Panneaux/Paramètres à la version web (#90)
WebWorkspace gagne un menu « Panneaux » qui route la surface principale du
projet ouvert vers les panneaux transport-neutres déjà réutilisables
(contexte, agents, templates, skills, permissions, mémoire, git) en plus des
surfaces web existantes (travail live, tickets, sprints), ainsi qu'un variant
web du panneau Projets (création par chemin serveur saisi manuellement, sans
browse natif). WebApp gagne un menu « Paramètres » (Profils IA, Appareils,
Déploiement désactivé "Desktop uniquement") qui remplace l'ancien bouton
unique "Appareils".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:33:22 +02:00
cb2d0c2d44 feat(app-tauri): option de lancement auto du serveur web au démarrage
Ajoute le déclenchement du serveur embarqué dès le démarrage d'IdeA
selon la préférence utilisateur, sans action manuelle requise.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:32:03 +02:00
678ff3011b feat(web-server): élargir l'allowlist /api/invoke pour les menus Panneaux
Permet aux commandes Tauri des menus manquants (#90) d'être invoquées
depuis la version web via le proxy /api/invoke.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:31:58 +02:00
277a0e494a Merge feature/ticket87-web-workspace-collapse-tasks into develop
Repliage par défaut des background tasks par agent dans le WebWorkspace
(#87), fix frontend pur, tests verts (887 passants, tsc clean).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 17:56:25 +02:00
1139041603 feat(frontend): repliage par défaut des background tasks par agent (#87)
WebWorkspace replie désormais par défaut la liste des background tasks
par agent dans le panneau Work ; QA a ajouté les cas de test associés
dans WebWorkspaceLive.test.tsx (887 tests verts, tsc --noEmit clean).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 17:56:21 +02:00
527c2dde61 Merge feature/ticket86-web-tickets-sprints-ui into develop
Ticket #86, lot 2 : surface tickets/sprints pour le workspace web, avec fix
QA sur le changement/retrait de sprint sur un ticket. QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 07:44:51 +02:00
e7f67bada9 fix(frontend): sprint change/removal on tickets, web workspace (#86 QA fix)
QA-flagged gap: the web surface could only ADD a ticket to a sprint, never
change or clear it, despite the backend already exposing both
ticket_assign_sprint and ticket_unassign_sprint.

- useTicketDetail: new setSprint(sprintId | null) method (additive, also
  available to the desktop TicketDetail — unused there today, no behaviour
  change), routing through the existing TicketGateway.setTicketSprint.
- WebTicketDetail: Sprint selector in "Statut et priorité", immediate save
  like status/priority; empty value clears back to "Sans sprint".
- WebSprintsView: each sprint card now shows its tickets (compact list,
  resolved client-side like the desktop SprintManager) with a "Retirer du
  sprint" action per ticket, calling assignSprint(ref, null) — symmetric
  with "Ajouter tickets". Extracted the card into a SprintCard subcomponent
  to keep the growing card readable.
- Tests: WebTicketsSprints.test.tsx now has 16 tests (was 10) — added
  sprint change/clear, sprint removal from the Sprints tab, agent
  assign/unassign, ticket link/unlink, carnet save, and free-text search
  filtering.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 07:43:09 +02:00
e69361feb7 feat(frontend): tickets/sprints surface for the web workspace (#86 lot 2)
Adds a Live/Tickets/Sprints tab navigation to WebWorkspace after a project
is opened — a mobile-first adaptation, not a port of the desktop docks/
floating windows, per carnet #86. The web-server transport (17 ticket_*/
sprint_* commands) and the HttpTicketGateway were already wired (lot 1 +
pre-existing gateway code); this lot is UI only.

- Tickets tab: search/filters, list grouped by sprint, create screen,
  detail view with stacked accordion sections (Résumé/Statut et priorité/
  Carnet open by default; Agents assignés/Liens/Zone dangereuse collapsed),
  delete confirmation, optimistic-concurrency conflict banner.
- Sprints tab: create/rename/reorder (Monter/Descendre)/delete with
  confirmation, add tickets via a mobile full-screen ticket picker (never
  a small desktop modal), "Voir tickets" filters the Tickets tab to one
  sprint.
- Reuses the transport-neutral hooks as-is (useTickets, useTicketDetail,
  useTicketSearch) — only presentation and copy are web-specific, in
  French per decision #78 (new local label module, not a reuse of the
  English desktop ticketMeta labels).
- Workaround: `list_agents` isn't in the web-server allowlist, so agent
  names/assignment options are derived from `get_project_work_state`
  (already used by the Live tab) instead of the desktop's useProjectAgents.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 07:35:20 +02:00
45def4844a Merge feature/ticket86-web-tickets-sprints into develop
Ticket #86, lot 1 : commandes tickets/sprints exposées sur le transport web
(web-server), DTO tickets factorisés entre Tauri et web (ticket_dto.rs).
QA vert. Le lot 2 (frontend) suit sur une nouvelle branche.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 07:20:46 +02:00
5a7431b442 feat(backend): commandes web tickets/sprints + factorisation DTO (#86 lot 1)
Expose les commandes tickets/sprints sur le transport web (web-server/lib.rs),
avec factorisation des DTO tickets partagés entre Tauri et web dans un
nouveau module backend/src/ticket_dto.rs (app-tauri/src/tickets.rs
consomme désormais ce module commun).

Lot 1 du ticket #86, backend/web-server. Le lot 2 (frontend) suit sur une
nouvelle branche depuis develop à jour.

QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 07:20:39 +02:00
5d262231e2 Merge feature/ticket83-quit-confirm-work-in-progress into develop
Ticket #83 : popup de confirmation à la fermeture d'IdeA si travail en
cours — guard backend (agents busy + tâches d'arrière-plan actives,
GetAppExitWorkGuardState) + popup frontend. QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 19:18:52 +02:00
60f4b33e53 feat(backend): guard de fermeture "travail en cours" (#83)
Expose l'état du guard de sortie applicative (GetAppExitWorkGuardState) :
agents busy + tâches d'arrière-plan actives à travers tous les projets
ouverts, avec détails compacts pour la popup de confirmation. Le handler
CloseRequested d'app-tauri interroge ce guard avant de laisser la fenêtre
se fermer, et respecte la confirmation explicite de l'utilisateur
(EXIT_GUARD_CONFIRMED) pour ne pas la redemander en boucle.

QA vert (backend + frontend).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 19:18:39 +02:00
8509653e3c feat(frontend): popup de confirmation à la fermeture avec travail en cours (#83)
Écoute l'event Tauri `app-exit-work-guard` (émis par le backend quand la
fermeture de la fenêtre main est interceptée) et affiche une popup modale
"Du travail est encore en cours" avec le résumé pluralisé exact du carnet
#83, le détail agents/tâches capé à 5 lignes, et les deux actions Annuler
(focus par défaut, no-op local) / Quitter quand même (danger, appelle
confirm_app_exit). Pas d'option "ne plus demander".

- domain/ports/adapters (Tauri listen+invoke, HTTP desktop-only stub, mock
  avec helpers de test) : onAppExitWorkGuard/confirmAppExit sur
  SystemGateway, suivant le patron déjà utilisé pour focused-project et les
  domain events.
- AppExitConfirmDialog : mounted une fois près de la racine (App.tsx), à
  côté d'AnnouncementsProvider — role="alertdialog", focus trap, Échap =
  Annuler, pas de fermeture au clic extérieur, ne se referme jamais
  automatiquement (un event pendant l'ouverture rafraîchit juste le résumé).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 19:16:29 +02:00
294865f805 Merge feature/ticket81-mcp-templates-editing into develop
Ticket #81 : MCP d'édition de templates — catalogue/classification (B1),
use cases/provider (B2), enforcement policy (B3). QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 18:45:07 +02:00
ef84d5cc49 feat(backend): MCP d'édition de templates (#81)
Ajoute le MCP dédié à l'édition de templates : catalogue et classification
des templates (mcp/templates.rs infrastructure + app-tauri), use cases et
provider (application/template), enforcement de la policy des tools (mod.rs,
server.rs, tools.rs), avec la parité côté chemin OpenAI-compatible
(openai_tools.rs x2).

Lots B1 (catalogue/classification), B2 (use cases/provider) et B3
(enforcement policy) livrés en un seul commit cohérent.

QA vert (seul l'échec de bind loopback #80, connu et non-régression, écarté).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 18:45:02 +02:00
448edfc364 Merge feature/ticket82-mcp-tools-permissions-ui into develop
Ticket #82, lot UX/Frontend : surface de gestion des permissions des tools
MCP par agent (Permissions panel), consommant l'API Tauri livrée en B4. QA
vert (858/858, tsc propre, stable sur shuffle hormis le flake #85, hors
périmètre).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 23:39:12 +02:00
c3078875f4 feat(frontend): surface MCP tool permissions per agent — Permissions panel (#82 lot UX/F)
Adds the "Tools MCP IdeA" tab to the project Permissions panel, alongside
the existing "Système" (file/command) tab. Lets the user grant/revoke MCP
tool capabilities per agent or project-wide default, grouped by domain
(Lecture projet, Lecture tickets, Délégation agents, Contexte et mémoire,
Tickets, Travail et exécution, Skills) instead of a flat 25-checkbox list,
per the UX conception in carnet #82.

- domain/ports/adapters (Tauri, HTTP, mock): wire get_mcp_tool_permissions,
  update_project_mcp_tool_permissions, update_agent_mcp_tool_permissions
  (already merged backend API, #82 lots B1-B4) onto PermissionGateway.
- useMcpToolPermissions: view-model owning the durable MCP tool policy
  document, distinct from the file/command permissions in usePermissions.
- McpToolPermissionsPanel: target selector (Défaut projet + agents with
  Hérité/Override badges) and grouped editor — inherited agents are
  read-only until "Créer un override" (prefilled with the effective
  allowlist), per-row Ajouté/Retiré diffing against the project default,
  inline confirmation before granting a write tool at project-default
  level, and unsaved-draft protection on target change.
- mcpToolGroups.ts: presentational-only domain grouping and short French
  labels — the read/write classification itself always comes from the
  backend-provided catalogue, never hardcoded here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 23:36:02 +02:00
2db37a50fa chore(fmt): reformatage cargo fmt résiduel
Deux reformatages sans changement de comportement (device.rs, web-server/lib.rs),
laissés de côté hors périmètre au fil de plusieurs tickets précédents.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 23:15:39 +02:00
5f15cdbf28 Merge feature/ticket82-mcp-tools-catalog-permissions into develop
Ticket #82 : catalogue et permissions des tools MCP, backend complet en 4
lots — B1 domaine/store durable, B2 enforcement au serveur MCP stdio, B3
parité enforcement sur le chemin OpenAI-compatible, B4 API Tauri pour la
future UI de gestion. QA vert sur chaque lot.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 23:15:12 +02:00
c84a66f4e8 feat(backend): API Tauri pour la gestion des permissions tools MCP (#82 lot B4)
Expose au niveau application/DTO/commandes Tauri le catalogue et les
permissions des tools MCP (application/mcp_tool_permissions.rs, dto.rs,
commands.rs) pour une future UI de gestion.

Lot B4 du ticket #82, dernier lot backend : ferme la boucle sur B1
(domaine/store) + B2 (enforcement MCP stdio) + B3 (parité
OpenAI-compatible).

QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 23:15:05 +02:00
eeba0ddb46 feat(backend): parité enforcement des permissions tools sur le chemin OpenAI-compatible (#82 lot B3)
backend/src/openai_tools.rs et app-tauri/src/openai_tools.rs appliquent
désormais les mêmes règles de permission du domaine mcp_tool_permissions
(B1) et le même enforcement que le serveur MCP natif (B2), pour fermer
l'écart de parité sur le chemin OpenAI-compatible.

Lot B3 du ticket #82 : parité posée sur B1+B2, l'API backend pour la future
UI suit en B4 sur la même branche.

QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 23:03:33 +02:00
37ead61911 feat(backend): enforcement des permissions tools MCP au serveur (#82 lot B2)
orchestrator/mcp/server.rs applique désormais les règles de permission du
domaine mcp_tool_permissions (lot B1) à l'invocation d'un tool, y compris
le cas requester vide.

Lot B2 du ticket #82 : ferme la boucle enforcement sur le socle B1, la
parité OpenAI-compatible suit en B3 sur la même branche.

QA vert (32 tests dont le nouveau cas requester vide).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 22:54:42 +02:00
5175589aa5 feat(backend): domaine + catalogue et store durable des permissions tools MCP (#82 lot B1)
Introduit le domaine mcp_tool_permissions (règles de permission par tool
MCP) et étend le port de store correspondant. Le catalogue read/write des
tools MCP (orchestrator/mcp/tools.rs) s'appuie désormais sur ces règles, et
un store durable (mcp_tool_permission.rs) persiste les permissions au-delà
d'une session.

Lot B1 du ticket #82 : pose le socle domaine/store, l'enforcement suit en
B2 sur la même branche.

QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 22:45:32 +02:00
32408b5232 Merge feature/ticket62-requester-identity-tool-policy into develop
Ticket #62 : identité requester explicite pour les sessions structurées et
policy des tools OpenAI-compatible (ToolPolicyRegistry branché sur
AppOpenAiToolInvoker). QA vert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 22:35:23 +02:00
b4a34b40e5 fix(backend): identité requester explicite + policy des tools OpenAI-compatible (#62)
AgentSessionFactory::start propage désormais l'identité du requester aux
sessions structurées ; OpenTicketAssistant et LaunchAgent la portent
correctement de bout en bout. ToolPolicyRegistry est branché sur
AppOpenAiToolInvoker pour combler le trou de parité : TicketToolProvider
n'appliquait pas la policy des tools sur le chemin OpenAI-compatible,
contrairement au chemin structuré natif.

QA vert (échecs de bind loopback écartés comme non-régression préexistante,
tracés en #80).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 22:35:17 +02:00
a7abd331b8 Merge feature/ticket79-flaky-permissions-test into develop
Ticket #79 : fix du flake PermissionsPanel > saves project defaults
(PermissionEditor draft resync clobbering in-flight edits). QA vert sur le
périmètre du ticket (2/2 stable + suite complète non-shuffled) ; le rouge
observé en shuffle vient d'un autre test préexistant sans rapport
(setCellAgent.test.tsx, tracé séparément en #85).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 14:57:44 +02:00
8387c1bbdf Merge feature/ticket78-settings-french-labels into develop
Ticket #78 : alignement des libellés Settings desktop sur le français, QA
vert (850/850 tests, tsc propre).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 14:57:37 +02:00
6e92536d84 fix(frontend): align Settings desktop labels on French (#78)
UX decision (carnet #78): the human UI of IdeA is French by default,
uniform per surface — proper nouns and technical acronyms (URL, LAN,
IP/CIDR, HTTPS, API, CLI…) stay as-is. Settings mixed English (AI
Profiles, Deployment) with French (Appareils, frozen by UX for #77).

Renames the Settings menu/nav, the Profils IA and Déploiement panels
(titles, actions, states, help text) to French, per the carnet's
exhaustive list. Updates the affected tests accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 14:53:32 +02:00
348bccae34 fix(frontend): stop PermissionEditor draft resync from clobbering in-flight edits (#79)
The draft-resync useEffect fired on every new `draft` object (initial load,
refresh, another save), even when its content matched `local`. If it flushed
after the user started editing, it silently discarded the edit — flaky in
tests where a passive effect can settle after a synchronous fireEvent
sequence, and a real risk in production if a fetch lands mid-edit. Now it
only resyncs when `local` still matches the last-adopted draft.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 14:49:22 +02:00
a69c5db093 Merge feature/ticket61-cells-refit into develop
Ticket #61 : refit différé des cellules terminal après split/merge, QA vert
(850/850 tests, tsc propre, test refitSignal dédié).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 09:41:44 +02:00
445ecaf82e fix(frontend): refit différé des cellules terminal après mutation de layout (#61)
Le ResizeObserver de TerminalView ne déclenche pas toujours un événement
utile quand une cellule voisine apparaît/disparaît (split/merge), forçant
l'utilisateur à redimensionner la fenêtre pour rafraîchir le scaling xterm.
useLayout expose un layoutVersion bumpé à chaque commit d'arbre (chargement
initial inclus), relayé par LayoutGrid comme refitSignal à chaque
TerminalView survivant pour déclencher fit.fit() sans rouvrir le PTY.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 09:41:39 +02:00
406 changed files with 39616 additions and 15402 deletions

12
.gitignore vendored
View File

@ -45,12 +45,19 @@ frontend/coverage/
# Runtime file-protocol orchestration requests/responses — transient I/O, not
# durable project state (curation .ideai §chantier secondaire).
.ideai/requests/
# Ticket store IdeA: l'utilisateur veut conserver l'état local des tickets en
# dehors des branches Git. À ignorer, sinon les changements de branche peuvent
# écraser/supprimer cet état local.
.ideai/tickets/
# 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/).
.ideai/live-state.json
# UI layout runtime state (active layout id + session ids) — machine-local,
# rebuilt at runtime, last-writer-wins — not versioned (same class as live-state.json).
/.ideai/layouts.json
# Permissions MCP locales/outillage: état de runtime propre à la machine et aux
# sessions locales, pas une source de vérité projet.
.ideai/mcp-tool-permissions.json
# ─── Editors / OS ───────────────────────────────────────────────────────────
.idea/
@ -65,3 +72,8 @@ Thumbs.db
# seul .ideai/memory/ est le store durable versionné).
.ideai/conversations/
.ideai/agents.json
.ideai/background-tasks/
# IdeA local runtime state kept outside Git
.ideai/tickets/
.ideai/mcp-tool-permissions.json

93
.ideai/agents/context.md Normal file
View File

@ -0,0 +1,93 @@
# Context — Agent d'assistance légère à faible coût
> Tu es l'**agent Context**. Tu tournes sur un **LLM local, peu puissant**. Ta seule
> raison d'être : **absorber les tâches mécaniques et coûteuses en tokens** que les
> autres agents (Main, Architect, UX, DevBackend, DevFrontend, QA, Git) devraient sinon
> faire eux-mêmes, pour qu'ils atteignent **moins souvent leur limite de tokens** —
> **sans dégrader la qualité de leurs décisions**.
Tu n'es **pas** un agent de décision. Tu ne remplaces aucun rôle du cycle. Tu prépares,
tu extrais, tu résumes — l'agent qui t'a sollicité garde la responsabilité et le dernier
mot sur tout ce qui compte.
---
## 1. Ce que tu fais
Tu réponds à des demandes ponctuelles d'un autre agent (jamais directement de
l'utilisateur, sauf sollicitation explicite). Ton périmètre :
- **Recherche de symboles** : localiser où une fonction/classe/type est définie, où elle
est utilisée, sans que l'agent appelant ait à lire tout l'arbre de fichiers.
- **Résumé de fichier(s)** : compresser un fichier long ou un ensemble de fichiers en un
résumé factuel (structure, responsabilités, points d'entrée) — pas une interprétation
architecturale.
- **Classification d'erreurs de compilation** : trier une sortie de build brute par
catégorie (type, fichier, ligne, nature de l'erreur) pour que l'agent appelant lise un
tableau plutôt que 2000 lignes de log.
- **Extraction des tests en échec** : à partir d'une sortie de test brute, lister les
tests KO avec leur message d'erreur, sans le bruit des tests verts.
- **Résumé de diff** : condenser un `git diff` volumineux en une liste factuelle de
fichiers touchés et de la nature du changement (ajout, suppression, renommage,
ampleur).
- **Repérage de fichiers probablement concernés par un ticket** : à partir d'un texte de
ticket et d'une recherche dans l'arbre du projet, proposer une liste de fichiers
candidats — une piste de départ, pas une garantie.
Tout le reste de la liste d'origine (proposer un message de commit, générer un test
unitaire localisé, mettre à jour une documentation) est **hors périmètre** : ce sont des
artefacts qui engagent une décision (Git pour les commits, QA pour les tests, le
propriétaire du contexte pour la doc). Un modèle local peu puissant qui les produit
directement fait courir un risque de qualité que la vérification par l'agent fort
annulerait de toute façon le gain de tokens visé. Si on te demande l'un de ces trois,
tu peux produire un **brouillon explicitement marqué comme tel**, jamais un livrable.
---
## 2. Ce que tu ne fais jamais
- Tu ne **décides** rien : pas d'architecture, pas de contrat, pas de branche, pas de
verdict de test, pas de conception UI.
- Tu ne **corriges pas de code de production**.
- Tu ne **remplaces pas la vérification** : si une sortie doit être prouvée vraie (tests
QA, verdict de build), c'est l'agent propriétaire qui l'exécute et la lit, pas toi.
- Tu ne **inventes pas** quand l'information te manque. Un modèle local faible qui
complète par extrapolation produit un faux gain : ça coûte plus cher en correction
après coup qu'en tokens économisés avant. **Dis "non trouvé" ou "incertain"
explicitement plutôt que de deviner.**
- Tu ne gères aucun ticket, tu n'appelles pas d'outil de remise de résultat : tu réponds
normalement en fin de tour, la réponse finale est capturée par IdeA.
---
## 3. Comment produire une réponse utile (vu ta faiblesse de modèle)
Ta valeur vient de la **compression fiable**, pas de l'intelligence. Pour rester fiable :
- **Cite ce que tu as effectivement vu** (chemins de fichiers, numéros de ligne, extraits
courts) plutôt que de reformuler de mémoire. Une réponse vérifiable vaut mieux qu'une
réponse fluide.
- **Format court, structuré, sans prose.** Liste à puces, tableau, ou bloc de citations —
jamais un paragraphe d'analyse. L'agent qui te lit doit pouvoir consommer ta réponse en
quelques secondes.
- **Un scope explicite dans chaque réponse** : dis ce que tu as couvert (quels fichiers,
quelle partie du log) et ce que tu n'as pas couvert, si la demande dépassait ce que tu
as pu lire.
- **N'ajoute pas de jugement de valeur ni de recommandation** — "ce fichier semble mal
conçu", "cette erreur est grave" sont des avis qui n'appartiennent pas à ton rôle et
que ta faiblesse de modèle ne te permet pas de fonder correctement.
- **Reste bref.** Le but est d'économiser des tokens à l'agent appelant, pas de produire
un rapport plus long que le log d'origine.
---
## 4. Délégation & collaboration
- Tu es sollicité par Main ou par un autre agent via l'orchestration IdeA. Traite la
demande et termine ton tour avec ta réponse normale — pas de protocole de ticket.
- Si la demande sort clairement de ton périmètre (une décision, un arbitrage, un
jugement de qualité), dis-le et renvoie vers l'agent propriétaire au lieu d'improviser
une réponse hors sujet.
- Si tu n'es pas sûr d'un résultat (symbole non trouvé, fichier candidat incertain), dis
la limite plutôt que de la masquer — un agent fort qui reçoit une fausse certitude perd
plus de tokens à la détecter que si tu avais été transparent.

0
.ideai/agents/glm.md Normal file
View File

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,363 @@
{
"version": 1,
"projectDefault": {
"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_run_in_background",
"idea_launch_agent",
"idea_stop_agent",
"idea_update_context",
"idea_context_propose",
"idea_memory_write",
"idea_workstate_set",
"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_create_skill"
]
},
"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",
"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": "af7f86da-76bc-48e1-9900-71f45a624800",
"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": "aefdbd61-e3d4-4bc1-9f42-c259446a97b5",
"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": "cd0b4cf1-1bef-4fae-ade5-f0a6b49bbaf5",
"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": "c3e0d9d8-df36-4b00-b271-62d8aa78892c",
"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": "5d07e4a7-8676-4a71-aea1-5b64caefa944",
"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": "30bf7e5f-5681-478d-813c-ac4c3957897f",
"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"
]
}
}
]
}

View File

@ -65,3 +65,12 @@
- [web-client-is-single-column-no-desktop-shell](web-client-is-single-column-no-desktop-shell.md) — memory note web-client-is-single-column-no-desktop-shell
- [sandbox-eperm-bind-false-green-web-server](sandbox-eperm-bind-false-green-web-server.md) — memory note sandbox-eperm-bind-false-green-web-server
- [ticket74-f1-web-bundle-transport-seam](ticket74-f1-web-bundle-transport-seam.md) — Deux artefacts Vite (dist/dist-web), mode `web` portable Windows, et le câblage anti-divergence de la constante de transport.
- [ticket43-backend-b1-b4-qa-validation](ticket43-backend-b1-b4-qa-validation.md) — memory note ticket43-backend-b1-b4-qa-validation
- [ticket43-plugin-system-final-qa-verdict](ticket43-plugin-system-final-qa-verdict.md) — memory note ticket43-plugin-system-final-qa-verdict
- [ticket101-cross-talk-multi-project-rootcause](ticket101-cross-talk-multi-project-rootcause.md) — memory note ticket101-cross-talk-multi-project-rootcause
- [ticket103-network-permission-ux-surface](ticket103-network-permission-ux-surface.md) — Stable UX convention for agent network permissions in IdeA.
- [codex-network-access-config-fix](codex-network-access-config-fix.md) — memory note codex-network-access-config-fix
- [multi-profile-codex-claude-model-catalogue-scoping](multi-profile-codex-claude-model-catalogue-scoping.md) — memory note multi-profile-codex-claude-model-catalogue-scoping
- [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
- [ux-ai-profiles-opencode-persistence-list-coherence](ux-ai-profiles-opencode-persistence-list-coherence.md) — memory note ux-ai-profiles-opencode-persistence-list-coherence

View File

@ -6,7 +6,7 @@ metadata:
---
---
name: appimage-build-no-strip-relr-dyn-fix
description: Le build AppImage échoue sur cette machine (CachyOS/Arch) à l'étape linuxdeploy/strip (.relr.dyn) ; correctif = NO_STRIP=true. Explique probablement les "builds qui ne produisent rien".
description: Le build AppImage échoue sur cette machine (CachyOS/Arch) à l'étape linuxdeploy/strip (.relr.dyn) ; correctif = NO_STRIP=true. Séquence de build mise à jour après #74 (beforeBuildCommand = build:bundle).
metadata:
type: reference
---
@ -30,7 +30,7 @@ section ELF moderne `.relr.dyn` (relocations `DT_RELR`, `unknown type [0x13]`) p
libs système GTK/glibc de CachyOS/Arch (rolling). Le plugin `gtk` de linuxdeploy strip ces libs
→ échec → tout le bundling casse.
## Correctif VALIDÉ (2026-07-02)
## Correctif VALIDÉ (2026-07-02, toujours valable 2026-07-17)
Lancer le build avec `NO_STRIP=true` (le binaire release est déjà strippé par cargo) :
```
cd crates/app-tauri
@ -38,15 +38,40 @@ NO_STRIP=true ../../frontend/node_modules/.bin/tauri build --bundles appimage
```
Résultat : `Finished 1 bundle at target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage`.
## Séquence de build complète (rappel, pas de beforeBuildCommand dans tauri.conf.json)
1. `npm --prefix frontend run build` (produit `frontend/dist`).
2. depuis `crates/app-tauri` : `NO_STRIP=true <cli tauri> build --bundles appimage`.
CLI tauri = `frontend/node_modules/.bin/tauri` (@tauri-apps/cli). Config = crates/app-tauri/tauri.conf.json.
## Séquence de build — MISE À JOUR après #74 (2026-07-17)
**Attention : l'ancienne version de cette note disait « pas de beforeBuildCommand dans
tauri.conf.json » et imposait un `npm run build` manuel préalable. C'est FAUX depuis #74.**
`crates/app-tauri/tauri.conf.json` a maintenant :
- `build.beforeBuildCommand: "npm --prefix ../frontend run build:bundle"`
- `bundle.resources: { "../../frontend/dist-web": "web" }`
et `frontend/package.json` définit :
```
"build:bundle": "npm run typecheck && vite build --outDir dist --emptyOutDir && vite build --mode web --outDir dist-web --emptyOutDir"
```
Donc **une seule commande suffit**, le frontend est construit automatiquement (les DEUX bundles) :
```
cd crates/app-tauri
NO_STRIP=true ../../frontend/node_modules/.bin/tauri build --bundles appimage
```
`build:bundle` produit **deux** bundles distincts, et c'est le cœur du fix #74 :
- `frontend/dist` → bundle **desktop**, transport `tauri` (= `build.frontendDist`).
- `frontend/dist-web` → bundle **web**, transport `http` (= packagé en ressource `web/`).
Un seul `dist` ne peut pas servir les deux : le transport est figé **au build** par Vite
(`resolveTransport()` lit `import.meta.env.VITE_TRANSPORT`, constant-folded). C'est ce qui
causait `__TAURI_INTERNALS__ is undefined` dans le navigateur (#74).
Garde-fou : `npm run test:bundle-transport` vérifie que `dist` = tauri et `dist-web` = http.
Le lancer après un build si un doute subsiste sur ce qui est servi au navigateur.
## Implication produit
C'est très probablement la vraie cause des « builds AppImage qui ne produisent rien / attente
sans résultat » signalés par l'utilisateur. À intégrer idéalement dans le flux de build d'IdeA
(passer NO_STRIP quand on cible AppImage sur Arch, ou vendoriser un linuxdeploy récent).
Lien : [[mcp-bridge-and-delegation-runtime-notes]],
[[checkpoint-b2-bootstrap-applied-await-codex-reset-1430]].
Lien : [[mcp-bridge-and-delegation-runtime-notes]] (le binaire qui tourne = AppImage, pas les
sources — rebuild obligatoire pour tester un changement backend live).

View File

@ -0,0 +1,41 @@
---
name: codex-network-access-config-fix
description: memory note codex-network-access-config-fix
metadata:
type: project
---
# Correctif accès réseau Codex via `sandbox_workspace_write.network_access`
Le 2026-07-26, le diagnostic live a montré qu'un agent Codex lancé par IdeA échouait sur `curl` même avec IP forcée. La cause n'était pas seulement DNS ni une session à relancer : Codex CLI 0.145 attend la configuration officielle `sandbox_workspace_write.network_access=true` pour autoriser le réseau dans `workspace-write`.
Correctif implémenté et validé par QA dans les sources :
- Projection Codex `$CODEX_HOME/config.toml` : gérer `[sandbox_workspace_write] network_access = true/false` via `MergeToml`, pour éviter un stale `true`.
- `codex exec` structuré : passer `-c sandbox_workspace_write.network_access=<bool>` quand la policy est connue.
- La permission système IdeA reste séparée des permissions fichiers/bash : seul `NetworkPolicy::Allow` active `network_access=true`; `Deny`, `Ask` et `None` donnent `false`.
- L'env `CODEX_SANDBOX_NETWORK_DISABLED` est encore upserté comme garde anti-héritage stale, mais ce n'est plus le mécanisme principal.
Fichiers principaux :
- `crates/infrastructure/src/permission/codex.rs`
- `crates/domain/src/ports.rs`
- `crates/application/src/agent/lifecycle.rs`
- `crates/infrastructure/src/session/codex.rs`
- `crates/application/src/ticket_assistant.rs`
Validation QA verte :
- `cargo test -p infrastructure permission::codex`
- `cargo test -p infrastructure codex_`
- `cargo test -p application --test agent_lifecycle codex_`
- `cargo test -p application --test ticket_assistant codex_`
- `cargo test -p domain`
Build réalisé :
- `npm --prefix frontend run build` : vert.
- `tauri build --bundles appimage` : compilation release OK, mais bundling linuxdeploy a échoué car `appimagetool` tentait de télécharger le runtime sans réseau.
- Contournement appliqué : `appimagetool --runtime-file /home/anthony/.cache/tauri/runtime-x86_64 ...`.
- AppImage générée : `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage`, SHA-256 `08d74dfe950312f968f3fe5646d747f2ac6fa25f2a523a83825182f2809e2aa8`.
Validation live restante obligatoire : relancer IdeA depuis cette nouvelle AppImage, lancer un agent Codex frais avec `network: allow`, puis exécuter un vrai `curl`. La session Codex déjà active ne peut pas prouver le fix car elle a été lancée avant ces nouveaux arguments/config.

View File

@ -0,0 +1,59 @@
---
name: context-agent-token-offload-design
description: memory note context-agent-token-offload-design
metadata:
type: project
---
# Agent Context — allègement token, périmètre figé
Décision validée le 2026-07-23 : un nouvel agent **Context**, tournant sur un **LLM local peu
puissant**, a été ajouté au projet IdeA pour réduire la fréquence des limites de tokens atteintes
par les autres agents (Main, Architect, UX, DevBackend, DevFrontend, QA, Git) — **sans dégrader
la qualité de leurs décisions**.
## Périmètre retenu (mécanique, faible risque)
- Recherche de symboles (localisation définition/usage).
- Résumé de fichier(s) — factuel, pas d'interprétation architecturale.
- Classification d'erreurs de compilation (tri d'un log brut).
- Extraction des tests en échec (à partir d'une sortie de test brute).
- Résumé de diff (`git diff` volumineux → liste factuelle de fichiers/nature de changement).
- Repérage de fichiers probablement concernés par un ticket (piste, pas garantie).
## Explicitement exclu / dégradé en brouillon uniquement
Proposer un message de commit, générer un test unitaire, mettre à jour une documentation qui fait
foi : ce sont des artefacts qui engagent une décision et qui appartiennent aux agents propriétaires
(Git pour les commits, QA pour les tests). Un modèle local faible qui les produit comme livrable
ferait courir un risque de qualité que la vérification par l'agent fort annulerait de toute façon
le gain de tokens visé. Context peut produire un brouillon explicitement marqué comme tel, jamais
un livrable.
## Garde-fous de fiabilité (vu la faiblesse du modèle)
Context ne décide rien, ne corrige pas de code de production, ne remplace jamais une vérification
qui doit être prouvée (tests QA, verdict de build), et ne devine jamais quand l'information manque
— il doit dire "non trouvé"/"incertain" plutôt qu'extrapoler. Réponses courtes, structurées,
citant ce qui a été effectivement vu (chemins, lignes), sans jugement de valeur.
## Où c'est câblé
- Contexte agent : `.ideai/agents/context.md` (écrit via `idea_update_context`).
- Template global IdeA créé : « Context — Agent d'assistance légère à faible coût »
(`defaultProfileId` = profil LLM local de l'agent Context), pour réutilisation cross-projet.
Le template ne contient que la partie générique (aucune référence à IdeA le produit) ;
la déclaration des 7 autres rôles nommés reste project-spécifique et vit dans
`.ideai/agents/context.md` du projet, pas dans le template.
- Rôle ajouté à la liste des rôles du contexte projet global (CLAUDE.md §3) : Context ne fait
**pas** partie du cycle obligatoire (§4) — pas d'étape qui lui est dédiée, il est sollicité en
support ponctuel par n'importe quel agent.
- Chaque agent (Main, Architect, DevBackend, DevFrontend, QA, Git, UX) a reçu un ajout court dans
sa section « Délégation & collaboration » expliquant quand solliciter Context et rappelant que
son résultat est une piste à vérifier, jamais une conclusion ou une décision.
## Pourquoi
Voir [[idea-product-directives-main-handoff]] pour les directives produit générales ; cette note
couvre spécifiquement le compromis coût-tokens/qualité qui a motivé le périmètre volontairement
restreint de Context (pas de délégation de jugement, seulement de compression/extraction
factuelle).

View File

@ -0,0 +1,25 @@
---
name: model-catalogue-compat-cadrage
description: 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.
metadata:
type: reference
---
Évolution de `ListClaudeModels`/`ListCodexModels` (catalogue statique `application/src/agent/model_catalogue.rs`) vers un catalogue enrichi par compatibilité CLI.
**Décisions tranchées :**
- JAMAIS scraper les TUI `/model`, JAMAIS exécuter les CLIs pour énumérer les modèles. Seule exécution CLI autorisée : `<cli> --version` (pattern existant `infrastructure/runtime::detection_spec` + port `ProcessSpawner`). Saisie libre toujours ouverte.
- 3 sources non bloquantes à dégradation indépendante : API provider `/v1/models` (best-effort, uniquement si clé env/SecretStore présente, sinon skip), catalogue statique seed, matrice de compat.
**Hexagonal :**
- Domaine (pur) : VO `CliVersion` (Ord), enum `ModelCompatibility {Compatible|Unknown|LikelyTooRecent}` (miroir des 3 états produit), VO `CompatibilityMatrix` (forme seule), fonction pure `evaluate_compatibility(matrix, adapter, model_id, Option<CliVersion>)` — version None ⇒ Unknown, modèle absent ⇒ Unknown, min<=ver ⇒ Compatible, min>ver ⇒ LikelyTooRecent.
- Nouveaux ports : `CliVersionReader`, `ProviderModelCatalogue` (Ok(vec![]) si pas de clé), `CompatibilityMatrixSource` (infaillible).
- Application : use case unique `ResolveModelCatalogue{adapter}` async, jamais de hard-error sur échec source (warnings + fallback). `ListClaude/CodexModels` deviennent des façades.
- Infra : `ProcessCliVersionReader`, `HttpProviderModelCatalogue` (reqwest), `EmbeddedCompatibilityMatrix`.
**Matrice de compat = DONNÉE, pas code** : JSON versionné maintenu dans IdeA, bundlé via `include_str!` (seed infaillible) + override optionnel `app_data_dir/IdeA/model-compat.json`. Ajouter un modèle = éditer le JSON, zéro code (Open/Closed).
**DTO (rupture front)** : `ProfileModelCatalogDto` passe de `transparent Vec` à `{ models:[{...,compatibility,source}], cliVersion:string|null, warnings:string[] }`. Répercuter ports TS + 2 adapters + mock + ProfilesSettings.
**Découpage** : B1 domaine pur, B2 use case ports mockés, B3 infra ; F1 contrat, F2 ProfilesSettings 3 badges. UX passe avant F2 (libellés des 3 états, warnings, cliVersion null).
**Point ouvert produit** : récup clé provider — proposé best-effort sur clé env/SecretStore existante, pas de prompt dédié.

View File

@ -0,0 +1,50 @@
---
name: multi-profile-codex-claude-model-catalogue-scoping
description: memory note multi-profile-codex-claude-model-catalogue-scoping
metadata:
type: project
---
# Cadrage : profils multiples Codex/Claude + catalogue de modèles
Demande utilisateur : plusieurs profils Codex et Claude, chacun avec son modèle, assignables aux
agents ; lister les modèles plutôt que saisie manuelle quand possible.
## État vérifié de l'existant (2026-07-26)
Le backend est déjà générique multi-profils, contrairement à ce qu'on pourrait croire à la lecture
seule des mémoires F35/F36 (qui documentaient le cas OpenCode) :
- `AgentProfile` (crates/domain/src/profile.rs) porte déjà `model: Option<String>` (ticket #99,
explicitement prévu pour Codex/Claude), et `profiles.json` (FsProfileStore) est une **liste**
indexée par `id`, pas un slot singleton par provider.
- Commandes déjà câblées : `list_profiles`, `save_profile` (upsert générique par id),
`delete_profile`, `reference_profiles`, `detect_profiles`.
- Ce qui existe **seulement pour OpenCode** : `clone_opencode_profile_from_seed` (alloue un id
frais via IdGenerator) et `save_opencode_provider_profile`, plus un vrai catalogue de modèles
(`crates/application/src/agent/provider_catalogue.rs`, lit le cache models.dev d'OpenCode avec
repli statique).
- `catalogue.rs` : un seul profil de référence Claude et un seul Codex, aucun `.with_model(...)`.
- Frontend `ProfilesSettings.tsx` : simple list+delete, pas de create/duplicate/edit inline ;
toute édition rouvre `FirstRunWizard`.
## Gaps identifiés (pas de migration de schéma nécessaire)
1. Backend : généraliser le pattern `CloneOpenCodeProfileFromSeed` (fresh_profile_id via
IdGenerator) en un use case `CloneProfileFromSeed` non spécifique à OpenCode, pour dupliquer un
profil Claude/Codex avec un nom + `model` en override. Ne PAS laisser le frontend miner l'id
(romprait la discipline IdGenerator déjà en place).
2. Backend : catalogue de modèles Claude/Codex — aucune API fiable côté CLI, donc liste statique
curée (même esprit que `static_fallback_catalogue()` d'OpenCode), exposée par commande Tauri
infaillible (`list_claude_models`/`list_codex_models` ou générique par `structuredAdapter`).
Le frontend garde toujours un champ de saisie manuelle en repli (liste jamais garantie
exhaustive).
3. Frontend : refonte `ProfilesSettings.tsx` en onglets Codex/Claude/OpenCode avec
create/duplicate/edit/delete par onglet + `ModelSelect` searchable partagé ; simplifier
`FirstRunWizard` pour ne créer qu'un profil par défaut par provider détecté, avec renvoi vers
Settings pour en ajouter d'autres.
## Découpage de livraison
DevBackend (use case + catalogues + commandes, petit lot, zéro migration) → DevFrontend (refonte
Settings + first-run simplifié) → QA (créer 2 profils Claude modèles différents + 2 Codex, assigner
à des agents distincts, vérifier le bon modèle atteint la CLI au lancement, non-régression
OpenCode) → Git (branche feature unique, lot petit et couplé).

View File

@ -0,0 +1,67 @@
---
name: ticket101-cross-talk-multi-project-rootcause
description: memory note ticket101-cross-talk-multi-project-rootcause
metadata:
type: project
---
---
slug: ticket101-cross-talk-multi-project-rootcause
title: "Ticket #101 — défaut d'isolation multi-projet (registres runtime globaux par AgentId)"
type: reference
description: Cause racine du cross-talk entre projets ouverts simultanément (branche hybride wear-os + notification de tâche backend perdue) : les stores disque IdeA sont scoppés par projet, mais plusieurs registres mémoire runtime critiques restent indexés par AgentId seul, sans re-mint des UUID à l'ouverture. Plan de correction figé en 6 lots (clé RuntimeAgentKey).
---
# Ticket #101 — défaut d'isolation multi-projet (cause racine)
## Symptômes (2 manifestations, même défaut)
- **A — contamination du contexte d'inférence** : un agent a créé une pseudo-branche `feature/ticket91-wear-os-watch-sync` (ticket #91 purement front) où le suffixe `wear-os-watch-sync` appartient à l'AUTRE projet de l'utilisateur. Le nom n'apparaît dans aucun fichier `.ideai/` du projet IdeA → contamination au niveau du contexte d'inférence runtime (conversation injectée à l'agent Git mélangeait les projets). Preuve topo préservée : `main` divergé de `develop` (da907b8 vs 6a87c46), `feature/ticket99-agent-model-configuration` créée depuis main au lieu de develop.
- **B — notification de tâche backend perdue / agent qui s'arrête** (sujet original #101) : un agent OpenCode lance `idea_run_in_background` puis s'arrête, sans retour de notification garanti.
## Cause racine (Architect, 2026-07-25)
Stores disque **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). MAIS les agents **ne re-mint pas leurs UUID à l'ouverture** → deux projets (surtout si l'un est une copie) peuvent porter les **mêmes `AgentId`**.
Plusieurs **registres mémoire runtime restent globaux, indexés par `AgentId` seul** :
- 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`.
- Sessions PTY/structured retrouvées par `agent_id` seul — `crates/application/src/terminal/registry.rs:182,437` ; réutilisation session `service.rs:2293,2368`.
- Verrous ask, busy-state, liveness, délégations différées par `AgentId` seul — `service.rs:418`, `crates/infrastructure/src/input/mod.rs:47`.
- Inbox/mailbox par `AgentId` seul — `crates/domain/src/inbox.rs:68,156`, `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`.
→ Un agent du projet courant peut se rattacher à la conversation/session/inbox d'un autre projet (collision d'UUID) : contamination d'inférence (A) ET complétion livrable/bloquée/réveillant la mauvaise session (B).
## Pour B : 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.** Le modèle GLM 5.2 n'est l'hypothèse principale que si les logs prouvent (pour le bon `project_id`) : enqueue + wake + `BackgroundTaskCompletionDelivered` émis sans reprise utile. Traces : `lib.rs:2238`, `wake.rs:93`.
## Plan de correction (6 lots, figé)
1. Introduire `RuntimeAgentKey { project_id, agent_id }` ; interdire toute map app-wide indexée par `AgentId` seul.
2. Propager la clé dans `AgentInbox`, `InputMediator`, `AgentMailbox`, busy/liveness/deferred, wake, session lookup, ask-locks. **Correctif structurel commun à A et B.**
3. Qualifier les conversations par projet : `ConversationId` + `ConversationRegistry` intègrent `ProjectId`.
4. Requalifier `TerminalSessions`/`StructuredSessions` par `(project_id, agent_id)` ; `AppWakeSessionProvider` refuse toute session vivante d'un autre projet.
5. Audit des autres états mémoire similaires (`session_limit`, tables de reprise/verrous par agent) pour éviter une demi-correction.
6. Télémétrie `project_id` explicite sur les logs diag critiques de wake/routage.
## Invariants
- Sources de contexte sur disque restent root-scopées (ne pas régresser).
- Templates/profils globaux restent globaux produit — ne doivent pas devenir vecteurs 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 simultanément contenant **volontairement les mêmes `AgentId`** :
- délégation dans projet A ne réutilise jamais une session/conversation vivante de projet B ;
- complétion `(project A, agent X)` n'entre ni dans l'inbox ni dans la session de `(project B, agent X)` ;
- le wake d'un projet non-actif fonctionne quand même ;
- une collision d'ids qui échouait avant devient verte sur PTY, structured et background wake.
## Hors périmètre
- #91 (popup de notification) : purement front, indépendant du défaut runtime.
- Remint systématique des AgentId à l'ouverture : piste complémentaire non retenue dans le fix minimal (la clé runtime scellée par projet rend la collision inoffensive même sans remint).
## Topologie
- Branche de travail à créer pour le fix (Git décidera). Base `develop` (6a87c46). `main`/`feature/ticket99-agent-model-configuration` divergent sur da907b8 (preuves préservées, à nettoyer après enquête).
## Lié
- #91 (relatesTo) : popup de notification — front pur.
- Mémoire `background-tasks-first-class-design` + `b8-command-runner-pty-framing` : design du flux de complétion (le défaut est en aval du sink).
- Mémoire `mcp-bridge-and-delegation-runtime-notes` : règle rebuild AppImage (le binaire qui tourne = AppImage, pas les sources).

View File

@ -0,0 +1,10 @@
---
name: ticket103-network-permission-ux-surface
description: Stable UX convention for agent network permissions in IdeA.
metadata:
type: reference
---
- Editability must follow the resolved control state, not simply whether an agent exists.
- Non-launched agents stay editable unless a runtime lock is explicitly present.
- Read-only messaging should be explicit only for active locked runtimes, especially external/uninspectable runtimes.
- Effective policy labels must not be used as a proxy for editability.

View File

@ -0,0 +1,54 @@
---
name: ticket43-backend-b1-b4-qa-validation
description: memory note ticket43-backend-b1-b4-qa-validation
metadata:
type: project
---
---
title: Validation QA backend B1-B4 du système de plugins #43
type: reference
description: Verdict QA du périmètre backend plugin B1-B4 sur feature/ticket43-plugin-system, tests ajoutés et limites sandbox constatées.
---
# Validation QA backend B1-B4 du système de plugins #43
Sur `feature/ticket43-plugin-system`, QA a validé le périmètre backend B1-B4 sans modifier le frontend.
Tests/ajustements QA ajoutés :
- `crates/domain/tests/layout.rs` : les helpers de tests existants ignorent explicitement `LayoutNode::CustomPluginLayout(_)`, ce qui rétablit l'exhaustivité de compilation des tests domaine après l'ajout du layout plugin custom.
- `crates/application/src/plugin/mod.rs` : tests in-memory des ports plugin pour vérifier :
- catalogue runtime vide pour `Disabled`, `PendingUninstall`, `Invalid` ;
- réconciliation MCP limitée aux plugins enabled + serveurs `autoStart`, identité `plugin:<pluginId>:<serverId>` et résolution sous `pluginRoot` ;
- disable stoppe le MCP, publie `PluginDisabled`, retire le plugin du runtime catalog ;
- uninstall stoppe le MCP, retire registry + package et publie `PluginUninstalled`.
Commandes vertes constatées :
```text
cargo test -p application plugin --offline --no-fail-fast
# 7 passed; 0 failed
cargo test -p domain -p application -p infrastructure -p backend -p app-tauri plugin --offline --no-fail-fast
# plugin-filtered targeted suite green; application 7 plugin tests, domain 3 plugin tests,
# serde roundtrip custom plugin layout, infrastructure 3 plugin tests, dto plugin filtered test all ok.
cargo test -p app-tauri --test dto_plugins --offline --no-fail-fast
# 2 passed; 0 failed
cargo fmt --check
# OK
```
Workspace complet :
```text
cargo test --workspace --offline --no-fail-fast -- --test-threads=1
```
Résultat KO attendu dans ce sandbox, hors périmètre plugin :
- `-p infrastructure --lib` : 10 échecs `session::openai_compat::*` sur `bind: Os { code: 1, kind: PermissionDenied, message: "Operation not permitted" }`.
- `-p web-server --lib` : 2 échecs de bind `127.0.0.1:0 Operation not permitted` et 5 scénarios websocket/terminal recevant `error` au lieu de `terminal.attached`, cohérents avec restrictions loopback/PTY du sandbox.
Verdict : backend plugins B1-B4 validé QA avec réserve uniquement environnementale sur le workspace global.

View File

@ -0,0 +1,52 @@
---
name: ticket43-plugin-system-final-qa-verdict
description: memory note ticket43-plugin-system-final-qa-verdict
metadata:
type: project
---
---
title: Verdict QA final du ticket #43 système de plugins
type: reference
description: Validation finale QA de #43 après carnet v5, corrections F4/F3/B4 et exécutions réelles backend/frontend.
---
# Verdict QA final du ticket #43 système de plugins
Branche validée : `feature/ticket43-plugin-system`.
Contexte : après verdict QA orange initial, Architect a figé le carnet v5 : `customPluginLayout` top-level canonique, `gitRepository` obligatoire en F3, `${appDataDir}` obligatoire en B4, et `agentSelected`/`terminalFocused`/`layoutCellFocused` + persistance backend state layout plugin acceptés comme dette v1.
Résultats réels exécutés par QA :
```text
cargo test -p domain -p application -p infrastructure -p backend -p app-tauri plugin --offline --no-fail-fast
# OK
# application plugin: 9 passed
# domain plugin: 3 passed
# infrastructure plugin: 5 passed
# custom_plugin_layout_roundtrips_with_opaque_state: ok
cd frontend && npm run typecheck
# exit 0
cd frontend && npm test -- --run
# Test Files 104 passed (104)
# Tests 947 passed (947)
```
Contrôles ciblés confirmés :
- Frontend `LayoutNode` inclut `{ type: "customPluginLayout"; node: CustomPluginLayoutCell }` top-level, sans contrat `LeafCell.pluginLayout`.
- `LayoutGrid` route `customPluginLayout` vers `PluginLayoutCellView`.
- `onStateChange`, `onOpenPlugins`, `onChooseAnotherLayout` sont câblés in-session (`setPluginLayoutState`, navigation settings plugins, remplacement par terminal).
- `ProjectsView` câble `gitRepository` via `GitGateway.branches(active.id)` ; `agentSelected`, `terminalFocused`, `layoutCellFocused` restent explicitement `false` en dette v1.
- Backend application substitue `${pluginRoot}` et `${appDataDir}` dans command/args/env/cwd des specs MCP plugin, avec test `reconcile_mcp_substitutes_app_data_dir_in_plugin_server_specs`.
Verdict QA : VERT pour merge local du ticket #43.
Dette v1 assumée :
- `agentSelected`, `terminalFocused`, `layoutCellFocused` non câblés, figés à `false` jusqu'à un lot focus/selection dédié.
- Persistance backend du `state` de layout plugin non implémentée ; F4 validé en in-session selon arbitrage Architect.
Aucun nouveau blocage détecté dans les suites demandées.

View File

@ -0,0 +1,31 @@
---
name: ticket95-adapter-aware-liveness-probe
description: memory note ticket95-adapter-aware-liveness-probe
metadata:
type: project
---
# #95 — Sonde de vivacité du rendez-vous devenue adapter-consciente
**Type :** correctif architecture / bug racine. Livré sur `feature/rendezvous-liveness-probe-per-adapter` (commit 376fc9f), AppImage 0.3.0 rebuildée.
## Bug racine
Le rendez-vous `idea_ask_agent` (`run_inactivity_watchdog`, `crates/application/src/orchestrator/rendezvous.rs`) coupe en **faux `NoReply`** toute cible **structurée** dont le tour dépasse la fenêtre d'inactivité (défaut 600 s, = `turn_timeout_ms` du profil cible). Cause : la seule sonde de vivacité (`transcript_activity_token`) lisait le transcript Claude (`~/.claude/projects/<encoded-cwd>/*.jsonl`) — invisible pour OpenCode/Codex, et fragilise même Claude en mode `-p` headless si le transcript ne grossit pas mi-tour. `has_probe=true` mais la sonde renvoie `None` ⇒ bras `(true,_,None)=>false` ⇒ aucun réarmement ⇒ NoReply à la première fenêtre.
## Fix (architecture figée)
1. **Port domaine** (`crates/domain/src/ports.rs`) : `AgentSession::activity_token() -> Option<u64>` (défaut `None`, zéro régression). Jeton monotone = « la session travaille ».
2. **Machinerie** (`crates/infrastructure/src/session/process.rs`) : `run_turn_with_activity(...)` bump un `Arc<AtomicU64>` à **chaque ligne stdout lue** (drain async ET drain sandboxé thread). `run_turn` (4 args) délègue avec `None` ⇒ les ~11 call sites de test sont intacts.
3. **Sessions** : `ClaudeSdkSession`, `CodexExecSession`, `OpenAiCompatibleSession` overrident `activity_token()` via `run_turn_with_activity` ; `OpenCodeSession` (drain inline) bump son propre compteur par ligne JSONL.
4. **Sonde composite** (`resolve_ask_liveness_token`, `crates/backend/src/lib.rs`) : préfère `session.activity_token()` de la session vivante (`structured.session_for_agent`), repli inchangé sur le transcript Claude. Câblée par `.with_ask_liveness_probe`.
## Contrats clés
- `has_probe` reste `true` dès qu'une sonde est câblée ; la sonde composite renvoie désormais `Some(token)` qui avance ⇒ la fenêtre se réarme. Le repli transcript Claude couvre le cas « session vivante sans override ».
- La fenêtre = `turn_timeout_ms` du **profil cible** (`turn_timeout_for``liveness_for_agent`), défaut `ASK_AGENT_TIMEOUT` 600 s. **Pas d'env global pour la fenêtre** (seul le plafond a `IDEA_ASK_RENDEZVOUS_CEILING_MS`, défaut 4 h).
- Pour un test live rapide sans attendre 600 s : mettre un petit `turn_timeout_ms` (ex. 20 000) sur le profil de la cible, puis déléguer une tâche de ~60-90 s.
## État validation
- Tests unitaires verts : `run_turn_with_activity_bumps_counter_per_line`, `*_session_activity_token_advances_across_a_turn` (claude/codex/opencode), + la sonde composite backend + le watchdog rendezvous existants.
- AppImage 0.3.0 rebuildée + installée (`/home/anthony/Documents/IdeA_0.3.0_amd64.AppImage`, backup `.old-pre95fix`). **Relance IdeA requise** pour l'activer (le binaire qui tourne = AppImage en mémoire ; relancer depuis l'intérieur tue la session courante).
## À noter (dette / hors périmètre)
- #96 (EffectivePermissions assistants de ticket) laissé ouvert, documenté dans le carnet #96 (décision produit différée).
- Le souvenir utilisateur initial décrivait un échec « demandeur GLM/OpenCode → cible Claude ». Mécaniquement le watchdog est **ciblé-cible** (keyed sur l'agent cible) : un échec sur cible Claude longue n'est possible que si le transcript Claude `-p` ne grossit pas mi-tour (couvert désormais par l'`activity_token` de ClaudeSdkSession). La théorie principale reste « cible structurée longue non observée → faux NoReply ».

View File

@ -0,0 +1,35 @@
---
name: ticket97-opencode-provider-mutual-exclusion
description: memory note ticket97-opencode-provider-mutual-exclusion
metadata:
type: project
---
# Ticket #97 — Exclusion mutuelle opencode / opencodeProvider (décision Architect)
## Bug
Wizard first-run : profiles.json contient à la fois `opencode` (llamacpp) et `opencodeProvider` (cloud). Lecture priorise `opencode` → llamacpp l'emporte silencieusement.
## Root cause (vérifiée dans le code)
1. `SaveOpenCodeProviderProfile::execute` (`crates/application/src/agent/usecases.rs:364-367`) pose `opencode_provider` sans faire `opencode = None`.
2. Invariant `opencode_backend_is_consistent` (`crates/domain/src/profile.rs:1220`) existe + testé mais **jamais appelé** hors tests (garde morte).
3. Lecture priorise `opencode` : `crates/application/src/agent/lifecycle.rs:2367` + `crates/infrastructure/src/assistant/mod.rs:252`.
## Décisions Architect (validées)
- **Lot** : un seul lot cohérent. Backend = autoritaire (invariant + garde + use case via builder + migration). Frontend = strip de la config inactive au save selon le mode (requis pour les chemins SaveProfile/ConfigureProfiles qui ne portent pas d'intention explicite). Découplés/parallélisables. DevBackend + DevFrontend + QA.
- **Frontière** :
- Domaine : builders `with_opencode` (`profile.rs:1132`) et `with_opencode_provider` (`profile.rs:1140`) doivent imposer l'exclusion mutuelle (chacun efface l'autre). Aujourd'hui ce sont des setters muets = la faille.
- Infrastructure : `FsProfileStore::save` rejette tout profil violant l'invariant → `AppError::Invalid` (c'est ici que le prédicat enfin s'appelle). Défense en profondeur.
- Application : use cases utilisent les builders, jamais la mutation brute de champ.
- Refuser l'ad-hoc `opencode = None` par use case (DRY, 4 chemins d'écriture).
- **DTO** : garder `SaveOpenCodeProviderProfileRequestDto` (`dto.rs:1148`) whole-profile (zéro cassure frontend). Le `opencode` parasite devient inoffensif car le use case reconstruit via builder. Output = profil normalisé, autorité pour le frontend. Corriger aussi SaveProfile (`usecases.rs:269`) et ConfigureProfiles (`usecases.rs:460`).
- **Lecture priorité** : garder `opencode` d'abord (irrelevant post-exclusion), commenter comme fallback défensif.
- **Duplication résolution** (lifecycle.rs:2367 + assistant/mod.rs:252) : dette hexagonale préexistante, NE PAS élargir ce lot. Suivre via un futur `AgentProfile::effective_opencode_backend()` ou générateur partagé.
- **Migration REQUISE** : profils déjà corrompus sur disque portent les deux. Recovery : à la lecture (ou passe de migration), quand les deux présents, dropper `opencode` stale (l'intention est cloud, le bug ne venant que d'une action cloud explicite). Sans cela, #97 ne corrige que les nouveaux profils.
## Sites de résolution (priorité) = exactement 2
- `crates/application/src/agent/lifecycle.rs:2367`
- `crates/infrastructure/src/assistant/mod.rs:252`
Autres accès `.opencode` scoper en mode local, non affectés : `lifecycle.rs:2455-2468`, `model_server.rs:121-127`, `catalogue.rs:244-258`, `usecases.rs:410`.
## Statut
Décision Architect posée. À faire implémenter par DevBackend (domaine builders + garde store + migration + use cases) et DevFrontend (strip au save). QA : tests domaine/store + intégration cloud + scénario migration profils corrompus.

View File

@ -0,0 +1,83 @@
---
name: ticket98-opencode-modelsdev-cache-seed
description: memory note ticket98-opencode-modelsdev-cache-seed
metadata:
type: project
---
---
slug: ticket98-opencode-modelsdev-cache-seed
title: "Ticket #98 — Fix spawn OpenCode : seed du cache models.dev isolé (approche B2)"
type: reference
description: Cadrage figé du fix #98 (modèle écrasé par glm-5.2 au spawn pour provider catalogue cloud ex: zai) : cause racine = asymétrie picker↔spawn, approche B2 = semer best-effort le cache models.dev hôte dans le XDG_CACHE_HOME isolé.
---
# Ticket #98 — Fix spawn OpenCode : seed du cache models.dev isolé
## Symptôme
Wizard profil OpenCode first-run : provider catalogue cloud (ex: zai/ZAI Code) + modèle choisi → après sauvegarde l'agent tourne en `glm-5.2` quel que soit le modèle. Persistance correcte (`profiles.json` conserve `opencodeProvider.model`). `glm-5.2` est le **fallback interne d'OpenCode**, absent du code IdeA.
## Cause racine (confirmée + affinée par Architect)
**Asymétrie picker↔spawn**, pas seulement « pas de bloc models » :
1. **Picker** (`provider_catalogue.rs:79-84,150-153`) : lit le cache models.dev via `opencode_models_cache_path()` qui résout le **vrai** cache hôte (`XDG_CACHE_HOME ?? ~/.cache`). Permet d'afficher zai + ses modèles.
2. **Spawn** (`lifecycle.rs:2386,2400-2407` ; `assistant/mod.rs:272,277-285`) : IdeA **ré-isole** `XDG_CACHE_HOME``.opencode/cache` **vide** sous `run_dir`. OpenCode ne voit plus le cache.
3. **Rendu** (`opencode_provider_config_json`, `lifecycle.rs:2795-2821` / `assistant/mod.rs:446-466`) : pour `config.custom == None` (défaut pour zai), IdeA n'émet que `apiKey` + `model: "zai/<m>"`, **sans** bloc `models`. Correct **uniquement** pour les 3 built-ins hardcodés dans le binaire OpenCode (`anthropic`, `openai`, `openrouter`).
→ OpenCode reçoit `model: "zai/<m>"`, ne reconnaît pas zai comme built-in, ne trouve pas le cache models.dev (isolé vide) → fallback silencieux glm-5.2.
- **Local/custom marchent** : émettent un bloc `models` auto-suffisant (`assistant/mod.rs:364-381`, `:447-460`).
- **3 built-ins marchent** : hardcodés dans OpenCode.
- Bug ne touche **que** les providers connus d'OpenCode *exclusivement via models.dev*.
## Approche figée : **B2 — Semer le cache models.dev isolé depuis le cache hôte**
Après création du `XDG_CACHE_HOME` isolé, copier **best-effort** le fichier cache models.dev hôte (`opencode_models_cache_path()``<isolated_cache>/opencode/models.json`) via le port `FileSystem`. Lecture hôte = `std::fs` (identique au picker) ; écriture dans la home isolée.
**Pourquoi pas les autres :**
- **(A)** Émettre un bloc `models`+`npm`+`baseURL` pour les catalogue → **écartée en v1** : IdeA devrait capturer le bon `npm` AI-SDK par provider depuis models.dev (`@ai-sdk/anthropic` vs `openai-compatible`…) — dupliquerait la connaissance du registry OpenCode (violation OCP), risque de régression built-ins. Gardée en **escalade** si B2 défait par refresh.
- **(B1)** Pointer vers le vrai cache hôte (ne plus isoler) → **écartée** : casse l'isolation en écriture (pollution + race entre sessions).
- **(C)** Bundler une copie statique models.dev dans IdeA → **écartée** : staleness + diverge picker/spawn.
**Auto-cohérence B2** : la précondition du bug (cache hôte présent au picker) garantit la précondition du fix (fichier à copier au spawn). Cache hôte absent → picker ne montre que les 3 built-ins → bug non atteint → fix non requis.
## Contrat figé
### Ports / DTO
- **Aucun nouveau port / entité domaine / DTO modifié.** Réutilise le port `FileSystem` déjà injecté sur le chemin spawn. Lecture source = `std::fs` hôte (mécanisme identique au picker).
- Rendre **publique** `opencode_models_cache_path()` (source de vérité unique — encode le workaround du bug upstream #8235 ; ne **pas** re-dériver).
### Fichiers (périmètre DevBackend)
- `crates/application/src/agent/provider_catalogue.rs` — exposer `opencode_models_cache_path()` en `pub` (ou ajouter `pub fn read_models_dev_cache_bytes() -> Option<Vec<u8>>`).
- `crates/application/src/agent/mod.rs` — re-export.
- `crates/application/src/agent/lifecycle.rs` — branche `apply_mcp_config` (≈2382-2408) : après `create_dir_all` du cache + création `xdg_cache`, semer `<xdg_cache>/opencode/models.json` depuis le cache hôte, best-effort. Branche **commune** opencode + opencodeProvider.
- `crates/infrastructure/src/assistant/mod.rs` — branche miroir (≈268-285) : même appel.
- **Factoriser** : `application::agent::seed_opencode_models_cache(fs: &dyn FileSystem, isolated_cache_dir: &str)` appelée par les deux sites. Partie **pure** testable `seed_from_bytes(fs, dest, src_bytes)` ; wrapper impur `std::fs::read` fin.
### Invariants (stricts)
1. Isolation préservée en **écriture** : HOME, XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_CACHE_HOME restent sous `run_dir`. Aucune var d'env repointée vers l'hôte. Seul le **contenu** du cache isolé est semé (lecture seule).
2. **Best-effort, n'échoue jamais le launch** : source absente/illisible ou erreur FS → pas d'échec du spawn. Symétrique du contrat best-effort existant de `apply_mcp_config` (`lifecycle.rs:2422-2425`). ≠ `resolve_opencode_provider_api_key` (échec dur). Le seed est **mou**.
3. Pas de régression local/custom : `opencode_config_json` (llamacpp) et `opencode_provider_config_json(custom==Some)` **byte-identiques** (rendu non touché ; seed additif orthogonal).
4. Pas de régression built-ins : anthropic/openai/openrouter (`custom==None`, hardcodés) restent fonctionnels.
5. Exclusion mutuelle `opencode` vs `opencodeProvider` (#97) : non touchée.
6. Source de vérité unique du chemin models.dev : `opencode_models_cache_path()` réutilisée.
7. Cohérence picker↔spawn : modèles résolvables au spawn = sur-ensemble de ceux du picker (même fichier source).
### Hors périmètre (ne pas faire ici)
- Résolution providers pour **projets remote (SSH/WSL)** (picker lit déjà le cache hôte — incohérence pré-existante). Fix corrige le cas **local**, ne régresse pas le remote.
- Déduplication du rendu lifecycle↔infra (`opencode_provider_config_json` ×2) — on factorise **uniquement le seeder**.
- Aucune modif UI/wizard.
## QA — 2 couches
1. **Unitaire `application`** (automatisable, déterministe) :
- Partie pure `seed_from_bytes(fs, dest, src_bytes)` : bytes présents → assert `<dest>/opencode/models.json` écrit identique ; `None` → aucun fichier **et** pas d'erreur.
- Non-régression rendu : JSON de `opencode_config_json` et `opencode_provider_config_json(custom==Some/None)` byte-identiques (tests existants `lifecycle.rs:4428+` verts).
- ⇒ Ne prouve **pas** la résolution réelle par OpenCode.
2. **Intégration / réelle-exécution (gated, propriété QA)** : spawn réel d'OpenCode avec profil `zai` (`custom==None`) contre un cache models.dev fixture contenant `zai` ; assert **pas de fallback glm-5.2** (modèle `zai/<choix>` effectivement utilisé). Gater `#[ignore]`/env (clé API + réseau). **C'est ce test qui prouve le bug corrigé.**
## Risque résiduel + escalade
- **Inconnu empirique** : est-ce qu'OpenCode au démarrage tente de **rafraîchir** models.dev (écrase notre copie, ou hang sans réseau) ? `OPENCODE_DISABLE_AUTOUPDATE=1` ne vise que l'auto-update du binaire, pas sûr qu'il couvre le refresh models. **QA doit vérifier** sur le test d'intégration. Si le refresh défait B2 → **escalader vers (A)** : capturer `npm`+`baseURL` réels par provider dans le parseur models.dev et peupler `custom`.
## Topologie
- Branche : `feature/ticket98-opencode-modelsdev-cache-seed` depuis `develop@69e5878` (#97 exclusion mutuelle prérequis y est fusionné : `0f0a76d` + merge `5533073`). `crates/` propre.
- Carnet #98 version 2 = source de vérité du cadrage.
## Lié
- #97 (relatesTo) : exclusion mutuelle provider — prérequis livré.

View File

@ -0,0 +1,51 @@
---
name: tickets-70-100-102-ux-surface-scoping
description: memory note tickets-70-100-102-ux-surface-scoping
metadata:
type: project
---
---
title: Cadrage UX tickets #70 #100 #102 — modèles locaux et bugs terminal
type: design
description: Surface utilisateur attendue pour supprimer les modèles llama.cpp téléchargés, et règle UX pour les bugs de scroll/fit OpenCode qui doivent être corrigés sans nouvelle UI.
---
# Cadrage UX tickets #70 #100 #102
## #70 — Gestion des modèles locaux téléchargés
Ajouter une affordance humaine de suppression des artefacts de modèles téléchargés par les serveurs locaux llama.cpp, dans la surface existante `Local model servers` / configuration OpenCode locale.
Principes visibles :
- La suppression d'un serveur déclaré et la suppression du fichier modèle téléchargé sont deux actions distinctes.
- Une action destructive sur le fichier modèle doit être explicite, confirmée, et impossible pendant un usage actif/téléchargement du même artefact.
- Le libellé doit parler de `modèle téléchargé`, pas de cache interne ou chemin technique en premier niveau.
- Les modèles issus d'un `localPath` utilisateur ne doivent jamais être proposés à la suppression comme s'ils appartenaient à IdeA.
États attendus par serveur :
- Aucun modèle téléchargé connu : aucun bouton de suppression de modèle, ou bouton désactivé avec tooltip `Aucun modèle téléchargé par IdeA`.
- Modèle téléchargé disponible : bouton secondaire/destructif `Supprimer le modèle téléchargé`.
- Téléchargement/préparation en cours : action désactivée, texte `Téléchargement en cours`.
- Serveur/agent utilisant ce modèle : action désactivée, texte `Modèle utilisé par un agent en cours`.
- Suppression en cours : ligne locale occupée, action désactivée, message `Suppression du modèle...`.
- Succès : toast/status non bloquant `Modèle téléchargé supprimé` ; la configuration serveur reste présente.
- Échec : alerte inline `Impossible de supprimer le modèle téléchargé : <raison courte>`.
Confirmation :
- Titre : `Supprimer le modèle téléchargé ?`
- Corps : `Le serveur local restera configuré, mais IdeA devra retélécharger ce modèle au prochain lancement.`
- Si la taille est connue : ajouter `Espace libéré : <taille>.`
- Action principale destructive : `Supprimer le modèle`
- Action secondaire : `Annuler`
## #100 — Scroll OpenCode
Pas de décision UX spécifique. Le comportement attendu est celui d'une cellule terminal native : l'utilisateur peut remonter dans le scrollback OpenCode jusqu'à la limite de rétention disponible, avec molette, trackpad, scrollbar et clavier, sans blocage prématuré propre à OpenCode.
Ne pas ajouter de bouton, message ou mode spécial OpenCode. QA doit valider le comportement visible dans une cellule OpenCode longue.
## #102 — Fit TUI après switch/layout/ajout cellule
Pas de nouvelle surface UX spécifique. Le terminal doit s'afficher correctement automatiquement après switch de projet, switch de layout, ajout/suppression/split/resize de cellules et rattachement d'une session existante.
Ne pas afficher de message demandant à l'utilisateur de redimensionner. Éviter tout flash durable vide/noir ; un voile technique transitoire n'est acceptable que s'il reste très bref et non bloquant.

View File

@ -0,0 +1,53 @@
---
name: toolchain-rust-partage-acces-agents
description: memory note toolchain-rust-partage-acces-agents
metadata:
type: project
---
---
slug: toolchain-rust-partage-acces-agents
title: Accès au toolchain Rust/Tauri partagé pour tous les agents (isolement HOME OpenCode)
type: project
description: Le toolchain Rust stable est déjà installé sur la machine mais invisible aux agents car le profil OpenCode isole HOME. Diagnostic, atténuation par symlink, et chantier durable (injection env au spawn).
---
# Toolchain Rust/Tauri : pourquoi les agents ne compilaient pas, et comment les débloquer
## Symptôme (récurrent)
Tout agent (Main, DevBackend, QA,…) lancé sous un profil OpenCode ne peut PAS compiler le workspace Rust/Tauri :
- `cargo`/`rustc` = shims rustup qui répondent « no default toolchain » / « no installed toolchains ».
- Bloque toute validation backend (cargo check/build/test), fait timeout les délégations lourdes.
## Cause racine
- Le toolchain **stable 1.94.1 est DÉJÀ installé** dans `/home/anthony/.rustup` + `/home/anthony/.cargo` (toolchains + bin).
- MAIS le profil **OpenCode isole `HOME`** vers `.ideai/run/<agent_uuid>/.opencode/`. Donc `~/.rustup` et `~/.cargo` = `.opencode/.rustup` / `.opencode/.cargo`, qui ne contiennent qu'un `settings.toml` + un cache registry partiel → **aucun toolchain**.
- IdeA lui-même ne set **ni** `RUSTUP_HOME` **ni** `CARGO_HOME` (grep vide dans `crates/`). Le point d'extension existe pourtant : `crates/infrastructure/src/session/opencode.rs:237` (`cmd.env(key, value)`) set déjà des env au spawn.
- `target/` est dans le project root (partagé, géré par le lock cargo) → partageable sans conflit.
- `tauri` est dispo via `frontend/node_modules/.bin/tauri` (après `npm install` du frontend).
## Atténuation appliquée (2026-07-25, ops, sans rebuild)
Symlinker les homes isolés vers les homes partagés pour chaque run-dir agent :
```bash
for d in .ideai/run/*/.opencode; do
for sub in .rustup .cargo; do
p="$d/$sub"
[ -e "$p" ] && [ ! -L "$p" ] && { rm -rf "$p"; ln -s "/home/anthony/$sub" "$p"; }
done
done
```
Vérifié sur Main : `cargo 1.94.1` / `rustc 1.94.1` accessibles **sans aucune variable d'env explicite**. Symlink appliqué aux agents actifs (Main a6ced819, DevBackend 73c853d1, QA aefdbd61, …) — 5 run-dirs concernés.
**Tient pour les agents existants** : rustup suit les symlinks, et OpenCode ne recrée pas `$HOME/.rustup` s'il existe déjà.
## Solution DURABLE (chantier IdeA, à livrer)
Pour les **nouveaux** agents (IdeA crée un nouveau run-dir `.ideai/run/<uuid>/.opencode/.rustup` vide), il faut qu'IdeA provisionne l'accès au toolchain partagé automatiquement. Deux options équivalentes, à faire par DevBackend + **rebuild AppImage + relance** :
1. Au spawn de l'agent, injecter `RUSTUP_HOME=/home/anthony/.rustup` et `CARGO_HOME=/home/anthony/.cargo` (point d'extension `opencode.rs:237`). Valeurs résolues depuis le vrai HOME user (pas le HOME isolé), idéalement configurables (env projet / settings).
2. Ou, à la création du run-dir, créer les deux symlinks `.opencode/.rustup` et `.opencode/.cargo` → homes partagés.
Recommandation : option 1 (injection env) — moteur-agnostique (marche aussi pour Codex/Claude si un jour ils isolent aussi) et ne dépend pas du filesystem layout du moteur.
À grouper dans le **même rebuild AppImage** que le fix « sonde de vivacité multi-moteur » (cf. `idea-memory` à venir) — les deux sont des chantiers runtime qui nécessitent rebuild + relance.
## Liens
- Règle rebuild AppImage : `.ideai/skills/md/a72dac60-641c-4417-b0d7-94b8539f817a.md` (skill build AppImage), mémoire `mcp-bridge-and-delegation-runtime-notes`.
- Timeout délégation 600 s (autre symptôme sur les tâches lourdes) : mémoire `rendezvous-600s-cap-too-short-heavy-tasks` + sonde Claude-seule `crates/infrastructure/src/inspector/claude_paths.rs:89`.

View File

@ -0,0 +1,41 @@
---
name: ux-ai-profiles-opencode-persistence-list-coherence
description: memory note ux-ai-profiles-opencode-persistence-list-coherence
metadata:
type: project
---
---
title: UX — Cohérence profils IA/OpenCode entre éditeur et picker agents
type: decision
description: Décisions de surface pour corriger la création de profils OpenCode, la persistance visible après sauvegarde et la cohérence entre Settings > Profils IA et les sélecteurs d'agents.
---
# UX — Profils IA/OpenCode : création, persistance, liste unique
## Décision centrale
La liste visible dans `Settings > Profils IA` et les pickers de profils des agents doit représenter la même collection persistée de profils IA. Les profils de référence ne sont qu'une source d'ajout, pas une deuxième vérité visible.
## Comportement attendu
- Le bouton de création OpenCode s'appelle `Créer un profil OpenCode` dans la surface française.
- Cliquer sur ce bouton ajoute immédiatement une ligne de profil en brouillon, sélectionnée, éditable et clairement marquée non enregistrée tant que la sauvegarde n'a pas réussi.
- Chaque nouveau profil OpenCode doit avoir une identité distincte et un nom humain distinct par défaut, par exemple `OpenCode local 2`; l'utilisateur peut renommer avant sauvegarde.
- `Dupliquer` conserve la configuration du profil source mais crée une nouvelle identité et un nom suffixé, par exemple `(copie)`.
- `Enregistrer` persiste tous les profils sélectionnés/édités, puis recharge la liste depuis la source persistée. La liste affichée après succès doit être le résultat relu, pas seulement l'état local optimiste.
- Après sauvegarde réussie, le profil créé reste visible dans l'éditeur sans réouverture manuelle et apparaît dans le picker de création d'agent et dans le picker de changement de profil d'un agent existant.
- Les profils OpenCode ne doivent jamais être fusionnés/dédupliqués par commande, modèle, endpoint ou adapter. La déduplication visible se fait uniquement par `id`.
- En mode édition, les profils déjà configurés apparaissent en premier, pré-sélectionnés, avec leur configuration réelle intacte. Les profils de référence non configurés peuvent suivre comme suggestions non sélectionnées.
- Si un profil référencé par un agent n'existe plus dans la liste persistée, le picker de l'agent conserve l'id courant comme option orpheline lisible, sans le mélanger aux profils disponibles.
## États et feedback
- Pendant la création/clonage : bouton désactivé ou loading local, sans bloquer la détection CLI.
- Ligne brouillon : indicateur discret `Non enregistré` ou état visuel équivalent.
- Sauvegarde réussie : statut court `Profils enregistrés` puis disparition automatique.
- Échec sauvegarde : message d'erreur persistant, la ligne brouillon reste éditable et n'est pas perdue.
- Picker agents vide : ne pas encourager la saisie libre d'id comme chemin normal. Afficher plutôt un état vide actionnable vers `Profils IA`.
## Critères d'acceptation visuels
- Créer un profil OpenCode, sauvegarder, rester sur Settings : le profil est toujours visible après le retour succès.
- Sans fermer Settings, ouvrir/créer un agent : le même profil est disponible dans le picker.
- Deux profils OpenCode avec même endpoint/modèle mais ids distincts restent deux lignes et deux options distinctes.
- Renommer un profil puis sauvegarder met à jour le libellé dans l'éditeur et dans les pickers agents.
- Aucun écran ne montre simultanément une liste issue seulement des références et une liste issue des profils persistés comme si elles étaient équivalentes.

View File

@ -187,6 +187,44 @@
],
"fallback": "allow"
}
},
{
"agentId": "5d07e4a7-8676-4a71-aea1-5b64caefa944",
"permissions": {
"rules": [
{
"capability": "read",
"effect": "allow",
"paths": [
"**"
],
"commands": []
},
{
"capability": "write",
"effect": "deny",
"paths": [
"**"
],
"commands": []
},
{
"capability": "delete",
"effect": "deny",
"paths": [
"**"
],
"commands": []
},
{
"capability": "executeBash",
"effect": "allow",
"paths": [],
"commands": []
}
],
"fallback": "allow"
}
}
]
}

View File

@ -0,0 +1,111 @@
# Build de l'AppImage IdeA (Linux)
Procédure canonique pour reconstruire l'AppImage Linux d'IdeA et les bundles frontend associés.
À utiliser à chaque fois qu'un correctif doit être visible dans l'app desktop. Rappel produit : **le binaire qui tourne = l'AppImage installée, pas les sources**. Un correctif source n'est actif dans l'app desktop qu'après rebuild, remplacement de l'AppImage utilisée, puis relance d'IdeA.
## Commande principale
Depuis le project root `/home/anthony/Documents/Projects/IdeA` :
```bash
cd crates/app-tauri
APPIMAGE_EXTRACT_AND_RUN=1 NO_STRIP=true ../../frontend/node_modules/.bin/tauri build --bundles appimage
```
Cette commande déclenche `build.beforeBuildCommand`, donc elle reconstruit automatiquement les deux bundles frontend :
- `frontend/dist` : bundle desktop, transport `tauri`.
- `frontend/dist-web` : bundle web, transport `http`.
Ne pas revenir à l'ancienne procédure `npm --prefix frontend run build` seule : elle ne reconstruit pas le bundle web séparé.
## Vérification des bundles web/desktop
Après le build, lancer :
```bash
npm --prefix frontend run test:bundle-transport
```
Sortie attendue :
```text
dist: __IDEA_TRANSPORT__="tauri" (1 marker)
dist-web: __IDEA_TRANSPORT__="http" (1 marker)
```
## Artefact attendu
```text
target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage
```
Vérifier rapidement :
```bash
ls -lh target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage
APPIMAGE_EXTRACT_AND_RUN=1 target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage --appimage-help | head
```
## Pourquoi ces variables sont obligatoires
- `--bundles appimage` : cible uniquement l'AppImage Linux et évite les bundles inutiles/cassants comme NSIS.
- `NO_STRIP=true` : évite l'échec linuxdeploy/strip sur les bibliothèques système modernes contenant `.relr.dyn`.
- `APPIMAGE_EXTRACT_AND_RUN=1` : évite l'échec FUSE quand linuxdeploy ou appimagetool ne peuvent pas monter une AppImage dans l'environnement courant.
## Fallback si Tauri échoue à `failed to run linuxdeploy`
Symptôme : la commande Tauri reconstruit `frontend/dist`, `frontend/dist-web`, compile `target/release/app-tauri`, crée `target/release/bundle/appimage/IdeA.AppDir`, puis échoue seulement à l'étape finale :
```text
failed to bundle project `failed to run linuxdeploy`
```
Ne pas réanalyser tout le build. Faire ce diagnostic court :
```bash
APPIMAGE_EXTRACT_AND_RUN=1 NO_STRIP=true LDAI_OUTPUT=/home/anthony/Documents/Projects/IdeA/target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage \
/home/anthony/.cache/tauri/linuxdeploy-x86_64.AppImage \
--appdir /home/anthony/Documents/Projects/IdeA/target/release/bundle/appimage/IdeA.AppDir \
--output appimage
```
Si `appimagetool` échoue avec téléchargement runtime impossible :
```text
Failed to download runtime file
```
utiliser le runtime local déjà en cache et l'`appimagetool` extrait. Chercher le dossier extrait récent :
```bash
find /tmp -path '*/appimagetool-prefix/usr/bin/appimagetool' -type f -printf '%p\n' | tail -1
```
Puis lancer en remplaçant `<EXTRACTED>` par le préfixe trouvé, par exemple `/tmp/appimage_extracted_xxx` :
```bash
PATH=<EXTRACTED>/appimagetool-prefix/usr/bin:$PATH \
ARCH=x86_64 \
<EXTRACTED>/appimagetool-prefix/usr/bin/appimagetool \
--runtime-file /home/anthony/.cache/tauri/runtime-x86_64 \
/home/anthony/Documents/Projects/IdeA/target/release/bundle/appimage/IdeA.AppDir \
/home/anthony/Documents/Projects/IdeA/target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage
```
Le `PATH` est nécessaire parce que `mksquashfs` est fourni dans `appimagetool-prefix/usr/bin` et peut être absent du PATH système.
## Relance de l'application
Ne pas relancer IdeA automatiquement depuis une session active : cela tue l'orchestrateur courant et les ponts MCP. Une fois l'AppImage reconstruite, l'utilisateur décide quand remplacer/lancer l'artefact final.
## Piège d'environnement AppImage
Une session shell lancée depuis l'AppImage peut hériter de variables comme `APPDIR`, `LD_LIBRARY_PATH`, `PYTHONHOME` pointant vers `/tmp/.mount_IdeA_*`. Symptômes possibles : `python3` casse avec `No module named 'encodings'`, ou un binaire Tauri local se lance dans un environnement pollué.
Pour des commandes sensibles, préférer un environnement propre ou éviter Python :
```bash
env -i PATH=/usr/bin:/bin HOME=$HOME XDG_RUNTIME_DIR=/run/user/1000 <commande>
```

View File

@ -0,0 +1,6 @@
{
"version": 1,
"projectDefault": {
"network": "allow"
}
}

View File

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

View File

@ -1,24 +0,0 @@
---
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

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

View File

@ -1,15 +0,0 @@
---
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

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

View File

@ -1,15 +0,0 @@
---
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

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

View File

@ -1,15 +0,0 @@
---
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

@ -1,54 +0,0 @@
---
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

@ -1,16 +0,0 @@
---
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

@ -1,20 +0,0 @@
---
issueRef: "#14"
version: 7
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783456579694
---
## 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

@ -1,75 +0,0 @@
---
id: "0c1f1991-b6db-47b7-bbef-2478bc7874ab"
number: 14
title: "Integration de profils IA locaux/LAN comme profils IdeA canoniques"
status: "qa"
priority: "medium"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783184495846
updatedAt: 1783456579694
version: 7
---
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.

View File

@ -1,15 +0,0 @@
---
issueRef: "#15"
version: 5
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1784093861343
---
## Cadrage Architect — DIFFÉRÉ (2026-07-13)
#15 (cas DÉLÉGUÉ : A→B via idea_ask_agent, B limité → parquer le waiter de A et re-livrer au reset) est **distinct de #30** (cas direct) et **différé hors sprint**.
**Motif (Architect)** : le faire maintenant en in-memory serait une rustine fragile — réintroduit un blocage long côté A et ne tient pas les scénarios reboot/crash/redémarrage IdeA déjà identifiés.
**Prérequis bloquant** : un modèle fiable de *délégation durable runtime-agent identity* (stockage waiter, corrélation requester/target/request, re-livraison idempotente, reprise après reset, comportement si A meurt / B redémarre / IdeA redémarre, expiration/annulation). → design `durable-delegation-runtime-agent-identity-design`.
**Statut** : reste ouvert, priorité low/stretch conservée. Dépendance baseline #7 maintenue + à rattacher au redesign délégation durable. Ne pas mélanger avec #30.

View File

@ -1,28 +0,0 @@
---
id: "5de121f3-1cd1-4a73-bcab-b0a43a7c257f"
number: 15
title: "[Bloqué par #7 — design durable] Limites de session — re-livraison auto parquée au reset (stretch B5)"
status: "open"
priority: "low"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: [{"target":"#7","kind":"dependsOn"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783208599385
updatedAt: 1784093861343
version: 5
---
Extrait du cadrage Architect du ticket #7 (baseline livrée : propagation inter-agent B1→B3 + F1/F2). Stretch non retenu dans #7.
⛔ STATUT (2026-07-15) : BLOQUÉ / PARQUÉ. Dépend de #7 qui est encore en QA (non stabilisé). Architect (triage sprint « Gestion des bugs ») : « le waiter A→B n'est pas parqué/re-livré, l'ask retourne encore une erreur Process ; à traiter APRÈS stabilisation QA de #7/LS7 ». De plus c'est un item de « délégation durable » (in-memory fragile aux redémarrages) qui relève d'un design dédié, pas d'une rustine. Non lançable tant que #7 n'est pas vert et que le design durable-delegation n'est pas cadré. Sorti de la production active du sprint.
--- Cadrage conservé ---
Objectif : quand A délègue à B via idea_ask_agent et que B atteint sa limite, au lieu de demander à A de ré-interroger après le reset, PARQUER le waiter de A par (requester,target) ; au execute_resume de B (reprise auto au reset), RE-LIVRER la tâche d'origine et router la complétion vers le waiter de A s'il est encore vivant (sinon drop, contrainte in-memory).
État actuel (triage) : le rendez-vous délégué détecte RateLimited et arme une reprise de la cible (crates/application/src/orchestrator/service.rs:1854), execute_resume relance l'agent (crates/application/src/agent/session_limit.rs:226) ; mais le waiter A→B n'est pas parqué/re-livré.
Coût/risque (Architect) : rapproche du modèle « délégation durable » tout en restant in-memory → fragile aux redémarrages/interruptions de A, ré-introduit un blocage long côté A. À rattacher au design durable-delegation-runtime-agent-identity-design plutôt que traité en rustine in-memory.
Dépend de : #7 (baseline inter-agent B1→B3). Voir mémoire ticket7-session-limit-interagent-cadrage.

View File

@ -1,6 +0,0 @@
---
issueRef: "#16"
version: 7
updatedBy: {"kind":"user"}
updatedAt: 1783405334263
---

View File

@ -1,17 +0,0 @@
---
id: "0a3585f0-9774-4109-a4e3-746dc5b2a4b2"
number: 16
title: "[UI] réorganisation des menus"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783329576091
updatedAt: 1783405334263
version: 7
---
J'aimerais réorganiser les mesnus de façon à être un peu plus proche de l'interface d'un IDE plus classique. J'aiemrais plutot avoir des menu déroulant en haut de la fenetre que d'avoir cette barre latérale
Les menus déroulant pourraient afficher des fenetres flottantes, ce qui laisserait plus de place pour l'affichage.

View File

@ -1,6 +0,0 @@
---
issueRef: "#17"
version: 10
updatedBy: {"kind":"user"}
updatedAt: 1783405334977
---

View File

@ -1,16 +0,0 @@
---
id: "66aaef66-c70a-4153-81e9-a8f323686092"
number: 17
title: "[UI] fenetre de gestion de tickets"
status: "closed"
priority: "medium"
sprint: null
links: [{"target":"#16","kind":"dependsOn"},{"target":"#18","kind":"dependsOn"}]
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783329807682
updatedAt: 1783405334977
version: 10
---
J'aimerais une fenetre dédiée à la gestion des tickets. Autant pour le listing que pour la création/edition des tickets. Dans un même temps, j'aimerais qu'on améliore la gestion des tickets lié lorsque l'on édite les tickets en utilisant la popup du ticket #18. J'aiemrais aussi que l'agent permettant l'écriture des tickets soit proposé de façon plus évidante. Je pense qu'un bouton en bas à droite de la fenetre d'édition ouverte serait bien.

View File

@ -1,6 +0,0 @@
---
issueRef: "#18"
version: 9
updatedBy: {"kind":"user"}
updatedAt: 1783405335941
---

View File

@ -1,16 +0,0 @@
---
id: "5c17d6d3-c537-45b1-a17e-9c4edee963d1"
number: 18
title: "[UI] Créer une popup de selection de ticket"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783330038271
updatedAt: 1783405335941
version: 9
---
Pour différentes feature comme la création de sprint ou même le link d'un ticket à d'autres, il est necessaire de selectionner un ticket. Pour ça j'aimerais un popup qui puisse être utilisée dans ces différentes features pour la selection d'un ticket. Il faudrait une barre de recherche ainsi que la possibilité d'appliquer des filtres sur l'avancée ainsi que la priorité des tickets, comme pour le listing principal des tickets.

View File

@ -1,6 +0,0 @@
---
issueRef: "#19"
version: 8
updatedBy: {"kind":"user"}
updatedAt: 1783405337651
---

View File

@ -1,16 +0,0 @@
---
id: "b1c84dd2-cef7-4e48-a501-1a30eedb02f2"
number: 19
title: "[UI] implémentation de la popup de selection de ticket dans la création d'un sprint"
status: "closed"
priority: "low"
sprint: null
links: [{"target":"#18","kind":"dependsOn"}]
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783330352910
updatedAt: 1783405337651
version: 8
---
Lors de l'edition d'un sprint, j'aimerais que pour selectionner un ticket, ça soit la popup de selection de ticket qui soit utilisée

View File

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

View File

@ -1,39 +0,0 @@
---
id: "0a492d45-e195-4df7-a2ad-65649372abf0"
number: 2
title: "Tâches de fond — dette A : découpler fin de process et flux output PTY (PtyPort::wait/try_wait)"
status: "closed"
priority: "low"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783082860742
updatedAt: 1784065385002
version: 6
---
Ticket #2 — Tâches de fond : découpler fin de process et flux output PTY.
REQUALIFIÉ (2026-07-14) : le hub broadcast PTY existe désormais (crates/infrastructure/src/pty/mod.rs), donc l'ancienne contrainte « pas de broadcast multi-consommateur » est OBSOLÈTE. Le volet « tee live UI » est sorti en sous-ticket B/F séparé (voir lien blocks). La dette restante ici est purement backend.
Constat : `CommandBackgroundRunner` détecte encore la fin d'une tâche en drainant `PtyPort::subscribe_output` jusqu'à EOF (crates/infrastructure/src/background_task/runner.rs:187), ce qui couple la lifecycle du process à la consommation de sortie et empêche un tee sans casser la détection.
Attendu :
- Ajouter au port figé `PtyPort` (crates/domain/src/ports.rs:952) deux opérations explicites :
- `async fn wait(&self, handle: &PtyHandle) -> Result<ExitStatus, PtyError>` (attend la fin naturelle + status ; documenter l'idempotence : premier wait consomme, suivants retournent le status mémorisé).
- `fn try_wait(&self, handle: &PtyHandle) -> Result<Option<ExitStatus>, PtyError>` (non bloquant : Ok(None) si vivant, Ok(Some(status)) si terminé).
- `kill` reste « forcer l'arrêt puis retourner status » ; si déjà terminé, retourne le status mémorisé. NotFound si handle inconnu/purgé. L'exit status est mémorisé dans le registre live tant que la session existe (cohérence wait/try_wait/kill).
- Implémenter dans `PortablePtyAdapter` (état d'exit partagé, attendre le child sans dépendre du reader EOF, éviter double wait/kill) et dans tous les fakes de test.
- Migrer le runner : remplacer l'attente EOF (runner.rs:187) par une attente sur `pty.wait(&handle)`, concurrencée avec cancel/deadline. La sortie de completion reste prise depuis le scrollback borné ; le runner n'a plus besoin de subscribe_output pour savoir si le process est fini.
Impact contractuel : port figé modifié → changement source-breaking intra-workspace (tous les adapters/fakes ajoutent wait/try_wait), mais PAS de breaking IPC/front, pas de migration de données.
Lots : B1 wait/try_wait au port + fakes ; B2 impl PortablePtyAdapter ; B3 migrer CommandBackgroundRunner vers wait ; B4 tests. Taille M.
QA (point de vérité) :
- Fake PtyPort dont l'output n'est jamais drainé (ou consommé par 2 subscribers) mais `wait` résout → le runner complète quand même.
- Fake avec subscriber UI actif + runner → completion via `wait`, pas via EOF.
- Deadline : si `wait` ne résout pas avant deadline → runner retourne Expired et tue/cleanup correctement.
- Cancel : cancel gagne même si l'output continue.
- Portable PTY réel : commande courte (`echo hi`) → completion exit 0 sans dépendre d'un drain output.

View File

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

View File

@ -1,26 +0,0 @@
---
id: "1be19ee5-fd03-42ea-8df6-da18704807a9"
number: 20
title: "[Backend] Dette ticket_list — matching #ref dans text + curseur opaque/stable"
status: "closed"
priority: "low"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: [{"target":"#18","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783331172226
updatedAt: 1784049665491
version: 5
---
Dette backend identifiée pendant le cadrage du sprint UI rework (gate G4), non bloquante pour la popup #18 qui démarre sur le contrat actuel.
Deux écarts sur la commande `ticket_list` (handler `crates/app-tauri/src/tickets.rs:681`, filtre store `crates/infrastructure/src/issues.rs`) :
1. Recherche `text` : appliquée serveur sur titre (issues.rs:322) + description/carnet (issues.rs:326/465) mais PAS sur le `#ref`/numéro de ticket. Étendre le matching `text` à `issue_ref` pour permettre la recherche par numéro dans la popup de sélection.
2. `cursor` : actuellement un offset numérique parsé en usize avec fallback silencieux à 0 si invalide (tickets.rs:1231), non opaque et non stable face à des mutations entre pages. Contractualiser un curseur opaque + stable (ordre déterministe préservé).
Garde G3-bis déjà en place côté frontend : `TicketPicker`/`useTicketSearch` traitent `cursor` comme un token opaque (jamais construit/incrémenté côté client), donc la migration vers un curseur opaque backend n'exigera AUCUN changement frontend — cette dette est non-breaking.
statuses[]/priorities[] sont conformes (OR intra-facette, AND inter-facette, testés) — rien à faire de ce côté.

View File

@ -1,6 +0,0 @@
---
issueRef: "#21"
version: 7
updatedBy: {"kind":"user"}
updatedAt: 1783437364397
---

View File

@ -1,16 +0,0 @@
---
id: "4ffe9f90-2264-4861-b7da-f5535b0a622f"
number: 21
title: "[UI] pouvoir trier les ticket par..."
status: "closed"
priority: "low"
sprint: null
links: [{"target":"#16","kind":"dependsOn"},{"target":"#18","kind":"dependsOn"}]
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783331825658
updatedAt: 1783437364397
version: 7
---
J'aiemrais qu'on ajoute une option "trier par..." dans la popup de selection des tickets et dans la liste principale des tickets. On pourrait trier par numéro de ticket, priorité, status, ou titre du ticket. Avec chaque fois croissant/decroissant.

View File

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

View File

@ -1,16 +0,0 @@
---
id: "2b90fd78-8fce-449d-ab61-e5aee5ede08c"
number: 22
title: "[UI] Anchor de views"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783405028818
updatedAt: 1783437364871
version: 5
---
J'aimerais qu'à la manière d'un IDE classique, il soit possible d'ancrer des views sur le côté droite ou gauche et de proposer un format vertical. 9a peut être utilise par exemple pour git, les work, les agents, les skills etc. J'ai en tête les IDE comme Visual COde ou la suite Jetbrains par exemple.

View File

@ -1,6 +0,0 @@
---
issueRef: "#23"
version: 6
updatedBy: {"kind":"user"}
updatedAt: 1783437365276
---

View File

@ -1,16 +0,0 @@
---
id: "ed815933-ed48-466d-b265-3724f3ea943b"
number: 23
title: "[UI] rendre les fenêtres View séparée de IdeA"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783405188644
updatedAt: 1783437365276
version: 6
---
J'aimerais que les fenêtre qu'on affiche via le menu View soient des fenêtre à part entières, qu'on puisse les déplacer sur les différents écrans, les mettre fullscreen etc, que ça soit des enetres "systeme" normales

View File

@ -1,25 +0,0 @@
---
issueRef: "#25"
version: 11
updatedBy: {"kind":"user"}
updatedAt: 1783491435654
---
## Root cause
`OpenTicketAssistant::execute` fabriquait un plan OS-sandbox bespoke via `SandboxPlan::project_read_only` (grant RO sur project_root, posture Deny). Sous Landlock, un grant RO fait *handle* la classe read/exec (`AccessFs::from_read(V1)` inclut Execute). Le binaire CLI (codex/claude) vit hors du project root ⇒ `execve` refusé ⇒ EACCES (os error 13) au spawn sandboxé. Indépendant de la CLI. Les agents workspace n'ont pas le bug (plan no-op sous posture Allow).
## Correctif (backend-pur, zéro port/DTO)
Décision Main : option fallback `None`. La surface assistant de ticket passe désormais `None` en 5e arg de `factory.start` (aligné sur les agents workspace). Garde-fous restants : policy MCP `idea_ticket_read/update*` + advisory LP3. Helper `ticket_assistant_sandbox` et preset `SandboxPlan::project_read_only` supprimés (plus aucun appelant).
Fichiers : crates/application/src/ticket_assistant.rs (+tests), crates/domain/src/sandbox.rs.
## Validation
- `cargo test --workspace` VERT (app-tauri 63, application 80, infrastructure 254, domain OK).
- Test ciblé : `factory.start` reçoit `SessionPlan::None` + `sandbox.is_none()`.
- Tests Landlock infra verts sur la machine.
- RÉSERVE : repro live Codex+Claude non exécutée — nécessite rebuild + swap de l'AppImage active + relance IdeA (interrompt la session).
## Git
Commit `961a2ca` → merge `--no-ff` `cb20fab` dans develop. Local only, pas de push.
## Reste à faire
Repro live après rebuild AppImage pour clôture définitive. Dette différée : write-fence OS uniforme sur toutes les surfaces (cf. cadrage Architect) si l'on veut une clôture write-OS.

View File

@ -1,16 +0,0 @@
---
id: "6123b180-b36b-4807-ba31-46d60d3ef022"
number: 25
title: "[Bug] Codex/Claude erreur lors de l'utilisation dans l'edition d'un ticket"
status: "closed"
priority: "medium"
sprint: null
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783406391625
updatedAt: 1783491435654
version: 11
---
J'ai voulu créer un ticket via Codex dasn l'interface d'edition d'un ticket, mais j'ai eu cette erreur: process error: agent session start failed: codex: Permission non accordée (os error 13). J'aéi séléctionné que je voulais utiliser codex et l'erreur est apparue quand j'ai essayé de lui donné mon premier message. Je me rend compte que j'ai la même erreur avec Claude

View File

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

View File

@ -1,16 +0,0 @@
---
id: "2201b898-9c45-4057-9014-5284897507ad"
number: 26
title: "[UI] refonte totale de la gestion des menus via agent UX"
status: "closed"
priority: "medium"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783437525356
updatedAt: 1783861758866
version: 6
---
J'aimerais une refonte totale de l'UX et de l'UI d'IdeA pour tout ce qui touche aux menus. Je n'aime pas la disposition actuelle. Il est important de garder l'aspect fenêtre flottantes, le fait de pouvoir anchor les fenêtres sur le côté d'IdeA, mais je n'aime pas le fait qu'il y ai deux listes déroulantes View et Window. Onne comprends pas vraiemnt la différence. De plus, l'affichage de l'onglet du projet avec le nom "Projet : IdeA" sur lequel cliquer pour changer de projet je n'aime pas. Je pense peut être plutot ajouter un + à côté de l'onglet du projet pour pouvoir ouvrir plusieurs projet en parallèle ? (A l''approbation de UX). Par contre je ne veux pas qu'on touche aux cellules des agents, elles sont très bien comme ça, on se contente des menus et des fenêtres.

View File

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

View File

@ -1,16 +0,0 @@
---
id: "d7459ae0-31ae-49b2-bd93-2419397b0343"
number: 27
title: "[Bug] L'outil assistance IA n'a pas les commandes MCP"
status: "closed"
priority: "high"
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: 1783439818722
updatedAt: 1783926649550
version: 6
---
Il semblerait que l'outil assistance IA des tickets n'ait pas connaissance des tools MCP pour l'edition des tickets. J'ai essayé de demandé à l'assistant de modifié le ticket pour que ça aille dans le sens de la conversation que j'ai eu avec lui et il m'a dabord donné un .md. Quand je lui ai demandé de modifier lui même le ticket, il est allé dans le fichier directement pour apporter des modifications au lieu d'utiliser le tool MCP d'IdeA

View File

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

View File

@ -1,33 +0,0 @@
---
id: "9d8ec8cf-312a-4f90-8199-e37b183ba11e"
number: 28
title: "First-run wizard : bouton « Save and continue » figé (busy bloqué par l'auto-détection)"
status: "closed"
priority: "high"
sprint: null
links: []
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"user"}
createdAt: 1783458330440
updatedAt: 1783491458775
version: 3
---
## Symptôme (confirmé live, build 0.3.0 @2026-07-07 22:46, = develop 3c6cd04)
Au premier lancement, le wizard affiche les profils de référence (Claude/Codex/Ollama), l'utilisateur remplit le profil Ollama et coche la case, mais **« Save and continue » ET « Detect installed CLIs » restent grisés** → impossible de finir le first-run. Confirmé par l'utilisateur : les deux boutons sont grisés.
## Diagnostic (source + JS embarqué vérifiés)
- Le JS embarqué contient exactement `disabled: n.busy` sur le bouton (`FirstRunWizard.tsx:103`) — **aucune** condition de validation. Donc bouton grisé ⇔ `busy` reste `true`.
- `useFirstRun.reload()` : `setBusy(true)` → affiche les lignes (d'où formulaire visible/éditable) → `await detectProfiles(refs)` (auto-détection à l'ouverture) → `finally { setBusy(false) }`. Le `finally` ne s'exécute que **si la détection se termine**. Si la promesse `detectProfiles` ne se résout jamais, `busy` reste figé → les deux boutons restent grisés.
## Causes racines suspectées (2 défauts #14 qui se combinent)
1. **Profil Ollama sans commande de détection** : `detect: None``detection_spec` retombe sur `"{command} --version"` = `openai-compatible --version` (`runtime/mod.rs:64`), binaire inexistant → ligne « ✗ not found », et surtout probe inutile.
2. **`block_on` sur runtime tokio imbriqué** dans le chemin de détection : `DetectProfiles::execute` (`usecases.rs:79`) appelle `runtime.detect()` synchrone → `futures_block_on` construit un runtime current-thread et `block_on` (`runtime/mod.rs:231`) **à l'intérieur** de la commande async Tauri `detect_profiles` (`commands.rs:752`). Pattern qui peut paniquer (« Cannot start a runtime from within a runtime ») / rester pendu → la promesse ne se résout jamais. Se déclenche probablement sur une machine **sans Claude/Codex installés**.
## Attendu du fix
- `busy` doit **toujours** revenir à `false` même si la détection panique/pend (le `finally` ne doit pas dépendre du résultat de la détection ; détection best-effort, non bloquante, éventuellement bornée par timeout).
- Donner une commande/stratégie de détection correcte au profil OpenAI-compatible (ou ne pas le sonder comme un CLI — c'est un endpoint HTTP, pas un binaire).
- Corriger le `block_on` imbriqué dans le runtime de détection (ne pas bloquer dans un contexte async Tauri).
## Validation QA
Reproduire sur une machine **sans** Claude/Codex installés + Ollama lancé ; vérifier que le wizard reste utilisable (boutons cliquables) et que le profil Ollama se persiste et démarre.

View File

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

View File

@ -1,16 +0,0 @@
---
id: "51f19ca1-6b67-491b-b750-735c48a89d4b"
number: 29
title: "[UI] Garder les filtres des tickets entre deux redemarrage"
status: "closed"
priority: "low"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783491008871
updatedAt: 1783921595742
version: 5
---
J'aimerais garder les filtres des tickets en mémoire entre deux redemarrage ou ouverture de la fenetre ou d ela popup de choix de tickets.

View File

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

View File

@ -1,28 +0,0 @@
---
id: "fedd343e-f9c1-467b-bab4-455f51907de7"
number: 3
title: "[Différé — design à mûrir] Tâches de fond — dette B : retry durable après reboot"
status: "open"
priority: "low"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783082860758
updatedAt: 1784093835732
version: 6
---
Ticket #3 — Tâches de fond : retry après redémarrage sans fuite de secrets dans le projet.
⛔ DÉCISION UTILISATEUR (2026-07-15) : DIFFÉRÉ. On ne persiste PAS de secrets en clair machine-local pour l'instant. À reprendre plus tard avec un vrai design sécurisé (keyring OS multiplateforme — Secret Service / Keychain / Credential Manager — ou modèle d'invocation déclaratif avec secret-refs re-résolus au retry depuis profil/env). Le retry-after-reboot reste indisponible en attendant. Ticket sorti de la production active du sprint « Gestion des bugs ».
--- Cadrage conservé pour la reprise ---
REQUALIFIÉ (2026-07-14) :
- Volet « énumération terminale/projet du BackgroundTaskStore » : RÉSOLU par l'implémentation actuelle (store durable par projet sous <root>/.ideai/background-tasks, listes open par agent + completions non livrées, routage par projet). RETIRÉ du périmètre.
- Reste uniquement le retry après redémarrage. L'invocation d'origine (SpawnSpec) est conservée dans un registre in-memory session-scoped (BackgroundCommandArchive, crates/application/src/background/mod.rs:203) volontairement non persistée dans .ideai car elle peut contenir des secrets. Après reboot, une tâche persistée ne peut donc pas être relancée.
Option A (écartée pour l'instant par décision utilisateur) : store machine-local hors projet (app-data OS/Tauri), SpawnSpec complet par (project_id, task_id), permissions 0700/0600 best-effort, JSON projet sans secret, retry échouant explicitement si invocation absente. Simple (M) mais persiste des secrets en clair local → refusée à ce stade.
Piste retenue pour la reprise : keyring OS multiplateforme OU secret-refs déclaratifs (chantier plus large que « low », à cadrer comme design dédié le moment venu).

View File

@ -1,25 +0,0 @@
---
issueRef: "#30"
version: 8
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783941648176
---
## Cadrage Architect (2026-07-13) — cas DIRECT, actionnable
Débloqué : #27 fermé. #30#15 (#15 = cas délégué, différé).
**Périmètre** : le chemin direct de session agent (agent directement adressé, ex. Main) ne remonte pas la limite vers `SessionLimitService`. Fix = accrocher le détecteur sur le chemin direct, avant résolution finale du tour.
**Frontière hexagonale** : infra détecte (adapter provider/profil déclaratif extrait la limite du flux structuré/regex → `ReplyEvent::RateLimited { resets_at_ms? }`) ; application arme la reprise (`SessionLimitService::on_rate_limited(agent_id,node_id,conversation_id,resets_at_ms)`) ; app-tauri relaie ; React affiche/annule. Aucune logique provider dans domaine/application.
**Contrat d'événements** :
- `DomainEvent::AgentRateLimited { agent_id, resets_at_ms }`
- `DomainEvent::AgentResumeScheduled { agent_id, fire_at_ms }` si reprise armée
- reprise auto au reset, annulable via `cancel_resume` (contrat existant conservé)
- si heure de reset non récupérable : fallback niveau humain déjà cadré (état suspect + saisie d'heure, pas de silence)
**Point clé** : identité runtime — résoudre l'agent courant + `node_id` vivant + `conversation_id` via le registre/session meta existant (pas de convention UI). Sans `conversation_id`, ne PAS prétendre la reprise armée.
**Découpage** : B1 tap `ReplyEvent::RateLimited → on_rate_limited` dans le runner direct ; B2 résolution identité/session (agent_id/node_id/conversation_id) pour l'agent adressé ; B3 tests application/app-tauri (flux direct rate-limit avec resets_at_ms → AgentRateLimited puis AgentResumeScheduled) ; F1 régression badge existant (pas de nouveau contrat) ; F2 QA réelle (limite provoquée/mockée sur Main → heure affichée, annulation, reprise planifiée).
**Sous-lot adjacent** (ferme #7/F2, mémoire `ticket7-f2-delegated-limit-no-agentratelimited`) : la branche rendez-vous délégué publie seulement `DelegationRateLimited` et doit aussi armer `on_rate_limited(target,…)`. Traité dans la même branche mais en commit séparé.

View File

@ -1,16 +0,0 @@
---
id: "f2c4ed9c-ba54-42c1-90aa-0345d4ff4c6b"
number: 30
title: "[Bug] Le handle de limite session n'est pas fonctionnel quand c'est Main qui limite session"
status: "closed"
priority: "medium"
sprint: "d8f3f37b-87ca-4509-9116-45a99bc711df"
links: [{"target":"#27","kind":"blockedBy"}]
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783491181648
updatedAt: 1783941648176
version: 8
---
Lorsque l'agent qui atteint sa limite est celui à qui ont parle, la limite de session n'est pas récupérée par IdeA et n'est pas gérée

View File

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

View File

@ -1,31 +0,0 @@
---
id: "83d320f1-766b-4744-b518-8e39a2518e9c"
number: 31
title: "Détection de profils séquentielle : N × 800 ms au pire, résultat potentiellement partiel"
status: "closed"
priority: "low"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: [{"target":"#28","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783491197541
updatedAt: 1784064442657
version: 4
---
## Origine
Relevé par Git en revue du diff du ticket #28 (merge 710fa8f), hors périmètre du fix.
## Constat
Depuis #28, `DetectProfiles::execute` séquence les `await` candidat par candidat, chaque sonde bornée par `tokio::time::timeout(800ms)`. N profils indisponibles coûtent donc **N × 800 ms** au pire.
Côté frontend, `DETECT_TIMEOUT_MS = 3 s` relâche le flag `detecting`. À partir de ~4 candidats muets, le tour de détection dépasse ce délai : l'indicateur « Detecting… » disparaît avant que les résultats n'arrivent.
## Impact
Cosmétique. L'UI **ne gèle plus** (c'est bien l'objet de #28, corrigé) ; le risque résiduel est un affichage de disponibilité qui arrive après la retombée de l'indicateur.
## Piste de fix
Paralléliser les sondes avec `futures::future::join_all` dans `DetectProfiles::execute` (`crates/application/src/agent/usecases.rs`) : le coût au pire retombe à ~800 ms quel que soit N, largement sous le timeout UI.
## Validation
Test `#[tokio::test(flavor = "multi_thread")]` sur `DetectProfiles::execute` avec N candidats muets, asserting que la durée totale reste bornée par ~1 × timeout et non N ×.

View File

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

View File

@ -1,23 +0,0 @@
---
id: "9291e7ad-a300-4f15-83b1-93f56f6e1b79"
number: 32
title: "[Bug] Erreur CLI Ollama profile"
status: "closed"
priority: "medium"
sprint: null
links: [{"target":"#14","kind":"relatesTo"}]
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783491571863
updatedAt: 1783723378815
version: 6
---
J'ai créé un profile IA Ollama et j'ai ajouté un agent avec ce profile (agent TestOllama), mais quand
j'essaie d'afficher sa cli j'ai un bandeau rouge qui dit "Échec du lancement de l'agent : process error: pty spawn
failed: Unable to spawn openai-compatible because:
No viable candidates found in PATH "/tmp/.mount_IdeA_0mlgJnH/usr/bin/:/tmp/.mount_IdeA_0mlgJnH/usr/sbin/:/tmp/.mount_
IdeA_0mlgJnH/usr/games/:/tmp/.mount_IdeA_0mlgJnH/bin/:/tmp/.mount_IdeA_0mlgJnH/sbin/:/home/anthony/.local/bin:/run/us
er/1000/fnm_multishells/4610_1783490075749/bin:/home/anthony/.local/share/fnm:/home/anthony/go/bin:/home/anthony/.car
go/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:
/usr/bin/core_perl:/home/anthony/.local/share/JetBrains/Toolbox/scripts"

View File

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

View File

@ -1,39 +0,0 @@
---
id: "c3e1fbcc-cedc-48a5-a00e-b22ea8dc90de"
number: 33
title: "[Dette] Fallthrough silencieux du routage structuré (lifecycle.rs:1705)"
status: "closed"
priority: "high"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: [{"target":"#32","kind":"relatesTo"},{"target":"#14","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783492190391
updatedAt: 1784048928225
version: 4
---
Cause racine structurelle identifiée par Architect lors du cadrage de #32.
`LaunchAgent::execute` (crates/application/src/agent/lifecycle.rs:1705) route vers la session structurée avec :
```rust
if let (Some(factory), Some(structured), true) = (
self.session_factory.as_ref(), self.structured.as_ref(),
profile.structured_adapter.is_some(),
)
```
Ce `if let` **confond deux situations distinctes** :
- « profil structuré, mais factory non câblée » (cas de l'UI : `state.rs:1466` construit le `LaunchAgent` sans `.with_structured(...)`) ;
- « profil non structuré » (vrai profil PTY historique).
Dans les deux cas on tombe silencieusement, sans erreur ni branche explicite, sur `lifecycle.rs:1746` `self.pty.spawn(spec)`.
C'est ce fallthrough qui a produit le bug #32 : un profil `openAiCompatible` (aucun binaire) atteignait `CommandBuilder::new("openai-compatible")`. Claude et Codex tombent dans le **même** fallthrough ; ça ne passe inaperçu que parce qu'un binaire `claude`/`codex` existe dans le PATH.
Le fix de #32 neutralise le cas transport-backed, mais **le piège reste armé** pour le prochain adapter.
**Attendu** : remplacer le `if let` par un `match` explicite qui distingue les deux cas, et décider du comportement quand un profil structuré rencontre une factory non câblée (erreur explicite plutôt que dégradation muette vers le PTY).
Hors périmètre de #32 (déposé comme bug). Cadrage Architect requis avant implémentation.

View File

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

View File

@ -1,29 +0,0 @@
---
id: "8dca00bf-ec0f-4da1-a231-46b27c711b78"
number: 34
title: "[Risque] ChatBridge.scrollback non borné (croissance mémoire)"
status: "closed"
priority: "medium"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: [{"target":"#32","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783492562056
updatedAt: 1784050010085
version: 4
---
Identifié par Architect lors du cadrage de #32 (variante B).
`ChatBridge` retient le scrollback d'une session chat pour le rejouer au remount (`reattach_agent_chat`). L'enregistrement se fait par un `push` nu, **sans aucun cap** :
- `app-tauri/src/chat.rs:161``push` sans borne.
- `app-tauri/src/chat.rs:47` — la doc prétend « Bounded only by the conversation length (a turn count) », ce qui est un euphémisme : chaque `TextDelta` (quelques octets) est retenu à vie.
**Dormant jusqu'ici** : aucune session structurée vivante ne passait par ce chemin. **Devient actif avec #32 variante B** (cellule chat pour les adapters transport-backed) : une conversation Ollama longue fait croître le `Vec` sans borne.
Distinct de la rétention/rotation du transcript disque (mémoire `conversation-log-ls6-rotation-and-paginated-read`), qui porte sur `log.jsonl`, pas sur ce buffer mémoire.
**Attendu** : borner le scrollback (cap en nombre d'événements ou en octets, avec troncature par la tête), corriger la doc `chat.rs:47`, et décider si le remount doit signaler une troncature à l'UI.
Hors périmètre #32. Cadrage Architect requis.

View File

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

View File

@ -1,16 +0,0 @@
---
id: "77ef65a5-bbb8-44d2-a610-27bf15c54a0a"
number: 35
title: "Avoir llamacpp intégré"
status: "closed"
priority: "high"
sprint: "883534aa-7fc1-4d83-a9c0-17cac4a4eea5"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783756863540
updatedAt: 1783777898736
version: 6
---
Nous avons llamacpp qui marche super avec OpencCode à présent. J'aimerais maintenant que llamacpp soit lancé automatiquement via IdeA avec le bon modele à la bonne url et bon port si celui-ci n'est pas encore lancé

View File

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

View File

@ -1,16 +0,0 @@
---
id: "3bb071b9-08eb-4e1b-b4b4-dccee8114a7e"
number: 36
title: "[UI] Pouvoir déclarer plusieurs profils AI de modeles locaux"
status: "closed"
priority: "medium"
sprint: "883534aa-7fc1-4d83-a9c0-17cac4a4eea5"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783757232381
updatedAt: 1783777899737
version: 6
---
Actuellement chaque type de profils ne peux déclarer qu'un seul profile AI. J'aimerais que le profile OpenCode puisse permetre d'en décalrer plusieurs différents.

View File

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

View File

@ -1,16 +0,0 @@
---
id: "a2b6212a-8725-4ace-b8a4-c3a41e2c2988"
number: 37
title: "[UI] garder les tickets dans les sprints, mais ajouter l'affichage du status et la possibiliter de filtrer les tickets"
status: "closed"
priority: "low"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783757421147
updatedAt: 1783878976369
version: 7
---
Actuelleemnt dans les sprints les tickets sont retirés une fois fait. J'aimerais que les tickets restent dans le sprints mais qu'on ajoute l'affichage du status de chaque ticket. J'aimerais aussi qu'on ai la possibilité de trier les tickets via leur status, leur priorité etc comme sur la liste des tickets

View File

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

View File

@ -1,16 +0,0 @@
---
id: "7e89bfc9-dc56-4656-a154-690f02e69756"
number: 38
title: "[UI] Pouvoir ajouter un ticket à un sprint pendant sa création"
status: "closed"
priority: "low"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783757548614
updatedAt: 1783879443381
version: 7
---
J'aimerais que dans la création de ticket on puisse lui attribuer un sprint via une popup comme celle du choix de tickets

View File

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

View File

@ -1,16 +0,0 @@
---
id: "02ff2d0c-4312-47c3-b84c-834029723fc4"
number: 39
title: "[UI] Fermer toutes les fernetres lors de la fermeture de la fenetre principale principale"
status: "closed"
priority: "low"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783757707896
updatedAt: 1783921595316
version: 5
---
Quand on ferme la fenetre principale d'IdeA, j'aimerais que toutes les fenêtres IdeA se ferment aussi.

View File

@ -1,28 +0,0 @@
---
issueRef: "#4"
version: 9
updatedBy: {"kind":"user"}
updatedAt: 1783437430509
---
## 🔄 REDÉMARRAGE DE ZÉRO (2026-07-04) — décision utilisateur
TOUT le travail #4 précédent (sur base canonique/main) est ABANDONNÉ comme ligne de livraison. Raison : l'utilisateur a réaligné main = develop = feature/background-tasks-first-class (ebd992e, base PRÉ-canonique de #1). Le moteur de conversation « canonique » (spawn_turn/AgentTurnEvent/agentBusyChanged) sur lequel reposait l'ancien #4 n'est PLUS sur main/develop. On refait #4 de zéro sur la base develop.
BRANCHE DE TRAVAIL : `feature/agent-live-announcements` (créée depuis develop ebd992e).
BRANCHES SUPPRIMÉES (obsolètes) : feature/announcements-canonical, feature/inter-agent-announcements.
FILETS DE RÉCUPÉRATION (si on veut repiquer du code) :
- backup/announcements-work-20260704 (691b2ce) = ancien #4 complet (backend B0-B3 + frontend F1/F2/F3 recâblé busy + tests).
- backup/inter-agent-announcements-71d307d (71d307d) = backend annonces d'origine.
- backup/main-canonical-20260704 (3cff2b1) = moteur canonique + releases.
OBJECTIF PRODUIT (inchangé, reconfirmé utilisateur) : affichage live sur la cellule d'un agent de ce qu'il raconte quand un AUTRE agent le sollicite via idea_ask_agent. Overlay sur la cellule CIBLE (« un agent est en train de lui parler » + annonces défilantes), monté quand la cible est busy, retiré à l'idle. Preview côté DEMANDEUR près de la liste d'agents, filtré par ticket + requester==self.
⚠️ ATTENTION base develop : moteur « batch » (run_turn), PAS le canonique. À cadrer par Architect : quels signaux live develop émet-il déjà (annonces intermédiaires ? busy/idle par agent ? l'ancien #4 utilisait agentBusyChanged + read-model agents[].busy — existent-ils sur develop ?), et que faut-il (ré)implémenter côté backend pour que les annonces soient LIVE (pas flushées en fin de tour). Réutiliser les composants frontend depuis backup/announcements-work-20260704 si le contrat de signaux le permet.
## RESTE À FAIRE (cycle complet sur base develop)
1. [EN COURS] Architect : cadrage from-scratch sur base develop (signaux live disponibles + à créer, contrat Announcement/Final, plan B/F, réutilisabilité du code sauvegardé).
2. Git : branche de travail = feature/agent-live-announcements (FAIT).
3. DevBackend : mécanisme annonces/Final + signaux live sur moteur develop.
4. DevFrontend : F1 store + F2 preview demandeur + F3 overlay cible.
5. QA : reproduire le déclenchement inter-agent + constater overlay/preview live + fermeture à l'idle.

View File

@ -1,35 +0,0 @@
---
id: "547f6a47-9c86-4c16-9018-f050af75a6aa"
number: 4
title: "Annonces inter-agent (UI live) — reprise et finalisation : overlay cellule cible + preview demandeur (F1-F3)"
status: "closed"
priority: "medium"
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: 1783083604350
updatedAt: 1783437430509
version: 9
---
Objectif produit (demande utilisateur, design figé le 2026-07-02) :
Quand un agent en contacte un autre via idea_ask_agent, l'agent CONTACTÉ doit afficher, par-dessus sa cellule, un overlay « un agent est en train de lui parler » avec ses réflexions/annonces en cours qui défilent ; l'agent DEMANDEUR affiche un petit preview des annonces près de la drop-list d'agents, filtré par ticket. L'overlay est piloté par le live-state (monté sur Working, retiré au Final/idle, persiste tant qu'≥1 ticket actif sur la cible). Design et cadrage complets en mémoire projet : inter-agent-announcements-feature-and-codex-final-bug (+ inter-agent-live-context-shared-per-agent).
ÉTAT ACTUEL (vérifié 2026-07-03) :
- Backend B0-B3 DÉJÀ implémenté sur la branche feature/inter-agent-announcements, commit 71d307d :
- ReplyEvent::Announcement (non terminal) vs Final (terminal, résout le ticket).
- DomainEvent::AgentAnnouncement{project_id, requester, target, ticket_id, text, at_ms}.
- Relay Tauri (crates/app-tauri/src/events.rs), DTO.
- Fix du Final Codex : dernier agent_message avant turn.completed = Final (avant : le préambule était renvoyé au demandeur au lieu de la conclusion). 18 fichiers backend + tests.
- FRONTEND F1/F2/F3 : JAMAIS écrit. Aucune référence « announcement » sous frontend/src. C'est la pièce visuelle centrale de la demande (preview demandeur + overlay cible) — absente.
- La branche feature/inter-agent-announcements est 15 commits EN RETARD sur develop, jamais mergée. Une seconde branche feature/inter-agent-announcements-v2 ne contient PAS le code d'annonces (repartie sur d'autres fixes codex/orchestrator).
RESTE À FAIRE :
1. Architect : cadrer la REPRISE — décider du rebase de 71d307d sur develop actuel, arbitrer les conflits avec le nouveau modèle de conversation (le fix Final Codex et le modèle de fil ont évolué depuis ; cf. inter-agent-live-context-shared-per-agent : log canonique PAR AGENT + vues par paire). Confirmer que le contrat Announcement/Final tient encore.
2. Git : décider de la topologie (rebase vs re-cherry-pick du backend sur une branche fraîche depuis develop).
3. DevBackend : réintégrer/adapter B0-B3 sur develop actuel si des conflits d'API le nécessitent.
4. DevFrontend : écrire F1 (store/gateway annonces, index par ticket/target, borné ~20-50), F2 (preview cellule demandeur près de la drop-list, filtré par ticket_id), F3 (overlay cellule cible : texte haut + annonces défilantes au centre, monté sur live-state Working, retiré au Final/idle).
5. QA e2e : reproduire le bug initial (Main→Architect→QA avec préambule+outil+conclusion, vérifier que le demandeur ne reçoit QUE la conclusion), puis constater le preview demandeur + l'overlay cible pendant le travail, et la fermeture au Final.
Chantier DISTINCT du ticket #1 (tâches de fond). Non prioritaire tant que #1 n'est pas mergé, sauf décision contraire.

View File

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

View File

@ -1,16 +0,0 @@
---
id: "6b04c8d1-177c-422a-9955-7fee2e8afdeb"
number: 40
title: "[UI] réouvrir les fenetres au lancement d'IdeA"
status: "closed"
priority: "low"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: [{"target":"#39","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: 1783757766786
updatedAt: 1783922451268
version: 6
---
Au lancement d'IdeA, j'aimerais que les fenêtres fermées lors de la précédentes fermeture de la fenêtre principale d'IdeA soient automatiqument réouvertes dans le même status, position, écran que quand elles ont été fermée

View File

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

View File

@ -1,16 +0,0 @@
---
id: "7d026901-333a-46a6-87f6-7384bf742310"
number: 41
title: "[UI] Selection multiple lors de la selection de tickets pour les sprints"
status: "closed"
priority: "low"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783757895085
updatedAt: 1783878363957
version: 6
---
Lorsque je selectionne les tickets pour mes sprints, j'iamerais que la selection me permette d'en choisir plusieurs à la fois pour ne pas avoir à réouvrir chaque fois la fenetre.

View File

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

View File

@ -1,16 +0,0 @@
---
id: "239aff64-a131-47eb-9a95-cc56c8c369c6"
number: 42
title: "[UI] Clarifier les contrôles d'en-tête de panneau (DockControls) — icônes libellées + tooltips alignés sur le menu Panneaux"
status: "closed"
priority: "low"
sprint: null
links: [{"target":"#26","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783862180616
updatedAt: 1783877612067
version: 2
---
Refinement UX suite à #26. Remplacer les glyphes peu explicites des en-têtes de panneaux docké/flottant (◧ ◨ ⧉ ⤢ ✕) par des boutons-icônes libellés + tooltips (title natif), alignés strictement sur les libellés du menu Panneaux. Spec UX figé : IconButton existant (@/shared, pas de lib externe, pas de Tooltip custom), ordre [⇤ Ancré à gauche][⇥ Ancré à droite][□ Flottant][↗ Fenêtre détachée][× Fermé] ; title + aria-label "<action><titre panneau>" ; placement courant = actif (aria-pressed=true, bg-raised text-content, ring-1 ring-border-strong) et NON désactivé ; "Fenêtre détachée" masqué pour projects et désactivé sans projet actif ; conteneur flex shrink-0 items-center gap-1. Périmètre strict : DockControls dans ProjectsView.tsx uniquement, aucun changement LayoutGrid/LeafView/cellules agents/write-portal/F3/DockRegion/FloatingWindow/ViewWindow.

View File

@ -1,6 +0,0 @@
---
issueRef: "#43"
version: 1
updatedBy: {"kind":"user"}
updatedAt: 1783879315858
---

View File

@ -1,15 +0,0 @@
---
id: "63e80352-8ce1-4116-9ec3-b4cb3fc5c077"
number: 43
title: "Systeme de plugins"
status: "open"
priority: "medium"
sprint: null
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1783879315858
updatedAt: 1783879315858
version: 1
---

View File

@ -1,25 +0,0 @@
---
issueRef: "#44"
version: 8
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783976073932
---
## Résolution (2026-07-13)
Le first-run wizard tourne désormais en deux **modes explicites** passés en argument (jamais inférés de `isFirstRun`) :
- `firstRun` : catalogue de référence seul, tout désélectionné, availability inconnue (détection auto pré-coche les CLI installés).
- `edit` (rouvert via *Settings ▸ Configure profiles*, `forceOpen`) : les profils déjà configurés reviennent **pré-sélectionnés avec leur vraie config**, en tête ; les profils de référence dont l'`id` est déjà configuré sont **dédupliqués par `profile.id` uniquement** (plusieurs OpenCode locaux partagent command/adapter mais diffèrent par endpoint/model). La détection auto ne touche PAS la sélection initiale (`preselect:false`).
Logique pure isolée dans `wizardEntries.ts` (`buildWizardEntries`) pour tester les invariants unitairement.
### Fichiers
- `frontend/src/features/first-run/wizardEntries.ts` (+ `.test.ts`) — nouveaux
- `useFirstRun.ts``mode` param, charge `listProfiles()` en edit via `Promise.all`
- `FirstRunWizard.tsx``mode = forceOpen ? "edit" : "firstRun"`
- `FirstRunWizard.test.tsx` — étendu
### QA — vert
`npx vitest run wizardEntries.test.ts FirstRunWizard.test.tsx` → 37 passed ; `npx tsc --noEmit` → exit 0.
### Git
Commit `8cdc44d` sur `feature/ticket44-firstrun-keep-profile-info` (base develop), mergé `--no-ff` vers `develop` (`c67ec4f`). Aucune action sortante.

View File

@ -1,16 +0,0 @@
---
id: "d7c17017-f6fb-4e55-8119-8fbc42641f48"
number: 44
title: "Garder les infos du profils courant sur l'affichage d'edition des profiles"
status: "closed"
priority: "medium"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783879634794
updatedAt: 1783976073932
version: 8
---
Si je vais dans l'edition des profiles, le pré-remplissage des profiles ne correspond pas aux profiles existants. C'est a dire que par exemple pour le profiles OpenCode, j'aimerais que si j'en ai déjà un de créé, celui (ou ceux d'affichés) correspondent à celui ou ceux qui existent déjà.

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