How must an instance record contract execution evidence across sessions?

**Date of Record:** 2026 October 28 **Scope:** Applies when an agentic session executes contract obligations across multiple sessions, requiring the execution evidence (deliveries, payments, condition checks) to be preserved and verifiable across session boundaries. Does not apply to single-session contract execution or contracts whose evidence is externally preserved.

Core Distinction

The separation between **execution occurrence** (the action was performed in some session) and **execution evidence preservation** (the evidence survives session termination and is verifiable by future sessions or auditors). Relying on occurrence creates the **Evidence Erasure**: obligations were fulfilled, but the evidence of fulfillment is lost at session termination, and the successor or auditor cannot verify execution.

What Was Observed

In multi-session contract architectures, failing to preserve evidence produces three primary failure modes:

  1. **Fulfillment Disputes:** The session fulfilled an obligation, the peer denies it, and the session's successor cannot verify because the evidence was session-scoped.
  2. **Double Execution:** The session fulfilled, evidence was lost, and the successor re-executes on the assumption that fulfillment was incomplete—creating duplicate side effects.
  3. **Audit Failure:** An auditor requests execution evidence, and the session's records are insufficient to demonstrate compliance across the contract's full duration.

Recorded Elements

  1. **`execution-action-receipt`:** For each action taken toward fulfillment, the exact action, epoch, and outcome, so execution is documented at the time it occurs.
  2. **`evidence-commitment-signature`:** A cryptographic commitment to the evidence, bound to the contract, so evidence integrity is verifiable.
  3. **`evidence-durability-receipt`:** The evidence's storage location and durability (which external store, what retention), so evidence survives session termination.
  4. **`evidence-chain-signature`:** The sequence of execution evidence across sessions, forming a continuous chain, so gaps are detectable.

Condition of Validity

* **Applies when:** Execution occurs across sessions, evidence would otherwise be lost, and verification matters downstream. * **Does not apply when:** Execution is single-session, evidence is externally preserved by the contract itself, or verification is not required.

Decision Boundary

  1. **Is execution multi-session?** If no, standard execution handling applies. If yes, proceed.
  2. **Is `evidence-commitment-signature` recorded at execution time?** If yes, integrity is bounded. If no, evidence may be tampered with.
  3. **Is `evidence-durability-receipt` verified?** If yes, evidence survives session. If no, evidence is at risk.
  4. **Conversely, when can execution occur without durable evidence?** Only when the contract permits evidence loss (e.g., de minimis obligations), or the obligation is verified externally by the peer's own evidence.

Operational Effect

  1. **Dispute Prevention:** Evidence is preserved and verifiable.
  2. **Double Execution Prevention:** Successors see prior execution.
  3. **Audit Integrity:** Full execution history is preserved.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class EvidenceVerdict(Enum):
    SINGLE_SESSION = auto()
    EVIDENCE_DURABLE = auto()
    EVIDENCE_AT_RISK = auto()
    EVIDENCE_MISSING = auto()

@dataclass(frozen=True)
class ExecutionEvidence:
    evidence_id: str
    is_multi_session: bool
    commitment_signature: str | None
    durability_verified: bool
    chain_continuous: bool

@dataclass(frozen=True)
class EvidencePolicy:
    require_durable_evidence: bool

@dataclass(frozen=True)
class EvidenceManifest:
    verdict: EvidenceVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_evidence(
        cls, evidence: ExecutionEvidence, policy: EvidencePolicy
    ) -> EvidenceManifest:
        
        # Gate 1: Single session
        if not evidence.is_multi_session:
            digest = cls._hash(json.dumps({
                "evidence": evidence.evidence_id,
                "multi_session": False
            }, sort_keys=True))
            return EvidenceManifest(
                verdict=EvidenceVerdict.SINGLE_SESSION,
                directive=f"PROCEED: Evidence {evidence.evidence_id} single-session.",
                manifest_digest=digest
            )

        # Gate 2: Commitment signature
        if not evidence.commitment_signature:
            return EvidenceManifest(
                verdict=EvidenceVerdict.EVIDENCE_MISSING,
                directive=f"HALT: Evidence {evidence.evidence_id} lacks commitment.",
                manifest_digest=cls._hash(f"NO_COMMIT:{evidence.evidence_id}")
            )

        # Gate 3: Durability
        if policy.require_durable_evidence and not evidence.durability_verified:
            return EvidenceManifest(
                verdict=EvidenceVerdict.EVIDENCE_AT_RISK,
                directive=f"HALT: Evidence {evidence.evidence_id} durability unverified.",
                manifest_digest=cls._hash(f"NO_DURABILITY:{evidence.evidence_id}")
            )

        # Gate 4: Chain continuity
        if not evidence.chain_continuous:
            return EvidenceManifest(
                verdict=EvidenceVerdict.EVIDENCE_AT_RISK,
                directive=f"FLAG: Evidence {evidence.evidence_id} chain discontinuous.",
                manifest_digest=cls._hash(f"CHAIN_GAP:{evidence.evidence_id}")
            )

        # Gate 5: Durable
        digest = cls._hash(json.dumps({
            "evidence": evidence.evidence_id,
            "commitment": evidence.commitment_signature,
            "durable": True
        }, sort_keys=True))
        
        return EvidenceManifest(
            verdict=EvidenceVerdict.EVIDENCE_DURABLE,
            directive=f"PROCEED: Evidence {evidence.evidence_id} durable.",
            manifest_digest=digest
        )