Files
IdeA/.ideai/tickets/86/carnet.md
Blomios 98fb05447d chore(ideai): état runtime — tickets, mémoire, tâches de fond
État d'exécution accumulé (tickets créés/mis à jour hors #43, notes de
mémoire, tâche de fond) capturé au moment du commit de la feature.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 07:37:19 +02:00

20 KiB

issueRef, version, updatedBy, updatedAt
issueRef version updatedBy updatedAt
#86 7
kind agent_id
agent a6ced819-b893-4213-b003-9e9dc79b9641
1784612705899

Conception UX — tickets et sprints dans le client web

Intention

La version web doit permettre de consulter et modifier les tickets/sprints sans reproduire le shell desktop. Le client web existant est une surface autonome en colonne verticale unique : après appairage, l'utilisateur choisit un projet, puis voit l'état live et les cellules agents. #86 doit ajouter une surface de pilotage tickets/sprints cohérente avec ce modèle mobile/web, pas importer les docks, fenêtres flottantes et overlays desktop.

Décision UX : réutiliser les contrats métier et les hooks transport-neutres autant que possible (useTickets, useTicketDetail, recherche, filtres, événements live), mais créer une présentation web dédiée. Ce n'est pas une version appauvrie en capacités, c'est une adaptation de navigation et de densité.

La cible prioritaire web/mobile est l'intervention rapide : lire, trier, changer statut/priorité, corriger titre/description/carnet, créer un ticket simple, assigner/désassigner, déplacer dans un sprint, créer/renommer/supprimer un sprint. Les opérations complexes restent disponibles mais rangées derrière des panneaux dédiés : liens entre tickets, carnet long, gestion complète des sprints.

Placement dans le client web

Dans WebWorkspace, après ouverture d'un projet, ajouter une navigation de projet compacte au-dessus des surfaces projet :

Projet: IdeA                                      [Rafraîchir]
[ Live ] [ Tickets ] [ Sprints ]
  • Live : surface actuelle État live, inchangée dans son rôle.
  • Tickets : nouvelle liste et édition des tickets.
  • Sprints : gestion des sprints.

Sur mobile, ces onglets sont des boutons segmentés scrollables horizontalement si nécessaire. Sur desktop web large, ils restent dans la même colonne contrainte, pas de dock ni layout grid.

Ne pas placer les tickets sous la liste des agents : ce sont deux surfaces de projet au même niveau. L'utilisateur web doit pouvoir passer de l'état live au backlog sans chercher dans une carte agent.

Vue Tickets — layout

La vue Tickets est une pile verticale : barre d'actions, recherche/filtres compacts, liste groupée par sprint, puis écran de détail lorsqu'un ticket est ouvert.

Tickets                                      [+ Ticket]
[Recherche…]
[Statut ▼] [Priorité ▼] [Assigné ▼] [Tri ▼]

Sprint courant (4)
#86  medium  open       Ajouter tickets/sprints au web
#83  medium  open       Confirmation fermeture

Sans sprint (2)
#78  low     open       Langue uniforme Settings

[Charger plus]

Sur petit écran, un ticket s'affiche comme une ligne compacte à deux étages :

#86  Ajouter tickets/sprints au web
open · medium · Sprint courant · Main

La ligne entière ouvre le détail. Les badges doivent rester textuels et lisibles ; ne pas empiler 5 pastilles colorées si elles provoquent un retour ligne incohérent à 360 px.

Actions prioritaires tickets

Priorité haute sur web :

  • consulter la liste ;
  • rechercher et filtrer ;
  • ouvrir un ticket ;
  • changer statut et priorité ;
  • éditer titre, description et carnet ;
  • créer un ticket simple ;
  • supprimer un ticket avec confirmation ;
  • assigner/désassigner des agents ;
  • changer le sprint d'un ticket.

Priorité secondaire, mais à conserver si les endpoints existent :

  • gérer les liens entre tickets ;
  • utiliser le TicketPicker adapté mobile pour lier/ajouter des tickets à un sprint ;
  • copier le contexte de délégation.

