{
  "contract_version": "gab_356_contract_v1",
  "gab_id": "GAB-356",
  "canonical_name": "MotivationLearningProgressCelebration",
  "module_owner": "EdTechMotivationLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "celebration_id",
    "progress_proof",
    "tone_options",
    "partial_progress_label",
    "partial_progress_message"
  ],
  "optional_fields": [
    "doc_kind",
    "tone_prompt",
    "slots",
    "use_when",
    "do_not_use_when"
  ],
  "field_types": {
    "celebration_id": "string — identifiant unique de l'instance de célébration",
    "progress_proof": "string — preuve mesurable du progrès (ex: score avant/après)",
    "doc_kind": "string — libellé de la catégorie du document de preuve",
    "tone_prompt": "string — question posée à l'apprenant sur le ton de célébration",
    "tone_options": "array<{id:string, label:string, panel_class:enum['ok','warn','bad','note'], message:string, next_action:string|null}>",
    "partial_progress_label": "string — libellé du bouton progrès partiel",
    "partial_progress_message": "string — message affiché lors de la reconnaissance d'un progrès partiel",
    "slots": "array<string> — liste des slots pédagogiques activés",
    "use_when": "array<string> — cas d'usage appropriés",
    "do_not_use_when": "array<string> — cas d'usage à éviter"
  },
  "constraints": [
    "progress_proof : doit contenir une preuve mesurable (valeurs chiffrées avant/après), jamais une assertion vague.",
    "tone_options : au moins 1 option requise ; panel_class ∈ ['ok','warn','bad','note'].",
    "partial_progress_message : valorise le chemin parcouru sans minimiser ni surjouer.",
    "tone_options[].next_action : null si non applicable (ex : mauvais ton) — jamais de string vide."
  ],
  "blocked_conditions": [
    "progress_proof absent",
    "tone_options vides",
    "celebration_id absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "tabindex sur chaque chip"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 0 erreur, chips cliquables" },
    { "case": "champ requis manquant (progress_proof)", "expected": "BLOCKED listant le champ" },
    { "case": "tone_options vide ([])", "expected": "BLOCKED listant tone_options vides" },
    { "case": "instance externe injectée via init(ext)", "expected": "le rendu change sans modifier le HTML" },
    { "case": "clic chip 'Sincère & mesuré'", "expected": "panel ok + next_action affiché" },
    { "case": "clic chip 'Surenchère totale'", "expected": "panel warn, next_action null ignoré" },
    { "case": "clic chip progrès partiel", "expected": "panel ok avec partial_progress_message" },
    { "case": "responsive 375/768/1024", "expected": "aucun débordement horizontal" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-356",
    "note": "Ce schema VALIDE l'instance. Le contrat pédagogique complet (input_contract/validation_logic/feedback_scoring_logic) vit dans le CORE-GAB officiel, pas ici (évite la duplication)."
  }
}
