{
  "contract_version": "gab_212_contract_v1",
  "gab_id": "GAB-212",
  "canonical_name": "AdaptiveLearningRecommendationCard",
  "module_owner": "EdTechAdaptiveLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "recommendation_id",
    "title",
    "summary",
    "reason",
    "next_action",
    "primary_cta"
  ],
  "optional_fields": [
    "recommendation_type",
    "secondary_cta",
    "skip_cta",
    "meta_duration",
    "meta_difficulty",
    "accessibility",
    "child_safety"
  ],
  "field_types": {
    "recommendation_type": "enum['visual','practice','memory','advance'] — détermine la couleur du tag affiché",
    "reason": "string — obligatoire, en langage élève, 1-2 phrases maximum, jamais de jargon technique",
    "primary_cta": "object{label:string, action:string}",
    "secondary_cta": "object{label:string, action:string}",
    "skip_cta": "object{label:string, action:string}",
    "meta_duration": "string — ex: '~ 8 min'",
    "meta_difficulty": "string — ex: 'Facile', 'Moyen', 'Difficile'"
  },
  "constraints": [
    "reason est obligatoire : aucune recommandation opaque sans explication pour l'élève.",
    "skip_cta doit être disponible si la recommandation est optionnelle (ne pas imposer).",
    "recommendation_type conditionne uniquement la couleur du tag — le rendu reste identique.",
    "Ne pas utiliser ce gabarit pour un pont diagnostic (→ GAB-180) ni une route multi-étapes (→ GAB-194).",
    "primary_cta.label vient du JSON — jamais hardcodé dans le HTML."
  ],
  "blocked_conditions": [
    "title absent (BLOCKED)",
    "summary absent (BLOCKED)",
    "reason absent (BLOCKED)",
    "primary_cta absent (BLOCKED)"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "skip_always_available"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 0 erreur, reason affiché" },
    { "case": "reason absent", "expected": "BLOCKED — transparence adaptative obligatoire" },
    { "case": "primary_cta absent", "expected": "BLOCKED — bouton structurel requis" },
    { "case": "skip_cta présent", "expected": "bouton Passer visible, style dashed" },
    { "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, CTAs en flex-wrap" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-212",
    "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-211 (AdaptiveLearningEntrySignal) — fournit le signal source qui déclenche cette recommandation",
      "GAB-180 (LevelTestRecommendationBridge) — gabarit distinct : pont sortie diagnostic LevelTest",
      "GAB-194 (PathMapRecommendedRoute) — gabarit distinct : route multi-étapes dans PathMap"
    ]
  }
}