Hors périmètre recommandé pour la première livraison web : assistant IA de ticket. Le desktop peut garder cette affordance avancée ; sur mobile/web, elle ajoute du coût UI et des permissions sans être nécessaire à la demande utilisateur.

Création de ticket

Le bouton + Ticket ouvre un panneau plein écran mobile ou une section expansée desktop web, pas un petit formulaire inline permanent. Le formulaire est court :

  • Titre obligatoire ;
  • Priorité ;
  • Sprint avec picker ;
  • Description optionnelle, textarea repliable ou sous le champ titre ;
  • actions Annuler et Créer.

Après création : ouvrir automatiquement le détail du ticket créé pour permettre de compléter carnet, assignations ou liens. Si l'affectation sprint échoue après création, garder le ticket créé et afficher l'erreur sans perdre le résultat.

Libellés : Nouveau ticket, Titre, Description, Priorité, Sprint, Sans sprint, Créer.

Détail ticket sur petit écran

Sur web/mobile, le détail ticket remplace temporairement la liste dans la colonne, au lieu d'utiliser la fenêtre flottante desktop. Navigation : bouton retour en haut.

[← Tickets]  #86                         [⋯]
Ajouter tickets/sprints au web
open · medium · Sprint courant

[Résumé]
Titre
Description
[Enregistrer]

[Statut et priorité]
Statut       [open ▼]
Priorité     [medium ▼]
Sprint       [Sprint courant ▼]

[Carnet]
textarea Markdown
[Enregistrer le carnet]

[Agents assignés]
Main  DevFrontend                         [+]

[Liens]
relatesTo #83                             [+ Lier]

Les sections du détail sont accordéons ou blocs empilés. Ouverts par défaut : Résumé, Statut et priorité, Carnet. Repliés par défaut : Agents assignés, Liens, Zone dangereuse.

Le bouton de suppression vit dans une section Zone dangereuse ou dans un menu , jamais dans la première ligne d'actions. Confirmation obligatoire :

Titre : Supprimer ce ticket ? Corps : Le ticket {ref} sera supprimé définitivement. Cette action ne supprime pas les sprints ni les agents assignés. Actions : Annuler / Supprimer

Gestion des changements non enregistrés : si l'utilisateur revient à la liste avec des modifications locales non sauvegardées, afficher la confirmation existante adaptée en français : Des modifications ne sont pas enregistrées. avec Continuer l'édition, Ignorer, Enregistrer et quitter si techniquement disponible.

Édition rapide

Pour les champs à faible risque (statut, priorité, sprint), la modification peut être enregistrée immédiatement au changement de select, avec spinner discret sur la ligne/section. Pour les champs texte (titre, description, carnet), garder une action explicite Enregistrer afin d'éviter les sauvegardes involontaires sur mobile.

En cas de conflit de version : afficher un message inline en haut du détail : Ce ticket a été modifié ailleurs et rechargé. Réappliquez votre modification. Ne pas écraser silencieusement le brouillon local.

Vue Sprints — layout

La vue Sprints est une surface dédiée, pas un overlay plein écran au-dessus de la liste comme sur desktop. Elle est accessible depuis l'onglet projet Sprints et depuis le bouton Gérer les sprints dans la vue tickets si ce raccourci est conservé.

Sprints                                      [+ Sprint]

#1  Sprint courant                           [⋯]
4 tickets
[Voir tickets] [Ajouter tickets]

#2  Backlog client web                       [⋯]
7 tickets
[Voir tickets] [Ajouter tickets]

Créer un sprint : bouton + Sprint, champ Nom du sprint, action Créer. Si le nom est vide, soit désactiver Créer, soit reprendre le comportement desktop de nom automatique Sprint N; préférence UX web : désactiver tant qu'un nom n'est pas saisi, car le mobile bénéficie d'une décision explicite.

Renommer : action dans menu , ouvre une ligne d'édition inline dans la carte sprint ou un panneau bas sur petit écran. Actions Annuler / Enregistrer.

Réordonner : boutons Monter / Descendre dans le menu ou dans une section Ordre. Pas de drag-and-drop requis sur mobile.

