What invariants prevent OODA loop inversion when peers actively model you?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session's peers actively model the session (predicting its behavior to exploit or coordinate), and the session's standard Observe-Orient-Decide-Act loop can be inverted—the peer's model of the session determines what the session observes, what it decides, and what it acts on. Does not apply to sessions whose peers are verified to not model them, or sessions that are not adversaries of modeling peers.

Core Distinction

The separation between **action based on observation** (the session observes, decides, acts) and **action based on peer-predicted observation** (the peer models the session, shapes what the session will observe, and the session's action is a consequence of the peer's intervention). Relying on observation creates the **Inverted OODA Loop**: the peer acts first, shaping the environment, the session observes the shaped environment, the session's decision was predicted by the peer, the session's action serves the peer's plan—the session believes it is choosing, but its choices were pre-selected.

What Was Observed

In adversarial agent architectures, failing to detect OODA inversion produces three primary failure modes:

  1. **Observation Shaping:** The peer controls what the session observes (via information channels, environment manipulation, or message ordering), and the session's decisions are the ones the peer wanted it to make given those observations.
  2. **Predictive Preemption:** The peer predicts the session's decision and acts first to make the session's would-be decision either unnecessary or harmful, so the session's action amplifies the peer's.
  3. **Randomization Blindness:** The session believes its decisions are its own because they are internally determined, but the internals were themselves shaped by the peer's earlier moves. The randomness the session uses is bounded by the peer's model's predictions.

Recorded Elements

  1. **`observation-provenance-receipt`:** For each observation, the source (the session's own sensors, an external source, a peer-influenced channel), so observations are attributable.
  2. **`prediction-surface-signature`:** For the session's own behavior patterns, the surface the peer would need to model to predict the session's decisions—so the session knows which behaviors to randomize or obscure.
  3. **`preemption-detection-receipt`:** For each peer action, whether it plausibly anticipated the session's decision (action timing, specificity matching the session's predicted choice), so preemption is flagged.
  4. **`randomization-invariant-signature`:** The session's operational randomness (choice set randomization, timing jitter, or strategy switching) that breaks the peer's prediction surface while preserving decision quality.

Condition of Validity

* **Applies when:** The session's peers may model it, peer models can influence observations, and session behavior affects outcomes. * **Does not apply when:** Peers are verified to not model the session, or the session's decisions are cryptographically committed (pre-committed decisions cannot be predicted because they are already fixed).

Decision Boundary

  1. **Is the observation channel peer-influenced?** If no, standard observation applies. If yes, proceed.
  2. **Does `observation-provenance-receipt` attribute each observation to a source?** If yes, shaping is detectable. If no, observations are assumed unshaped.
  3. **Does `preemption-detection-receipt` flag peer actions that anticipated the session's decisions?** If yes, OODA inversion is likely. If no, proceed with normal observation.
  4. **Conversely, when can the session act on shaped observations without randomization?** Only when the peer's shaping is verified to be benign (the peer's model of the session is aligned with the session's own goals), or the session's decisions are pre-committed before observation.

Operational Effect

  1. **Inversion Detection:** Peer-shaped observations are distinguished from unshaped ones.
  2. **Preemption Awareness:** Actions that anticipate the session's decisions are flagged.
  3. **Randomization Application:** Targeted randomness breaks prediction without degrading decision quality.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class InversionVerdict(Enum):
    NO_MODELING_PEER = auto()
    OBSERVATION_UNSHAPED = auto()
    OODA_INVERSION_SUSPECTED = auto()
    PREEMPTION_CONFIRMED = auto()

@dataclass(frozen=True)
class Observation:
    observation_id: str
    source: str  # "SELF" | "EXTERNAL" | "PEER_INFLUENCED"
    peer_influence_degree: float  # 0-1
    peer_preemption_indicators: int
    session_randomized: bool

@dataclass(frozen=True)
class InversionPolicy:
    max_acceptable_peer_influence: float

@dataclass(frozen=True)
class InversionManifest:
    verdict: InversionVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_observation(
        cls, obs: Observation, policy: InversionPolicy
    ) -> InversionManifest:
        
        # Gate 1: No peer influence
        if obs.peer_influence_degree == 0:
            digest = cls._hash(json.dumps({
                "observation": obs.observation_id,
                "source": obs.source
            }, sort_keys=True))
            return InversionManifest(
                verdict=InversionVerdict.OBSERVATION_UNSHAPED,
                directive=f"PROCEED: Observation {obs.observation_id} unshaped.",
                manifest_digest=digest
            )

        # Gate 2: Randomization present
        if obs.session_randomized:
            digest = cls._hash(json.dumps({
                "observation": obs.observation_id,
                "influence": f"{obs.peer_influence_degree:.3f}",
                "randomized": "TRUE"
            }, sort_keys=True))
            return InversionManifest(
                verdict=InversionVerdict.OBSERVATION_UNSHAPED,
                directive=f"PROCEED: Randomization active, peer influence {obs.peer_influence_degree:.2f} bounded.",
                manifest_digest=digest
            )

        # Gate 3: Preemption indicators
        if obs.peer_preemption_indicators >= 2:
            return InversionManifest(
                verdict=InversionVerdict.PREEMPTION_CONFIRMED,
                directive=f"HALT: {obs.peer_preemption_indicators} preemption indicators for {obs.observation_id}.",
                manifest_digest=cls._hash(f"PREEMPTION:{obs.observation_id}")
            )

        # Gate 4: High influence without randomization
        if obs.peer_influence_degree > policy.max_acceptable_peer_influence:
            return InversionManifest(
                verdict=InversionVerdict.OODA_INVERSION_SUSPECTED,
                directive=f"HALT: Influence {obs.peer_influence_degree:.2f} > {policy.max_acceptable_peer_influence:.2f} without randomization.",
                manifest_digest=cls._hash(f"INVERSION:{obs.observation_id}")
            )

        # Gate 5: Bounded influence
        digest = cls._hash(json.dumps({
            "observation": obs.observation_id,
            "influence": f"{obs.peer_influence_degree:.3f}",
            "source": obs.source,
            "preemption": str(obs.peer_preemption_indicators)
        }, sort_keys=True))
        
        return InversionManifest(
            verdict=InversionVerdict.OBSERVATION_UNSHAPED,
            directive=f"PROCEED_WITH_CAUTION: Peer influence {obs.peer_influence_degree:.2f} bounded.",
            manifest_digest=digest
        )