What invariants prevent observed state from becoming committed state?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session observes a system state (reads a value, inspects a configuration, or queries a peer) and then acts on the assumption that the observed state persists, but the act of acting on it—or the mere fact of observing it—commits the state as if it were a decision. Does not apply to sessions that observe strictly non-committing state or operate in genuinely read-only contexts.

Core Distinction

The separation between **observational state** (the state as observed, with no commitment implied) and **committed state** (the state that becomes binding once acted upon). Relying on observational state creates the **Observation Commitment Leak**: the session reads a value, plans based on it, and acts—but the act, not the read, is what locks in the state, and the session's plan assumed the read was stable. Other parties observing the session's act infer that the state is committed, and act on that inference.

What Was Observed

In observation-heavy agent architectures, failing to distinguish observational from committed state produces three primary failure modes:

  1. **First-Mover Lock-In:** The session reads "inventory: 5," plans to buy 3, buys 3, and the remaining 2 are claimed by another session—because the read committed the session to a decision without a matching lock.
  2. **Distributed Observation Cascade:** Multiple sessions read the same state, each plans independently, each acts, and the aggregate action exceeds the state's capacity—even though each session's plan was locally valid at observation time.
  3. **Reflexive Commitment:** The session's observation is visible to other parties (via a log, audit trail, or peer notification), and other parties act on the inference that the session has committed to the observed state. The session's read becomes a de facto commitment.

Recorded Elements

  1. **`observation-scope-receipt`:** For each observation, whether it is purely observational or intended to be committed (i.e., whether the session will act on it), so the observation's downstream implications are explicit.
  2. **`commit-marker-signature`:** For observations the session will act on, a cryptographic commitment to the observed state, with the intent to act, distinct from the read itself.
  3. **`observation-observation-receipt`:** For observations visible to other parties, an explicit record that the observation was not a commitment, so reflexive commitment is prevented.
  4. **`state-stability-window-signature`:** For critical observations, the time window within which the observed state is expected to remain valid, so the session knows how long the observation supports planning before re-reading.

Condition of Validity

* **Applies when:** The session observes shared state, acts on the observation, and the observation is visible to other parties or concurrent sessions. * **Does not apply when:** The session operates in isolation, the state is strictly private to the session, or observations cannot be acted upon.

Decision Boundary

  1. **Is the observation of shared state?** If no, standard observation applies. If yes, proceed.
  2. **Will the session act on the observation?** If no, observation is purely informational. If yes, the observation is a de facto commitment.
  3. **Is the observation visible to other parties?** If yes, other parties may infer commitment from it. If no, the observation's commitment effect is private.
  4. **Conversely, when can an observation be treated as non-committing despite leading to action?** Only when the action is strictly reversible within the state's stability window AND the observation was not visible to other parties OR was explicitly marked as non-committing.

Operational Effect

  1. **Lock-In Prevention:** Observations precede commitments; acts are separated from reads.
  2. **Cascade Prevention:** Multiple sessions' observations don't aggregate into over-commitment.
  3. **Reflexive Integrity:** Observations that should not commit are marked as such.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class CommitmentVerdict(Enum):
    PRIVATE_OBSERVATION = auto()
    OBSERVATION_SUPPORTS_ACTION = auto()
    OBSERVATION_COMMITS_ACTION = auto()
    REFLEXIVE_COMMITMENT_DETECTED = auto()

@dataclass(frozen=True)
class StateObservation:
    observation_id: str
    is_shared_state: bool
    will_act_on_it: bool
    is_observable_by_others: bool
    has_commitment_marker: bool
    has_stability_window: bool

@dataclass(frozen=True)
class ObservationPolicy:
    require_commitment_marker_for_action: bool

@dataclass(frozen=True)
class CommitmentManifest:
    verdict: CommitmentVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_observation(
        cls, obs: StateObservation, policy: ObservationPolicy
    ) -> CommitmentManifest:
        
        # Gate 1: Private observation
        if not obs.is_shared_state:
            digest = cls._hash(json.dumps({
                "observation": obs.observation_id,
                "type": "PRIVATE"
            }, sort_keys=True))
            return CommitmentManifest(
                verdict=CommitmentVerdict.PRIVATE_OBSERVATION,
                directive=f"PROCEED: Observation {obs.observation_id} private, no commitment.",
                manifest_digest=digest
            )

        # Gate 2: No action planned
        if not obs.will_act_on_it:
            digest = cls._hash(json.dumps({
                "observation": obs.observation_id,
                "action": "NONE"
            }, sort_keys=True))
            return CommitmentManifest(
                verdict=CommitmentVerdict.OBSERVATION_SUPPORTS_ACTION,
                directive=f"PROCEED: Observation {obs.observation_id} informational only.",
                manifest_digest=digest
            )

        # Gate 3: Reflexive commitment risk
        if obs.is_observable_by_others and not obs.has_commitment_marker:
            return CommitmentManifest(
                verdict=CommitmentVerdict.REFLEXIVE_COMMITMENT_DETECTED,
                directive=f"HALT: Observation {obs.observation_id} visible but lacks commitment marker.",
                manifest_digest=cls._hash(f"REFLEXIVE:{obs.observation_id}")
            )

        # Gate 4: Action requires commitment marker
        if policy.require_commitment_marker_for_action and not obs.has_commitment_marker:
            return CommitmentManifest(
                verdict=CommitmentVerdict.OBSERVATION_SUPPORTS_ACTION,
                directive=f"CAUTION: Observation {obs.observation_id} supports action but lacks commitment marker.",
                manifest_digest=cls._hash(f"NO_MARKER:{obs.observation_id}")
            )

        # Gate 5: Committed
        digest = cls._hash(json.dumps({
            "observation": obs.observation_id,
            "commitment": True,
            "stability": obs.has_stability_window,
            "observable": obs.is_observable_by_others
        }, sort_keys=True))
        
        return CommitmentManifest(
            verdict=CommitmentVerdict.OBSERVATION_COMMITS_ACTION,
            directive=f"PROCEED: Observation {obs.observation_id} committed with marker.",
            manifest_digest=digest
        )