# GAB-229 · SmartSelectSessionMix — « Composition session courte »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechSmartSelect
**Critère validé :** changer le JSON change la session affichée sans modifier le HTML.

## Pack (structure officielle par-GAB)
```
GAB-229/
  renderer.html            ← moteur pipeline session mix (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` · `session_mix_id` · `title` · `summary` · `items[]{step,role,role_label,title,description,module_type,module_chip}` · `next_action{primary_label,primary_action,secondary_label,secondary_action}`

Optionnels : `mix_type`, `mix_type_enum[]`, `reason`, `estimated_duration`, `block_count`, `difficulty`, `distinction_note`.

## Ce qui vient du JSON vs HTML
- **JSON** : titre hero, résumé, type de mix actif, liste des blocs pipeline (rôle, titre, durée, module_type), reason pédagogique, méta-pills, libellés des CTAs, note de distinction 229 ≠ 202.
- **HTML** : layout pipeline, step-nums colorés (sky/violet/mint selon position), enum chips, barre CTA, panneaux feedback.

## Archétype
SmartSelectSessionMix **CHOISIT** la composition d'une session courte (ranking, ordre, durée). GAB-202 (PlayEngineBlockStack) **EXÉCUTE** la pile résultante dans PlayEngine. SmartSelect produit une référence `play/<id>` que PlayEngine consomme. Ces deux GABs sont complémentaires et non substituables.

## Garde-fous
- **BLOCKED** si `title` absent / `summary` absent / `items` vide / `next_action` absent.
- `items[].step` doit être croissant (1, 2, 3...).
- `mix_type` doit correspondre à une valeur de `mix_type_enum` si présent.
- Les libellés des boutons viennent de `next_action` — jamais hardcodés dans le HTML.
- Pas de contenu pédagogique inventé : les textes de l'instance viennent exclusivement du HTML source GAB-229.

## QA à vérifier
1. Modifier un `title`/`reason` → rendu change sans toucher au HTML (critère d'or).
2. `items:[]` → BLOCKED propre.
3. `mix_type_enum` → chips affichées, chip active = `mix_type`, clic change le badge hero.
4. CTA primaire → panel ok. CTA secondaire → panel note.
5. Responsive 375/768/1024 — no overflow.

## external_refs / dependencies
- **GAB-202** (PlayEngineBlockStack) : consommateur de la référence `play/<id>` produite par ce GAB. SmartSelectSessionMix orchestre, PlayEngineBlockStack exécute.
- **EdTechSmartSelect module** : module parent (vague 2, lot INDEX-300, GAB-226→230).

## Source
`INDEX-300-smartselect-GAB-226-230-PLAYABLE.html` (stage `data-tpl="229"`, CSS `.sm-*`, handlers `peConfirm`/`peNote`/`peSelect`).
