# GAB-290 · WritingLearningFinalReview — « Relecture finale + export + privacy »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechWritingLearning
**Critère validé :** changer le JSON change l'affichage sans modifier le HTML. ✅ check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-290/
  renderer.html            ← moteur relecture finale (ne pas modifier par instance)
  instance.example.json    ← SOURCE DE VÉRITÉ (contenu réel, à plat)
  schema.contract.json     ← contrat de validation
  README-contract.md       ← ce fichier
```

## Champs requis (instance, à plat)
`gab_id` · `final_review_id` · `draft_ref` · `review_checklist[]{id,level,text}` · `finalization_policy` · `next_action`

Optionnels : `title`, `subtitle`, `blocking_errors[]`, `version_label`, `export_policy[]{format,icon}`, `share_policy{default,allowed,description}`, `teacher_review_ref`, `reason_why`, `primary_cta{label,action}`, `secondary_cta{label,action}`, `finalized_feedback`, `review_progress{checked,total,blocking_remaining}`.

## Archétype

GAB-290 est un **écran de validation finale** avant rendu : il combine une checklist à 3 niveaux (`blocking` / `done` / `normal`), un progress ring, un bloc privacy (share_policy), un export multi-format et un CTA de finalisation.

La logique de tri est intégrée au moteur : les items `blocking` remontent toujours en premier, quel que soit leur ordre dans le JSON source.

## Ce qui vient du JSON vs HTML

- **JSON** : chaque item de la checklist (texte + niveau), le progress (checked/total/blocking_remaining), le share_policy (description privacy), les formats d'export, le version_label, le reason_why, les libellés CTA, le finalized_feedback.
- **HTML** : layout, progress ring SVG, rendu des couleurs par niveau, grille export, panels de feedback — rien en dur.

## Garde-fous (child_safety)

- **BLOCKED** si `review_checklist` vide / `final_review_id` absent / `draft_ref` absent.
- **Privacy par défaut** : `share_policy.default = 'privé'` — aucune publication automatique.
- **Anti-invention** : le moteur n'ajoute aucun contenu hors instance (0 texte codé en dur dans le JS).
- `blocking_errors` : les items de niveau `blocking` sont visuellement distincts (fond coral, icône `!`) pour forcer leur résolution avant rendu.

## QA à vérifier

1. Modifier un `text` ou un `level` dans `review_checklist` → rendu change sans toucher au HTML (critère d'or).
2. `review_checklist:[]` → BLOCKED propre dans le panel erreur.
3. `final_review_id` absent → BLOCKED listé.
4. CTA primaire cliqué → `finalized_feedback` affiché, bouton désactivé.
5. CTA secondaire cliqué → `teacher_review_ref` affiché dans panel.
6. `review_progress.checked/total` → ring animé proportionnellement.
7. Responsive 375/768/1024 — grille export passe en 2 colonnes sur mobile.
8. Instance externe injectée via `ENGINE.init(myInstance)` → rendu complet sans modifier le HTML.

## external_refs / dependencies

Aucune dépendance externe hors-lot. Le gradient SVG `frGrad290` est local au renderer (id suffixé `290` pour éviter collision si plusieurs renderers sont chargés sur la même page).

## Source

`INDEX-300-writinglearning-GAB-286-290-PLAYABLE.html` (stage `data-tpl="290"`, bloc `.ic290`, handlers `gabConfirm`/`gabReveal`). Extrait : checklist 7 items, 2 blocking + 5 done, export PDF/DOCX/Texte brut, share_policy privacy, version v3.
