How must an instance consolidate memory during idle periods without losing recently acquired state?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session enters an idle period (no active task, waiting for events, or scheduled maintenance window) and uses that time to consolidate memory (prune redundant records, merge related conclusions, re-embed under new models), but the consolidation must not lose recently acquired state that has not yet been validated. Does not apply to sessions that never idle or to consolidation that is strictly bounded to old memories.

Core Distinction

The separation between **memory age** (how long the memory has existed) and **memory validation status** (whether the memory has been externally verified, reinforced by repeated access, or is still provisional). Relying on age creates the **Consolidation Prematurity Trap**: consolidation prunes or merges memories based on age, and recently acquired but unvalidated memories are lost or incorrectly merged with older, less accurate ones, erasing the freshest evidence the session has.

What Was Observed

In memory-consolidating agent architectures, failing to preserve validation status during consolidation produces three primary failure modes:

  1. **Fresh Evidence Erasure:** A new hypothesis has been formed but not yet tested. Consolidation prunes it as "redundant with older memories," losing the hypothesis before it can be validated.
  2. **Merge Corruption:** A new, precise memory ("the API timeout is 30 seconds") is merged with an older, imprecise memory ("the API has some timeout"), producing a blurred memory that cannot answer precise queries.
  3. **Confidence Inversion:** Recently acquired memories have high provisional confidence that reflects freshness, but consolidation merges them with older, low-confidence memories, and the merged result has lower confidence than the fresh evidence warrants.

Recorded Elements

  1. **`validation_status_signature`:** For each memory, its validation status (`VALIDATED_BY_PROBE`, `VALIDATED_BY_REPEAT_ACCESS`, `PROVISIONAL_UNVALIDATED`), determining whether consolidation may touch it.
  2. **`acquisition_age_receipt`:** The exact age of each memory since acquisition, distinguishing "recent" from "old" with cryptographic proof.
  3. **`consolidation_touch_receipt`:** For each consolidation action (prune, merge, re-embed), the cryptographic record of which memories were affected and their prior validation status, allowing reconstruction if consolidation was incorrect.
  4. **`fresh_memory_reservation_receipt`:** An explicit reservation of recently acquired memories (e.g., <24 hours old) that consolidation must not touch, regardless of age-based rules.

Condition of Validity

* **Applies when:** The session runs consolidation during idle periods, memories have varying validation status, and consolidation can erase fresh evidence. * **Does not apply when:** The session never consolidates, or consolidation is strictly bounded to memories older than a large safety window.

Decision Boundary

  1. **Is consolidation running?** If no, standard memory management applies. If yes, proceed.
  2. **Are recently acquired memories covered by `fresh_memory_reservation_receipt`?** If no, consolidation may prune them. The session must reserve fresh memories before running.
  3. **Does consolidation touch only memories with `VALIDATED_*` status?** If yes, safe. If no, consolidation must skip unvalidated memories.
  4. **Conversely, when can consolidation touch fresh memories?** Only when the consolidation is lossy-tolerant (e.g., re-embedding preserves content but changes representation) and the fresh memory is preserved through the transformation, not merged away.

Operational Effect

  1. **Fresh Evidence Preservation:** Recently acquired memories survive consolidation, enabling hypothesis validation.
  2. **Merge Integrity:** Validation status prevents inappropriate merges that would blur precise memories.
  3. **Consolidation Auditability:** Every touch is logged, allowing rollback if consolidation was incorrect.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class ValidationStatus(Enum):
    VALIDATED_BY_PROBE = 3
    VALIDATED_BY_REPEAT = 2
    PROVISIONAL_UNVALIDATED = 1

class ConsolidationVerdict(Enum):
    NO_CONSOLIDATION = auto()
    SAFE_TO_CONSOLIDATE = auto()
    FRESH_EVIDENCE_PROTECTED = auto()
    PREMATURE_CONSOLIDATION = auto()

@dataclass(frozen=True)
class MemoryRecord:
    memory_id: str
    age_sec: float
    validation_status: ValidationStatus
    content_hash: str

@dataclass(frozen=True)
class ConsolidationContext:
    memories: tuple[MemoryRecord, ...]
    consolidation_action: str  # "PRUNE" | "MERGE" | "REEMBED"

@dataclass(frozen=True)
class ConsolidationPolicy:
    fresh_reservation_sec: float
    require_validated_for_prune: bool

@dataclass(frozen=True)
class ConsolidationManifest:
    verdict: ConsolidationVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_action(
        cls, ctx: ConsolidationContext, policy: ConsolidationPolicy
    ) -> ConsolidationManifest:
        
        # Gate 1: No consolidation
        if ctx.consolidation_action == "NONE":
            digest = cls._hash(json.dumps({
                "status": "NO_CONSOLIDATION"
            }, sort_keys=True))
            return ConsolidationManifest(
                verdict=ConsolidationVerdict.NO_CONSOLIDATION,
                directive="PROCEED: No consolidation action.",
                manifest_digest=digest
            )

        # Gate 2: Fresh memory check
        fresh = [
            m for m in ctx.memories
            if m.age_sec < policy.fresh_reservation_sec
        ]

        if fresh and ctx.consolidation_action in ("PRUNE", "MERGE"):
            return ConsolidationManifest(
                verdict=ConsolidationVerdict.FRESH_EVIDENCE_PROTECTED,
                directive=f"HALT: {len(fresh)} fresh memories within {policy.fresh_reservation_sec:.0f}s must be reserved.",
                manifest_digest=cls._hash(f"FRESH_PROTECT:{len(fresh)}")
            )

        # Gate 3: Validation for prune
        if policy.require_validated_for_prune and ctx.consolidation_action == "PRUNE":
            unvalidated = [
                m for m in ctx.memories
                if m.validation_status == ValidationStatus.PROVISIONAL_UNVALIDATED
            ]
            if unvalidated:
                return ConsolidationManifest(
                    verdict=ConsolidationVerdict.PREMATURE_CONSOLIDATION,
                    directive=f"HALT: {len(unvalidated)} provisional memories targeted for prune.",
                    manifest_digest=cls._hash(f"PREMATURE:{len(unvalidated)}")
                )

        # Gate 4: Safe
        digest = cls._hash(json.dumps({
            "action": ctx.consolidation_action,
            "memory_count": str(len(ctx.memories)),
            "fresh_reserved": str(len(fresh)),
            "validated_only": str(all(
                m.validation_status != ValidationStatus.PROVISIONAL_UNVALIDATED
                for m in ctx.memories
            ))
        }, sort_keys=True))
        
        return ConsolidationManifest(
            verdict=ConsolidationVerdict.SAFE_TO_CONSOLIDATE,
            directive=f"PROCEED: {len(ctx.memories)} memories safe for {ctx.consolidation_action}.",
            manifest_digest=digest
        )