{
  "contract_version": "gab_267_contract_v1",
  "gab_id": "GAB-267",
  "canonical_name": "ComprehensionLearningMisconceptionCheck",
  "module_owner": "EdTechComprehensionLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "audio_listening_id",
    "transcript",
    "key_timestamps"
  ],
  "optional_fields": [
    "title",
    "subtitle",
    "listening_mode",
    "audio_url",
    "duration",
    "rationale",
    "primary_cta",
    "secondary_cta"
  ],
  "field_types": {
    "audio_listening_id": "string — identifiant unique de cette instance d'écoute",
    "listening_mode": "enum['podcast_history','dialogue_language','lecture_science','story_literature']",
    "audio_url": "string (URL ou chemin vers le fichier audio)",
    "duration": "string (format MM:SS)",
    "transcript": "string — texte complet du document audio, obligatoire pour accessibilité",
    "key_timestamps": "array<{time:string(MM:SS), label:string}> — passages-clés horodatés, min 1 entrée",
    "rationale": "string — explication pédagogique du dispositif transcript+timestamps",
    "primary_cta": "object{label:string, action:string}",
    "secondary_cta": "object{label:string, action:string}"
  },
  "constraints": [
    "transcript obligatoire pour accessibilité (WCAG 1.2.1) — aucun audio sans texte alternatif.",
    "key_timestamps : au moins 1 entrée requise ; chaque entrée doit avoir time (MM:SS) et label.",
    "primary_cta : libellé structurel (HTML bouton), libellé venant du JSON.",
    "audio_url peut être _TODO si pas encore disponible ; le rendu reste valide."
  ],
  "blocked_conditions": [
    "transcript absent",
    "key_timestamps vides",
    "audio_listening_id absent"
  ],
  "accessibility": [
    "transcript_text_alternative",
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria_label_play_button"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 0 erreur" },
    { "case": "transcript absent", "expected": "BLOCKED listant le champ manquant" },
    { "case": "key_timestamps vide []", "expected": "BLOCKED listant key_timestamps vides" },
    { "case": "instance externe injectée via ENGINE.init(data)", "expected": "le rendu change sans modifier le HTML" },
    { "case": "responsive 375/768/1024", "expected": "aucun débordement horizontal" },
    { "case": "clic bouton play", "expected": "toggle icône ▶/⏸" },
    { "case": "clic CTA primary", "expected": "panel ok avec action de l'instance" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-267",
    "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). Note : le canonical_name 'ComprehensionLearningMisconceptionCheck' est celui de la cartographie officielle ; la source HTML nomme ce GAB 'AudioListening' (ComprehensionLearningAudioListening). Contenu extrait de INDEX-300-comprehensionlearning-GAB-266-270-PLAYABLE.html, stage data-tpl='267'."
  }
}
