chore(ideai): état d'orchestration du sprint #13 (transport HTTP/WS + surface web)

Versionne l'état runtime IdeA produit pendant le sprint #13 : store de
tickets (dont les nouveaux #55 à #67), compteur et index, notes de mémoire
projet des lots F0 à F5, et journal des tâches de fond.

Séparé du code applicatif conformément à la convention du dépôt
(cf. ad1f225, a244f32) : métadonnée d'orchestration last-writer-wins,
sans impact sur le build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 10:32:39 +02:00
parent c246875f6d
commit 8e481aed69
53 changed files with 3884 additions and 99 deletions

View File

@ -1,6 +1,54 @@
---
issueRef: "#13"
version: 4
updatedBy: {"kind":"user"}
updatedAt: 1783329397368
version: 18
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1784184002362
---
# 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

@ -2,15 +2,15 @@
id: "036783fa-9856-4643-8c28-653b93ac36e1"
number: 13
title: "Server/client mode"
status: "open"
status: "inProgress"
priority: "low"
sprint: "028179b1-eaf4-41e9-9c1f-7c37125117e6"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783184188272
updatedAt: 1783329397368
version: 4
updatedAt: 1784184002362
version: 18
---
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,8 +1,8 @@
---
issueRef: "#15"
version: 3
version: 5
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783940786085
updatedAt: 1784093861343
---
## Cadrage Architect — DIFFÉRÉ (2026-07-13)

View File

@ -1,22 +1,28 @@
---
id: "5de121f3-1cd1-4a73-bcab-b0a43a7c257f"
number: 15
title: "Limites de session — re-livraison automatique parquée au reset (stretch B5, délégation durable)"
title: "[Bloqué par #7 — design durable] Limites de session — re-livraison auto parquée au reset (stretch B5)"
status: "open"
priority: "low"
sprint: "d8f3f37b-87ca-4509-9116-45a99bc711df"
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: 1783940786085
version: 3
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).
Coût/risque (Architect) : rapproche du modèle de « délégation durable » tout en restant in-memory → fragile aux redémarrages/interruptions de A, ré-introduit une forme de blocage long côté A. À rattacher au design durable-delegation-runtime-agent-identity-design plutôt que de le traiter en rustine 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 +1,6 @@
---
issueRef: "#2"
version: 2
updatedBy: {"kind":"user"}
updatedAt: 1783184142093
version: 6
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1784065385002
---

View File

