{
  "contract_version": "gab_314_contract_v1",
  "gab_id": "GAB-314",
  "canonical_name": "RevisionLearningMistakeReview",
  "module_owner": "EdTechRevisionLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "review_id",
    "errors",
    "cta_label",
    "cta_action"
  ],
  "optional_fields": [
    "intro_hint",
    "errors[].frequency_color",
    "proof_of_return_message",
    "remediation_panel_prefix",
    "error_source"
  ],
  "field_types": {
    "review_id": "string — identifiant unique de la session de revue",
    "intro_hint": "string — texte d'introduction affiché au-dessus de la liste (principe pédagogique)",
    "errors": "array<{error_id:string, typology:string, frequency:integer>=1, frequency_color:enum['gold','coral','violet','mint','sky'], remediation:string}>",
    "cta_label": "string — libellé du bouton de confirmation de l'exercice refait",
    "cta_action": "string — identifiant de l'action déclenchée par le bouton",
    "proof_of_return_message": "string — message affiché après validation du CTA",
    "remediation_panel_prefix": "string — emoji/icône préfixant le panel de remédiation",
    "error_source": "string — référence à l'exercice source des erreurs"
  },
  "constraints": [
    "errors doit contenir au moins 1 entrée — liste vide déclenche BLOCKED.",
    "errors[].typology et errors[].remediation sont obligatoires dans chaque item.",
    "errors[].frequency doit être un entier >= 1.",
    "Le moteur commente la réponse, jamais l'élève — le contenu de typology/remediation doit respecter ce principe.",
    "cta_label vient du JSON : le libellé HTML du bouton est piloté par l'instance.",
    "Un seul clic sur le CTA suffit : après validation, le bouton est désactivé (logique moteur)."
  ],
  "blocked_conditions": [
    "errors absent ou vide",
    "review_id absent",
    "cta_label absent",
    "cta_action absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria_selected_on_active_error"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, liste d'erreurs cliquables, panel remédiation au clic, CTA visible, 0 erreur" },
    { "case": "champ requis manquant (errors vide)", "expected": "BLOCKED listant le champ" },
    { "case": "clic sur erreur", "expected": "panel remédiation affiché avec typology + remediation" },
    { "case": "clic CTA après sélection", "expected": "panel proof_of_return_message affiché, bouton désactivé" },
    { "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" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-314",
    "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)."
  }
}
