{
  "contract_version": "gab_271_contract_v1",
  "gab_id": "GAB-271",
  "canonical_name": "MethodLearningIntro",
  "module_owner": "EdTechMethodLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "method_intro_id",
    "title",
    "method_goal",
    "use_case",
    "expected_output",
    "primary_cta"
  ],
  "optional_fields": [
    "prerequisites",
    "limit",
    "estimated_duration",
    "difficulty",
    "method_scope",
    "fallback_help_ref",
    "secondary_cta"
  ],
  "field_types": {
    "method_intro_id": "string — identifiant unique de l'intro méthode",
    "title": "string — titre de la méthode",
    "method_goal": "string — phrase introductive (contrat d'usage)",
    "use_case": "string — quand appliquer la méthode (clause WHEN)",
    "expected_output": "string — ce que l'élève doit produire (clause RESULT)",
    "primary_cta": "object{label,action} — bouton principal structurel",
    "prerequisites": "string — ce qu'il faut avoir appris avant (clause PREREQ)",
    "limit": "string — quand la méthode ne s'applique pas (clause LIMIT)",
    "estimated_duration": "string — durée estimée (ex : '5-10 min')",
    "difficulty": "string — niveau de difficulté (ex : '2/4')",
    "method_scope": "string — domaine de la méthode (ex : 'math_proof')",
    "fallback_help_ref": "object{label,gab_ref,gab_type,text} — référence de fallback si l'élève est bloqué",
    "secondary_cta": "object{label,action} — bouton secondaire optionnel"
  },
  "constraints": [
    "primary_cta.label : libellé du bouton principal venant du JSON.",
    "use_case doit décrire un cas concret déclencheur, pas un principe générique.",
    "expected_output doit lister les éléments attendus de la production.",
    "fallback_help_ref.gab_ref : référence à un GAB existant (ne pas inventer).",
    "difficulty : format 'N/4' si présent.",
    "secondary_cta : omissible si pas de second bouton documenté."
  ],
  "blocked_conditions": [
    "method_intro_id absent (BLOCKED)",
    "title absent (BLOCKED)",
    "method_goal absent (BLOCKED)",
    "use_case absent (BLOCKED)",
    "expected_output absent (BLOCKED)",
    "primary_cta absent (BLOCKED)"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "fallback_text"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 4 clauses affichées, 0 erreur" },
    { "case": "champ requis manquant (ex: use_case)", "expected": "BLOCKED listant le champ" },
    { "case": "prerequisites absent", "expected": "clause PREREQ masquée, reste rendu OK" },
    { "case": "limit absent", "expected": "clause LIMIT masquée, reste rendu OK" },
    { "case": "fallback_help_ref absent", "expected": "bloc fallback masqué, reste rendu OK" },
    { "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-271",
    "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). Chaîne module 19 : GAB-271 Intro → GAB-272 StepByStep → GAB-273 AnswerStructure → GAB-274 JustificationBuilder → GAB-275 ExamChecklist."
  }
}