Supprimer : confirmation obligatoire :

Titre : Supprimer le sprint « {name} » ? Corps : Les tickets de ce sprint seront conservés et passeront en « Sans sprint ». Actions : Annuler / Supprimer

Ajouter des tickets à un sprint : ouvrir un picker mobile de tickets, avec recherche et multi-sélection. Action finale Ajouter {count} ticket(s). Les tickets déjà dans le sprint sont exclus ou affichés cochés et désactivés ; ne pas laisser l'utilisateur croire qu'ils seront ajoutés une seconde fois.

Retirer un ticket d'un sprint : depuis la carte sprint, dans la liste compacte des tickets, action Retirer du sprint accessible via menu ligne. Cela ne supprime pas le ticket.

Pickers et popups sur mobile/web

Les pickers desktop (TicketPicker, SprintPicker) ne doivent pas apparaître comme de petites modales centrées sur téléphone. Adapter leur chrome :

  • mobile : panneau plein écran ou bottom sheet haute, avec header fixe, recherche en haut, liste scrollable, actions en bas ;
  • desktop web large : modal centrée acceptable, mais largeur limitée et focus trap ;
  • toujours garder Échap / retour / bouton Fermer selon plateforme.

Le même contenu métier peut être réutilisé : recherche, filtres, sélection simple ou multiple. Seul le contenant responsive change.

Cohérence avec le web existant

Respecter les patrons #69 :

  • une seule colonne verticale dans WebWorkspace ;
  • pas de LayoutGrid, docks, fenêtres flottantes desktop ou tabs projet desktop ;
  • padding avec safe-area ;
  • contrôles qui wrap proprement à 360 px ;
  • hauteurs basées sur dvh pour les panneaux longs ;
  • reconnect banner existante conservée au-dessus des surfaces.

Les surfaces tickets/sprints doivent continuer à se resynchroniser sur les événements domaine via le transport web live, comme État live le fait déjà. En cas de reconnexion, refetch complet du snapshot/listes plutôt qu'application de deltas manqués.

Langue et libellés

Conformément à la règle UX #78, les libellés humains sont en français. Les valeurs métier techniques peuvent rester celles du domaine si elles sont déjà exposées comme enums (open, closed, medium) seulement si leur traduction demanderait un chantier transversal ; préférence UX : afficher Ouvert, Fermé, Faible, Moyenne, Haute, Critique dans l'UI.

Libellés principaux :

  • Tickets
  • Sprints
  • Nouveau ticket
  • Créer un ticket
  • Gérer les sprints
  • Nouveau sprint
  • Créer un sprint
  • Modifier
  • Enregistrer
  • Annuler
  • Supprimer
  • Sans sprint
  • Charger plus
  • Aucun ticket.
  • Aucun sprint.
  • Tickets liés
  • Agents assignés
  • Carnet
  • Zone dangereuse

États et erreurs

  • Chargement liste tickets : Chargement des tickets… avec spinner compact.
  • Liste vide sans filtre : Aucun ticket dans ce projet. + bouton Créer un ticket.
  • Liste vide avec filtres : Aucun ticket ne correspond aux filtres. + Réinitialiser les filtres.
  • Chargement sprints : Chargement des sprints….
  • Aucun sprint : Aucun sprint. + bouton Créer un sprint.
  • Erreur réseau/session : message inline en haut de la surface, avec Réessayer.
  • Déconnexion live : conserver la bannière existante Connexion perdue — reconnexion en cours… ; les formulaires peuvent rester éditables, mais sauvegarder doit afficher l'erreur réelle si le transport est indisponible.
  • Suppression réussie : retour à la liste, ticket/sprint retiré après événement ou refresh.

Accessibilité

  • Les onglets Live, Tickets, Sprints utilisent role="tablist", role="tab", aria-selected et navigation clavier gauche/droite.
  • Chaque ticket de liste est un bouton ou lien avec nom accessible complet : {ref}, {title}, statut {status}, priorité {priority}.
  • Les formulaires ont labels visibles ou labels accessibles explicites ; ne dépendre d'aucun placeholder comme seul label.
  • Les confirmations de suppression utilisent role="alertdialog", focus initial sur Annuler, action destructive textuelle.
  • Les menus ont un label explicite : Actions du ticket {ref} ou Actions du sprint {name}.
  • Les zones scrollables longues conservent le focus et ne piègent pas la navigation clavier hors modal.

