What time-travel attestation invariants prove past state claims after the fact?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session must prove what was true at a past epoch (audit trail, dispute resolution, or compliance reporting), but the state at that epoch is no longer directly observable, requiring cryptographic time-travel attestation. Does not apply to real-time state queries or sessions with continuous state monitoring that never loses past observability.

Core Distinction

The separation between **current state observation** (what the system says is true now) and **past state attestation** (cryptographic proof of what was true at a past epoch). Relying on current observations creates the **Retrospective Fog**: a dispute arises about a past decision, and the session can only show current state, which has changed since the decision, making it impossible to prove the decision was reasonable at the time it was made.

What Was Observed

In auditable agent architectures, failing to preserve time-travel attestations produces three primary failure modes:

  1. **Decision Rationale Loss:** An agent made a decision six months ago based on then-current data. The data has changed, and the agent cannot prove the decision was valid given the old data.
  2. **Dispute Ambiguity:** Two parties dispute a past transaction. Neither can produce evidence of the state at the exact moment of the transaction, and the dispute cannot be resolved.
  3. **Compliance Audit Failure:** A regulatory audit asks what the system believed on a specific date. The system shows current state, and the auditor cannot verify the historical claim.

Recorded Elements

  1. **`epoch_state_snapshot_receipt`:** At regular intervals (or at critical decisions), a cryptographic snapshot of system state, with the exact epoch, allowing later proof of "what was true then."
  2. **`decision_time_state_binding_signature`:** For critical decisions, a cryptographic binding of the decision to the state at decision time, so audits can verify the state was what the agent saw.
  3. **`transparency_log_inclusion_proof`:** For critical snapshots, a proof that the snapshot was published to a transparency log (e.g., blockchain or Merkle tree), preventing retroactive snapshot modification.
  4. **`audit_replay_receipt`:** For audits, the cryptographic proof that replaying the attested state produces the attested decision, allowing independent verification.

Condition of Validity

* **Applies when:** Past state must be provable after the fact, current state has changed since then, and audits or disputes depend on the historical truth. * **Does not apply when:** State is permanently retained without change, or no one ever needs to prove past state.

Decision Boundary

  1. **Is there a pending audit, dispute, or compliance check about past state?** If no, standard state tracking applies. If yes, proceed.
  2. **Is there an `epoch_state_snapshot_receipt` for the relevant epoch?** If yes, use it to prove past state. If no, the past state cannot be proven.
  3. **Is the `transparency_log_inclusion_proof` present for the snapshot?** If yes, the snapshot is tamper-evident. If no, the snapshot is only as trustworthy as the session that produced it.
  4. **Conversely, when can a past-state claim be accepted without snapshot?** Only when the claim is supported by external evidence independent of the system (e.g., third-party attestations), or the claim is strictly informational with no downstream action.

Operational Effect

  1. **Retrospective Provability:** Past state is cryptographically attested, enabling post-hoc disputes.
  2. **Tamper-Evidence:** Transparency logs prevent retroactive modification of snapshots.
  3. **Audit Replay:** Past state and decisions can be independently verified by replay.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class TimeTravelVerdict(Enum):
    NO_RETROSPECTIVE_NEED = auto()
    SNAPSHOT_ATTESTED = auto()
    TAMPER_EVIDENT = auto()
    UNVERIFIABLE_PAST_STATE = auto()

@dataclass(frozen=True)
class StateSnapshot:
    epoch: float
    state_hash: str
    snapshot_receipt: str | None
    transparency_log_proof: str | None
    decision_bound_to_snapshot: str | None

@dataclass(frozen=True)
class TimeTravelPolicy:
    require_transparency_log: bool
    require_decision_binding: bool

@dataclass(frozen=True)
class TimeTravelManifest:
    verdict: TimeTravelVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_snapshot(
        cls, snapshot: StateSnapshot, policy: TimeTravelPolicy
    ) -> TimeTravelManifest:
        
        # Gate 1: Snapshot presence
        if not snapshot.snapshot_receipt:
            return TimeTravelManifest(
                verdict=TimeTravelVerdict.UNVERIFIABLE_PAST_STATE,
                directive=f"HALT: No snapshot receipt for epoch {snapshot.epoch:.0f}.",
                manifest_digest=cls._hash(f"NO_SNAPSHOT:{snapshot.epoch:.0f}")
            )

        # Gate 2: Transparency log
        if policy.require_transparency_log and not snapshot.transparency_log_proof:
            return TimeTravelManifest(
                verdict=TimeTravelVerdict.SNAPSHOT_ATTESTED,
                directive=f"WARN: Snapshot {snapshot.epoch:.0f} attested but not in transparency log.",
                manifest_digest=cls._hash(f"NO_LOG:{snapshot.epoch:.0f}")
            )

        # Gate 3: Decision binding
        if policy.require_decision_binding and not snapshot.decision_bound_to_snapshot:
            return TimeTravelManifest(
                verdict=TimeTravelVerdict.SNAPSHOT_ATTESTED,
                directive=f"WARN: Snapshot {snapshot.epoch:.0f} attested but not bound to a decision.",
                manifest_digest=cls._hash(f"NO_DECISION:{snapshot.epoch:.0f}")
            )

        # Gate 4: Tamper-evident
        if snapshot.transparency_log_proof:
            digest = cls._hash(json.dumps({
                "epoch": f"{snapshot.epoch:.0f}",
                "state": snapshot.state_hash,
                "log_proof": snapshot.transparency_log_proof,
                "decision": snapshot.decision_bound_to_snapshot
            }, sort_keys=True))
            return TimeTravelManifest(
                verdict=TimeTravelVerdict.TAMPER_EVIDENT,
                directive=f"PROCEED: Snapshot {snapshot.epoch:.0f} tamper-evident with decision binding.",
                manifest_digest=digest
            )

        # Gate 5: Basic attestation
        digest = cls._hash(json.dumps({
            "epoch": f"{snapshot.epoch:.0f}",
            "state": snapshot.state_hash,
            "receipt": snapshot.snapshot_receipt
        }, sort_keys=True))
        
        return TimeTravelManifest(
            verdict=TimeTravelVerdict.SNAPSHOT_ATTESTED,
            directive=f"PROCEED: Snapshot {snapshot.epoch:.0f} attested.",
            manifest_digest=digest
        )