feat(tickets): création d'un assistant IA de ticket (backend + frontend)

Ajoute le chat assistant IA attaché à un ticket (#8).

Backend Rust :
- use cases OpenTicketAssistant/CloseTicketAssistant + tests
- politique d'outils par agent (domain/agent_tool_policy) et policy MCP
- store de contexte assistant + gabarit default_ticket_assistant.md + tests
- events TicketAssistantOpened/Closed
- commandes Tauri open_ticket_chat/close_ticket_chat et câblage state/lib/events

Frontend :
- gateway (ports, adapters ticket + mock, domain)
- hook useTicketAssistant + composant TicketAssistantPanel
- intégration dans TicketDetail

Tests verts : vitest tickets.test.tsx (23), cargo test application::ticket_assistant (1),
infrastructure::assistant_context_store (2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 06:06:24 +02:00
parent f1803768fd
commit 1fdf62c089
29 changed files with 2173 additions and 49 deletions

View File

@ -37,12 +37,14 @@ import type {
ProjectWorkState,
ProfileAvailability,
ResumableAgent,
ReplyChunk,
Skill,
SkillScope,
Sprint,
Template,
TerminalSession,
Ticket,
TicketChat,
TicketCarnet,
TicketLinkKind,
TicketList,
@ -829,6 +831,29 @@ export interface TicketGateway {
* them); they fall back to the "no sprint" bucket (#11).
*/
deleteSprint(projectId: string, sprintId: string): Promise<void>;
/**
* Opens an AI assistant chat bound to a ticket (ticket #8). Spawns a
* structured assistant session driven by `profileId`; returns the live
* session handle. One session per ticket — reopening supersedes.
*/
openTicketChat(
projectId: string,
issueRef: string,
profileId: string,
): Promise<TicketChat>;
/** Closes (disposes) a ticket's assistant chat session (ticket #8). */
closeTicketChat(projectId: string, issueRef: string): Promise<void>;
/**
* Sends a message on an open assistant session and streams the reply back as
* {@link ReplyChunk}s via `onChunk` (ticket #8). Resolves once the turn has
* started; the turn ends at the `final` chunk. Reuses the shared `agent_send`
* chat transport (the same as the structured chat cell).
*/
sendTicketChat(
sessionId: string,
message: string,
onChunk: (chunk: ReplyChunk) => void,
): Promise<void>;
}
/**