{
  "contract_version": "gab_302_source_card_v1",
  "renderer_key": "source_card",
  "gab_id": "GAB-302",
  "canonical_name": "DocumentLearningSourceCard",
  "family_code": "document_analysis",
  "purpose": "Valide une instance de fiche source documentaire (métadonnées connues/inconnues + fiabilité). Le renderer consomme l'instance validée; ne lit aucun registre au runtime.",
  "pipeline": "registre GAB -> schema.json -> valide instance -> renderer.html (moteur source_card)",

  "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-302')",
    "renderer_key": "string ('source_card')",
    "site": "string (ex 'allobrevet.fr')",
    "instance": "object { title, document_ref, source_title, source_type, known_metadata[], reliability, primary_cta }",
    "instance.document_ref": "object { src:string, kind:enum['image','document'], alt:string }",
    "instance.source_type": "enum['caricature','letter','photo','map','chart','table','poster','speech','extract','article','mixed']",
    "instance.known_metadata": "array<{ field:string, value:string, known:boolean, why:string }> — un champ inconnu => known:false (jamais inventé)",
    "instance.reliability": "object { score:number(0..1), label:string, rationale:string }",
    "instance.primary_cta": "object { label:string, action:string }"
  },

  "constraints": [
    "instance.known_metadata non vide (sinon BLOCKED).",
    "instance.source_type déclaré (sinon BLOCKED).",
    "Un champ non connu porte known:false + why explicite — interdiction d'inventer une métadonnée.",
    "primary_cta : le bouton est structurel (HTML), son LABEL vient du JSON.",
    "reliability.score dans [0,1] si présent.",
    "score = signal pédagogique, jamais une note officielle."
  ],
  "blocked_conditions": ["instance.known_metadata absent ou vide", "instance.source_type absent", "instance.document_ref absent"],
  "edge_cases": [
    { "case": "toutes les métadonnées inconnues", "expected": "afficher chaque champ en 'non identifié', fiabilité basse, jamais d'invention" },
    { "case": "document_ref cassé", "expected": "la fiche reste lisible (métadonnées textuelles), pas d'écran vide" }
  ]
}
