Files
IdeA/.ideai/memory/ui-rework-sprint-scoping-contracts.md
Blomios ffc458e477 docs(memory): notes projet du sprint UI rework et des tickets #7/#14/#16/#17/#18/#25/#28
Capitalise les notes durables produites pendant le sprint UI rework et les
tickets livrés depuis. Commit séparé du code : `.ideai/memory/` est le store
durable versionné, il ne doit jamais être mélangé aux commits de feature.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 08:38:16 +02:00

2.9 KiB

name, description, metadata
name description metadata
ui-rework-sprint-scoping-contracts Frontières hexagonales et contrats figés du sprint UI rework — les 4 tickets sont frontend-purs, la popup TicketPicker
type
reference

Sprint « UI rework » (order 1), cadré 2026-07-06. Les 4 tickets sont frontend-purs : aucun nouveau port/read-model/endpoint.

Fait clé : filtrage/recherche tickets déjà backend-driven via TicketGateway.list(projectId, TicketListQuery{statuses[],priorities[],assignedAgentId,text,limit,cursor}) (ports/index.ts:717) → adapter transmet à ticket_list. Client ne fait que le groupement par sprint. #18 réutilise ce contrat, pas d'endpoint dédié.

G4 (contrat ticket_list) levé pour B après revue DevBackend : statuses/priorities OK (OR intra / AND inter). Deux écarts en DETTE BASSE : (a) text ne matche pas #ref (tickets.rs:681, issues.rs:322/326/465) ; (b) cursor = offset numérique non opaque/non stable inter-pages (tickets.rs:1231). Acceptable pour picker single-select court.

G3-bis (garde non-breaking) : TicketPicker/useTicketSearch traitent cursor comme token OPAQUE — ne jamais le construire/incrémenter, ne relayer que le cursor de la page précédente. Migration curseur opaque backend = zéro changement frontend.

Base de code : pas de routeur ni store global (navigation = useState local App.tsx + ProjectsView.tsx, sidebar inline ProjectsView.tsx:224). Aucune primitive Modal/Portal partagée ; ~7 features hand-roll fixed inset-0 role=dialog z-50/z-[60]. Pas de createPortal. #16 introduit shared/ui/FloatingWindow (focus-trap, monté niveau chrome) + shared/ui/zIndex.ts.

Contrat #18 figéTicketPicker props {open, projectId, title?, confirmLabel?, selectionMode?:"single"|"multi" (défaut single), excludeRefs?: TicketRef[] (filtré client-side), initialQuery?: TicketListQuery, onSelect(TicketPickerResult|[]), onClose}. TicketPickerResult={ref,id,number,title,status,priority}. Extraire TicketFacetsBar (fieldsets statut/priorité + recherche depuis TicketsPanel.tsx) + hook useTicketSearch (ne PAS réutiliser useTickets, trop lourd). #17 et #19 consomment en single.

Échelle z-index figée (G2) : in-cell inchangé (chrome 2-5, F3 z-20, write-portal z-4, resume z-5) ; chrome full-window menuDropdown=40, floatingWindow=50, floatingWindowNested=60, toast=70.

Règle intégration (G5) : fenêtres flottantes/menus montées niveau chrome (ProjectsView/App), JAMAIS dans LayoutGrid/LeafView. Ne pas toucher shouldShowWritePortalVeil ni exclusion write-portal↔F3 (cf. ticket4-overlay-composition-leafview). Focus-trap obligatoire (xterm garde le focus clavier).

Ordre : A(#16) ∥ B(#18) racines → prioriser B (chemin critique #17+#19) ; D(#19) après B ; C(#17) après A+B. Tout DevFrontend ; DevBackend = ticket dette basse (matching #ref + curseur opaque/stable).