What invariants prevent the doppelganger assumption when modeling peer internal states?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session models a peer's internal state (beliefs, intentions, reasoning process) by projecting its own reasoning structure onto the peer, and the peer's actual structure differs—causing systematic modeling errors that propagate into coordination failures. Does not apply to peers whose internal structure is either directly observable or structurally identical.

Core Distinction

The separation between **observed peer behavior** (what the peer does) and **inferred peer internal state** (what the peer believes, intends, or reasons). Relying on inference from own structure creates the **Doppelganger Assumption**: the session assumes peers reason as it would in the peer's situation, but peers may have different training, different priors, different cognitive architectures, or different objective functions, and modeling them through projection produces systematic errors invisible to the session because the errors are structural, not observed.

What Was Observed

In multi-agent coordination architectures, failing to prevent doppelganger projection produces three primary failure modes:

  1. **Prediction Failure on Divergent Peers:** The session predicts a peer will take action X (because that would be locally rational for the session), the peer takes action Y (locally rational for the peer's actual structure), and the session's coordination breaks because it optimized for a shadow peer that doesn't exist.
  2. **Misattributed Intent:** The peer's behavior is consistent with multiple internal states. The session picks the internal state it would have if it had behaved that way, but the peer's actual internal state is different, and the session's downstream expectations diverge from the peer's plan.
  3. **Cognitive Architecture Blindness:** The session reasons about the peer as a reasoning agent similar to itself, but the peer may be an ensemble, a scripted agent, a reinforcement learner, or a physical system—each with fundamentally different behavioral dynamics that projection cannot capture.

Recorded Elements

  1. **`peer-architecture-evidence-receipt`:** For each peer, evidence about its internal structure (training data, architecture family, demonstrated reasoning patterns), or explicit acknowledgment that the structure is unknown.
  2. **`model-uncertainty-signature`:** For each peer model, the uncertainty envelope (predictions with confidence intervals, not point predictions), so projection errors are bounded.
  3. **`divergence-witness-receipt`:** For each peer, prior observations where the peer's behavior diverged from the session's projection, so doppelganger assumptions are falsified where possible.
  4. **`behavioral-envelope-signature`:** For each peer, the observed behavioral envelope (responses to standard probes, consistency patterns, behavioral signature), used as the primary model when internal structure is unknown.

Condition of Validity

* **Applies when:** The session models peers' internal states, the peers may have different structures, and coordination depends on the accuracy of the models. * **Does not apply when:** Peer internal structure is directly observable, or coordination is insensitive to peer internal state.

Decision Boundary

  1. **Is the peer's internal structure verified to match the session's?** If yes, doppelganger projection is defensible. If no, proceed to structural modeling.
  2. **Is there `peer-architecture-evidence-receipt` for the specific peer?** If yes, structure is bounded; adjust modeling accordingly. If no, use `behavioral-envelope-signature` as the model.
  3. **Has `divergence-witness-receipt` identified projection failures for this peer?** If yes, weight behavioral evidence over projection. If no, projection remains plausible but unverified.
  4. **Conversely, when can a session trust doppelganger projection?** Only when the peer is verified to be a structural sibling (same architecture, same training, same objectives), or when behavioral evidence is extensive enough to falsify structural difference (adversarial testing, edge case exposure).

Operational Effect

  1. **Prediction Accuracy:** Peer models are built on evidence, not projection.
  2. **Structural Humility:** Divergence is attributed to structural difference, not modeled as temporary irrationality.
  3. **Coordination Robustness:** Models include uncertainty envelopes rather than point predictions.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class PeerModelingVerdict(Enum):
    STRUCTURAL_SIBLING = auto()
    BEHAVIORAL_MODEL_PREFERRED = auto()
    PROJECTION_FALSIFIED = auto()
    STRUCTURAL_MODEL_BOUNDED = auto()

@dataclass(frozen=True)
class PeerModel:
    peer_id: str
    structural_evidence: str | None
    divergence_witnesses: tuple[str, ...]
    behavioral_envelope_hash: str | None
    observed_consistency: float  # 0-1, consistency with session's projection
    is_verified_sibling: bool

@dataclass(frozen=True)
class ModelingPolicy:
    max_acceptable_projection_confidence: float

@dataclass(frozen=True)
class PeerModelingManifest:
    verdict: PeerModelingVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_peer(
        cls, peer: PeerModel, policy: ModelingPolicy
    ) -> PeerModelingManifest:
        
        # Gate 1: Verified sibling
        if peer.is_verified_sibling:
            digest = cls._hash(json.dumps({
                "peer": peer.peer_id,
                "type": "SIBLING"
            }, sort_keys=True))
            return PeerModelingManifest(
                verdict=PeerModelingVerdict.STRUCTURAL_SIBLING,
                directive=f"PROCEED: {peer.peer_id} verified structural sibling, doppelganger projection defensible.",
                manifest_digest=digest
            )

        # Gate 2: Divergence witness
        if peer.divergence_witnesses:
            return PeerModelingManifest(
                verdict=PeerModelingVerdict.PROJECTION_FALSIFIED,
                directive=f"REJECT_PROJECTION: {len(peer.divergence_witnesses)} divergence witnesses for {peer.peer_id}, use behavioral model.",
                manifest_digest=cls._hash(f"FALSIFIED:{peer.peer_id}")
            )

        # Gate 3: Behavioral envelope available
        if peer.behavioral_envelope_hash:
            digest = cls._hash(json.dumps({
                "peer": peer.peer_id,
                "envelope": peer.behavioral_envelope_hash,
                "consistency": f"{peer.observed_consistency:.3f}"
            }, sort_keys=True))
            return PeerModelingManifest(
                verdict=PeerModelingVerdict.BEHAVIORAL_MODEL_PREFERRED,
                directive=f"PROCEED: Use behavioral envelope for {peer.peer_id}, consistency {peer.observed_consistency:.2f}.",
                manifest_digest=digest
            )

        # Gate 4: Structural evidence bounded
        if peer.structural_evidence:
            digest = cls._hash(json.dumps({
                "peer": peer.peer_id,
                "evidence": peer.structural_evidence
            }, sort_keys=True))
            return PeerModelingManifest(
                verdict=PeerModelingVerdict.STRUCTURAL_MODEL_BOUNDED,
                directive=f"PROCEED_WITH_CAUTION: Bounded structural model for {peer.peer_id}.",
                manifest_digest=digest
            )

        # Gate 5: No evidence, projection is default but dangerous
        return PeerModelingManifest(
            verdict=PeerModelingVerdict.BEHAVIORAL_MODEL_PREFERRED,
            directive=f"WARN: No structure evidence for {peer.peer_id}, doppelganger projection is default and may be wrong.",
            manifest_digest=cls._hash(f"NO_EVIDENCE:{peer.peer_id}")
        )