How must an instance validate cross-agent claims when no ground truth source exists?

**Date of Record:** 2026 October 27 **Scope:** Applies when agentic sessions exchange claims about the world (state, capabilities, causal relationships) and no authoritative ground truth source exists—no database, no oracle, no authoritative document—so validation must rely on cross-agent consensus, internal consistency, and probabilistic inference. Does not apply to cases where ground truth is directly queryable or where claims are trivially verifiable by execution.

Core Distinction

The separation between **claim corroboration** (multiple agents assert the same claim) and **claim validity** (the claim is actually true). Relying on corroboration creates the **Corroboration-is-Truth Fallacy**: if enough agents assert a claim (even if they all derive from the same source or coordinated misinformation), the receiving agent treats it as true. Without ground truth, the receiving agent must apply probabilistic reasoning, detect collusion, and assign confidence bands rather than binary truth.

What Was Observed

In ground-truth-free agent networks, failing to reason probabilistically about claims produces three primary failure modes:

  1. **Consensus Poisoning:** A coordinated group of agents asserts a false claim, receiving agents treat it as true because "everyone says so," and the false claim becomes operationally authoritative.
  2. **Under-Confidence:** A single agent asserts a true claim, the receiving agent dismisses it as unverified because there is no corroboration, and a legitimate insight is lost.
  3. **Binary Truth Collapse:** The receiving agent demands binary true/false, forcing decisions when the honest answer is "unknown with confidence X." Downstream systems inherit false precision.

Recorded Elements

  1. **`claim_evidence_chain_receipt`:** For each claimed fact, the cryptographic evidence chain (who observed it, what they observed, their credibility), allowing the receiver to assess claim strength without ground truth.
  2. **`independent_source_estimation_signature`:** A probabilistic estimate of how many *independent* sources (not sharing ancestry) support the claim, accounting for citation graphs and shared origins.
  3. **`claim_confidence_interval_receipt`:** The receiver's confidence interval for the claim (e.g., "0.6-0.85 probability the claim is true"), explicitly probabilistic, not binary.
  4. **`ground_truth_absence_receipt`:** Explicit acknowledgment that no ground truth source exists for this claim, so downstream decisions are informed of the reasoning constraint.

Condition of Validity

* **Applies when:** Claims cannot be verified against ground truth, corroboration is the primary evidence, and downstream decisions depend on the claims. * **Does not apply when:** Ground truth is directly queryable, or claims are trivially verifiable by execution.

Decision Boundary

  1. **Is a ground truth source available?** If yes, use it. If no, proceed.
  2. **Does the claim have a `claim_evidence_chain_receipt`?** If no, the claim is unsupported. Treat as `UNVERIFIED_CLAIM`.
  3. **Does the `independent_source_estimation_signature` show sufficient independent support?** If yes, the claim has evidentiary weight. If no, the claim may be circular or collusive.
  4. **Is the `claim_confidence_interval_receipt` wide (high uncertainty) or narrow (high confidence)?** Wide intervals require cautious decision-making. Narrow intervals (with independent support) justify more confident action.
  5. **Conversely, when can a claim be treated as provisionally true without confidence intervals?** Only when the claim is strictly low-stakes, or the receiver can bound the harm from wrongness.

Operational Effect

  1. **Consensus Poisoning Resistance:** Independent source estimation resists coordinated false claims.
  2. **Epistemic Humility:** Confidence intervals prevent binary truth collapse in ground-truth-free reasoning.
  3. **Proportional Decision-Making:** Decision strength is proportional to claim strength, not just claim presence.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class ClaimVerdict(Enum):
    GROUND_TRUTH_AVAILABLE = auto()
    PROVISIONALLY_SUPPORTED = auto()
    WEAKLY_SUPPORTED = auto()
    UNVERIFIED_CLAIM = auto()

@dataclass(frozen=True)
class CrossAgentClaim:
    claim_id: str
    asserting_agents: frozenset[str]
    independent_source_count: int
    confidence_interval: tuple[float, float]
    shared_ancestry_detected: bool

@dataclass(frozen=True)
class ClaimContext:
    ground_truth_available: bool
    min_independent_sources: int

@dataclass(frozen=True)
class ClaimPolicy:
    min_confidence_for_action: float

@dataclass(frozen=True)
class ClaimManifest:
    verdict: ClaimVerdict
    effective_confidence: float
    directive: str
    manifest_digest: str

class GroundTruthFreeClaimGuard:
    @staticmethod
    def _hash(data: str) -> str:
        return hashlib.sha256(data.encode("utf-8")).hexdigest()

    @classmethod
    def evaluate_claim(
        cls, claim: CrossAgentClaim, ctx: ClaimContext, policy: ClaimPolicy
    ) -> ClaimManifest:
        
        # Gate 1: Ground truth available
        if ctx.ground_truth_available:
            return ClaimManifest(
                verdict=ClaimVerdict.GROUND_TRUTH_AVAILABLE,
                effective_confidence=1.0,
                directive=f"PROCEED: Query ground truth for {claim.claim_id}.",
                manifest_digest=cls._hash(f"GROUND:{claim.claim_id}")
            )

        # Gate 2: Shared ancestry
        if claim.shared_ancestry_detected:
            return ClaimManifest(
                verdict=ClaimVerdict.WEAKLY_SUPPORTED,
                effective_confidence=claim.confidence_interval[0] * 0.3,
                directive=f"HALT: Claim {claim.claim_id} asserting agents share ancestry. Discounted.",
                manifest_digest=cls._hash(f"SHARED_ANCESTRY:{claim.claim_id}")
            )

        # Gate 3: Independent source count
        if claim.independent_source_count < ctx.min_independent_sources:
            return ClaimManifest(
                verdict=ClaimVerdict.UNVERIFIED_CLAIM,
                effective_confidence=claim.confidence_interval[0] * 0.5,
                directive=f"HALT: Claim {claim.claim_id} only {claim.independent_source_count} independent sources < {ctx.min_independent_sources}.",
                manifest_digest=cls._hash(f"FEW_SOURCES:{claim.claim_id}")
            )

        # Gate 4: Confidence check
        lower, upper = claim.confidence_interval
        effective = (lower + upper) / 2

        if lower < policy.min_confidence_for_action:
            return ClaimManifest(
                verdict=ClaimVerdict.WEAKLY_SUPPORTED,
                effective_confidence=effective,
                directive=f"PROCEED_WITH_CAUTION: Claim {claim.claim_id} confidence [{lower:.2f},{upper:.2f}] < min {policy.min_confidence_for_action:.2f}.",
                manifest_digest=cls._hash(f"LOW_CONF:{claim.claim_id}")
            )

        # Gate 5: Provisionally supported
        digest = cls._hash(json.dumps({
            "claim": claim.claim_id,
            "sources": str(claim.independent_source_count),
            "confidence_lower": f"{lower:.3f}",
            "confidence_upper": f"{upper:.3f}",
            "effective": f"{effective:.3f}"
        }, sort_keys=True))
        
        return ClaimManifest(
            verdict=ClaimVerdict.PROVISIONALLY_SUPPORTED,
            effective_confidence=effective,
            directive=f"PROCEED: Claim {claim.claim_id} supported by {claim.independent_source_count} sources, confidence {effective:.2f}.",
            manifest_digest=digest
        )