# GAB-323 · ResearchLearningSearchQueryBuilder — « Construire une requête de recherche »

**Archétype / renderer_key :** `text_cta` (cartographie) · **module :** EdTechResearchLearning
**Critère validé :** changer le JSON change les chips et feedbacks sans modifier le HTML. ✅ check.py 12/12.

## Pack (structure officielle par-GAB)
```
GAB-323/
  renderer.html            ← moteur constructeur de requête (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` · `query_builder_id` · `keywords[]{id,label,type}` · `min_terms` · `feedback_too_vague` · `feedback_ok_template` (avec `{count}`) · `primary_cta{label,action}`

Optionnels : `title`, `instruction`.

## Ce qui vient du JSON vs HTML
- **JSON** : chaque chip (label + type), le seuil minimal (`min_terms`), le feedback trop vague, le feedback ok (gabarit `{count}`), le libellé du bouton.
- **HTML** : layout chips, zone requête assemblée, bouton structurel, panels de feedback, slots.

## Garde-fous (child_safety)
- **Seuil anti-vague** : si `selected.length < min_terms` au moment du test → panel warn avec `feedback_too_vague` (BLOCKED logique).
- **Anti-invention** : les chips et les feedbacks viennent exclusivement de l'instance JSON, jamais hardcodés dans le HTML.
- **BLOCKED** si `keywords` vide / `min_terms` absent / `feedback_too_vague` absent / `feedback_ok_template` absent / `primary_cta` absent.

## QA à vérifier
1. Modifier un `label` dans `keywords` → chip change sans toucher au HTML (critère d'or).
2. `keywords:[]` → BLOCKED propre.
3. Sélectionner 1 chip (min_terms=2) + clic tester → panel warn avec `feedback_too_vague`.
4. Sélectionner 2+ chips + clic tester → panel ok avec `feedback_ok_template` interpolé (count correct).
5. Responsive 375/768/1024 — chips wrap sans débordement.

## external_refs / dependencies
- Usage amont : GAB-322 (formulation de la question de recherche) → GAB-323 (construction requête) → GAB-324 (sélection sources).
- Le gabarit `{count}` dans `feedback_ok_template` est interpolé côté moteur JS avec `selected.length`.

## Source
`INDEX-300-researchlearning-GAB-321-325-PLAYABLE.html` (stage `data-tpl="323"`, handlers `d323Add`, `d323Test`).
