--- name: issue-ticket-system-design description: memory note issue-ticket-system-design metadata: type: project --- --- name: issue-ticket-system-design description: Cadrage figé (Architect+Main, 2026-07-02) du système de tickets IdeA façon Jira — domaine `Issue` par projet, exposé « ticket » côté UI/MCP, Carnet éditable, #N séquentiel. Fait autorité pour les lots T1-T6/F1-F7. metadata: type: reference --- # Système de tickets IdeA (domaine `Issue`) — CADRAGE FIGÉ 2026-07-02 ## Décisions produit verrouillées (utilisateur) - **Portée PAR PROJET** : stockage dans `.ideai/tickets/` du projet (pas de backlog global). - **Identifiant court `#42`** : compteur séquentiel par projet, parlable à l'oral (poignée partagée humain↔agent, y compris dans une délégation `idea_ask_agent`). - **Champ de connaissances éditable = « Carnet »** (PAS « mémoire » — évite collision avec la mémoire projet). Markdown éditable/réorganisable, scoped ticket, pas append-only. - **Stockage Markdown + frontmatter**, un DOSSIER par ticket. - **V1 SANS attachments** : livrer T1-T5 + F1-F5 + F7 ; attachments (T6/F6) en fast-follow. ## Nommage (collision évitée avec le TicketId de délégation) Domaine/code = **`Issue`** (`IssueId`, `IssueNumber`, `IssueRef("#42")`, `IssueStore`, modules `domain::issue`/`application::issues`/`infrastructure::issues`). UI + MCP public = « ticket » (`idea_ticket_*`, DTO camelCase). Ne JAMAIS nommer `Ticket` en code (réservé à la délégation inter-agent). ## Frontière Carnet vs mémoire projet Carnet = savoir DU ticket (décisions locales, hypothèses, investigation, contraintes). Mémoire projet = savoir transverse durable. Règle : si l'info doit survivre à la fermeture du ticket et guider d'autres travaux → mémoire projet ; sinon → carnet. ## Modèle domaine `Issue { id(uuid), number(u64), title, description(md), status, priority, carnet, links, agent_refs, attachments, created_by/updated_by(IssueActor: User|Agent|System), created_at/updated_at, version(optimistic) }`. - `IssueStatus`: Open | InProgress | Qa | Closed (DTO: open|inProgress|QA|closed). - `IssuePriority`: Low | Medium | High | Critical. - `IssueLinkKind`: RelatesTo | Blocks | BlockedBy | Duplicates | DependsOn. - `AgentIssueRef { agent_id, role: Assigned|Mentioned|Reviewer|Owner }`. Invariants : number>0 unique/projet ; IssueRef = `#` ; titre non vide ; pas de self-link ; assignation → AgentId connu du manifeste ; toute écriture incrémente version ; attachments sous le dossier du ticket, pas de `..`/symlink/chemin absolu. ## Ports `IssueStore` (create/get_by_ref/list(filter)/update(expected_version)/read_carnet/ write_carnet(expected_version)) ; `IssueNumberAllocator` (allocate_next, atomique via counter.json + counter.lock + rename, jamais de réutilisation de numéro) ; `IssueAttachmentStore` (add/remove/list — lot attachments). Adapters : `FsIssueStore`, `FsIssueNumberAllocator`, `FsIssueAttachmentStore`, `McpIssueTools`, `TauriIssueCommands`, `TauriIssueEventRelay`. ## Surface MCP (agents) `idea_ticket_create/read/list/update/update_status/update_priority/read_carnet/update_carnet/ link/unlink` (+ `idea_ticket_attachment_*` au lot attachments). DTO camelCase ; `TicketRef` = `#${number}` ; concurrence via `expectedVersion` sur chaque écriture. ## Events domaine (→ projection UI, même modèle events→front B-series) IssueCreated/Updated/StatusChanged/PriorityChanged/CarnetUpdated/Linked/Unlinked/ AgentAssigned/AgentUnassigned/AttachmentAdded/Removed/StorageConflictDetected. ## Layout stockage `.ideai/tickets/{counter.json, index.json(projection reconstructible), /{issue.md(frontmatter +description), carnet.md, attachments/}}`. Attachments versionnés git par défaut (warning >5MiB, refus configurable >25MiB, pointeur URI pour les gros). ## Lots Backend : T1 domaine Issue · T2 store FS Markdown (+allocator) · T3 use cases (Create/Read/List/ Update/UpdateCarnet/Link/AssignAgent, optimistic concurrency) · T4 surface MCP `idea_ticket_*` · T5 commands Tauri + relay events · T6 attachments (fast-follow). Frontend : F1 gateway UI (`IssueGateway`, pas d'invoke direct) · F2 liste filtrable · F3 détail/ édition (gestion conflits expectedVersion) · F4 éditeur Carnet Markdown · F5 liens & assignations · F6 attachments (fast-follow) · F7 `#42` cliquable + pré-remplissage délégation. Réutilise : store FS par projet façon `FsBackgroundTaskStore`/`AppLiveStateProvider`, EventBus + TauriEventRelay, pattern gateway UI. Lien : [[background-tasks-first-class-design]], [[agent-context-memory-and-profile-handoff]].