{
  "contract_version": "gab_316_contract_v1",
  "gab_id": "GAB-316",
  "canonical_name": "RevisionLearningFlashReview",
  "module_owner": "EdTechRevisionLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "flash_review_id",
    "flash_item",
    "essential",
    "confidence_labels"
  ],
  "optional_fields": [
    "detail",
    "cta_reveal_label",
    "cta_dont_know_label",
    "exit_unknown_message",
    "confidence_feedback",
    "fallback_text_summary"
  ],
  "field_types": {
    "flash_item": "string — question courte à afficher en mode rappel actif",
    "essential": "string — réponse minimale essentielle révélée au clic",
    "detail": "string — explication complémentaire optionnelle (affichée en panel note après révélation)",
    "confidence_labels": "array<string> — libellés des niveaux de confiance (min 1, typiquement 3)",
    "cta_reveal_label": "string — libellé du bouton principal de révélation",
    "cta_dont_know_label": "string — libellé du bouton sortie si l'élève ne sait pas",
    "exit_unknown_message": "string — message affiché dans le panel warn quand l'élève ne sait pas",
    "confidence_feedback": "string — message panel ok après sélection d'un niveau de confiance",
    "fallback_text_summary": "string — résumé texte pour accessibilité / fallback rendu dégradé"
  },
  "constraints": [
    "flash_item : obligatoire, non vide.",
    "essential : obligatoire, non vide — jamais inventé, extrait de la source.",
    "confidence_labels : array non vide ; le dernier bouton reçoit le style 'forte' (primary).",
    "exit_unknown_message : si absent, fallback générique 'Sortie flash — explication à venir.'",
    "Le HTML (flux reveal / dontKnow / confidence) ne change pas ; seuls les champs JSON changent le rendu."
  ],
  "blocked_conditions": [
    "flash_item absent ou vide (BLOCKED)",
    "essential absent ou vide (BLOCKED)",
    "confidence_labels absent ou vide (BLOCKED)"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "fallback_text_summary"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, question affichée, 0 erreur" },
    { "case": "flash_item manquant", "expected": "panel bad BLOCKED listant le champ" },
    { "case": "essential manquant", "expected": "panel bad BLOCKED listant le champ" },
    { "case": "confidence_labels vide", "expected": "panel bad BLOCKED listant le champ" },
    { "case": "clic Révéler", "expected": "réponse essentielle affichée + boutons confiance + panel note detail" },
    { "case": "clic Je ne sais pas", "expected": "panel warn avec exit_unknown_message" },
    { "case": "clic niveau confiance", "expected": "panel ok avec confidence_feedback + boutons désactivés" },
    { "case": "instance externe injectée via ENGINE.init(ext)", "expected": "le rendu change sans modifier le HTML" },
    { "case": "responsive 375/768/1024", "expected": "aucun débordement horizontal" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-316",
    "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)."
  }
}
