État d'exécution accumulé (tickets créés/mis à jour hors #43, notes de mémoire, tâche de fond) capturé au moment du commit de la feature. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
11 KiB
issueRef, version, updatedBy, updatedAt
| issueRef | version | updatedBy | updatedAt | ||||
|---|---|---|---|---|---|---|---|
| #81 | 5 |
|
1784565918809 |
Cadrage — ticket #81
Objectif
Permettre aux agents IdeA d'administrer les templates d'agents via MCP, sans surface humaine nouvelle : créer, éditer et supprimer des templates globaux IdeA depuis des tools idea_*.
UX n'est pas concerné pour ce ticket : il n'y a pas d'écran, de workflow humain ni de libellés UI à concevoir. La seule surface est le catalogue MCP exposé aux agents.
État réel du système templates
Surfaces inspectées :
- Domaine :
crates/domain/src/template.rs - Port :
TemplateStoredanscrates/domain/src/ports.rs - Use cases :
crates/application/src/template/usecases.rs - Store :
crates/infrastructure/src/store/template.rs - Commands Tauri :
crates/app-tauri/src/commands.rs - DTO :
crates/backend/src/dto.rs/crates/app-tauri/src/dto.rs - Frontend existant :
frontend/src/features/templates/*,frontend/src/adapters/template.ts - MCP + permissions #82 :
crates/infrastructure/src/orchestrator/mcp/tools.rs,server.rs,backend/src/openai_tools.rs,app-tauri/src/openai_tools.rs
Templates existants :
AgentTemplate {
id: TemplateId,
name: String,
content_md: MarkdownDoc,
version: TemplateVersion,
default_profile_id: ProfileId,
}
Invariants existants :
namenon vide ;versiondémarre à1;versionest bumpée parAgentTemplate::with_updated_content, donc par changement de contenu Markdown ;default_profile_idsert aux futurs agents créés depuis le template.
Stockage existant : global app-data, pas projet :
<app_data_dir>/templates/
├── index.json
└── md/<template-id>.md
index.json porte les métadonnées (id, name, version, contentHash, defaultProfileId) ; le Markdown vit dans md/<id>.md. Le store est déjà derrière TemplateStore, donc Tauri-agnostique côté infra.
Synchronisation template → agents
Les agents créés depuis un template copient le content_md dans leur propre contexte .md projet et gardent dans le manifeste :
template_idsynchronizedsynced_template_version
UpdateTemplate actuel met à jour le template global, bump la version et publie DomainEvent::TemplateUpdated. Il ne modifie pas directement les agents existants.
DetectAgentDrift compare template.version > synced_template_version pour les agents synchronized == true et publie AgentDriftDetected.
SyncAgentWithTemplate est l'opération explicite qui remplace le .md de l'agent synchronisé par le contenu courant du template et met à jour synced_template_version.
Conclusion : si un agent édite un template via MCP, les agents synchronisés qui l'utilisent ne sont pas impactés immédiatement. Ils deviennent en drift jusqu'à appel explicite de sync. Au lancement suivant, ils relisent leur .md agent existant, pas automatiquement le template global. Ce comportement doit rester tel quel pour #81, sauf arbitrage produit séparé.
Tools MCP à ajouter
Ajouter une surface templates explicite ; idea_skill_read, idea_context_read et les tools existants ne couvrent pas les templates. Les templates ne sont ni des skills ni des contextes agent.
Proposition de catalogue :
Lecture, autorisée par défaut (#82)
-
idea_template_list- Rôle : lister les templates globaux disponibles.
- Payload conseillé : templates complets ou résumés. Pour l'ergonomie agent, retour complet acceptable au premier lot (
id,name,contentMd,version,defaultProfileId) carListTemplatesrenvoie déjà les entités complètes.
-
idea_template_read- Rôle : lire un template par id.
- Input :
{ "templateId": "..." } - Retour : même DTO qu'un template Tauri.
- Nécessite un thin use case
ReadTemplateou un provider qui appelleTemplateStore::getvia un use case applicatif dédié.
Écriture/action, refusée par défaut (#82)
-
idea_template_create- Input :
{ name, content, defaultProfileId } - Réutilise
CreateTemplate. - Retour : template créé.
- Input :
-
idea_template_update- Input minimal aligné existant :
{ templateId, content }. - Réutilise
UpdateTemplateactuel, qui met à jour le contenu et bump la version. - Extension recommandée si on veut couvrir pleinement "éditer" : accepter aussi
name?etdefaultProfileId?, avec bump de version seulement sicontentchange. Cela nécessite d'étendre le domaine/use case car aujourd'hui l'UI elle-même ne persiste pas le changement de nom/profil en mode edit. - Option de sûreté à arbitrer : ajouter
expectedVersionpour éviter les écrasements concurrents entre agents. Le store/use case Tauri actuel n'a pas d'optimistic concurrency sur templates, donc ce serait une extension de contrat, pas une simple exposition MCP.
- Input minimal aligné existant :
-
idea_template_delete- Input :
{ templateId } - Réutilise
DeleteTemplate. - Effet existant : supprime de l'index global ; le fichier Markdown orphelin peut rester sur disque car le port FS n'a pas de delete. Les agents créés depuis ce template gardent leur
.md; drift detection ignore le template absent.
- Input :
Intégration obligatoire avec #82
#82 a introduit la classification canonique dans crates/infrastructure/src/orchestrator/mcp/tools.rs :
READ_ONLY_TOOLSWRITE_ACTION_TOOLStool_access- test garde-fou
catalogue_tools_have_explicit_read_or_write_access
Tout tool ajouté au catalogue doit être classé immédiatement, sinon le test doit échouer.
Classification #81 attendue :
READ_ONLY_TOOLS += [
"idea_template_list",
"idea_template_read",
]
WRITE_ACTION_TOOLS += [
"idea_template_create",
"idea_template_update",
"idea_template_delete",
]
Comportement policy attendu :
- agent sans override #82 : peut lire/lister les templates, ne peut pas créer/éditer/supprimer ;
- agent avec override incluant un ou plusieurs tools
idea_template_*d'écriture : peut seulement appeler ceux explicitement autorisés ; - le refus doit arriver avant effet applicatif, sur le serveur MCP stdio et sur l'invoker OpenAI-compatible.
Ce comportement est cohérent avec la demande #82 : par défaut seuls les tools de lecture sont autorisés. Pas d'arbitrage produit nécessaire sauf si l'utilisateur veut que certains agents aient une permission template-write préconfigurée par défaut.
Point d'implémentation recommandé
Ne pas ajouter ces opérations au OrchestratorCommand sauf nécessité. Les templates sont une famille CRUD applicative, comme les tickets, pas un protocole d'orchestration inter-agent. Le pattern le plus local est donc de créer un provider MCP dédié, parallèle à TicketToolProvider :
-
crates/infrastructure/src/orchestrator/mcp/templates.rsTemplateToolProviderTemplateToolErroris_template_tool(name)catalogue()des tools templates
-
crates/infrastructure/src/orchestrator/mcp/tools.rs- étendre
catalogue()avectemplates::catalogue(); - ajouter
is_template_tool; - ajouter les 5 tools dans les classifications #82 ;
- si besoin, faire retourner
tool_returns_replypour les read/create/update/list/delete selon convention (delete peut retourner un ACK JSON).
- étendre
-
crates/infrastructure/src/orchestrator/mcp/server.rs- ajouter
template_tools: Option<Arc<dyn TemplateToolProvider>>; - dans
tools_call, après enforcement #82 et avantmap_tool_call, routeris_template_toolvers le provider, comme les tickets ; - garder l'enforcement durable/éphémère avant provider.
- ajouter
-
Composition root backend/app-tauri
- créer
LateBoundTemplateToolProvidersi besoin pour casser les cycles commeLateBoundTicketToolProvider; - binder un
AppTemplateToolProviderconstruit aveccreate_template,list_templates,update_template,delete_templateet le nouveauread_templatesi ajouté ; - injecter ce provider dans
McpServer::new(...).with_template_tools(...); - injecter aussi dans
AppOpenAiToolInvokerpour parité OpenAI-compatible.
- créer
Alternative possible : ajouter des variants OrchestratorCommand::Template* et mapper les tools via map_tool_call. Je ne la recommande pas en premier choix : cela gonfle l'orchestrateur avec un CRUD global qui n'est pas une coordination agent-agent, alors que le précédent ticket système a déjà accepté le pattern provider pour les tickets.
Lots proposés
Lot B1 — Catalogue MCP + classification #82 + provider squelette
- Ajouter
templates.rscôté MCP infra. - Ajouter les 5 tool defs.
- Classer immédiatement
idea_template_list/readen lecture etcreate/update/deleteen écriture/action. - Tests : garde-fou catalogue/classification vert ;
tools/listexpose les templates selon policy #82.
Lot B2 — Use cases/DTO/provider templates
- Ajouter
ReadTemplateuse case fin si on gardeidea_template_read. - Implémenter
AppTemplateToolProvideravec les use cases existants. - Mapper erreurs :
notFound,invalid,store,internal. - Tests provider : create/list/read/update/delete sur fakes, version bump sur update contenu.
Lot B3 — Enforcement policy + OpenAI-compatible parity
- Vérifier MCP stdio : un agent default read-only peut
idea_template_list/read, maisidea_template_create/update/deleteest refusé avant provider. - Vérifier override #82 : autoriser seulement
idea_template_updaten'autorise pas create/delete. - Répliquer le dispatch provider dans
AppOpenAiToolInvoker, avec même policy durable avant effet.
Lot B4 — Édition complète optionnelle
À faire seulement si le produit veut que "éditer" couvre autre chose que le contenu Markdown :
- étendre
UpdateTemplateInputavecname?,defaultProfileId?,content?; - préserver l'invariant : bump version uniquement quand
content_mdchange ; - décider si changement de
defaultProfileIddoit avoir un effet sur agents existants (recommandation : non, seulement futursCreateAgentFromTemplate) ; - ajouter éventuellement
expectedVersionpour update/delete, avec erreur de conflit.
Frontières
Frontend/UX : hors périmètre. Aucune surface humaine nouvelle.
Domaine templates : réutiliser AgentTemplate, TemplateVersion, TemplateStore. Extension domaine seulement si B4 est retenu.
Projet .ideai/agents.json : hors périmètre pour CRUD templates. Les agents créés depuis template et leur sync existante restent inchangés.
Synchronisation automatique : hors périmètre. #81 ne doit pas auto-écraser les .md des agents synchronisés après update template ; laisser DetectAgentDrift/SyncAgentWithTemplate piloter cela.
Permissions #82 : dans le périmètre obligatoire. Aucun tool template ne doit entrer dans le catalogue sans classification explicite et sans enforcement identique MCP stdio/OpenAI-compatible.
Critères d'acceptation
- Les agents voient les tools template dans le catalogue MCP selon leur policy #82.
- Les tools lecture template sont accessibles à un agent sans override.
- Les tools create/update/delete sont refusés à un agent sans override, avant mutation.
- Une policy agent qui autorise un write template permet uniquement ce write.
idea_template_updatebump la version quand le contenu change et publieTemplateUpdatedvia le use case existant.- Les agents synchronisés au template passent en drift, mais ne sont pas modifiés tant qu'un sync explicite n'est pas demandé.
- Les chemins MCP stdio et OpenAI-compatible ont la même sémantique et les mêmes refus.