docs(knowledge): capitalisation workflow + ux — intégration du triage local (mai-juin 2026)

Triage et intégration des propositions workflow et UX du buffer 95_a_capitaliser.md.

WORKFLOW :
- risques/story-tracking.md : 24 risques de suivi de story (enabler AC non-bloquant,
  tests plumbing vs scénario, reformat hors scope, xit sans story de suivi, re-scope mid-PR,
  statut migré non vérifié, périmètre auto-déclaré vs git diff, composant/page livré sans
  câblage — reciblages venus de backend #21 et frontend #257)
- patterns/general.md : audit cartographique pré-chantier, Go/No-Go par lot, sub-agent review
  fresh-context, sweep read-only délégué (#156), revue adverse de spec, audit-first migration

UX (domaine amorcé — était vide) :
- patterns/general.md : 9 patterns (mount-based read, fiche détail single-scroll, FAB étendu,
  ligne de contexte filtres, état read-only caché, avatar par hash, audit a11y touch targets)
- risques/general.md : 5 risques (bouton retour dans ScrollView #108, lien sans handler,
  wording cross-écran divergent, token sans détection, padding multi-écrans)
- READMEs ux/workflow mis à jour

Vérifié : aucun doublon d'ancre/titre, fichiers racine 40_/90_ non modifiés (propositions
réservées pour validation séparée). Source 95_ non purgée (purge en fin de capitalisation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MaksTinyWorkshop
2026-06-25 15:48:53 +02:00
parent 5f5c87296e
commit 81fde91259
7 changed files with 1089 additions and 6 deletions
+1 -1
View File
@@ -8,4 +8,4 @@ Avant toute proposition workflow, identifie le fichier dont le nom et la descrip
| Fichier | Domaine | Entrées clés |
|---------|---------|--------------|
| `general.md` | Review adversarial, isolation de hunks, méthode de chantier | Review adversarial obligatoire sur chemin critique, isolation chirurgicale d'un hunk via `git apply --cached` |
| `general.md` | Review adversarial, méthode de chantier, sub-agents, migration, traçabilité | Review adversarial sur chemin critique, isolation de hunk via `git apply --cached`, triangulation sub-agent, audit cartographique avant chantier, Go/No-Go par lot, phasage feature avec placeholders, préparation Epic N+1 via rétro, sub-agent review fresh-context, revue adverse "information asymmetry", sweep read-only double-agent, audit-first migration large-scale, story polish multi-écrans, test obsolète après durcissement enum, génération palette Stitch MCP |
+260 -2
View File
@@ -5,8 +5,8 @@ bucket: patterns
tags: [review, adversarial, git, chantier, agent]
applies_to: [analysis, implementation, review]
severity: high
validated_on: 2026-04-27
source_projects: [RL799_V2]
validated_on: 2026-06-25
source_projects: [RL799_V2, app-alexandrie]
---
# Workflow — Patterns : Général
@@ -155,3 +155,261 @@ Les `index` et `@@` viennent du `git diff` original — pas besoin de recalculer
### Communication au user
> *"Sub-agent X signale 4 fichiers, j'ai validé 1/4 et invalidé 3/4. Voici le plan d'action corrigé."*
---
<a id="pattern-audit-cartographique-avant-chantier"></a>
## Pattern : Audit cartographique 15-30 min avant tout chantier de fusion ou refacto transverse
- Objectif : cadrer le chantier sur la **vraie** surface d'impact, pas sur une estimation à priori souvent fausse à ×3-5.
- Contexte : chantier qui touche un composant/pattern utilisé en plusieurs endroits (fusion de 2 composants, migration de N call-sites, consolidation de pattern).
- Quand l'utiliser : avant de planifier les sous-lots, dès que le scope annoncé dépasse 1-2 fichiers.
- Quand l'éviter : modification locale à un seul fichier sans dépendance inverse.
- Validé le : 05-05-2026
- Contexte technique : monorepo Vue / pnpm — RL799_V2
### Checklist d'audit
1. **Call-sites directs** : `grep` du nom du composant/symbole (`<X />`, `<x />`, `import X`).
2. **Call-sites indirects** : grep des **classes CSS**, des **data-testid**, des **types/enums** exportés. Piège fréquent : un composant scoped qui réutilise une classe CSS globale sans importer le composant.
3. **Tests** : grep dans `__tests__/`, `tests/e2e/`, `tests/`. Inclure string-match (lecture du source) ET tests de mount.
4. **Dépendances inverses** : qui produit/consomme les types métier exportés ? (un call-site peut dépendre du type sans dépendre du composant.)
5. **Doublons CSS scoped vs global** : une classe nommée identiquement en `<style scoped>` Vue et en `style.css` global est isolée par le hash scoped — pas de collision réelle même si le grep matche les deux.
6. **Convention déjà appliquée ailleurs** : si la cible ressemble à un pattern existant dans le repo, c'est le **modèle cible** — copier sa structure.
### Anti-pattern
- Faire confiance au scope annoncé dans une todo (écrite il y a 4 minutes ou 4 mois) sans le valider.
- Attaquer en mode "je verrai les surprises en route" — découvrir 3 call-sites de plus après avoir committé 2 lots.
- Grep uniquement `import X from` : on rate les usages par classe CSS, data-testid, type exporté.
Cas validé : fusion `AppBadge``StatusBadge` (RL799_V2) — todo annonçait "~17 call-sites", audit a révélé 3 directs. Scope final divisé par ~5.
---
<a id="pattern-go-no-go-par-lot"></a>
## Pattern : Go/No-Go par lot sur chantier > 8 h estimées
- Objectif : préserver la possibilité de bisect/rollback ciblé et garder la revue lisible diff par diff sur un chantier long.
- Contexte : chantier estimé > 6-8 h (refonte schéma DB + endpoints + UI + hooks), trop gros pour un seul commit reviewable.
- Quand l'utiliser : dès qu'un chantier dépasse ~6-8 h ou touche un changement structurel (schéma, cascade de types).
- Quand l'éviter : fix ponctuel, story atomique.
- Validé le : 13-05-2026
- Contexte technique : monorepo — RL799_V2, app-alexandrie
### Mécanique
1. **Décomposer en lots atomiques** avant la première ligne. Chaque lot = un commit indépendant qui passe les tests existants seul. Idéalement lot 1 = schéma DB + cascade de types (pas de feature visible), lots suivants = endpoints/services/UI.
2. **Point d'étape (1-2 phrases + état tests) à la fin de chaque lot** ; le dev valide explicitement "Go pour le suivant" — pas d'autopilot multi-lots.
3. **Commit par lot** avec message structuré : Pourquoi (lien spec), Quoi (Schéma/Services/UI/Tests), décisions clés, stats tests, récap chantier dans le commit final.
4. **Tests complets entre chaque lot** (`test:api`, `test:shared`, `test:frontend`) — l'effet iceberg émerge dès qu'un changement structurel touche un fichier référencé ailleurs.
5. **Lot plus gros que prévu** (ex. 3-4 h estimées, 5 h sans fin) → arrêter, mini point d'étape : sous-découper (1a/1b/1c) ou confirmer. Pas de "on verra".
### Anti-pattern
- "Je commit tout en fin pour un beau commit propre" : on perd la granularité de bisect et le diff de relecture (~4500 LOC) devient illisible. Un méga-commit rend impossible le `git revert <lot>` chirurgical.
---
<a id="pattern-phasage-feature-placeholders-ux"></a>
## Pattern : Phasage feature avec placeholders UX
- Objectif : livrer rapidement la structure UX d'une feature multi-volets et brancher le backend coûteux en phase 2, pour valider le design avant l'investissement backend.
- Contexte : feature multi-volets dont certains panels nécessitent un backend significatif (endpoints, DTOs, tests api, streaming) ; la structure UX seule prend < 1 h.
- Quand l'utiliser : feature à N volets où l'utilisateur bénéficie déjà de la navigation/structure avant le backend complet.
- Quand l'éviter : feature mono-volet ; ou si la structure UX ne peut pas être validée sans données.
- Validé le : 06-05-2026
- Contexte technique : Vue / monorepo — RL799_V2
### Forme
- **Phase 1 (~1-2 h)** : structure UX complète (page wrapper, tabs, routing, redirections legacy, FAB conditionnel) + panel "core" 100% opérationnel + panels périphériques en **placeholder "Bientôt disponible"** + tests mount complets (les placeholders sont assertés).
- **Phase 2 (commit séparé)** : backend complet (endpoints + DTOs + repository + tests api) + branchement des placeholders + tests mount adaptés.
### Anti-pattern
- **Cacher les onglets futurs** : l'utilisateur ne sait pas que la feature s'étendra. Le placeholder rend l'intention visible.
- **Backend partiel** : ne JAMAIS livrer un endpoint qui retourne `[]` sans test. Le panel placeholder doit être **frontend-only** tant qu'il n'est pas branché.
- Placeholder ambigu : préférer "Bientôt disponible — la liste s'affichera ici" à "Aucun résultat" (confusion avec un empty state normal).
### Détection en review
`grep "Bientôt disponible"` / `data-testid=".*-placeholder"` → vérifier `data-testid` stable + commentaire JSDoc (Phase X, cible backend) + test mount.
---
<a id="pattern-preparation-epic-n-plus-1-via-retro"></a>
## Pattern : Préparation Epic N+1 via rétro Epic N
- Objectif : trancher les dépendances et arbitrages d'Epic N+1 pendant la rétro Epic N, où le contexte est frais — zéro refonte mid-epic.
- Contexte : enchaînement d'epics où Epic N+1 a des dépendances techniques/produit sur Epic N, surtout s'il introduit un domaine cross-cutting.
- Quand l'utiliser : à la clôture de tout epic suivi d'un epic dépendant.
- Quand l'éviter : epic terminal ou totalement indépendant du suivant.
- Validé le : 13-05-2026
- Contexte technique : NestJS + Expo / BMAD — app-alexandrie
### En clôture d'Epic N, identifier explicitement
1. **Dépendances N → N+1 non documentées** (comportement d'Epic N utilisé par N+1 sans spec — ex. soft delete → comportement DM destinataire).
2. **Décisions d'architecture à trancher AVANT le dev** (transport polling/WebSocket, persistance, cache/concurrence) → documentées dans les dev notes de la première story N+1.
3. **Schémas de contrat partagés à créer dans `packages/contracts` AVANT le dev** (schéma Zod canonique du nouveau domaine) → évite la divergence API ↔ mobile.
4. **Matrice de test combinatoire pré-définie** quand N+1 croise plusieurs domaines.
Format rétro : section "Préparation Epic N+1 — chemin critique" avec tableau `# | Tâche | Owner | Bloquant ? | Critère de succès`. Au démarrage N+1, vérifier que tous les items bloquants sont traités.
Indicateurs de succès : zéro refonte mid-epic ; review adversariale concentrée sur les angles techniques (concurrence, sécurité) plutôt que sur des arbitrages métier oubliés.
---
<a id="pattern-sub-agent-review-fresh-context"></a>
## Pattern : Sub-agent review fresh-context pour stories non triviales
- Objectif : casser le biais de rationalisation du dev qui review son propre code, via un relecteur sans contexte de conception.
- Contexte : story non triviale (multi-fichiers, async, state management complexe) avant de marquer "done".
- Quand l'utiliser : stories non triviales touchant un chemin sensible.
- Quand l'éviter : stories triviales (1 fichier, peu de logique), fixes mineurs — l'overhead n'est pas justifié.
- Validé le : 14-05-2026
- Contexte technique : multi-agent / BMAD — app-alexandrie
### Mécanique
1. Push le commit à reviewer.
2. Spawn un subagent (general-purpose) fresh-context avec un prompt self-contained : "aucun contexte" + working dir + branche + commit SHA + persona ([CR]) + story (path) + ACs + bug class à vérifier + format de sortie + "N'APPLIQUE AUCUN FIX, rapport pur".
3. Le parent décide quoi faire des findings (croisé par grep — cf. pattern de triangulation ci-dessus).
Coût ~3 min wall-clock, contexte parent préservé. Cas validé : story 11.2 (app-alexandrie) — 3 HIGH légitimes (race-token sur loadMore/refresh) ratés par le dev.
**Caveat** : même modèle = biais d'entraînement partagés. Pour les concerns architecture/sécurité critiques, la review humaine reste indispensable.
---
<a id="pattern-revue-adverse-information-asymmetry"></a>
## Pattern : Revue adverse de spec en "information asymmetry"
- Objectif : trouver les angles morts qu'un auteur ne peut PAS voir de l'intérieur (fichiers fantômes, ACs impossibles, analogies de pattern fausses), avant de marquer une spec `ready-for-dev`.
- Contexte : spec/story complexe avant le dev, surtout multi-lots dépendants.
- Quand l'utiliser : avant de figer une spec non triviale.
- Quand l'éviter : spec triviale ou déjà très bien cadrée.
- Validé le : 18-06-2026
- Contexte technique : quick-spec + review-adversarial / sous-agent — RL799_V2
### Mécanique
Passer la spec à un relecteur (sous-agent isolé) qui : (a) a accès **lecture** au repo, (b) ne connaît QUE le fichier de spec (zéro historique de conception), (c) doit **vérifier chaque affirmation** (numéros de ligne, noms de symboles, existence de fichiers/helpers) dans le code réel, posture cynique "assume que des problèmes existent, ≥10 findings". Pour une spec multi-lots, lui faire lire AUSSI les lots prérequis (contradictions inter-specs).
Catégories de findings que l'asymétrie révèle et que la relecture par l'auteur rate :
1. **fichier déclaré NEW qui existe déjà** ailleurs (doublon, régression des tests existants) ;
2. **AC testant un cas impossible** (ex. `onDelete` sur User alors que les Users sont soft-deleted) ;
3. **analogie de pattern fausse** ("imite X" alors que X fait l'inverse) ;
4. **coercition runtime silencieuse** non signalée par TS ;
5. **garde RBAC mal nommée** (`requireVenerable` inexistant = en fait `ROLES_GOVERNANCE`).
Traitement : numéroter les findings (sévérité + validité réel/bruit/indécis), ne pas exclure par sévérité, corriger AVANT dev. Cas validé : 3 specs ODJ RL799 → 44 findings dont plusieurs Critical réels.
---
<a id="pattern-sweep-read-only-double-agent"></a>
## Pattern : Sweep read-only délégué à 2 agents Explore + cross-check grep
- Objectif : produire un audit/sweep haute précision sans toucher au code source.
- Contexte : story d'audit/migration en mode read-only (relevé d'occurrences, cartographie de dette).
- Quand l'utiliser : sweep dont la précision ligne-à-ligne est critique pour la story consommatrice.
- Quand l'éviter : recherche ponctuelle d'un seul symbole.
- Validé le : 28-05-2026
- Contexte technique : multi-agent / BMAD — app-alexandrie
### Mécanique
Déléguer le sweep à 2 agents Explore parallèles + un cross-check `grep` direct. Filet anti-régression en review : revérifier les numéros de ligne ET la claim de complétude ("X % propre") par un sweep indépendant ciblé sur les zones déclarées propres. Confirmer l'invariant read-only via `git status` / `git show --stat` (seuls les artefacts `_bmad-output/` doivent bouger).
**Convention de comptage obligatoire** : poser explicitement en tête du rapport la règle de comptage ("1 ligne de code = 1 hit, hors NOISE"). Résumé exécutif, tableaux de détail ET Completion Notes doivent citer les MÊMES chiffres. Un "Total" ne doit jamais additionner un ensemble et son sous-ensemble. En review, recompter à partir des tableaux de détail (source de vérité), pas des chiffres de tête.
---
<a id="pattern-audit-first-migration-large-scale"></a>
## Pattern : Audit-first sur migration large-scale
- Objectif : confronter le prémis de la story à la réalité du code AVANT d'engager une migration transverse, et permettre au scope de muter.
- Contexte : story enabler à effort large (2-3 j+) sur une migration transverse (theming, refacto archi, sécurité).
- Quand l'utiliser : avant toute migration > ~30 fichiers ou estimée > 2 j.
- Quand l'éviter : migration mécanique triviale à scope connu et fermé.
- Validé le : 29-05-2026
- Contexte technique : NestJS + Expo / BMAD — app-alexandrie
### Phases
1. **Audit (1-2 h)** : extraire la réalité (grep, métriques, dette). Rapport : nombre exact de fichiers/lignes, hotspots (top 10 concentrant >50% de la dette), cas spéciaux, 2-4 options stratégiques avec effort **révisé**.
2. **Arbitrage stakeholder** : présenter rapport + options. **Permettre au scope de muter** — l'audit révèle souvent que la story était mal cadrée.
3. **Migration découpée par phases** : chaque phase = livrable autonome (commit + push), pour pouvoir s'arrêter sans laisser l'app dans un état pire qu'avant.
### Délégation à un agent (migration > 30 fichiers, mode mécanique)
Brief structurant : liste **exhaustive** des fichiers (pas "trouve-les"), pattern canon AVANT/APRÈS, mapping sémantique pour les choix non-mécaniques (ex. `'red' → themed.error`), règles strictes ("ne déborde pas", "ne touche pas aux tests"), récap structuré attendu (occurrences/fichier, faux positifs, incidents).
Anti-pattern : engager une migration large sans audit — à mi-parcours on découvre un scope 2-3× plus gros, working tree déjà sali. Cas validé : ux-cleanup-8 (app-alexandrie) — "tokens light cassés" → en réalité pas de palette light du tout, scope 2-3 j → 4-7 j.
---
<a id="pattern-story-polish-multi-ecrans-sous-livraisons"></a>
## Pattern : Story "polish multi-écrans" en sous-livraisons logiques
- Objectif : garder pilotable une story qui agrège de nombreux items courts mais cohérents (4-8 écrans + transverses).
- Contexte : story de polish/cleanup couvrant plusieurs écrans avec des dépendances internes.
- Quand l'utiliser : story à N items cohérents trop gros pour 1 commit, mais qui perdraient leur cohérence en N stories.
- Quand l'éviter : items indépendants sans dépendance partagée (préférer des stories distinctes).
- Validé le : 29-05-2026
- Contexte technique : Expo / BMAD — app-alexandrie
### Découpage
A (helpers + composants génériques) → B (refonte des écrans utilisant A) → C (transverses post-refonte). **DoD lint + typecheck + tests à chaque palier** — signal anti-régression fort, prévient l'accumulation silencieuse.
Anti-patterns : (1) tout faire en 1 commit (context-window + review massive) ; (2) éclater en N stories (perd la cohérence, multiplie les cycles) ; (3) skipper la DoD intermédiaire.
HALT et escalader si : audit révèle > 3-4 points complexes inattendus / nouvelle dépendance / champ de contrat absent (décider : extension dans la story ou story dédiée). Cas validé : ux-cleanup-15 — 18 ACs / 3 sous-livraisons / 971 tests verts à chaque palier.
---
<a id="pattern-test-obsolete-durcissement-enum"></a>
## Pattern : Test obsolète après durcissement de type — supprimer plutôt que muter
- Objectif : ne pas conserver un test qui protège contre un cas devenu structurellement impossible.
- Contexte : durcissement d'un type (String → enum DB, `z.enum()`, union TS strict) qui rend une valeur invalide impossible en runtime.
- Quand l'utiliser : un test force une valeur invalide pour vérifier un fallback applicatif, et cette valeur ne peut plus arriver.
- Quand l'éviter : voir exceptions ci-dessous.
- Validé le : 05-05-2026
- Contexte technique : Prisma enum / Zod — RL799_V2
### Règle
Quand un test force une valeur invalide (`status: 'unknown_value'`) devenue **structurellement impossible** (rejetée par la DB/Zod/le compilateur) : **supprimer le test**, ne pas le muter (`as any`, `@ts-expect-error`). Le filet structurel **remplace** le filet test ; un test qui valide un cas impossible ne protège plus contre rien et porte une charge de maintenance à chaque évolution du type. Documenter la suppression dans le commit.
### Quand garder/muter quand même
- Test E2E qui simule un INSERT admin (raw SQL bypass) : garder.
- Test de boundary sur entrées externes (HTTP body avant Zod) : garder.
- Test unitaire qui force une valeur via mock pour tester un branch : garder, en re-typant proprement le mock.
---
<a id="pattern-generation-palette-stitch-mcp"></a>
## Pattern : Génération de variante de palette via Stitch MCP
- Objectif : générer une variante d'un design system existant (ex. light depuis dark) sans repartir de zéro.
- Contexte : projet avec un design system Stitch (Google) déjà validé via `mcp__stitch__list_design_systems`.
- Quand l'utiliser : besoin d'une variante de palette cohérente avec un seed/source existant.
- Quand l'éviter : pas de design system Stitch ; ou besoin programmatique de récupérer les hex (voir limite ci-dessous).
- Validé le : 29-05-2026
- Contexte technique : Stitch MCP — app-alexandrie
### Limites connues (vérifiées 2026-05-29)
1. **`namedColors` n'est PAS retourné** par `create_design_system` ni `update_design_system` — la palette n'est visible que via l'UI Stitch web. Workaround : ouvrir `https://stitch.withgoogle.com/projects/<projectId>`, copier l'objet `namedColors`.
2. **`update_design_system` retourne une session** (`projects/{id}/sessions/{id}`) — l'update est asynchrone / stocké en draft.
3. Récupérer la palette finale par programme nécessite probablement `apply_design_system` sur un screen test (non confirmé).
### Workflow recommandé
Créer le design system avec le `designMd` complet (philosophie + contraintes WCAG) → copier les `namedColors` depuis l'UI → coller dans `colors.ts` → auditer les ratios WCAG (texte ≥ 4.5:1, UI ≥ 3:1) → dériver manuellement les tokens custom hors MD3 standard.
Anti-pattern : attendre une réponse synchrone de l'API avec les hex — elle ne fonctionne pas ainsi.