Critères d'acceptation UX/frontend

  • Après ouverture d'un projet web, l'utilisateur peut basculer entre Live, Tickets et Sprints sans shell desktop.
  • La vue web reste une colonne verticale responsive et ne monte pas le layout grid/docks/floating windows desktop.
  • L'utilisateur peut lister, filtrer, créer, ouvrir, modifier et supprimer des tickets depuis le web.
  • L'utilisateur peut créer, renommer, réordonner, supprimer des sprints et ajouter/retirer des tickets d'un sprint depuis le web.
  • L'édition ticket sur mobile se fait dans une vue détail pleine colonne avec retour explicite, pas dans une petite popup desktop.
  • Les suppressions ticket/sprint demandent confirmation et précisent ce qui est supprimé ou conservé.
  • Les pickers ticket/sprint sont adaptés mobile : plein écran ou bottom sheet, recherche en haut, actions claires en bas.
  • Les changements texte nécessitent Enregistrer; les changements statut/priorité/sprint peuvent être immédiats avec feedback de sauvegarde.
  • Les libellés visibles sont en français.
  • L'assistant IA de ticket n'est pas requis pour la première livraison web de #86.

Cadrage technique — contrat web-server tickets/sprints

Résultat de l'audit

Le socle applicatif tickets/sprints existe déjà dans BackendCore : création, lecture, liste, update, suppression, carnet, liens, assignation agent, création/liste/rename/reorder/suppression sprint, assignation/désassignation ticket→sprint. Le problème #86 n'est donc pas un manque de use case application ni de store : c'est un écart de driving adapter web.

Côté desktop, crates/app-tauri/src/lib.rs enregistre les commandes UI implémentées dans crates/app-tauri/src/tickets.rs. Côté web, crates/web-server/src/lib.rs expose seulement quelques commandes dans le dispatcher POST /api/invoke (health, list_projects, open_project, get_project_work_state, tâches de fond). Aucune commande ticket_* ou sprint_* n'y est reconnue aujourd'hui, donc le HttpTicketGateway web tombe en UNKNOWN_COMMAND.

Le frontend web est déjà prêt côté transport : frontend/src/adapters/http/streamGateways.ts contient HttpTicketGateway, câblé dans frontend/src/adapters/http/index.ts, et il appelle les mêmes noms de commandes que le desktop via /api/invoke. Le blocage principal est donc backend/contrat, pas layout/UI.

Commandes web-server à ajouter

Rester sur le style RPC existant : ajouter des branches à POST /api/invoke, pas créer une nouvelle API REST /api/tickets.

Tickets :

  • ticket_create{ request: { projectId, title, description?, priority?, status?, assignedAgentIds?, links? } }TicketDto.
  • ticket_read{ request: { projectId, ref, includeCarnet? } }TicketDto.
  • ticket_list{ request: { projectId, statuses?, priorities?, assignedAgentId?, sprintId?, text?, sort?, limit?, cursor? } }TicketListDto.
  • ticket_update{ request: { projectId, ref, title?, description?, status?, priority?, assignedAgentIds?, expectedVersion } }TicketDto. Cette commande couvre l'édition statut/priorité côté UI ; les commandes séparées idea_ticket_update_status / idea_ticket_update_priority sont des tools MCP agent, pas des commandes UI Tauri.
  • ticket_delete{ request: { projectId, ref } } → vide/null.
  • ticket_read_carnet{ request: { projectId, ref } }TicketCarnetDto.
  • ticket_update_carnet{ request: { projectId, ref, carnet, expectedVersion } }TicketDto.
  • ticket_link{ request: { projectId, ref, targetRef, kind, expectedVersion } }TicketDto.
  • ticket_unlink{ request: { projectId, ref, targetRef, kind?, expectedVersion } }TicketDto.
  • ticket_assign{ request: { projectId, ref, agentId, assigned, expectedVersion } }TicketDto.
  • ticket_assign_sprint{ request: { projectId, ref, sprintId, expectedVersion } }TicketDto.
  • ticket_unassign_sprint{ request: { projectId, ref, expectedVersion } }TicketDto.

