PD-298 — Retour d'expérience (REX)
1. Résumé exécutif
| Métrique | Valeur |
| Objectif initial | UI propriétaire (création, liste, détail, révocation, journal) des liens de partage sans compte PD-287, côté React Native / Expo |
| Résultat obtenu | Livraison 10/10 agents, 25 fichiers TS (2 333 lignes) — conforme au plan en surface, partiel sur 4 invariants matérialisés |
| Verdict final | RESERVE (Gate 8 v1, moyenne 7.5) |
| Tests contractuels | 0/45 preuve d'exécution PASS fournie (aucun test Jest dans src/sharing/**) |
2. Métriques de convergence
2.1 Temps et itérations
Temps calculés à partir des timestamps artefacts (dir créé 08:56, verdict step 8 15:44).
| Étape | Durée estimée | Durée réelle | Itérations | Écart |
| 0 - Besoin + clarifications | 30 min | 96 min | 1 | +220% |
| 1 - Spécification | 2h | 12 min | 1 | -90% |
| 2 - Tests | 1h | 7 min | 1 | -88% |
| 3 - Gate spec | 1h | 14 min | 1 | -77% |
| 4 - Plan + code-contracts | 1h | 8 min | 1 | -87% |
| 5 - Gate plan | 1h | 15 min | 1 | -75% |
| 6 - Décomposition + implémentation | 4h | 282 min | 1 (10 agents) | +17% |
| 7 - Acceptabilité | 2h | 18 min | 1 | -85% |
| 8 - Gate acceptabilité | 1h | 12 min | 1 | -80% |
| 9 - REX | 30 min | 30 min | 1 | ±0% |
| TOTAL | ~14h | 7h44 | 10 | -45% |
Commits implémentation : 14:59:30 (agent 1) → 15:14:20 (agent 10) — 15 min de commits sur 4h42 d'étape 6, soit ≈4h de recherche/décomposition/textes ARB/contrats avant les commits.
2.2 Scores de convergence par gate
| Gate | Score v1 | Score final | Delta | Itérations |
| Gate 3 | 8.0/10 | 8.0/10 | +0.0 | 1 |
| Gate 5 | 7.875/10 | 7.875/10 | +0.0 | 1 |
| Gate 8 | 7.5/10 | 7.5/10 | +0.0 | 1 |
Toutes les gates en RESERVE v1 avec moyenne ≥ 7.0 mais au moins un critère < 8.0. Aucune correction de cycle (pas de v2) — l'orchestrateur a laissé les réserves ouvertes à l'appréciation humaine plutôt que de relancer une itération.
2.3 Écarts par catégorie
Extraits des confrontations (step 3, step 5, step 8) + acceptability.
| Catégorie d'écart | Gate 3 | Gate 5 | Gate 8 | Total |
| ECT (complétude/testabilité) | 2 | 5 | 3 | 10 |
| DIV (divergence spec/impl) | 1 | 7 | 3 | 11 |
| AMB (ambiguïté) | 1 | 3 | 0 | 4 |
| SEC (sécurité) | 0 | 0 | 3 | 3 |
| PERF (performance) | 0 | 1 | 0 | 1 |
| TOTAL écarts | 4 | 16 | 9 | 29 |
Acceptabilité : 4 majeurs confirmés (ACC-01..04) + 2 mineurs (ACC-05, ACC-06) ; 3 faux positifs écartés (E-07, E-09, E-10).
3. Points fluides
- Décomposition 6a exceptionnellement productive : les 3 textes normatifs manquants (ARB-7, ARB-8, RGPD rétention) ont été résolus lors de la décomposition en négociant des textes par défaut alignés PD-287, sans escalade PO — ce qui a permis d'éviter un blocage v1 des gates ⅗.
- Waves séquentielles 10 agents en 15 min : de 14:59 à 15:14, chaque agent a produit son module en ~1-2 min (cache-first très efficace). Aucun retry, 0 erreur TS bloquante.
- Réutilisation PD-287 comme accélérateur documentaire : la story frontend PD-298 a consommé directement les artefacts PD-287 backend (5 états FSM, endpoints, enum
eventType) sans redécouverte. - Formal-check : aucun blocage formel sur toute la chaîne (domaine sharing-UI non instrumenté, SKIP attendu).
- Convergence v1 sur toutes les gates : aucune relance, délais inter-gates courts (<30 min chacun).
4. Points difficiles
- 0 test Jest livré pour les 10 modules (répétition exacte du pattern PD-287). Prérequis Acceptabilité
Tests CI : N/A coché sans escalade, puis Gate 8 critère test_coverage: 7.0 — pattern « acceptabilité tacite » déjà identifié PD-287. - Sonar scanner local non exécutable (token auth) — dérogation « QG vérifié via API REST » conforme au pattern déjà documenté (12 occurrences récurrentes).
- Guard owner-only partiellement câblé :
src/sharing/guards/index.ts:34 existe mais n'est pas monté dans ProofDetailScreen.tsx → INV-298-12 non matériellement garanti (ACC-01). useProofShares(undefined) dans ShareDetailScreen.tsx:46 : appel déterministe cassé, aucun test ne l'a capturé. - Étape 0 longue (96 min) : 3,2× la cible 30 min. Domaine sharing riche (17 invariants, 4 clarifications PO, injection de veille/learnings, formal-check) — répétition quasi-exacte de PD-287 step 0 (101 min).
- Divergences plan→spec : le plan introduit
GET /shares/:id, Idempotency-Key, timeout 30 s, re-check anti-race revoke — non spécifiés et non testés (DIV-01/02/03/04 Gate 5). Pattern « extensions plan→spec non ratifiées » récurrent PD-287.
5. Hypothèses révélées tardivement
- HT-01 / D-287-03 (regex email) — découverte step 1 ; résolue step 6a via fallback
class-validator @IsEmail() + trim/lowercase aligné backend. - HT-02 / texte RGPD — découverte step 3 ; résolue step 6a par template FR structuré (finalité/base/rétention 90j/destinataires/droits) — sans validation Legal.
- HT-03 / ARB-7 + ARB-8 — découverte step 3 ; résolues step 6a par textes injectés dans les clarifications (cohérents PD-287). Aucun blocage PO requis.
- HT-04 / mapping
eventType — découverte step 3 ; acceptée comme UNKNOWN_EVENT fallback. - HT-05 / borne max
maxViews — découverte step 3 ; non validée côté client, 400 backend propagée. - HT-06/07/08 / contrat PD-287 (offset/limit,
?state=, 204/409 revoke) — non levées avant Gate 5 (plan §8.1 prévoyait levée Wave 2, non documentée) — DIV-14 Gate 5. - Stub
getAuthToken() — non mentionné ni plan ni spec, découvert en acceptabilité → DIV-08 Gate 8 (ERR-298-11 non vérifiable).
6. Invariants complexes
- INV-298-07 (emails non loggés) / ACC-03 —
metadata: Record<string, string|number|boolean> relaie encore n'importe quelle valeur. L'invariant exige un allowlist runtime strict, non implémenté. - INV-298-09 (IP masquée) / ACC-04 — fallback retourne IP brute/trimmée sur entrée invalide, contraire à l'intention du TC-NEG-07.
- INV-298-12 (CTA owner-only) / ACC-01 — le guard est écrit mais pas câblé dans l'écran preuve — zone cross-module classique (pattern récurrent PD-251/279).
- INV-298-17 (pas d'offline) / ACC-05 — aucune garde
NetInfo dans les hooks/écrans. - INV-298-11 (actions selon état) / DIV-05 step 8 —
useProofShares(undefined) dans ShareDetailScreen casse le contrat proofId non vide.
7. Dette technique
- Suite tests Jest intégrée (45 TC contractuels) — impact : élevé (aucune garantie runtime, gouvernance partielle).
- Câblage guard CTA
ProofDetailScreen.tsx (cross-module) — impact : élevé (INV-298-12). - Allowlist PII telemetry (INV-298-07) — impact : moyen (risque RGPD fuite PII via metadata libre).
- Fallback masquage IP robuste (INV-298-09) — impact : moyen (affichage IP brute possible sur entrée malformée).
- Détection NetInfo offline (INV-298-17) — impact : moyen (UX incohérente offline).
- Levée des placeholders ARB-7/ARB-8/RGPD par validation Legal/PO — impact : faible à moyen (textes corrects techniquement, non juridiquement validés).
- Intégration auth existante : remplacer
getAuthToken() stub — impact : élevé (ERR-298-11 non fonctionnel).
8. Risques résiduels
| Risque | Type | Probabilité | Impact | Mitigation |
| Régression UX CTA partage visible sur preuve non possédée | tech | élevé | élevé | Story suivante : câbler ShareCta dans ProofDetailScreen.tsx + test intégration |
Fuite PII email via metadata telemetry | sec | moyen | élevé | Typer metadata avec allowlist stricte (zod.object({...})) + test runtime Sentry |
Écran détail cassé sur appel useProofShares(undefined) | tech | élevé | moyen | Refactor hook pour tolérer null OU retirer l'appel |
400 backend sur maxViews > borne sans message i18n dédié | ux | faible | faible | Ajout mapping erreur backend spécifique quand borne fournie |
| Divergence normalisation email backend vs client | tech | faible | moyen | Test contractuel en backend-dev avant release |
| 45 TC non exécutés — régression future non détectée | tech | élevé | élevé | Story dédiée test coverage sharing/** |
| Extensions plan→spec (GET /shares/:id, Idempotency-Key) non ratifiées | process | moyen | faible | Check PD-287 Swagger + rétro-ajout à la spec ou retrait du client |
8bis. Matrice de délégation inter-PD
| Story | Direction | Statut | Nature de la dépendance | Problème rencontré |
| PD-287 | ← dépend de | DONE (RESERVE) | Endpoints API, FSM 5 états, enum events, textes ARB-7/ARB-8 implicites | FSM backend non entièrement confirmée (HT-07), ?state= non documenté (HT-08), Idempotency-Key non tracé (DIV-03 Gate 5) |
| PD-298-TESTS | → bloque | TODO | Suite Jest 45 TC (17 NOM + 12 ERR + 8 NR + 8 NEG) | À créer |
| PD-298-GUARD | → bloque | TODO | Câblage ShareCta dans ProofDetailScreen.tsx + guard navigation share/create/:proofId | INV-298-12 non garanti sans cette story |
| PD-298-ACC-FIX | → bloque | TODO | Correction ACC-02/03/04/05 (useProofShares, PII allowlist, maskIp fallback, NetInfo) | À planifier sprint suivant |
| PD-298-PLACEHOLDERS | → bloque | TODO | Validation Legal/PO des textes ARB-7, ARB-8, RGPD rétention 90j | Textes fournis par PD-287 mais non Legal-validés |
| PD-99 (auth core) | ← dépend de | Existant | getAuthToken() réel à substituer au stub | Pas d'interface claire documentée dans la story |
8ter. Bugs de tests
| Pattern incorrect | Pattern correct | Cause | Coût |
| (aucun test écrit → aucun bug de test observé) | — | — | — |
Aucun bug de test capitalisable — il n'y a eu aucun test livré pour la story.
8quater. Corrections post-Gate 8
Aucune correction post-Gate 8 appliquée ; le verdict RESERVE reste ouvert pour décision humaine (stories filles PD-298-GUARD, PD-298-ACC-FIX, PD-298-TESTS à lancer).
9. Patterns récurrents détectés
9.1 Patterns confirmés (déjà vus dans d'autres stories)
- 0 test CI livré sur story multi-agents — aussi dans PD-287, PG-03, PG-04, IM-01 — pattern structurel lorsque décomposition 6a ne mandate pas un test par module.
- Faux positifs LLM en reviews — review code a signalé E-07 (code-contracts YAML vs implémentation adaptée), E-09 (SharingStack absent — faux), E-10 (markdownlint) — 3 faux positifs sur 12 écarts remontés (≈25%) — aligne la fréquence cross-stories.
- Sonar Phase 1.5 indisponible — dérogation de fait — 13e occurrence (token auth local).
- Extensions plan→spec non ratifiées (pattern PD-287) — DIV-01/02/03/04 Gate 5 (endpoint détail, anti-race, Idempotency-Key, timeout 30s).
- Placeholders contractuels résolus en décomposition plutôt qu'escaladés — similaire PD-287 (ARB-7/ARB-8 fournis décomp) ; pattern fragile si Legal refuse les textes.
- Guard cross-module avec câblage externe oublié — pattern PD-251/PD-279 (guard écrit mais non monté sur la route cible) ; ACC-01 reproduit.
- Format non contractualisé dans spec v1 bloque en Gate 3 — 25e occurrence : regex D-287-03, textes ARB, copy RGPD, borne
maxViews. - Machine à états explicite avec transitions autorisées/interdites — 24e occurrence : matrice
ALLOWED_ACTIONS 5×5 correctement implémentée. - Stubs inter-PD acceptés en Gate 8 si documentés — 19e occurrence (
getAuthToken() stub documenté).
9.2 Nouveaux patterns identifiés
- Décomposition 6a comme point de résolution des placeholders normatifs — PD-287 et PD-298 ont utilisé la décomposition pour fournir des textes ARB/RGPD par défaut plutôt que d'escalader. ROI : -1 iteration par gate. Risque : textes non Legal-validés livrés en production si pas de story follow-up.
- Réutilisation backend story (PD-287) comme accélérateur frontend (PD-298) — première paire backend→frontend livrée sur un même domaine en 3 jours (PD-287 DONE 2026-04-19, PD-298 DONE 2026-04-22). Temps story frontend -45% vs cible (-3h sur 7h estimées pour une UI 10 modules). À évaluer comme template « pair backend/frontend ».
- Implémentation 10 agents multi-wave en 15 min chrono — du 1er commit au dernier (14:59→15:14). Plus rapide que PD-287 (10 fichiers en 1h30) grâce à cache prompt-first effectivement appliqué et décomposition 6a détaillée. Rendement décroissant non observé (10 agents = pas d'accélération additionnelle mesurable vs 5).
Idempotency-Key UUID v4 côté client sans ratification backend — introduit par le plan unilatéralement (DIV-03 Gate 5). À surveiller si pattern se répète pour valider un besoin cross-story « clés d'idempotence ».
10. Améliorations du workflow
10.1 Améliorations des prompts/templates
| Fichier | Amélioration suggérée | Priorité |
templates/prompts/6a-decomposition.md | Ajouter un bloc obligatoire « Données résolues (pré-implémentation) » avec traçabilité PO/Legal des décisions — actuellement PD-298 a tranché ARB-7/ARB-8/RGPD sans validation humaine | haute |
templates/prompts/6a-decomposition.md | Exiger livraison d'au moins 1 test unitaire par agent 6b (reprise recommandation PD-287, toujours non appliquée) | haute |
templates/prompts/9-rex.md | Ajouter section « Résolution des placeholders » pour tracer la source des textes normatifs livrés | moyenne |
templates/prompts/4-plan-implementation.md | Détecter automatiquement les extensions plan→spec (endpoints, headers, timeouts non spec'ifiés) et forcer ratification PO ou retour Gate 3 (reprise PD-287) | haute |
templates/prompts/7a-review-code.md | Ajouter item déterministe « guard cross-module câblé au point d'entrée cible » (check grep point d'intégration) | moyenne |
templates/outputs/PD-XX-acceptability.md | Bloquer l'étape 7 si Tests CI : N/A coché sans escalade explicite (reprise PD-287) | haute |
.claude/commands/gov-gate.md | Gate 8 : check déterministe pré-verdict tests > 0 dans le module livré ; refuser si 0 test (reprise PD-287) | haute |
templates/prompts/6b-agent-task.md | Rappeler que tout hook signant un contrat (proofId non vide) DOIT voir ses usages vérifiés en fin de phase 6c (synthèse) | moyenne |
10.2 Améliorations des agents
| Agent | Amélioration suggérée | Justification |
agents/agent-screens.md | Ajouter en mission : « vérifier que les hooks consommés respectent leur contrat de type (proofId non undefined) » | Bug useProofShares(undefined) non capturé step 6b (ACC-02) |
agents/agent-guards.md | Ajouter en mission : « câbler explicitement le guard dans le ou les écrans cibles identifiés par le plan §Mécanismes cross-module » | ACC-01 : guard écrit mais non monté |
agents/agent-telemetry.md | Ajouter en mission : « typer strictement metadata avec allowlist Zod ; refuser clés non explicitement autorisées » | ACC-03 : PII fuite potentielle via metadata libre |
agents/agent-tests.md (à créer) | Agent dédié test 6b.N+1 consommant la décomposition et produisant le squelette Jest | Absence structurelle de tests — 6b ne livre pas de test, pas d'agent tests |
10.3 Améliorations du processus
- Forcer l'escalade PO sur les placeholders normatifs avant Gate 5 — décomposition 6a ne doit pas se substituer à Legal/PO pour des textes contractuels (ARB-7/ARB-8/RGPD). Rattaché au pattern structurel PD-287/PD-298.
- Check « 0 test = 0 gate 8 » au niveau skill
/gov-gate : refuser le verdict si find src/<module> -name "*.test.ts*" | wc -l == 0. - Pair backend/frontend template : documenter l'enchaînement PD-287 → PD-298 comme pattern pour toute feature cross-layer (API livrée puis UI consommatrice). ROI mesuré : -45% temps frontend vs cible.
- Audit plan→spec automatique : script
detect-plan-extensions.py comparant les endpoints/headers/timeouts du plan aux contrats spec, invoqué par /gov-check-plan.
11. Enseignements clés
- Tests-as-gate-prerequisite — Une story multi-agents qui livre 25 fichiers sans un seul test renvoie un signal de gouvernance faible même avec Gate 8 RESERVE. Rendre
tests > 0 un prérequis déterministe pré-verdict Gate 8 (reprise PD-287). La « dette test » systématique creuse un écart structurel entre conformité formelle et garantie runtime. - Décomposition 6a comme mini-arbitre normatif — Quand spec/plan portent des placeholders contractuels (ARB, RGPD), la décomposition est devenue de facto le point où les textes sont tranchés. Ce shift non documenté fait que des décisions PO/Legal sont prises par l'orchestrateur. À formaliser : soit interdire (escalade obligatoire avant 6a), soit tracer (§« Données résolues » avec source humaine).
- Guard cross-module : écrire ne suffit pas, câbler est l'invariant — ACC-01 reproduit un pattern déjà vu PD-251/PD-279. Le plan listait
src/screens/proofs/ProofDetailScreen.tsx comme fichier à modifier, mais l'agent guards a uniquement écrit le composant ShareCta. Ajouter une phase 6c.bis « vérification cross-module » avec grep du point d'intégration. - Pair backend→frontend accélérateur — La paire PD-287/PD-298 a tiré bénéfice de la FSM partagée, des endpoints réutilisés, et de 3 textes normatifs déjà tranchés côté backend. Temps frontend -45% vs cible. Réutiliser ce séquencement pour toute feature cross-layer.
- Extensions plan→spec récurrentes — PD-287 et PD-298 ont tous deux introduit 4+ extensions non ratifiées (endpoints, headers, timeouts, flux additionnels). Automatiser la détection dans
/gov-check-plan phase 4 pour forcer soit la ratification soit le retour Gate 3.
12. Métriques cumulatives (auto-calculées)
| Métrique | Cette story | Moyenne projet | Tendance |
| Temps total | 7.74h | 6.27h (31 stories) | ↑ |
| Itérations gates | 3 | 5.4 | ↓ |
| Écarts totaux | 29 | 21.2 | ↑ |
| Score convergence moyen | 7.79/10 | 8.42/10 | ↓ |
| Temps step 6 (impl) | 4.70h | 1.33h | ↑↑ |
| Stories app mesurées (avec PD-298) | 5 | avg 9.16h | ↓ (plus rapide) |