Compare commits
97 Commits
17d6baf15a
...
feature/11
| Author | SHA1 | Date | |
|---|---|---|---|
| 045e0984cc | |||
| 78f7c8fe2d | |||
| 851f1f8f2c | |||
| 41aa2789a7 | |||
| f4895208d7 | |||
| 88a5256a1e | |||
| efbd084b7d | |||
| b734c237d3 | |||
| e1d8f5885f | |||
| 6f532d7434 | |||
| ce375c3e70 | |||
| 0b83b5bbd2 | |||
| e74a9703f9 | |||
| 865f90eafd | |||
| d7b6038f23 | |||
| cf074a7d61 | |||
| 038e90ecec | |||
| 02603441c1 | |||
| 4321d048ac | |||
| ca70ec75f4 | |||
| e7bf1d3666 | |||
| e5bafc30e7 | |||
| ea7ea71230 | |||
| c807a70fea | |||
| d741035c47 | |||
| 455eba3f91 | |||
| 13ff1a4f51 | |||
| 480cdc41ac | |||
| 0821739924 | |||
| b5d7e16501 | |||
| dae07d35bb | |||
| 13fb538880 | |||
| 3047dc9195 | |||
| e8731834f4 | |||
| 6e98fd89f7 | |||
| da907b880e | |||
| 6a87c4635f | |||
| ad491e765f | |||
| 69e5878679 | |||
| 55330732dd | |||
| 0f0a76d806 | |||
| 7fee56acf5 | |||
| 6e9a3ff657 | |||
| 7d3e74a114 | |||
| 56631bd3c8 | |||
| c9fffd7c47 | |||
| 0f57e7323a | |||
| 4ac2dd1568 | |||
| 557d1c3f24 | |||
| e8f6e9eded | |||
| ef747cd156 | |||
| 1784027f5d | |||
| e943a0efed | |||
| 162e3ae641 | |||
| 12c7d103d0 | |||
| c181b43d04 | |||
| 23a3c2788f | |||
| bece7c92c5 | |||
| 98fb05447d | |||
| ac726d075e | |||
| bb35641715 | |||
| 47aacc6da9 | |||
| 3a18556ffa | |||
| a197197a90 | |||
| 4fd339c047 | |||
| e9b01795d1 | |||
| 30f6415d51 | |||
| cb2d0c2d44 | |||
| 678ff3011b | |||
| 277a0e494a | |||
| 1139041603 | |||
| 527c2dde61 | |||
| e7f67bada9 | |||
| e69361feb7 | |||
| 45def4844a | |||
| 5a7431b442 | |||
| 5d262231e2 | |||
| 60f4b33e53 | |||
| 8509653e3c | |||
| 294865f805 | |||
| ef84d5cc49 | |||
| 448edfc364 | |||
| c3078875f4 | |||
| 2db37a50fa | |||
| 5f15cdbf28 | |||
| c84a66f4e8 | |||
| eeba0ddb46 | |||
| 37ead61911 | |||
| 5175589aa5 | |||
| 32408b5232 | |||
| b4a34b40e5 | |||
| a7abd331b8 | |||
| 8387c1bbdf | |||
| 6e92536d84 | |||
| 348bccae34 | |||
| a69c5db093 | |||
| 445ecaf82e |
12
.gitignore
vendored
12
.gitignore
vendored
@ -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
93
.ideai/agents/context.md
Normal 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
0
.ideai/agents/glm.md
Normal file
File diff suppressed because one or more lines are too long
363
.ideai/mcp-tool-permissions.json
Normal file
363
.ideai/mcp-tool-permissions.json
Normal 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"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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).
|
||||
41
.ideai/memory/codex-network-access-config-fix.md
Normal file
41
.ideai/memory/codex-network-access-config-fix.md
Normal 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.
|
||||
59
.ideai/memory/context-agent-token-offload-design.md
Normal file
59
.ideai/memory/context-agent-token-offload-design.md
Normal 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).
|
||||
25
.ideai/memory/model-catalogue-compat-cadrage.md
Normal file
25
.ideai/memory/model-catalogue-compat-cadrage.md
Normal 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é.
|
||||
@ -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é).
|
||||
@ -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).
|
||||
10
.ideai/memory/ticket103-network-permission-ux-surface.md
Normal file
10
.ideai/memory/ticket103-network-permission-ux-surface.md
Normal 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.
|
||||
54
.ideai/memory/ticket43-backend-b1-b4-qa-validation.md
Normal file
54
.ideai/memory/ticket43-backend-b1-b4-qa-validation.md
Normal 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.
|
||||
52
.ideai/memory/ticket43-plugin-system-final-qa-verdict.md
Normal file
52
.ideai/memory/ticket43-plugin-system-final-qa-verdict.md
Normal 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.
|
||||
31
.ideai/memory/ticket95-adapter-aware-liveness-probe.md
Normal file
31
.ideai/memory/ticket95-adapter-aware-liveness-probe.md
Normal 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 ».
|
||||
35
.ideai/memory/ticket97-opencode-provider-mutual-exclusion.md
Normal file
35
.ideai/memory/ticket97-opencode-provider-mutual-exclusion.md
Normal 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.
|
||||
83
.ideai/memory/ticket98-opencode-modelsdev-cache-seed.md
Normal file
83
.ideai/memory/ticket98-opencode-modelsdev-cache-seed.md
Normal 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é.
|
||||
51
.ideai/memory/tickets-70-100-102-ux-surface-scoping.md
Normal file
51
.ideai/memory/tickets-70-100-102-ux-surface-scoping.md
Normal 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.
|
||||
53
.ideai/memory/toolchain-rust-partage-acces-agents.md
Normal file
53
.ideai/memory/toolchain-rust-partage-acces-agents.md
Normal 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`.
|
||||
@ -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.
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
111
.ideai/skills/md/eb76ce50-c05c-443b-8ba5-36bda091a148.md
Normal file
111
.ideai/skills/md/eb76ce50-c05c-443b-8ba5-36bda091a148.md
Normal 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>
|
||||
```
|
||||
6
.ideai/system-permissions.json
Normal file
6
.ideai/system-permissions.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"projectDefault": {
|
||||
"network": "allow"
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
@ -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 F1–F4). 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).
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#10"
|
||||
version: 5
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783241883970
|
||||
---
|
||||
@ -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)
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#11"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783278726067
|
||||
---
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#12"
|
||||
version: 5
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783312900907
|
||||
---
|
||||
@ -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
|
||||
@ -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).
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#16"
|
||||
version: 7
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783405334263
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#17"
|
||||
version: 10
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783405334977
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#18"
|
||||
version: 9
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783405335941
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#19"
|
||||
version: 8
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783405337651
|
||||
---
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#2"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1784065385002
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#20"
|
||||
version: 5
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1784049665491
|
||||
---
|
||||
@ -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é.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#21"
|
||||
version: 7
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783437364397
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#22"
|
||||
version: 5
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783437364871
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#23"
|
||||
version: 6
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783437365276
|
||||
---
|
||||
@ -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
|
||||
@ -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.
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#26"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783861758866
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#27"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783926649550
|
||||
---
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#28"
|
||||
version: 3
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783491458775
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#29"
|
||||
version: 5
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783921595742
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#3"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1784093835732
|
||||
---
|
||||
@ -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).
|
||||
@ -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é.
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#31"
|
||||
version: 4
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1784064442657
|
||||
---
|
||||
@ -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 ×.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#32"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783723378815
|
||||
---
|
||||
@ -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"
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#33"
|
||||
version: 4
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1784048928225
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#34"
|
||||
version: 4
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1784050010085
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#35"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783777898736
|
||||
---
|
||||
@ -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é
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#36"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783777899737
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#37"
|
||||
version: 7
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783878976369
|
||||
---
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#38"
|
||||
version: 7
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783879443381
|
||||
---
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#39"
|
||||
version: 5
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783921595316
|
||||
---
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#40"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783922451268
|
||||
---
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#41"
|
||||
version: 6
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783878363957
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#42"
|
||||
version: 2
|
||||
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
|
||||
updatedAt: 1783877612067
|
||||
---
|
||||
@ -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.
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
issueRef: "#43"
|
||||
version: 1
|
||||
updatedBy: {"kind":"user"}
|
||||
updatedAt: 1783879315858
|
||||
---
|
||||
@ -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
|
||||
---
|
||||
@ -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.
|
||||
@ -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
Reference in New Issue
Block a user