{
  "contract_version": "gab_273_contract_v1",
  "gab_id": "GAB-273",
  "canonical_name": "MethodLearningAnswerStructure",
  "module_owner": "EdTechMethodLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "structure_id",
    "task_type",
    "answer_slots",
    "ordering_rules",
    "success_criteria"
  ],
  "optional_fields": [
    "title",
    "subtitle",
    "sentence_starters",
    "forbidden_patterns",
    "primary_cta",
    "secondary_cta",
    "example_full",
    "why_rationale",
    "rubric_ref",
    "word_count_guidance",
    "source_metadata"
  ],
  "field_types": {
    "structure_id": "string — identifiant unique de la structure (slug kebab-case)",
    "task_type": "enum['paragraph_argument','dissertation','synthesis','explanation','proof','description','narrative','analysis']",
    "answer_slots": "array<{slot_index:integer, slot_type:enum['intro','body','conclusion','transition','evidence'], label:string, content:string, starter?:string}>",
    "ordering_rules": "string — description de l'ordre obligatoire des slots",
    "success_criteria": "array<string> — critères mesurables observables",
    "sentence_starters": "array<string> — amorces de phrases pour débloquer la rédaction",
    "forbidden_patterns": "array<string> — patterns à détecter et bloquer",
    "primary_cta": "object{label:string, action:string}",
    "secondary_cta": "object{label:string, action:string}",
    "example_full": "string — exemple complet de réponse structurée",
    "why_rationale": "string — explication pédagogique du pourquoi de cette structure"
  },
  "constraints": [
    "answer_slots doit contenir au moins 1 slot.",
    "slot_index doit être unique et en ordre croissant dans le tableau.",
    "success_criteria doit contenir au moins 1 critère mesurable et observable.",
    "primary_cta.label vient du JSON — jamais hardcodé en HTML.",
    "Le renderer ne modifie pas l'ordre des answer_slots — il les affiche dans l'ordre du tableau."
  ],
  "blocked_conditions": [
    "structure_id absent",
    "task_type absent",
    "answer_slots vides",
    "ordering_rules absent",
    "success_criteria vides"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "textarea avec placeholder explicite"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 3 slots affichés, critères et patterns lisibles, 0 erreur" },
    { "case": "champ requis manquant (ex: structure_id)", "expected": "BLOCKED listant le champ manquant" },
    { "case": "answer_slots vides []", "expected": "BLOCKED avec message 'answer_slots vides'" },
    { "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, cta-row en colonne sur mobile" },
    { "case": "clic Rédiger ma réponse", "expected": "textarea + bouton Rendre apparaissent dans le panel" },
    { "case": "clic Voir un exemple complet", "expected": "example_full affiché dans le panel" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-273",
    "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)."
  }
}