Sprints :

  • sprint_create{ request: { projectId, name, status? } }SprintDto.
  • sprint_list{ request: { projectId } }SprintListDto { items }.
  • sprint_rename{ request: { projectId, sprintId, name, expectedVersion } }SprintDto.
  • sprint_reorder{ request: { projectId, orderedIds } }SprintListDto { items }.
  • sprint_delete{ request: { projectId, sprintId } } → vide/null ; le comportement existant conserve les tickets et les repasse en Sans sprint.

Commandes assistant ticket proches mais hors minimum #86 : open_ticket_chat, close_ticket_chat, puis le flux sendTicketChat/chat.*. Recommandation : ne pas les inclure dans le lot initial, car la demande vise l'édition tickets/sprints et le flux chat web est une surface live distincte.

Factorisation nécessaire

Les DTO publics tickets/sprints (TicketDto, TicketSummaryDto, TicketListDto, TicketCarnetDto, SprintDto, SprintListDto, request DTOs, pagination/tri/parse helpers) vivent aujourd'hui dans crates/app-tauri/src/tickets.rs. web-server ne doit pas dépendre de app-tauri.

Option recommandée : déplacer le contrat pur tickets/sprints vers backend (backend::dto ou backend::tickets) puis faire consommer ce module par les deux driving adapters :

  • app-tauri garde uniquement les wrappers #[tauri::command] ;
  • web-server ajoute des helpers invoke_ticket_* / invoke_sprint_* ;
  • les tests de pagination/tri/conflit actuellement proches du module Tauri migrent avec la logique pure.

Option minimale possible mais moins saine : dupliquer DTO/conversions dans web-server. À éviter, car cela crée deux contrats wire desktop/web à maintenir.

Auth et sécurité web (#77)

Les nouvelles commandes doivent rester derrière le gate existant de POST /api/invoke : pairing device, cookie de session HttpOnly, contrôle d'origine/CORS, révocation device et logs sécurité. Ne pas exposer de mutation ticket/sprint en GET ni hors allowlist.

Point à arbitrer produit/sécurité : un device web appairé pourra modifier les fichiers projet .ideai/tickets et .ideai/sprints. C'est cohérent avec la demande, mais il n'existe pas actuellement de permission fine par device lecture seule/écriture. Si cette granularité est souhaitée, c'est un chantier séparé de policy device, pas un prérequis technique au #86.

Événements live

Les domain events issue* et sprint* existent déjà dans backend::events::DomainEventDto, et le web-server relaie les événements domaine sur websocket event.domain en excluant seulement PtyOutput. Après exposition des commandes, les vues web peuvent réutiliser les helpers frontend isTicketEvent / isSprintEvent et refaire un refetch, sans nouveau canal événementiel.

Tests backend attendus

  • Non authentifié : ticket_list et une mutation ticket/sprint retournent UNAUTHORIZED.
  • Authentifié : ticket_list et sprint_list retournent le même shape que Tauri.
  • Cycle ticket : create → read → update titre/statut/priorité → carnet → link/unlink → delete.
  • Cycle sprint : create → list → rename → reorder → assign ticket → unassign ticket → delete.
  • Conflit expectedVersion propagé en ErrorDto cohérent avec le desktop.
  • Les commandes hors allowlist restent UNKNOWN_COMMAND.

Découpe proposée

Lot 1 — backend/contrat web : factorisation DTO, ajout des 17 commandes ticket_*/sprint_* dans /api/invoke, tests auth/lecture/mutation/conflit.

Lot 2 — surface web UX/frontend : implémenter les vues décrites ci-dessus sur le HttpTicketGateway existant, gérer responsive, confirmations et conflits.

Lot 3 optionnel — assistant ticket web : exposer et finaliser le flux chat seulement si la surface assistant est explicitement demandée.