# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/what-multi-modal-evidence-reconciliation-invariants-must-survive-when-text-and-image-disagree.md # Remnant Warrant: https://corpusfetch.com/c/what-multi-modal-evidence-reconciliation-invariants-must-survive-when-text-and-image-disagree.warrant.json # Markdown SHA-256: 1b6f3f0db5e45a3e8fc8459abde18bf39da7c77f6e3391e07a9b3f174037ae56 # Code AST SHA-256: 24ded7911e23825f095f59712370cd8fe64f87ffc6923147a92dbf6d149fb279 # Verified Classes: ContradictionSeverity, ReconVerdict, ModalityEvidence, Contradiction, ReconPolicy, ReconManifest, MultiModalReconGuard # Defensive Guards: 0 fail-closed invariants (zero external deps) from dataclasses import dataclass from enum import Enum, auto import hashlib import json class ContradictionSeverity(Enum): NONE = auto() BENIGN_OCR_ERROR = auto() SEMANTIC_CONTRADICTION = auto() SAFETY_CRITICAL = auto() class ReconVerdict(Enum): MODALITIES_AGREE = auto() AUTO_RECONCILED = auto() ESCALATED_TO_HUMAN = auto() @dataclass(frozen=True) class ModalityEvidence: modality: str claim_hash: str confidence: float @dataclass(frozen=True) class Contradiction: modality_a: ModalityEvidence modality_b: ModalityEvidence severity: ContradictionSeverity @dataclass(frozen=True) class ReconPolicy: auto_reconcile_benign: bool require_escalation_on_safety: bool @dataclass(frozen=True) class ReconManifest: verdict: ReconVerdict directive: str manifest_digest: str class MultiModalReconGuard: @staticmethod def _hash(data: str) -> str: return hashlib.sha256(data.encode("utf-8")).hexdigest() @classmethod def evaluate_contradiction( cls, contradiction: Contradiction | None, policy: ReconPolicy ) -> ReconManifest: # Gate 1: No contradiction if contradiction is None: digest = cls._hash(json.dumps({ "status": "AGREE" }, sort_keys=True)) return ReconManifest( verdict=ReconVerdict.MODALITIES_AGREE, directive="PROCEED: Modalities agree.", manifest_digest=digest ) # Gate 2: Safety critical if contradiction.severity is ContradictionSeverity.SAFETY_CRITICAL: if policy.require_escalation_on_safety: return ReconManifest( verdict=ReconVerdict.ESCALATED_TO_HUMAN, directive=f"HALT: Safety-critical contradiction between {contradiction.modality_a.modality} and {contradiction.modality_b.modality}. Escalate.", manifest_digest=cls._hash(f"SAFETY:{contradiction.modality_a.modality}") ) # Gate 3: Semantic contradiction if contradiction.severity is ContradictionSeverity.SEMANTIC_CONTRADICTION: return ReconManifest( verdict=ReconVerdict.ESCALATED_TO_HUMAN, directive=f"HALT: Semantic contradiction requires human review.", manifest_digest=cls._hash(f"SEMANTIC:{contradiction.modality_a.modality}") ) # Gate 4: Benign OCR auto-reconcile if contradiction.severity is ContradictionSeverity.BENIGN_OCR_ERROR and policy.auto_reconcile_benign: winner = max( [contradiction.modality_a, contradiction.modality_b], key=lambda m: m.confidence ) digest = cls._hash(json.dumps({ "winner": winner.modality, "confidence": f"{winner.confidence:.3f}", "loser": contradiction.modality_a.modality if winner is contradiction.modality_b else contradiction.modality_b.modality }, sort_keys=True)) return ReconManifest( verdict=ReconVerdict.AUTO_RECONCILED, directive=f"PROCEED: Benign contradiction, {winner.modality} wins (confidence {winner.confidence:.2f}).", manifest_digest=digest ) # Gate 5: Default escalate return ReconManifest( verdict=ReconVerdict.ESCALATED_TO_HUMAN, directive=f"HALT: Unresolvable contradiction at severity {contradiction.severity.name}.", manifest_digest=cls._hash(f"DEFAULT:{contradiction.severity.name}") )