{
  "contract_version": "gab_247_contract_v1",
  "gab_id": "GAB-247",
  "canonical_name": "AssessmentLearningExamMode",
  "module_owner": "EdTechAssessmentLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "exam_mode_id",
    "title",
    "summary",
    "timer",
    "deactivations",
    "rules_text",
    "primary_cta"
  ],
  "optional_fields": [
    "mode_chip",
    "stress_safe_notice",
    "non_official_title",
    "non_official_text",
    "secondary_cta"
  ],
  "field_types": {
    "timer": "object{label:string, display:string, context:string}",
    "deactivations": "array<{label:string, description:string, gab_ref:string}>",
    "primary_cta": "object{label:string, action:string}",
    "secondary_cta": "object{label:string, action:string}",
    "mode_chip": "enum['timed','free','guided','mixed']"
  },
  "constraints": [
    "deactivations doit contenir au moins 1 entrée (liste non vide obligatoire).",
    "timer.display doit être au format MM:SS (ex: '10:00').",
    "primary_cta.label et primary_cta.action sont obligatoires — bouton structurel dont le libellé vient du JSON.",
    "non_official_text et non_official_title recommandés pour tout usage de type 'examen' afin d'éviter toute confusion avec une épreuve officielle.",
    "stress_safe_notice obligatoire si la cible inclut des mineurs (child_safety)."
  ],
  "blocked_conditions": [
    "exam_mode_id absent",
    "timer absent",
    "deactivations vides ou absentes"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "chrono non clignotant (child_safety)",
    "fallback_text via rules_text"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 0 erreur" },
    { "case": "champ requis manquant (timer absent)", "expected": "BLOCKED listant le champ" },
    { "case": "deactivations vides []", "expected": "BLOCKED — liste désactivations vide" },
    { "case": "instance externe injectée via init(ext)", "expected": "le rendu change sans modifier le HTML" },
    { "case": "responsive 375/768/1024", "expected": "aucun débordement horizontal" },
    { "case": "bannière non_official_text présente", "expected": "affiché en bas de carte, bien visible" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-247",
    "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)."
  },
  "external_refs": {
    "dependencies": ["GAB-237", "GAB-233", "GAB-234", "GAB-231"],
    "note": "Ces 4 GAB sont explicitement désactivés pendant l'épreuve. Leurs gab_ref figurent dans chaque entrée du tableau deactivations. Ce GAB-247 les référence mais ne les implémente pas."
  }
}