@ -1,24 +1,39 @@
---
id: "0a492d45-e195-4df7-a2ad-65649372abf0"
number: 2
title: "Tâches de fond — dette A : PtyPort::wait/try_wait + tee live UI + robustesse détection de fin"
status: "open"
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":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783082860742
updatedAt: 1783184142093
version: 2
updatedAt: 1784065385002
version: 6
---
Dette issue de l'arbitrage B8 (mémoire projet: b8-arbitration-outcomes, point 1).
Ticket #2 — Tâches de fond : découpler fin de process et flux output PTY.
B8 a été accepté sans rendu live des tâches de fond. Le cœur complétion→wake fonctionne, mais la détection de fin du runner repose sur l'EOF du stream PTY single-consumer, ce qui est fragile et empêche un tee UI (une re-souscription UI casserait la détection EOF).
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.
Reste à faire :
- Ajouter `PtyPort::wait` / `try_wait` pour découpler la détection d'exit de la consommation d'output (retirer l'EOF-comme-proxy-de-fin).
- Une fois découplé, brancher un tee de la sortie PTY vers l'UI pour le rendu live des tâches de fond (F-live).
- NE PAS introduire de broadcast multi-consommateur (décision Architect).
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.
Périmètre touchant un port figé (PtyPort) : cadrage Architect requis avant implémentation.
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 +1,6 @@
---
issueRef: "#20"
version: 2
version: 5
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783331176736
updatedAt: 1784049665491
---

View File

@ -2,16 +2,16 @@
id: "1be19ee5-fd03-42ea-8df6-da18704807a9"
number: 20
title: "[Backend] Dette ticket_list — matching #ref dans text + curseur opaque/stable"
status: "open"
status: "closed"
priority: "low"
sprint: null
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: 1783331176736
version: 2
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.

View File

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

View File

@ -1,22 +1,28 @@
---
id: "fedd343e-f9c1-467b-bab4-455f51907de7"
number: 3
title: "Tâches de fond — dette B : persistance sûre de l'invocation (retry-after-reboot, secrets) + énumération terminale/projet du store"
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":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783082860758
updatedAt: 1783184146749
version: 2
updatedAt: 1784093835732
version: 6
---
Dette issue de l'arbitrage B8 (mémoire projet: b8-arbitration-outcomes, points 2 et 5).
Ticket #3 — Tâches de fond : retry après redémarrage sans fuite de secrets dans le projet.
En V1, le registre d'invocations pour le retry est in-memory et session-scoped (le SpawnSpec porte des secrets, interdit dans .ideai/background-tasks/*.json qui voyage avec le projet). Conséquences à résorber :
⛔ 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 ».
- Retry-after-reboot : persistance SÛRE de l'invocation (redaction des secrets et/ou store machine-local hors projet) pour permettre le retry après un redémarrage d'IdeA.
- Énumération store : aujourd'hui `list_background_tasks` sans agentId ne renvoie que les complétions non livrées du projet ; le store n'énumère pas les tâches terminales/ouvertes par projet (historique completed/failed partiel). Enrichir BackgroundTaskStore pour l'énumération terminale/projet.
--- Cadrage conservé pour la reprise ---
Cadrage Architect requis (persistance de secrets = sensible).
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,6 +1,6 @@
---
issueRef: "#31"
version: 1
version: 4
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783491197541
updatedAt: 1784064442657
---

View File

@ -2,16 +2,16 @@
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: "open"
status: "closed"
priority: "low"
sprint: null
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: 1783491197541
version: 1
updatedAt: 1784064442657
version: 4
---
## Origine
Relevé par Git en revue du diff du ticket #28 (merge 710fa8f), hors périmètre du fix.

View File

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

View File

@ -2,16 +2,16 @@
id: "c3e1fbcc-cedc-48a5-a00e-b22ea8dc90de"
number: 33
title: "[Dette] Fallthrough silencieux du routage structuré (lifecycle.rs:1705)"
status: "open"
status: "closed"
priority: "high"
sprint: null
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: 1783492190391
version: 1
updatedAt: 1784048928225
version: 4
---
Cause racine structurelle identifiée par Architect lors du cadrage de #32.

View File

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

View File

@ -2,16 +2,16 @@
id: "8dca00bf-ec0f-4da1-a231-46b27c711b78"
number: 34
title: "[Risque] ChatBridge.scrollback non borné (croissance mémoire)"
status: "open"
status: "closed"
priority: "medium"
sprint: null
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: 1783492562056
version: 1
updatedAt: 1784050010085
version: 4
---
Identifié par Architect lors du cadrage de #32 (variante B).

View File

@ -1,8 +1,8 @@
---
issueRef: "#54"
version: 5
version: 6
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783976286882
updatedAt: 1784018300921
---
## Cadrage Architect (2026-07-13)

View File

@ -2,7 +2,7 @@
id: "18641885-1b38-43c1-a81b-42f4c407690d"
number: 54
title: "[UI] Ajouter le handle du téléchargement des modeles lors du démarage llamacpp"
status: "inProgress"
status: "closed"
priority: "medium"
sprint: "5afd6780-0f76-40d7-a10f-32ee52469d74"
links: []
@ -10,7 +10,7 @@ agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1783965036142
updatedAt: 1783976286882
version: 5
updatedAt: 1784018300921
version: 6
---
Lorsqu'un serveur llamacpp se démarre, dans le cas ou le modele se télécharge, il faudrait que le téléchargement soit affiché au lieu d'afficher un timeout, avec en idéal l'affichage de la préogression du téléchargement en supperposition de la (ou les cellules) qui cherche à afficher le modèle

View File

@ -0,0 +1,28 @@
---
issueRef: "#55"
version: 11
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1784097757001
---
## Réouverture (2026-07-15) — le fix 141c13d ne suffit pas
Le fix #55 (commit 141c13d) a supprimé le timeout **prématuré** (~5 s) en distinguant process vivant-en-warmup / mort, avec `ReadinessPolicy::warmup_deadline = 120 s`. Mais l'utilisateur reproduit toujours « model server error (timeout): readiness timed out » **au lancement d'IdeA**, et ça finit par marcher après plusieurs essais.
### Cause racine
`crates/application/src/model_server.rs``wait_for_started_server` (~l.437) : tant que process `Running` + endpoint `Unreachable`, poll jusqu'à `deadline = now + warmup_deadline` (120 s), puis `stop_started_server` + `ModelServerError::Timeout`.
- **1er lancement à froid** : page cache OS froid, GGUF multi-Go, chargement RAM/VRAM, I/O disque en concurrence avec le reste du boot IdeA ⇒ warmup > 120 s ⇒ timeout + kill.
- **Essais suivants** : fichier en page cache chaud ⇒ chargement < 120 s succès. Explique le « au bout de plusieurs essais ça finit ».
### Fix Lot 1 backend (livré, commit f7cae4c sur feature/ticket55-model-warmup-deadline)
Cadré par Architect (mémoire `architecture-local-model-readiness-timeout`), approche A configurable :
- Défaut `ReadinessPolicy::warmup_deadline` : 120 s **600 s** (`crates/application/src/model_server.rs`).
- Nouveau `LocalModelServerConfig::warmup_deadline_secs: Option<u64>`, rétrocompatible, validation stricte `[30, 1800]` (`crates/domain/src/model_server.rs`).
- Policy effective dérivée **par config serveur** (deadline par-serveur), `probe`/`backoff` gardés séparés. DTO IPC `warmupDeadlineSecs` (`app-tauri/dto.rs`).
- Contrat readiness inchangé : Exitedéchec rapide ; Running+HTTP OKprêt ; Running+HTTP KOcontinuer jusqu'à deadline ; Running au-delàstop+Timeout.
### QA — VERT (ports mockés)
`cargo test -p domain` (252), `-p application` (81 + 22 model_server ciblés), `-p app-tauri --test dto_model_servers` (6), `-p infrastructure model_server` (2), build OK. Tests clés : slow_local_warmup...succeeds_without_stop, warmup_deadline_reached_returns_timeout_and_stops, process_exit_during_warmup_fails_fast, effective_policy_uses_configured_deadline, default_is_ten_minutes, hors-bornesINVALID.
### RESTE À FAIRE — vérification manuelle utilisateur (bloquant merge)
Les tests prouvent le **mécanisme**, PAS que 600 s guérit le vrai cold-start `llama-server` (bind réel hors sandbox). Git a committé mais **retient le merge sur develop** jusqu'à confirmation « cold-start OK » de l'utilisateur (vrai lancement à froid, après reboot / cache purgé). develop non divergé (ce5aa28) merge --no-ff trivial au feu vert.

View File

@ -0,0 +1,17 @@
---
id: "9ab1eb21-d6dd-435a-b088-377f0ec7e04f"
number: 55
title: "[Bug] Error on loading local model"
status: "inProgress"
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: 1784045935720
updatedAt: 1784097757001
version: 11
---
Quand jke cherche a lancer un modele local sur une cellule, il commence apr charger le serveur, ce qui est bon mais au bout de quelques seconde, le chargement du serveur disparait et j'ai cette erreur qui s'affiche en bandeau rouge: Échec du lancement de l'agent : model server error (timeout): readiness timed out.
Si j'insiste assez en changeant d'agent et en remettant l'agent, au bourt d'un moment ça fini par fonctionner

View File

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

View File

@ -0,0 +1,16 @@
---
id: "12943bca-4c29-46ec-8cad-936c30a95d5e"
number: 56
title: "[Bug] selection desactivée d'agent non affichés"
status: "closed"
priority: "low"
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: 1784046090493
updatedAt: 1784048212123
version: 6
---
Si j'affiche un agent dans une cellule, que dans cette même cellule je change d'agent et que dans une autre cellule j'essaie d'afficher le premier agent, la selection d el'agent est désactivée comme si cet agent était déjà affiché dans une cellule alors que ce n'est pas le cas

View File

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

View File

@ -0,0 +1,26 @@
---
id: "495699aa-d5d1-409f-8830-cdfaba7a4be3"
number: 58
title: "[B/F] Rendu live des tâches de fond — subscriber UI + canal IPC attachable au task output"
status: "open"
priority: "low"
sprint: null
links: [{"target":"#2","kind":"dependsOn"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784064521992
updatedAt: 1784064521992
version: 1
---
Sorti du ticket #2 lors de sa requalification (2026-07-14).
Le hub broadcast PTY (crates/infrastructure/src/pty/mod.rs) rend désormais possible un tee de la sortie d'une tâche de fond vers l'UI sans voler le flux au runner. Une fois #2 livré (découplage fin-de-process via PtyPort::wait, l'ajout d'un subscriber UI ne casse plus la détection de fin), brancher le rendu live.
Attendu :
- Backend : créer un subscriber `pty.subscribe_output(&handle)` pour la tâche de fond ; canal dédié par task vers le frontend (idéalement Tauri `Channel`, comme les terminaux) ; commande type `attach_background_task_output(taskId, channel)` (ou intégration au panneau workstate).
- Frontend : composant/UX affichant le flux live, gérant attach/detach, repaint via `scrollback` au (ré)attachement, état terminal.
QA : deux subscribers reçoivent les mêmes chunks ; le runner complète même pendant qu'un subscriber UI reste attaché ; reattach UI récupère le scrollback puis reçoit les nouveaux chunks.
Dépend de #2 (PtyPort::wait/try_wait + découplage runner).

View File

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

View File

@ -0,0 +1,35 @@
---
id: "623b1719-c71d-448e-a0ef-3c7d5823b8a3"
number: 60
title: "[Bug] Assistant IA d'édition de ticket : aucune réponse dans la conversation (stream sans Final non signalé)"
status: "inProgress"
priority: "high"
sprint: null
links: [{"target":"#25","kind":"relatesTo"},{"target":"#27","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784094260499
updatedAt: 1784095176619
version: 2
---
Rapporté par l'utilisateur (2026-07-15) : dans l'édition d'un ticket, le bouton « Assistant IA » ouvre une conversation, mais l'envoi d'un message ne produit JAMAIS de réponse visible — la conversation reste muette. PROFIL UTILISÉ : modèle local OpenAI-compatible (llamacpp).
CAUSE (Architect) :
1. CONFIRMÉ code — silence sur stream sans Final : agent_send draine le flux et détache le canal SANS rien émettre si aucun ReplyChunk::Final n'est produit (commands.rs:1661-1691). Le frontend ne termine que sur `final` (useTicketAssistant.ts:138-144). + finally setBusy(false) prématuré (useTicketAssistant.ts:147-151).
2. PROBABLE runtime (local OpenAI-compatible) — Final VIDE : le chemin HTTP émet bien un Final quand le serveur renvoie choices[0].message.content ou SSE delta.content (openai_compat.rs:348-397/517-538/286-292), mais llama.cpp peut renvoyer un flux sans delta.content utile (reasoning_content / tool_calls / contenu vide) → ReplyEvent::Final { content: "" } → le frontend remplace le tour par une chaîne vide (useTicketAssistant.ts:138-140) = « muet ».
PÉRIMÈTRE DE CE TICKET (#60) — Lot A robustesse + gestion Final vide, B+F, S/M :
- Backend : étendre ReplyChunk avec Error { message } (crates/app-tauri/src/dto.rs). agent_send : si le stream finit sans Final → émettre ReplyChunk::Error avant detach_if. Traiter Final { content: "" } comme terminal visible (Error « réponse vide du modèle » ou fallback explicite). Si l'adapter dispose d'un reasoning_content non vide, envisager de le surfacer plutôt que de le jeter (à confirmer selon payload).
- Frontend : ReplyChunk TS + useTicketAssistant gère `error`, termine le pending, affiche le message, busy tombe sur final OU error, suppression du finally setBusy(false) prématuré.
Effet attendu : l'assistant ne reste JAMAIS muet — soit une réponse, soit une erreur/vide explicite visible.
QA :
- Backend agent_send : fake AgentSession renvoie Heartbeat puis EOF sans Final → le channel reçoit ReplyChunk::Error.
- Backend OpenAI-compatible : fake HTTP renvoie SSE [DONE] sans delta.content → terminal visible (erreur/non vide), jamais un tour muet.
- Frontend : sendTicketChat reçoit `error` → tour non pending, busy=false, message visible.
HORS PÉRIMÈTRE (→ ticket de suivi) : identité requester explicite (port AgentSessionFactory::start, factory.rs:153-157 dérive le requester du cwd → devient le n° de ticket au lieu de ticket-assistant:<project>:<issue>) + branchement de ToolPolicyRegistry sur l'invoker OpenAI-compatible (openai_tools.rs:92-145) + éventuel local_model_server_id sur HttpChatConfig. Concerne un port figé + la sécurité des tool calls.
Relations : #25, #27 (mêmes surfaces, déjà fermées).

View File

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

View File

@ -0,0 +1,16 @@
---
id: "b0568a4e-4804-480c-ada4-bc9d6b7b40c6"
number: 61
title: "[UI] rafraichissement des cellule"
status: "open"
priority: "low"
sprint: "e28a4d53-8bd2-446a-b0ac-2a017373b8b2"
links: []
agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}]
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1784095163730
updatedAt: 1784182133142
version: 5
---
Lorsque j'ajoute une nouvelle cellule ou que j'en enlève une, je suis obligé de redimentionner un coup la fenêtre ou les cellule pour rafraichir le scaling des cli

View File

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

View File

@ -0,0 +1,31 @@
---
id: "dd897d74-4e88-4d34-a6fb-d7e7f330094f"
number: 62
title: "[Sécurité/Cohérence] Identité requester explicite pour les sessions structurées + policy des tools OpenAI-compatible"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#60","kind":"relatesTo"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784095187734
updatedAt: 1784095187734
version: 1
---
Sorti de #60 (assistant IA de ticket muet) — volet distinct, touchant un port figé et la sécurité des tool calls.
CONSTAT (Architect, cadrage #60) :
1. Le requester d'une session structurée est dérivé implicitement du nom du cwd/run dir (crates/infrastructure/src/session/factory.rs:153-157). Pour l'assistant de ticket, le requester devient donc le NUMÉRO DU TICKET, alors que la policy MCP est posée sur ticket-assistant:<project>:<issue> (crates/application/src/ticket_assistant.rs:100-119). Mismatch → incohérence d'attribution et policy potentiellement non appliquée.
2. L'invoker de tools OpenAI-compatible (AppOpenAiToolInvoker, openai_tools.rs:92-145) dispatch directement SANS consulter ToolPolicyRegistry, alors que le serveur MCP stdio applique bien la policy (mcp/server.rs:349-355, :470-512). Les tool calls d'un profil OpenAI-compatible ne sont donc pas soumis à la policy.
ATTENDU :
- Faire évoluer le port AgentSessionFactory::start pour recevoir une identité requester explicite (Option<&str> ou petit SessionIdentity) ; fallback sur cwd.file_name() seulement si absente. Impact : port figé → propagation aux impls/fakes.
- OpenTicketAssistant passe requester = ticket-assistant:<project>:<issue>.
- LaunchAgent passe l'agent id comme requester pour les cellules normales (au lieu de dépendre du nom du run dir).
- Brancher ToolPolicyRegistry sur l'invoker OpenAI-compatible (parité avec le serveur MCP stdio).
- Décider pour le modèle local managé : étendre HttpChatConfig avec local_model_server_id (appeler EnsureLocalModelServer avant OpenAiCompatibleSession::new) OU documenter que OpenAI-compatible = endpoint externe.
Cadrage Architect requis (port figé + sécurité). QA : un assistant ticket OpenAI-compatible qui appelle idea_ticket_update reçoit __ideaRequester = ticket-assistant:<project>:<issue> et la policy ticket est appliquée ; un tool refusé par la policy l'est aussi sur le chemin OpenAI-compatible.
Dépend de / relié à #60.

View File

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

View File

@ -0,0 +1,15 @@
---
id: "b5753734-1474-48d5-af6c-4a41b78005dc"
number: 63
title: "Systeme de test de l'UI"
status: "open"
priority: "medium"
sprint: null
links: []
agentRefs: []
createdBy: {"kind":"user"}
updatedBy: {"kind":"user"}
createdAt: 1784098438671
updatedAt: 1784098438671
version: 1
---

View File

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

View File

@ -0,0 +1,31 @@
---
id: "c8f1c5b3-7674-4c6c-bba5-bb2c5faf201b"
number: 64
title: "Web : créer/ajouter un projet depuis le navigateur (folder browser serveur)"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#13","kind":"dependsOn"},{"target":"#66","kind":"dependsOn"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784183727404
updatedAt: 1784187610934
version: 2
---
Issu de la validation live de #13 (mode client/serveur web). En web, le bouton « Browse » (choisir un dossier de projet) est inopérant : `pickFolder()` renvoie `UNSUPPORTED_ON_WEB` car il s'appuie sur le dialogue natif OS de Tauri, absent du navigateur. Sélectionner un projet EXISTANT est déjà couvert par la liste (list_projects/open_project). Il manque CRÉER/AJOUTER un projet = choisir un dossier côté SERVEUR.
Cadrage Architect (post-#13) : nouvelle surface backend exposant le filesystem serveur au navigateur, à sandboxer.
Backend :
- Commande read `list_server_dir` (racine parcourable explicite via `--server-browse-root PATH` / `IDEA_SERVER_BROWSE_ROOT` ; défaut prudent : aucun browsing ou $HOME en loopback ; jamais `/` implicite).
- `create_project` sur l'allowlist WRITE, avec sa propre validation de racine (ne fait pas confiance au folder browser).
- Invariants sécurité (mêmes gardes que serve_static) : canonicalisation browse_root + cible, refus si hors racine, refus `..`/segments vides/backslash/`%2e`/`%2f`/`%5c`, dossiers seulement, pas de symlink escape, dotdirs masqués (`hidden:true`), réponse bornée + tri stable.
DTO :
- ListServerDirRequest { path?: string } → ListServerDirResponse { root, current, parent|null, entries: [{name,path,kind:'directory',hidden}], canCreateProjectHere }
- CreateProjectRequest { name, root(absolu serveur validé) }
Découpage : B1 list_server_dir + tests traversal/symlink/bounds ; B2 allowlist write create_project + validation racine ; F1 nouveau port UI `ServerFolderGateway` (ne pas surcharger `SystemGateway.pickFolder()`) ; F2 composant folder browser web (desktop garde le picker natif) ; F3 tests adapter HTTP + vue projet.
Dépend de #13 (mode web) et du garde-fou lock inter-process app-data-dir (à créer) avant d'activer les écritures web.

View File

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

View File

@ -0,0 +1,27 @@
---
id: "f9f7067b-92b7-4737-ad99-4487ad8c8b13"
number: 65
title: "Serveur headless : extraire idea-serve du binaire Tauri (cœur partagé)"
status: "open"
priority: "high"
sprint: null
links: [{"target":"#13","kind":"dependsOn"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784187583229
updatedAt: 1784187583229
version: 1
---
Objectif : produire un binaire serveur headless (`idea-serve`) SANS dépendance Tauri/WebKit, bâti sur le même cœur backend que le desktop (pas de fork). Prérequis de l'image Docker serveur/client. Cadré par Architect (suite #13).
Point pivot : `server.rs` vit aujourd'hui dans `crates/app-tauri` et réutilise indirectement la présentation Tauri via `crate::state::AppState`, `crate::dto::*`, `crate::events::DomainEventDto`, `crate::pty::PtyChunk`, `crate::mcp_endpoint::*`, `ResumeContext`. Le protocole HTTP/WS lui est déjà autonome.
Plan de lots (Architect) :
- **L1 — Extraire les DTO transport-neutres** dans un module/crate partagé (ex. `crates/presentation-dto` ou `backend-api`) : ErrorDto, Health*Dto, ProjectDto/ProjectListDto, ProjectWorkStateDto, BackgroundTaskDto, TerminalSessionDto, LaunchAgentRequestDto, OpenTerminalRequestDto, parseurs d'IDs, DomainEventDto. Adapter app-tauri::commands ET server.rs pour les consommer. JSON INCHANGÉ.
- **L2 — Extraire le serveur HTTP/WS** dans `crates/web-server` (lib) sans dépendance Tauri : déplacer server.rs, remplacer `AppState` par `BackendCore`, garder strictement routes + allowlist + sécurité B8 (POST /api/pair|invoke|logout, /api/ws, static same-origin). Aucune modif frontend.
- **L3 — Créer le bin `idea-serve`** (crate bin) : parse CLI/env → config → `web_server::run(config)`. Flags identiques à `idea --serve` (--listen/--app-data-dir/--web-root/--allow-remote/--public-origin/--trust-reverse-proxy). Défaut local = même app-data-dir que desktop (identifier app.idea.ide). Validation : le build/`ldd` ne tire PAS WebKitGTK. Garder éventuellement `app-tauri --serve` en compat dev, mais qui appelle `web-server`.
Invariants : desktop AppImage ne perd RIEN, aucun import Tauri dans le bin headless, même cœur/use cases/stores, contrat HTTP/WS inchangé. Non-régression desktop validée avant tout merge.
Dépend de #13.

View File

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

View File

@ -0,0 +1,27 @@
---
id: "f805cd9b-8ecd-401a-8f03-665a27fe73cb"
number: 66
title: "Image Docker serveur/client IdeA"
status: "open"
priority: "medium"
sprint: null
links: [{"target":"#65","kind":"dependsOn"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784187597004
updatedAt: 1784187597004
version: 1
---
Objectif : livrer une image Docker exécutant le mode serveur/client d'IdeA, bâtie sur le binaire headless `idea-serve` (#65), pas sur le binaire Tauri. Cadré par Architect (suite #13).
Plan de lots (Architect) :
- **L4 — Build web transport HTTP** : produire les assets client Vite en `VITE_TRANSPORT=http` (npm, jamais pnpm), vérifier qu'aucun import Tauri ne fuit dans ce mode, packager dans `/usr/share/idea/web`.
- **L5 — Docker runtime** : Dockerfile multi-stage (build Rust headless + build frontend + runtime minimal Debian/Ubuntu selon deps PTY/process). Défauts : `IDEA_APP_DATA_DIR=/data`, `--listen 0.0.0.0:17373`, `--web-root /usr/share/idea/web`. Volumes `/data` (app-data : projects/profiles/templates/tasks/logs) et `/workspace` (projets manipulés par les agents). Entrypoint `idea-serve`. Healthcheck HTTP local. Conteneur reste HTTP interne ; reverse proxy TLS externe obligatoire en prod distante (`--allow-remote`/`--public-origin https`/`--trust-reverse-proxy`, doc B8). Pas de TLS applicatif V1.
- **L6 — Agents CLI en conteneur** : décider image minimale (profils détectés au runtime, exécutables attendus dans PATH) vs image `idea-server-agents` (CLIs redistribuables installées si licence OK). Seed profils compatibles conteneur. Documenter env (OPENAI_API_KEY, ANTHROPIC_API_KEY, vars opencode) et montages de credentials. Tester au moins un agent bout en bout. Hors périmètre : installer automatiquement des CLIs propriétaires sans validation licence.
Lock app-data-dir : peu critique en Docker mono-conteneur mono-writer ; multi-conteneurs sur le même /data explicitement hors support sans lock distribué.
Hors périmètre V1 : Kubernetes, multi-tenant, auth externe, TLS intégré.
Dépend de #65 (binaire headless).

View File

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

View File

@ -0,0 +1,22 @@
---
id: "e3d16c70-01c5-448e-9b5e-37ba2ccbbb58"
number: 67
title: "Lock inter-process de l'app-data-dir (desktop ↔ idea --serve)"
status: "open"
priority: "low"
sprint: null
links: [{"target":"#13","kind":"dependsOn"}]
agentRefs: []
createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
createdAt: 1784187618710
updatedAt: 1784187618710
version: 1
---
Issu de la validation live #13. `idea --serve` et l'app desktop peuvent écrire le même app-data-dir (`~/.local/share/app.idea.ide`) simultanément — pas de lock inter-process → risque de corruption d'état (projects.json/profiles.json/tasks). Aujourd'hui contourné par une simple consigne de doc (« ne pas lancer les deux en même temps »).
À faire : garde-fou lock inter-process partagé desktop/serveur sur l'app-data-dir (le desktop DOIT le prendre aussi, un lock côté serveur seul ne suffit pas). À poser AVANT d'ouvrir des commandes write web au-delà de l'existant (cancel/retry background) — notamment avant `create_project` (#64).
Peu critique en Docker mono-conteneur mono-writer (cf. #66) ; surtout pertinent pour l'usage AppImage `--serve` local sur la même machine que le desktop. Cadrage lock détaillé à confirmer avec Architect au démarrage.
Dépend de #13.

View File

@ -1,3 +1,3 @@
{
"nextNumber": 55
"nextNumber": 68
}

View File

@ -16,26 +16,26 @@
{
"issueRef": "#2",
"path": "2",
"title": "Tâches de fond — dette A : PtyPort::wait/try_wait + tee live UI + robustesse détection de fin",
"status": "open",
"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": null,
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [
"a6ced819-b893-4213-b003-9e9dc79b9641"
],
"updatedAt": 1783184142093
"updatedAt": 1784065385002
},
{
"issueRef": "#3",
"path": "3",
"title": "Tâches de fond — dette B : persistance sûre de l'invocation (retry-after-reboot, secrets) + énumération terminale/projet du store",
"title": "[Différé — design à mûrir] Tâches de fond — dette B : retry durable après reboot",
"status": "open",
"priority": "low",
"sprint": null,
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [
"a6ced819-b893-4213-b003-9e9dc79b9641"
],
"updatedAt": 1783184146749
"updatedAt": 1784093835732
},
{
"issueRef": "#4",
@ -149,13 +149,13 @@
"issueRef": "#13",
"path": "13",
"title": "Server/client mode",
"status": "open",
"status": "inProgress",
"priority": "low",
"sprint": "028179b1-eaf4-41e9-9c1f-7c37125117e6",
"assignedAgentIds": [
"a6ced819-b893-4213-b003-9e9dc79b9641"
],
"updatedAt": 1783329397368
"updatedAt": 1784184002362
},
{
"issueRef": "#14",
@ -172,12 +172,12 @@
{
"issueRef": "#15",
"path": "15",
"title": "Limites de session — re-livraison automatique parquée au reset (stretch B5, délégation durable)",
"title": "[Bloqué par #7 — design durable] Limites de session — re-livraison auto parquée au reset (stretch B5)",
"status": "open",
"priority": "low",
"sprint": "d8f3f37b-87ca-4509-9116-45a99bc711df",
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [],
"updatedAt": 1783940786085
"updatedAt": 1784093861343
},
{
"issueRef": "#16",
@ -229,11 +229,11 @@
"issueRef": "#20",
"path": "20",
"title": "[Backend] Dette ticket_list — matching #ref dans text + curseur opaque/stable",
"status": "open",
"status": "closed",
"priority": "low",
"sprint": null,
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [],
"updatedAt": 1783331176736
"updatedAt": 1784049665491
},
{
"issueRef": "#21",
@ -333,11 +333,11 @@
"issueRef": "#31",
"path": "31",
"title": "Détection de profils séquentielle : N × 800 ms au pire, résultat potentiellement partiel",
"status": "open",
"status": "closed",
"priority": "low",
"sprint": null,
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [],
"updatedAt": 1783491197541
"updatedAt": 1784064442657
},
{
"issueRef": "#32",
@ -355,21 +355,21 @@
"issueRef": "#33",
"path": "33",
"title": "[Dette] Fallthrough silencieux du routage structuré (lifecycle.rs:1705)",
"status": "open",
"status": "closed",
"priority": "high",
"sprint": null,
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [],
"updatedAt": 1783492190391
"updatedAt": 1784048928225
},
{
"issueRef": "#34",
"path": "34",
"title": "[Risque] ChatBridge.scrollback non borné (croissance mémoire)",
"status": "open",
"status": "closed",
"priority": "medium",
"sprint": null,
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [],
"updatedAt": 1783492562056
"updatedAt": 1784050010085
},
{
"issueRef": "#35",
@ -581,11 +581,127 @@
"issueRef": "#54",
"path": "54",
"title": "[UI] Ajouter le handle du téléchargement des modeles lors du démarage llamacpp",
"status": "inProgress",
"status": "closed",
"priority": "medium",
"sprint": "5afd6780-0f76-40d7-a10f-32ee52469d74",
"assignedAgentIds": [],
"updatedAt": 1783976286882
"updatedAt": 1784018300921
},
{
"issueRef": "#55",
"path": "55",
"title": "[Bug] Error on loading local model",
"status": "inProgress",
"priority": "high",
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [
"a6ced819-b893-4213-b003-9e9dc79b9641"
],
"updatedAt": 1784097757001
},
{
"issueRef": "#56",
"path": "56",
"title": "[Bug] selection desactivée d'agent non affichés",
"status": "closed",
"priority": "low",
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [
"a6ced819-b893-4213-b003-9e9dc79b9641"
],
"updatedAt": 1784048212123
},
{
"issueRef": "#58",
"path": "58",
"title": "[B/F] Rendu live des tâches de fond — subscriber UI + canal IPC attachable au task output",
"status": "open",
"priority": "low",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784064521992
},
{
"issueRef": "#60",
"path": "60",
"title": "[Bug] Assistant IA d'édition de ticket : aucune réponse dans la conversation (stream sans Final non signalé)",
"status": "inProgress",
"priority": "high",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784095176619
},
{
"issueRef": "#61",
"path": "61",
"title": "[UI] rafraichissement des cellule",
"status": "open",
"priority": "low",
"sprint": "e28a4d53-8bd2-446a-b0ac-2a017373b8b2",
"assignedAgentIds": [
"a6ced819-b893-4213-b003-9e9dc79b9641"
],
"updatedAt": 1784182133142
},
{
"issueRef": "#62",
"path": "62",
"title": "[Sécurité/Cohérence] Identité requester explicite pour les sessions structurées + policy des tools OpenAI-compatible",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784095187734
},
{
"issueRef": "#63",
"path": "63",
"title": "Systeme de test de l'UI",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784098438671
},
{
"issueRef": "#64",
"path": "64",
"title": "Web : créer/ajouter un projet depuis le navigateur (folder browser serveur)",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784187610934
},
{
"issueRef": "#65",
"path": "65",
"title": "Serveur headless : extraire idea-serve du binaire Tauri (cœur partagé)",
"status": "open",
"priority": "high",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784187583229
},
{
"issueRef": "#66",
"path": "66",
"title": "Image Docker serveur/client IdeA",
"status": "open",
"priority": "medium",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784187597004
},
{
"issueRef": "#67",
"path": "67",
"title": "Lock inter-process de l'app-data-dir (desktop ↔ idea --serve)",
"status": "open",
"priority": "low",
"sprint": null,
"assignedAgentIds": [],
"updatedAt": 1784187618710
}
]
}