PD-105 — Retour d'expérience (REX)¶
Story : Implémenter push notifications iOS Date : 2026-02-10 Epic : MOBILE-IOS (PD-195)
1. Résumé exécutif¶
| Métrique | Valeur |
|---|---|
| Objectif initial | Notifications push iOS pour événements probatoires |
| Résultat obtenu | Conforme avec réserves mineures |
| Verdict final | RESERVE (7.875/10) |
| Tests contractuels | 1399/1399 passés (100%) |
| Couverture code | 92%+ sur modules notifications |
2. Métriques de convergence¶
2.1 Temps et itérations¶
| Étape | Durée estimée | Durée réelle | Itérations | Écart |
|---|---|---|---|---|
| 0 - Besoin | 30 min | 30 min | 1 | 0% |
| 1 - Spécification | 2h | 1.5h | 1 | -25% |
| 2 - Tests | 1h | 1h | 1 | 0% |
| 3 - Gate spec | 1h | 2h | 2 | +100% |
| 4 - Plan | 1h | 1.5h | 1 | +50% |
| 5 - Gate plan | 1h | 2h | 2 | +100% |
| 6 - Implémentation | 4h | 6h | 1 | +50% |
| 7 - Acceptabilité | 2h | 2.5h | 2 | +25% |
| 8 - Gate acceptabilité | 1h | 2h | 2 | +100% |
| 9 - REX | 30 min | 30 min | 1 | 0% |
| TOTAL | ~14h | ~19h | 14 | +36% |
2.2 Scores de convergence par gate¶
| Gate | Score v1 | Score final | Delta | Itérations |
|---|---|---|---|---|
| Gate 3 | 5.75/10 | 7.75/10 | +2.0 | 2 |
| Gate 5 | 6.25/10 | 7.75/10 | +1.5 | 2 |
| Gate 8 | 6.00/10 | 7.875/10 | +1.875 | 2 |
Score moyen final : 7.79/10
2.3 Écarts par catégorie¶
| Catégorie d'écart | Gate 3 | Gate 5 | Gate 8 | Total |
|---|---|---|---|---|
| ECT (complétude/testabilité) | 3 | 2 | 2 | 7 |
| DIV (divergence spec/impl) | - | 4 | - | 4 |
| AMB (ambiguïté) | 2 | 3 | - | 5 |
| SEC (sécurité) | - | - | 2 | 2 |
| PERF (performance) | - | - | - | 0 |
| TOTAL écarts | 5 | 9 | 4 | 18 |
3. Points fluides¶
Ce qui a bien fonctionné :
- Architecture Git-first — Chaque agent commit sur la feature branch, traçabilité parfaite
- Multi-agents parallèles — 3 tâches frontend exécutées en parallèle (5,7,8)
- Sérialisation badge via PQueue — Pattern robuste pour éviter les race conditions
- Déduplication multi-niveaux — Notification ID vérifié à chaque étape du pipeline
- Tests exhaustifs — 83 tests couvrant tous les invariants avec assertions spécifiques
- OpenCode intégration — Reviews LLM automatisées sans copier-coller
4. Points difficiles¶
Obstacles rencontrés (sans justification) :
- Jest ESM modules — p-queue et eventemitter3 non transformés, nécessité de mocks manuels
- RNTL getByAccessibilityLabel — API différente de ce qui était attendu (getByLabelText)
- FlatList ListEmptyComponent — Ne rend pas sans layout dans les tests
- Cast TypeScript expo-notifications — Types incomplets, nécessité de casts
as unknown as - Pipeline Sonar Quality Gate — Échec non lié à PD-105 (dette technique préexistante)
5. Hypothèses révélées tardivement¶
Hypothèses non explicites découvertes en cours de workflow :
- H: p-queue est ESM-only — découverte à l'étape 6c (synthèse)
- H: expo-notifications types incomplets — découverte à l'étape 6b (agents)
- H: RNTL queries différentes de RTL web — découverte à l'étape 6c
6. Invariants complexes¶
Invariants difficiles à implémenter ou sensibles aux régressions :
- INV-105-09 (Badge = non-lus) — Nécessite queue sérialisée, reconciliation, atomicité — TC-NOM-05
- INV-105-10 (Navigation contextuelle) — Resolver + whitelist + fallback — TC-NOM-06, TC-NOM-07
- INV-105-08 (Historisation UUID v4) — Déduplication multi-niveaux requise — TC-NOM-04
7. Dette technique¶
Compromis acceptés et non bloquants :
Validation payload runtime manquante (ECT-03)— RÉSOLU (Zod ajouté en v2)- Schema Zod permissif (SEC-01) — impact: faible, canal APNs contrôlé, passthrough accepté
- Pas de validation sémantique targetId/eventType (SEC-02) — impact: faible, resolver whitelisté
- Listeners non nettoyés après reset() — impact: faible, tests uniquement
- Test PQueue sans preuve d'ordonnancement strict — impact: faible, cohérence prouvée
8. Risques résiduels¶
| Risque | Type | Probabilité | Impact | Mitigation |
|---|---|---|---|---|
| Payload malformé exploité | sec | faible | moyen | Canal APNs contrôlé, validation future |
| Quota iOS silent push dépassé | ops | moyen | faible | Documentation + monitoring |
| Désalignement badge après crash | tech | faible | faible | Reconciliation au lancement |
| Token rotation manquée | ops | faible | moyen | Listener token + retry backend |
9. Patterns récurrents détectés¶
9.1 Patterns confirmés (déjà vus dans d'autres stories)¶
- Mock Jest ESM — Modules ESM-only nécessitent mocks manuels (aussi vu dans crypto)
- Type casting expo — Types Expo souvent incomplets (aussi vu dans PD-99 auth)
- Zustand persist — Pattern fiable pour état persistant
9.2 Nouveaux patterns identifiés¶
- PQueue pour sérialisation — Pattern efficace pour éviter race conditions sur opérations atomiques
- Whitelist navigation — Map statique eventType → screen pour sécuriser la navigation
- Déduplication par ID — Vérifier existence avant ajout pour idempotence
10. Améliorations du workflow¶
10.1 Améliorations des prompts/templates¶
| Fichier | Amélioration suggérée | Priorité |
|---|---|---|
docs/prompts/7c Review Security.md | Ajouter section "Validation des payloads externes" | haute |
docs/templates/PD-XX-acceptability.md | Aligner table invariants avec spec (14 vs 13) | moyenne |
10.2 Améliorations des agents¶
| Agent | Amélioration suggérée | Justification |
|---|---|---|
| agent-developer | Ajouter vérification ESM vs CJS pour dépendances | Éviter erreurs jest.config |
| agent-qa-unit | Inclure pattern de test pour FlatList vide | Éviter faux positifs |
10.3 Améliorations du processus¶
- Checker ESM/CJS — Script pré-implémentation pour identifier les modules ESM-only
- Gate 8 multi-phase — Séparer review ChatGPT et confrontation Claude plus clairement
- Pipeline Sonar — Ignorer Quality Gate pour branches feature (non bloquant)
11. Enseignements clés¶
5 enseignements génériques réutilisables :
-
Sérialiser les opérations atomiques — Utiliser PQueue ou mutex pour les updates concurrents (badge, compteurs)
-
Prévoir la déduplication tôt — Vérifier l'unicité par ID à chaque niveau du pipeline (handler, store, storage)
-
Tester les mocks ESM — Vérifier si les dépendances sont ESM-only avant d'écrire les tests
-
Whitelist > blacklist pour navigation — Sécuriser les deep links avec une map statique d'écrans autorisés
-
Confrontation invalide les faux positifs — La phase 2 de gate permet de reclasser les écarts ChatGPT (7 → 1 majeur confirmé)
-
Respecter strictement les seuils de gate — Un score < 7.0 est NON_CONFORME même si proche. Ne jamais rationaliser un verdict non conforme en RESERVE.
12. Métriques cumulatives¶
| Métrique | Cette story | Référence |
|---|---|---|
| Temps total | 19h | - |
| Itérations gates | 6 | - |
| Écarts totaux | 20 | - |
| Score convergence moyen | 7.79/10 | - |
| Tests | 1399 passés | 100% |
| Coverage | 92%+ | seuil 80% |
| Commits agents | 10 | - |
| Fichiers modifiés | 57 | - |
| Lignes ajoutées | ~9600 | - |
Signature¶
Produit par : Claude (orchestrateur) Date : 2026-02-10 Validation : Automatique (workflow gouvernance)