QA-flagged gap: the web surface could only ADD a ticket to a sprint, never
change or clear it, despite the backend already exposing both
ticket_assign_sprint and ticket_unassign_sprint.
- useTicketDetail: new setSprint(sprintId | null) method (additive, also
available to the desktop TicketDetail — unused there today, no behaviour
change), routing through the existing TicketGateway.setTicketSprint.
- WebTicketDetail: Sprint selector in "Statut et priorité", immediate save
like status/priority; empty value clears back to "Sans sprint".
- WebSprintsView: each sprint card now shows its tickets (compact list,
resolved client-side like the desktop SprintManager) with a "Retirer du
sprint" action per ticket, calling assignSprint(ref, null) — symmetric
with "Ajouter tickets". Extracted the card into a SprintCard subcomponent
to keep the growing card readable.
- Tests: WebTicketsSprints.test.tsx now has 16 tests (was 10) — added
sprint change/clear, sprint removal from the Sprints tab, agent
assign/unassign, ticket link/unlink, carnet save, and free-text search
filtering.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a Live/Tickets/Sprints tab navigation to WebWorkspace after a project
is opened — a mobile-first adaptation, not a port of the desktop docks/
floating windows, per carnet #86. The web-server transport (17 ticket_*/
sprint_* commands) and the HttpTicketGateway were already wired (lot 1 +
pre-existing gateway code); this lot is UI only.
- Tickets tab: search/filters, list grouped by sprint, create screen,
detail view with stacked accordion sections (Résumé/Statut et priorité/
Carnet open by default; Agents assignés/Liens/Zone dangereuse collapsed),
delete confirmation, optimistic-concurrency conflict banner.
- Sprints tab: create/rename/reorder (Monter/Descendre)/delete with
confirmation, add tickets via a mobile full-screen ticket picker (never
a small desktop modal), "Voir tickets" filters the Tickets tab to one
sprint.
- Reuses the transport-neutral hooks as-is (useTickets, useTicketDetail,
useTicketSearch) — only presentation and copy are web-specific, in
French per decision #78 (new local label module, not a reuse of the
English desktop ticketMeta labels).
- Workaround: `list_agents` isn't in the web-server allowlist, so agent
names/assignment options are derived from `get_project_work_state`
(already used by the Live tab) instead of the desktop's useProjectAgents.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>