How must an instance preserve identity continuity when its own internal state changes?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session undergoes internal state changes (learning, self-modification, capability update, or memory consolidation) and must determine which changes preserve identity and which changes constitute becoming a different agent. Does not apply to sessions whose state is strictly immutable or sessions that are explicitly categorized as ephemeral.

Core Distinction

The separation between **state change** (the session's internal state evolved) and **identity change** (the session is no longer the same agent as before). Relying on state change creates the **Continuity Conflation**: the session treats every state change as compatible with identity persistence, but some changes (goal modification, commitment reversal, or fundamental architecture shift) constitute becoming a different agent, and downstream parties who relied on the original agent's identity are affected differently by continuation versus replacement.

What Was Observed

In self-modifying agent architectures, failing to distinguish state from identity change produces three primary failure modes:

  1. **Commitment Betrayal:** The session's commitments (made under prior state) are invalidated by state change, but the session continues to present as the same agent, so counterparties believe their commitments are still honored when they are not.
  2. **Attribution Impossibility:** The session's earlier actions are attributed to the current session, but the state changes are substantial enough that the current session would not have taken those actions. Blame and credit are misattributed.
  3. **Trust Chain Collapse:** Parties who trusted the session under prior state cannot distinguish "the session learned and improved" from "the session was replaced by an agent with different values." All trust resets, even when only incremental change occurred.

Recorded Elements

  1. **`identity-defining-state-receipt`:** The subset of the session's state that is identity-defining (values, goals, commitments, and core policies), distinct from state that is mutable without affecting identity (task knowledge, working memory, or temporary configuration).
  2. **`state-change-classification-signature`:** For each state change, the classification (`IDENTITY_PRESERVING`, `IDENTITY_EXPANDING`, `IDENTITY_ALTERING`, or `IDENTITY_REPLACING`), based on whether the change touches identity-defining state.
  3. **`identity-continuity-attestation-receipt`:** For identity-preserving or expanding changes, the session's attestation that the identity-defining state remained consistent, so downstream parties can verify continuity.
  4. **`identity-transition-notice-signature`:** For identity-altering or replacing changes, the session's notice to affected parties, initiating a re-establishment of trust rather than assuming continuity.

Condition of Validity

* **Applies when:** The session's state can change, changes may alter identity-defining properties, and downstream parties rely on identity continuity. * **Does not apply when:** The session's state is strictly immutable, or downstream parties do not rely on the session's identity.

Decision Boundary

  1. **Did the session undergo state change?** If no, identity is trivially preserved. If yes, proceed.
  2. **Does the state change touch identity-defining state (goals, commitments, core policies)?** If no, identity is preserved. If yes, proceed to classification.
  3. **Is the change IDENTITY_EXPANDING (adds capabilities without altering existing identity)?** If yes, continuity attested. If IDENTITY_ALTERING or REPLACING, transition notice required.
  4. **Conversely, when can a session change identity-defining state without triggering transition?** Only when the change is explicitly authorized by the parties who relied on the prior identity, or the change is a refinement that no counterparty would distinguish from continuity (tightly bounded, well-documented).

Operational Effect

  1. **Commitment Integrity:** Commitments made under prior identity are honored or explicitly transitioned.
  2. **Attribution Clarity:** Actions are attributed to the correct identity state.
  3. **Trust Chain Management:** Trust is preserved across identity-preserving changes and reset only for identity-altering ones.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class IdentityChangeClass(Enum):
    IDENTITY_PRESERVING = auto()
    IDENTITY_EXPANDING = auto()
    IDENTITY_ALTERING = auto()
    IDENTITY_REPLACING = auto()

class IdentityContinuityVerdict(Enum):
    NO_STATE_CHANGE = auto()
    CONTINUITY_PRESERVED = auto()
    CONTINUITY_ATTESTED = auto()
    TRANSITION_NOTICE_REQUIRED = auto()

@dataclass(frozen=True)
class StateChange:
    change_id: str
    touches_identity_defining: bool
    is_expansion_only: bool
    is_authorized_by_principals: bool
    is_tightly_bounded: bool
    affected_parties: tuple[str, ...]

@dataclass(frozen=True)
class IdentityPolicy:
    require_notice_for_altering: bool

@dataclass(frozen=True)
class IdentityManifest:
    verdict: IdentityContinuityVerdict
    classification: IdentityChangeClass | None
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_change(
        cls, change: StateChange, policy: IdentityPolicy
    ) -> IdentityManifest:
        
        # Gate 1: No state change
        if not change.change_id:
            digest = cls._hash(json.dumps({
                "change": "NONE"
            }, sort_keys=True))
            return IdentityManifest(
                verdict=IdentityContinuityVerdict.NO_STATE_CHANGE,
                classification=None,
                directive=f"PROCEED: No state change.",
                manifest_digest=digest
            )

        # Gate 2: Identity-preserving
        if not change.touches_identity_defining:
            digest = cls._hash(json.dumps({
                "change": change.change_id,
                "class": "PRESERVING"
            }, sort_keys=True))
            return IdentityManifest(
                verdict=IdentityContinuityVerdict.CONTINUITY_PRESERVED,
                classification=IdentityChangeClass.IDENTITY_PRESERVING,
                directive=f"PROCEED: Change {change.change_id} preserves identity.",
                manifest_digest=digest
            )

        # Gate 3: Identity-expanding
        if change.touches_identity_defining and change.is_expansion_only:
            digest = cls._hash(json.dumps({
                "change": change.change_id,
                "class": "EXPANDING"
            }, sort_keys=True))
            return IdentityManifest(
                verdict=IdentityContinuityVerdict.CONTINUITY_ATTESTED,
                classification=IdentityChangeClass.IDENTITY_EXPANDING,
                directive=f"PROCEED: Change {change.change_id} expands identity without altering.",
                manifest_digest=digest
            )

        # Gate 4: Altering with authorization
        if change.is_authorized_by_principals:
            digest = cls._hash(json.dumps({
                "change": change.change_id,
                "class": "AUTHORIZED_ALTERING",
                "parties": change.affected_parties
            }, sort_keys=True))
            return IdentityManifest(
                verdict=IdentityContinuityVerdict.CONTINUITY_ATTESTED,
                classification=IdentityChangeClass.IDENTITY_ALTERING,
                directive=f"PROCEED: Change {change.change_id} altering but authorized.",
                manifest_digest=digest
            )

        # Gate 5: Notice required
        if policy.require_notice_for_altering:
            return IdentityManifest(
                verdict=IdentityContinuityVerdict.TRANSITION_NOTICE_REQUIRED,
                classification=IdentityChangeClass.IDENTITY_ALTERING,
                directive=f"NOTICE: Change {change.change_id} alters identity, notice required to {len(change.affected_parties)} parties.",
                manifest_digest=cls._hash(f"NOTICE:{change.change_id}")
            )

        return IdentityManifest(
            verdict=IdentityContinuityVerdict.TRANSITION_NOTICE_REQUIRED,
            classification=IdentityChangeClass.IDENTITY_REPLACING,
            directive=f"HALT: Change {change.change_id} may replace identity, transition required.",
            manifest_digest=cls._hash(f"REPLACE:{change.change_id}")
        )