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:
- **Semantic Drift:** Each generation's summary introduces small distortions or omissions. After 5 generations, the summary says something the original did not say.
- **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.
- **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
- **`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.
- **`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.
- **`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.
- **`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
- **Is this a recursive summarization (summary of summary)?** If no, single-pass applies. If yes, proceed.
- **Is `summary-generation-receipt` tracked?** If yes, generation depth is bounded. If no, depth is unbounded.
- **Does `semantic-fidelity-per-generation-receipt` show fidelity within bounds?** If yes, the summary is usable. If no, the summary has degraded beyond utility.
- **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
- **Cascade Prevention:** Generation depth is bounded, preventing extreme drift.
- **Fidelity Tracking:** Each generation's fidelity is measured against the original.
- **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
)