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>
This commit is contained in:
2026-07-08 08:38:16 +02:00
parent 710fa8fdd7
commit ffc458e477
13 changed files with 299 additions and 0 deletions

View File

@ -0,0 +1,17 @@
---
name: ticket28-f1-frontend-delivered
description: Lot F1 du ticket #28 livré sur feature/ticket28-firstrun-detect-hang — invariant busy/detectProfiles, flag detecting, timeout UI, test de non-régression.
metadata:
type: reference
---
Lot **F1** (frontend) du bug #28 implémenté sur `feature/ticket28-firstrun-detect-hang` (non committé, Git s'en charge).
**Invariant posé** : dans `frontend/src/features/first-run/useFirstRun.ts`, le retour de `busy` à `false` ne dépend d'aucun appel à `detectProfiles`. `busy` n'entoure plus que `firstRunState()` (reload) et `configureProfiles()` (finish). Toute future régression qui remet un `await profile.detectProfiles(...)` sur un chemin gouvernant `busy` re-gèle le wizard.
**Mécanisme** : `runDetection(candidates, { preselect, reportError })` factorise auto-détection et bouton manuel. Le flag `detecting` est relâché par un `setTimeout(DETECT_TIMEOUT_MS = 3_000)`, **jamais** par la promesse — car le `finally` d'un `await` sur une promesse jamais settled (panic Rust ⇒ pas de réponse IPC) n'est jamais atteint. Un compteur `detectRun` invalide les rounds périmés (re-clic, unmount).
**Piège UI à retenir** : `<Button loading>` implique `disabled` dans le design system (`shared/ui/Button.tsx:46`). Donc `detecting` ne peut pas être surfacé via `loading` sur les boutons Save/Detect sans réintroduire le grisage — il est rendu comme un `role="status"` « Detecting… » séparé.
**Point de vérité QA** : `FirstRunWizard.test.tsx`, describe « detection that never answers (ticket #28) », gateway `HangingDetectGateway` dont `detectProfiles` renvoie `new Promise(() => {})`. Vérifié à teeth : en réintroduisant `setBusy(true); await runDetection(...)` dans `reload`, 2 des 3 tests échouent avec exactement le symptôme du ticket.
Vert : `npx vitest run` 59 fichiers / 569 tests, `npx tsc --noEmit` exit 0. Pas de lint dans ce projet (aucun eslint config ni script). F1 débloque l'UI mais **B1 (DevBackend, `AgentRuntime::detect` sync→async) reste requis** pour que la détection remonte réellement un résultat.