Rétrospective — PD-298¶
Résumé story¶
- Story : PD-298 — [APP] UI de création et gestion des liens de partage sans compte
- Domaine : sharing
- Date : 2026-04-23
- Gates : G3 RESERVE (v1, 8.0) | G5 RESERVE (v1, 7.875) | G8 RESERVE (v1, 7.5)
Learnings de cette story¶
Depuis les gates¶
| Gate | Verdict | Score | Tags | Note |
|---|---|---|---|---|
| G3 | RESERVE | 8.0 | #sharing, #react-native, #rgpd | Spec companion doit inclure textes contractuels source pour autonomie documentaire |
| G5 | RESERVE | 7.875 | #sharing, #plan, #code-contracts | Écarts viennent de textes absents du contexte LLM, pas de défauts structurels |
| G8 | RESERVE | 7.5 | #sharing, #branded-types | 0 tests Jest, guard owner non câblé, maskIp fallback brut, PII metadata |
Depuis le REX¶
- Pattern "0 test CI accepté tacitement" (severity: high) — 2e occurrence (PD-287, PD-298). Le workflow Gate 8 ne bloque pas sur l'absence de tests dans le module livré.
- Décomposition résout silencieusement les placeholders normatifs (severity: high) — ARB-7, ARB-8, RGPD résolus dans la décomposition sans traçabilité PO/Legal explicite.
- Guard cross-module écrit mais jamais câblé (severity: high) — 3e occurrence (PD-251, PD-279, PD-298). Le guard de propriété existe dans
src/sharing/guards/mais n'est pas intégré dansProofDetailScreen.tsx. - Paire backend→frontend comme accélérateur (severity: medium) — PD-287 DONE → PD-298 DONE en 3 jours. -45% vs estimation. Réutilisation FSM/endpoints/textes normatifs déjà tranchés.
- Metadata telemetry libre = fuite PII (severity: high) —
Record<string, unknown>permet l'injection derecipientEmail. Typer avec Zod allowlist stricte. - Extensions plan→spec non ratifiées (severity: high) — 4 extensions dans le plan non validées formellement.
Patterns récurrents (domaine sharing + app)¶
Pattern 1 — Guard cross-module non câblé (3 stories : PD-251, PD-279, PD-298)¶
Description : Un guard (ownership, permission, validation) est implémenté dans le module feature mais jamais câblé au point d'entrée existant (écran parent, route, middleware). Fréquence : 3/3 stories app avec cross-module. Impact : INV-298-12 non tenu → MAJEUR en Gate 8 à chaque fois. Recommandation : Ajouter une Phase 6c.bis "vérification cross-module" dans /gov-impl : après la synthèse 6c, grep systématique des points d'intégration listés dans le plan §Mécanismes cross-module. Si le point d'intégration n'est pas modifié → corriger avant step 7.
Pattern 2 — Absence de tests unitaires acceptée en Gate 8 (2 stories : PD-287, PD-298)¶
Description : Le module livré a 0 test Jest mais Gate 8 passe en RESERVE. Fréquence : 2/2 stories sharing. Impact : test_coverage = 7.0 systématiquement. Aucune régression détectable. Recommandation : Ajouter un check déterministe pré-verdict Gate 8 : si find src/{module}/ -name "*.test.ts" | wc -l == 0 → test_coverage plafonné à 6.0. Force le NON_CONFORME ou l'ajout de tests.
Pattern 3 — Textes contractuels absents du contexte LLM reviewer (2 stories : PD-298 G3, G5)¶
Description : Le reviewer LLM (Claude ou Codex) n'a pas accès aux textes normatifs (ARB-⅞, regex email, copy RGPD) qui existent dans d'autres documents du corpus. Il signale des "bloquants" qui sont des faux positifs après confrontation. Fréquence : Gates 3 et 5 de PD-298 (4 bloquants reclassés). Impact : Inflation des écarts, temps de confrontation allongé. Recommandation : Le script assemble-prompt.sh pour les gates companion (PD-298 = companion de PD-287) devrait injecter les arbitrages PO et invariants de la story source dans le bloc stable du prompt reviewer. Coût : +2KB de contexte. Gain : -4 faux positifs par gate.
Pattern 4 — PII libre en metadata telemetry (nouveau, PD-298)¶
Description : Un module telemetry avec invariant "aucun email en log" accepte Record<string, any> en metadata. Fréquence : 1 story (émergent). Impact : Fuite PII reproductible, MAJEUR sécurité. Recommandation : Dans learnings-universal.md, ajouter : "Pour tout module telemetry avec invariant PII-free, typer metadata avec Zod allowlist stricte. Jamais Record<string, unknown>."
Recommandations¶
Priorité haute (≥ 3 stories ou pattern bloquant)¶
- Phase 6c.bis cross-module : Ajouter dans
/gov-implun grep post-synthèse des points d'intégration cross-module. Si absent du diff → correction obligatoire. (Pattern 1 — 3 stories) - Gate 8 check tests : Si 0 test dans le module livré →
test_coverageplafonné à 6.0. (Pattern 2 — 2 stories) - Injection arbitrages story source : Pour stories companion, injecter les arbitrages PO de la story source dans les prompts de gate. (Pattern 3 — 2 stories, 4 faux positifs)
Priorité normale¶
- Zod allowlist telemetry : Ajouter règle dans
learnings-universal.mdpour metadata stricte. (Pattern 4) - Traçabilité résolution placeholders : La décomposition 6a doit avoir une section "Données résolues" avec source humaine explicite. (Learning 2)
Signal CLAUDE.md¶
| Section | Suggestion |
|---|---|
procedures.md § Étape 6 | Ajouter Phase 6c.bis : "Après 6c, vérifier les points d'intégration cross-module listés dans le plan. Si le fichier cible n'est pas dans le diff → corriger avant step 7." |
procedures.md § Gates PMO | Ajouter garde déterministe : "Si find src/{module}/ -name '*.test.ts' \| wc -l == 0, plafonner test_coverage à 6.0." |
learnings-universal.md | Ajouter : "Metadata telemetry avec invariant PII-free : typer avec Zod allowlist stricte. Jamais Record |
workflow-rules.md § Assemblage cache-first | Pour stories companion, inclure les arbitrages PO de la story source (besoin §9 Arbitrages) dans le bloc stable des prompts de gate. |