{
  "contract_version": "gab_287_contract_v1",
  "gab_id": "GAB-287",
  "canonical_name": "WritingLearningTransitionBuilder",
  "module_owner": "EdTechWritingLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "transition_builder_id",
    "previous_idea",
    "next_idea",
    "relation_type",
    "transition_goal"
  ],
  "optional_fields": [
    "title",
    "intro_text",
    "relation_label",
    "connector_options",
    "output_example",
    "bad_transition_examples",
    "pedagogical_note",
    "primary_cta",
    "secondary_cta"
  ],
  "field_types": {
    "transition_builder_id": "string — identifiant unique de l'instance",
    "previous_idea": "string — texte de l'idée qui précède la transition",
    "next_idea": "string — texte de l'idée qui suit la transition",
    "relation_type": "enum['opposition','addition','consequence','example','reformulation','cause','conclusion']",
    "transition_goal": "string — objectif pédagogique de la transition",
    "connector_options": "array<{label:string, selected:boolean}> — liste des connecteurs proposés avec sélection initiale",
    "output_example": "string — phrase complète montrant la transition réussie",
    "bad_transition_examples": "array<{connector:string, reason:string}> — exemples à éviter avec explication",
    "primary_cta": "object{label:string, action:string}",
    "secondary_cta": "object{label:string, reveal_text:string}"
  },
  "constraints": [
    "relation_type doit correspondre au registre des connecteurs proposés (cohérence logique).",
    "connector_options : exactement un élément avec selected:true si le champ est présent.",
    "bad_transition_examples : au moins un exemple si le champ est présent.",
    "primary_cta : bouton structurel (HTML), libellé venant du JSON.",
    "output_example doit contenir le connecteur sélectionné (selected:true) dans connector_options."
  ],
  "blocked_conditions": [
    "previous_idea absent",
    "next_idea absent",
    "relation_type absent",
    "transition_builder_id absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "aria_labels_on_interactive_chips"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 0 erreur" },
    { "case": "champ requis manquant (ex: previous_idea)", "expected": "BLOCKED listant le champ" },
    { "case": "connector_options vide", "expected": "section connecteurs absente, pas d'erreur bloquante" },
    { "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": "secondary_cta cliqué", "expected": "reveal_text affiché dans le panneau de sortie" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-287",
    "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)."
  }
}
