{
  "contract_version": "gab_281_contract_v1",
  "gab_id": "GAB-281",
  "canonical_name": "WritingLearningIntro",
  "module_owner": "EdTechWritingLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "writing_id",
    "title",
    "writing_goal",
    "writing_type",
    "expected_output",
    "start_cta"
  ],
  "optional_fields": [
    "icon",
    "writing_type_label",
    "subtitle",
    "source_metadata",
    "contract_label",
    "contract_clauses",
    "idea_starters_label",
    "idea_starters",
    "privacy_notice",
    "reason_block",
    "secondary_cta",
    "accessibility",
    "child_safety"
  ],
  "field_types": {
    "writing_id": "string — identifiant unique de l'instance (ex: wi-lettre-ami-absent-cm1)",
    "writing_type": "enum['letter_personal','letter_formal','narrative','description','argument','dialogue','poem','report','summary','mixed']",
    "contract_clauses": "array<{key:string, icon:string, value:string, detail:string}> — 6 clauses nominales",
    "idea_starters": "array<string> — 1 à 5 amorces textuelles si page blanche",
    "privacy_notice": "object{heading:string, text:string}",
    "reason_block": "object{heading:string, text:string}",
    "start_cta": "object{label:string, action:string}",
    "secondary_cta": "object{label:string, action:string}",
    "source_metadata": "object{duration_label:string, level_label:string, length_label:string}"
  },
  "constraints": [
    "writing_id doit être unique par instance de production écrite.",
    "contract_clauses : si fourni, doit contenir exactement les clés WRITING_GOAL et EXPECTED_OUTPUT.",
    "start_cta : bouton structurel principal (HTML), libellé venant du JSON.",
    "idea_starters : maximum 5 amorces ; chaque amorce est une phrase d'entrée en matière pour l'élève."
  ],
  "blocked_conditions": [
    "writing_id absent",
    "title absent",
    "start_cta absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "fallback_text"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 0 erreur" },
    { "case": "champ requis manquant (writing_id, title ou start_cta)", "expected": "BLOCKED listant le champ manquant" },
    { "case": "idea_starters absent", "expected": "bloc amorces masqué, pas d'erreur" },
    { "case": "privacy_notice absent", "expected": "bloc privacité masqué, pas d'erreur" },
    { "case": "instance externe injectée via init(ext)", "expected": "le rendu change sans modifier le HTML" },
    { "case": "responsive 375/768/1024", "expected": "grille contrat passe en 1 colonne sur 375, aucun débordement horizontal" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-281",
    "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)."
  }
}
