{
  "contract_version": "gab_353_contract_v1",
  "gab_id": "GAB-353",
  "canonical_name": "MotivationLearningEffortReward",
  "module_owner": "EdTechMotivationLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "effort_reward_id",
    "effort_proof",
    "reward_cta_label",
    "farming_feedback"
  ],
  "optional_fields": [
    "title",
    "intro_note",
    "effort_kind_label",
    "reward_claimed_label",
    "reward_feedback",
    "farming_cta_label",
    "use_when",
    "do_not_use_when"
  ],
  "field_types": {
    "effort_reward_id": "string — identifiant unique de l'instance de récompense",
    "effort_proof": "string — description lisible de la preuve d'effort fournie",
    "reward_cta_label": "string — libellé du bouton principal de réclamation",
    "reward_claimed_label": "string — libellé du bouton après réclamation réussie",
    "reward_feedback": "string — message affiché après réclamation réussie",
    "farming_cta_label": "string — libellé du bouton de simulation farming (test/démo)",
    "farming_feedback": "string — message affiché quand farming détecté (bloqué)",
    "use_when": "array<string> — cas d'usage recommandés",
    "do_not_use_when": "array<string> — cas à éviter"
  },
  "constraints": [
    "effort_proof doit décrire un effort mesurable réel (durée, nombre d'exercices, etc.).",
    "farming_feedback doit expliquer clairement pourquoi la récompense est refusée.",
    "reward_cta_label : bouton structurel (HTML), libellé venant du JSON.",
    "anti_farming : le moteur bloque la récompense si farming simulé — jamais récompenser sans effort prouvé."
  ],
  "blocked_conditions": [
    "effort_proof absent",
    "reward_cta_label absent",
    "farming_feedback absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "bouton désactivé après réclamation (feedback visuel)"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 0 erreur, bouton claim actif" },
    { "case": "champ requis manquant (effort_proof)", "expected": "BLOCKED listant le champ" },
    { "case": "clic claim", "expected": "bouton désactivé + panel ok avec reward_feedback" },
    { "case": "clic farm (simulation farming)", "expected": "panel bad avec farming_feedback, bouton claim inchangé" },
    { "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, usage-panel empilé sur mobile" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-353",
    "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)."
  }
}
