# GAB-259 · CollaborationLearningOralPartnerPractice — « Entraînement oral à deux »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechCollaborationLearning
**Critère validé :** changer le JSON change le rendu (rôles, étapes, timer, libellé CTA) sans modifier le HTML.

## Pack (structure officielle par-GAB)
```
GAB-259/
  renderer.html            ← moteur entraînement oral (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
```

## Archétype pédagogique
GAB-259 = concrétisation du variant **oral_partner** de la chaîne PairTask (PART-17A/B).
Principe : 2 élèves alternent les rôles **ORATEUR** (présente sans interruption) et **JURY** (écoute, note clarté/structure, pose 1 question de relance). Routine en 4 étapes. Timer affiché. Feedback structuré 2 stars + 1 wish.

**Chaîne :** 256 ParentChild → 257 Explain → 258 Correction → **259 Oral** → 260 Team

## Champs requis (instance, à plat)
`gab_id` · `oral_practice_id` · `title` · `oral_format` · `roles[]{id,label,description}` · `items[]{step,label,body}` · `primary_cta{label,action}`

Optionnels : `subtitle`, `icon`, `oral_format_enum`, `estimated_duration`, `timer_duration_seconds`, `rounds`, `context_hint`, `secondary_cta`, `use_when`, `do_not_use_when`.

## Ce qui vient du JSON vs HTML
- **JSON** : titre, sous-titre, icône, format oral, rôles (label + description), étapes (label + body), durée timer, libellés CTA.
- **HTML** : grille rôles, barre timer animée, numéros d'étapes, boutons structurels, layout, fallback BLOCKED.

## Garde-fous
- **BLOCKED** si `oral_practice_id` absent / `oral_format` absent / `roles` vide / `items` vide.
- Rôles toujours 2 (orateur A = violet, jury B = sky) — jamais un seul rôle affiché.
- Timer animé en CSS pur (pas de setInterval) — safe prefers-reduced-motion.
- `primary_cta.label` vient du JSON — jamais hardcodé dans le HTML.
- `timer_duration_seconds` en entier positif (secondes) ; affiché converti en mm:ss.

## QA à vérifier
1. Modifier `title` / `roles[0].description` → rendu change sans toucher au HTML.
2. `oral_format` absent → BLOCKED propre.
3. `roles:[]` → BLOCKED "roles absent ou vide".
4. `items:[]` → BLOCKED "items absent ou vide".
5. Instance externe injectée (format `débat_court`) → titre, rôles, étapes et CTA changent.
6. Responsive 375/768/1024 : grille rôles passe en 1 colonne sous 560px.

## Source
`INDEX-300-collaborationlearning-GAB-256-260-PLAYABLE.html` (stage `data-tpl="259"`, handlers `oppPick`, objet `OPP_TYPES`).

## external_refs / dependencies
- **GAB-254** : mentionné dans l'étape 3 (feedback "2 stars + 1 wish → GAB-254"). Référence pédagogique, pas de dépendance technique.
- **Lot** : LOT-collaborationlearning-GAB-256-260 — vague 2 module 17.
