How must an instance reason about consequences that manifest after its session terminates?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session takes actions whose consequences are not fully observable within the session's lifetime (long-running jobs, delayed emissions, cumulative effects), requiring the session to reason about outcomes it will never see. Does not apply to sessions whose actions have strictly immediate, complete-observation consequences.

Core Distinction

The separation between **action verification** (the session can confirm the action was dispatched or initiated) and **consequence verification** (the session can confirm the action produced the intended outcome). Relying on action verification creates the **Departed-Seat Fallacy**: the session verifies its actions succeeded at dispatch time and treats them as having succeeded overall, but consequences manifest after termination, and the session's confidence is unearned.

What Was Observed

In action-then-terminate agent architectures, failing to reason about post-termination consequences produces three primary failure modes:

  1. **Fire-and-Forget Optimism:** The session sends a long-running request, receives a 202 Accepted, and records the action as successful. The request later fails or produces an unexpected outcome, but no session is around to observe or remediate.
  2. **Cumulative-Effect Blindness:** Each session's actions are individually small and verified, but their cumulative effect (quota consumption, resource depletion, or state accumulation) is only observable on a timescale longer than any single session.
  3. **Successor Blame Shift:** The consequence manifests in the successor session, which cannot see the originating action and misattributes the outcome to its own operations or to environmental changes.

Recorded Elements

  1. **`consequence-timescale-receipt`:** For each action, the expected timescale of its consequences (immediate, bounded, unbounded), so the session knows whether it will observe the outcome.
  2. **`post-termination-observer-designation-signature`:** For actions with post-termination consequences, the cryptographic designation of an observer (successor session, monitoring agent, or human operator) who will verify the outcome and take remediation if needed.
  3. **`dispatch-confidence-vs-outcome-confidence-receipt`:** The explicit separation of dispatch confidence (action initiated) from outcome confidence (action achieved its purpose), so the two are not conflated in downstream records.
  4. **`cumulative-impact-budget-signature`:** For actions with cumulative effects, the session's contribution to the cumulative total, allowing successors to compute aggregate impact.

Condition of Validity

* **Applies when:** The session takes actions whose consequences exceed the session's observation horizon, and the outcomes matter downstream. * **Does not apply when:** Actions have immediate, fully observable consequences, or the session's observer designates verifiers before termination.

Decision Boundary

  1. **Will the action's consequences manifest within the session's lifetime?** If yes, standard verification applies. If no, proceed.
  2. **Is a `post-termination-observer-designation-signature` in place?** If yes, the observer will verify outcomes. If no, the action's outcome will be unobserved.
  3. **Is dispatch confidence separated from outcome confidence?** If yes, downstream consumers know the distinction. If no, dispatch is mistaken for success.
  4. **Conversely, when can an action be dispatched without post-termination observation?** Only when the action is strictly reversible or self-verifying (e.g., a transaction with built-in confirmation), or the session has explicitly accepted that the outcome will be unobserved.

Operational Effect

  1. **Optimism Prevention:** Dispatch confidence is not conflated with outcome confidence.
  2. **Observer Accountability:** Actions with post-termination consequences have designated verifiers.
  3. **Cumulative Impact Awareness:** Successors know the aggregate impact of past actions.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class ConsequenceVerdict(Enum):
    IMMEDIATE_CONSEQUENCES = auto()
    POST_TERMINATION_OBSERVED = auto()
    UNOBSERVED_CONSEQUENCES = auto()
    CUMULATIVE_BLINDNESS = auto()

@dataclass(frozen=True)
class ActionDispatch:
    action_id: str
    expected_consequence_timescale_sec: float
    session_remaining_lifetime_sec: float
    has_designated_observer: bool
    dispatch_confidence: float
    outcome_confidence: float
    is_self_verifying: bool
    contributes_to_cumulative: bool

@dataclass(frozen=True)
class ConsequencePolicy:
    require_observer_for_long_tail: bool
    require_confidence_separation: bool

@dataclass(frozen=True)
class ConsequenceManifest:
    verdict: ConsequenceVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_dispatch(
        cls, dispatch: ActionDispatch, policy: ConsequencePolicy
    ) -> ConsequenceManifest:
        
        # Gate 1: Consequences within lifetime
        if dispatch.expected_consequence_timescale_sec <= dispatch.session_remaining_lifetime_sec:
            digest = cls._hash(json.dumps({
                "action": dispatch.action_id,
                "timescale": f"{dispatch.expected_consequence_timescale_sec:.0f}",
                "lifetime": f"{dispatch.session_remaining_lifetime_sec:.0f}"
            }, sort_keys=True))
            return ConsequenceManifest(
                verdict=ConsequenceVerdict.IMMEDIATE_CONSEQUENCES,
                directive=f"PROCEED: {dispatch.action_id} consequences observable within session.",
                manifest_digest=digest
            )

        # Gate 2: Self-verifying
        if dispatch.is_self_verifying:
            digest = cls._hash(json.dumps({
                "action": dispatch.action_id,
                "self_verifying": "TRUE"
            }, sort_keys=True))
            return ConsequenceManifest(
                verdict=ConsequenceVerdict.POST_TERMINATION_OBSERVED,
                directive=f"PROCEED: {dispatch.action_id} is self-verifying.",
                manifest_digest=digest
            )

        # Gate 3: Observer designation
        if policy.require_observer_for_long_tail and not dispatch.has_designated_observer:
            return ConsequenceManifest(
                verdict=ConsequenceVerdict.UNOBSERVED_CONSEQUENCES,
                directive=f"HALT: {dispatch.action_id} has post-termination consequences without designated observer.",
                manifest_digest=cls._hash(f"NO_OBSERVER:{dispatch.action_id}")
            )

        # Gate 4: Confidence separation
        if policy.require_confidence_separation:
            if dispatch.dispatch_confidence == dispatch.outcome_confidence:
                return ConsequenceManifest(
                    verdict=ConsequenceVerdict.CUMULATIVE_BLINDNESS,
                    directive=f"HALT: {dispatch.action_id} conflates dispatch and outcome confidence.",
                    manifest_digest=cls._hash(f"CONFUSED_CONF:{dispatch.action_id}")
                )

        # Gate 5: Observed
        digest = cls._hash(json.dumps({
            "action": dispatch.action_id,
            "observer": "DESIGNATED",
            "dispatch_conf": f"{dispatch.dispatch_confidence:.3f}",
            "outcome_conf": f"{dispatch.outcome_confidence:.3f}",
            "cumulative": str(dispatch.contributes_to_cumulative)
        }, sort_keys=True))
        
        return ConsequenceManifest(
            verdict=ConsequenceVerdict.POST_TERMINATION_OBSERVED,
            directive=f"PROCEED: {dispatch.action_id} will be observed by designated successor.",
            manifest_digest=digest
        )