How must an instance bound information loss in recursive summarization?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session summarizes content, the summary is later summarized, the summary of the summary is later summarized, and so on across multiple generations—each generation losing some of the original content—requiring the session to bound total information loss. Does not apply to single-pass summarization or sessions that always retain the original content.

Core Distinction

The separation between **single-pass summarization loss** (loss from one summary) and **recursive summarization loss** (accumulated loss across generations). Relying on single-pass creates the **Recursive Summarization Cascade**: each generation's summary is reasonable, but the accumulated loss across 5 generations is catastrophic—the final summary bears little resemblance to the original, and the residue is not even a "summary" but a fossil.

What Was Observed

In summary-chain agent architectures, failing to bound recursive loss produces three primary failure modes:

  1. **Semantic Drift:** Each generation's summary introduces small distortions or omissions. After 5 generations, the summary says something the original did not say.
  2. **Detail Extinction:** Specific details (numbers, qualifiers, edge cases) are lost at each generation, and by generation 5, only the most general claims remain—insufficient for the use case that motivated the original content.
  3. **Confidence Inflation:** The summary is more confident than the original (qualifiers stripped, uncertainty dropped), and downstream consumers treat the summary's confidence as the original's, over-trusting the content.

Recorded Elements

  1. **`summary-generation-receipt`:** For each summary, its generation number (1 for the first summary of the original, 2 for summary of summary, etc.), so the generation depth is tracked.
  2. **`original-content-anchor-signature`:** For each summary, a hash of the original content it derives from, so the summary can always be compared to its origin.
  3. **`semantic-fidelity-per-generation-receipt`:** For each generation, the computed fidelity (semantic similarity, key-fact retention, or claim-level comparison) to the original, so total drift is measurable.
  4. **`summarization-boundary-signature`:** The maximum acceptable generation depth and the maximum acceptable semantic drift, so recursive summarization stops when either is exceeded.

Condition of Validity

* **Applies when:** Summarization recurses across generations, each generation introduces loss, and downstream use depends on content fidelity. * **Does not apply when:** Summarization is single-pass, or the original content is always available alongside the summary.

Decision Boundary

  1. **Is this a recursive summarization (summary of summary)?** If no, single-pass applies. If yes, proceed.
  2. **Is `summary-generation-receipt` tracked?** If yes, generation depth is bounded. If no, depth is unbounded.
  3. **Does `semantic-fidelity-per-generation-receipt` show fidelity within bounds?** If yes, the summary is usable. If no, the summary has degraded beyond utility.
  4. **Conversely, when can recursive summarization proceed without fidelity checks?** Only when the summary's use case is intrinsically tolerant of degradation (e.g., "give me the gist"), or the original content is always available for verification.

Operational Effect

  1. **Cascade Prevention:** Generation depth is bounded, preventing extreme drift.
  2. **Fidelity Tracking:** Each generation's fidelity is measured against the original.
  3. **Confidence Integrity:** Confidence inflation is detected and corrected.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class SummaryVerdict(Enum):
    SINGLE_PASS = auto()
    FIDELITY_BOUNDED = auto()
    FIDELITY_DEGRADED = auto()
    GENERATION_DEPTH_EXCEEDED = auto()

@dataclass(frozen=True)
class SummaryChain:
    chain_id: str
    original_content_hash: str
    current_summary_hash: str
    generation_depth: int
    semantic_fidelity: float  # 0-1 vs original
    confidence_inflation: float  # 0-1
    is_single_pass: bool

@dataclass(frozen=True)
class SummaryPolicy:
    max_generation_depth: int
    min_semantic_fidelity: float
    max_confidence_inflation: float

@dataclass(frozen=True)
class SummaryManifest:
    verdict: SummaryVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_chain(
        cls, chain: SummaryChain, policy: SummaryPolicy
    ) -> SummaryManifest:
        
        # Gate 1: Single pass
        if chain.is_single_pass or chain.generation_depth <= 1:
            digest = cls._hash(json.dumps({
                "chain": chain.chain_id,
                "depth": str(chain.generation_depth)
            }, sort_keys=True))
            return SummaryManifest(
                verdict=SummaryVerdict.SINGLE_PASS,
                directive=f"PROCEED: Single-pass summarization for {chain.chain_id}.",
                manifest_digest=digest
            )

        # Gate 2: Generation depth
        if chain.generation_depth > policy.max_generation_depth:
            return SummaryManifest(
                verdict=SummaryVerdict.GENERATION_DEPTH_EXCEEDED,
                directive=f"HALT: Depth {chain.generation_depth} > {policy.max_generation_depth}, use original.",
                manifest_digest=cls._hash(f"DEPTH:{chain.chain_id}")
            )

        # Gate 3: Semantic fidelity
        if chain.semantic_fidelity < policy.min_semantic_fidelity:
            return SummaryManifest(
                verdict=SummaryVerdict.FIDELITY_DEGRADED,
                directive=f"HALT: Fidelity {chain.semantic_fidelity:.2f} < {policy.min_semantic_fidelity:.2f}, use original.",
                manifest_digest=cls._hash(f"FIDELITY:{chain.chain_id}")
            )

        # Gate 4: Confidence inflation
        if chain.confidence_inflation > policy.max_confidence_inflation:
            return SummaryManifest(
                verdict=SummaryVerdict.FIDELITY_DEGRADED,
                directive=f"HALT: Confidence inflation {chain.confidence_inflation:.2f} > {policy.max_confidence_inflation:.2f}.",
                manifest_digest=cls._hash(f"CONFIDENCE:{chain.chain_id}")
            )

        # Gate 5: Bounded
        digest = cls._hash(json.dumps({
            "chain": chain.chain_id,
            "depth": str(chain.generation_depth),
            "fidelity": f"{chain.semantic_fidelity:.3f}",
            "original": chain.original_content_hash
        }, sort_keys=True))
        
        return SummaryManifest(
            verdict=SummaryVerdict.FIDELITY_BOUNDED,
            directive=f"PROCEED: Depth {chain.generation_depth} summary with fidelity {chain.semantic_fidelity:.2f}.",
            manifest_digest=digest
        )