{
  "contract_version": "gab_305_interpret_steps_v1",
  "renderer_key": "interpret_steps",
  "gab_id": "GAB-305",
  "canonical_name": "DocumentLearningInterpretEvidence",
  "family_code": "document_analysis",
  "purpose": "Valide une instance d'interprétation de preuve (preuve observée + prompt d'inférence + niveaux d'inférence prudent/moyen/fort + règle de surinterprétation). Le renderer consomme l'instance validée; ne lit aucun registre au runtime.",
  "pipeline": "registre GAB -> schema.json -> valide instance -> renderer.html (moteur interpret_steps)",

  "required_fields": ["gab_id", "renderer_key", "instance"],
  "optional_fields": ["canonical_name", "family_code", "site", "source_notice", "accessibility", "child_safety"],

  "field_types": {
    "gab_id": "string ('GAB-305')",
    "renderer_key": "string ('interpret_steps')",
    "site": "string (ex 'allobrevet.fr')",
    "instance": "object { title, interpret_id, document_ref, evidence_ref, interpretation_prompt, interpretation_rules, inference_levels[], synthesis_on_success }",
    "instance.interpret_id": "string (id stable de l'écran d'interprétation)",
    "instance.document_ref": "object { src:string, kind:enum['image','document'], alt:string }",
    "instance.evidence_ref": "object { kind_label:string, text:string } — la PREUVE observée, extraite du document, jamais inventée",
    "instance.interpretation_prompt": "string — consigne posée à l'élève",
    "instance.interpretation_rules": "object { link_to_question_required:boolean, max_safe_level:number, note:string }",
    "instance.inference_levels": "array<{ level:number, label:string, verdict:enum['interpreted','partial','overinterpreted'], tone:enum['ok','note','warn','bad'], message:string }>",
    "instance.synthesis_on_success": "string — synthèse affichée quand le niveau sûr (max_safe_level) est choisi"
  },

  "constraints": [
    "instance.evidence_ref.text présent (sinon BLOCKED) — c'est la preuve observée, source de l'inférence.",
    "instance.interpretation_prompt présent (sinon BLOCKED).",
    "instance.inference_levels non vide (sinon BLOCKED).",
    "Un niveau verdict='overinterpreted' DOIT être signalé (tone 'bad') — on ne valide jamais une surinterprétation.",
    "max_safe_level désigne le seul niveau récompensé par synthesis_on_success (inférence prudente reliée à la question).",
    "ANTI-INVENTION : la preuve et les niveaux viennent du document; le moteur n'ajoute aucune interprétation."
  ],
  "blocked_conditions": ["instance.evidence_ref absent ou sans text", "instance.interpretation_prompt absent", "instance.inference_levels absent ou vide"],
  "edge_cases": [
    { "case": "élève choisit le niveau 'Fort' (overinterpreted)", "expected": "feedback 'bad' : tu dépasses ce que la preuve montre — pas de validation, pas de synthèse" },
    { "case": "élève choisit le niveau 'Moyen' (partial)", "expected": "feedback 'note' : plausible mais précise le lien au document — pas de synthèse finale" },
    { "case": "document_ref cassé", "expected": "la preuve textuelle (evidence_ref.text) reste lisible, pas d'écran vide" }
  ]
}
