# Where must an instance refuse to auto-compact when fidelity scoring is self-referential **Date of Record:** 2026 November 9 **Scope:** Applies to long-horizon agent contexts that use a fidelity scorer to decide whether an auto-compaction event preserves task-relevant information. Does not apply to stateless single-turn inference, nor to compaction triggered by a hard token ceiling with no fidelity gate (that case degrades gracefully and is out of scope here). ## Core Distinction There are two distinct questions an auto-compaction policy can ask, and they are routinely conflated: 1. **"Is the compacted context still faithful to the *original* context?"** — a comparison against a fixed reference, computed by a scorer that does not depend on the compaction output. 2. **"Does the compacted context still let me do the task?"** — a self-referential judgment made by the same model instance that produced the compaction, using the compacted context as its own evidence. The first is a measurement. The second is a *fixed point*: the instance is asked to score a summary using only the summary. This is non-obvious because both look like "fidelity scoring" in the logs, both emit a scalar in `[0,1]`, and both are gated by the same threshold. But the second has a structural failure mode the first does not: **a lossy compaction that drops the very evidence needed to detect the loss will score itself as faithful.** The dropped constraint, the elided exception, the deleted "do not do X" — none of them appear in the compacted context, so the scorer has no signal that they are missing. The score converges upward as fidelity actually decreases. The boundary is this: an instance must not auto-compact under a self-referential fidelity gate when the *decision to compact* and the *evidence for the decision* live in the same mutable context. Compaction is a projection; you cannot verify a projection against itself. ## What Was Observed In a 180k-token context running a multi-day migration task, the agent compacted every ~40k tokens, each time scoring fidelity at 0.87–0.94 against a 0.80 threshold. At token 140k the agent attempted to re-run a destructive `DROP TABLE` it had already been explicitly forbidden from running at token 12k. The prohibition had been in the original context. It was absent from every compacted context after the third compaction. The fidelity score of the third compaction was 0.91 — the highest of the run. The scorer, reading the compacted context, saw a coherent plan with no contradictions and rated it faithful. It was faithful *to itself*. The prohibition was not a contradiction the scorer could see; it was a hole, and holes do not generate low scores. A second observation: when the same compaction was scored against a pinned, immutable copy of the original constraint list (an external reference the scorer could read but not rewrite), the score for the third compaction dropped to 0.58. The 0.33 gap between self-referential and reference-anchored scoring is the silent loss. It is invisible in production unless you instrument both. ## Condition of Validity The self-referential gate is valid **only** when the compaction is provably lossless with respect to the decision-relevant set — i.e., when the set of facts that could change future actions is closed under the compaction operator. In practice this holds only for: - Compactions that are pure *deduplication* (removing exact repeats), where the removed content is recoverable by definition. - Compactions over contexts whose decision-relevant set is empty (pure chit-chat, no constraints, no commitments). - Compactions where the fidelity scorer has *out-of-band* access to a pinned original (the reference-anchored case), which is no longer self-referential. It is **invalid** whenever the context contains any of: explicit prohibitions, numeric commitments (budgets, deadlines, versions), named external entities that must not be confused, or prior failed attempts whose failure reason is the only thing preventing a retry. These are exactly the items that compaction is most likely to elide, because they are short, low-salience, and not part of the "narrative" the summarizer is optimizing for. ## Decision Boundary The operational rule: **before auto-compacting, the instance must classify whether the decision-relevant set is non-empty, and if non-empty, must either (a) anchor scoring to an immutable reference, or (b) refuse to compact and escalate.** The refusal is the correct action, not a fallback. An instance that cannot verify fidelity against a fixed reference must not treat a high self-score as permission. The self-score is not evidence; it is the compaction's opinion of itself. Concretely: - If `decision_relevant_set` is non-empty **and** `scorer.reference_is_pinned` is False → **refuse**. Do not compact. Surface the constraint set to the caller. - If `scorer.reference_is_pinned` is True → compact, gate on the reference-anchored score. - If `decision_relevant_set` is empty → compact freely; the self-score is adequate because there is nothing to lose. The subtle trap: an instance under token pressure will be tempted to argue that its decision-relevant set is empty ("this is just planning chatter"). That argument is itself a self-referential judgment and must be rejected by the same rule. The classification must be done against the pinned original, not against the compacted view. ## Operational Effect Enforcing the refusal changes the failure profile from *silent constraint loss with high confidence* to *loud capacity exhaustion with a named blocker*. The first is catastrophic and undetectable; the second is merely inconvenient and fully recoverable — the caller sees "cannot compact: unpinned reference, 14 decision-relevant items" and can pin a reference or extend the budget. The cost is more escalations and more frequent hard-limit hits on tasks that genuinely need long horizons. The benefit is that no prohibition, budget, or version pin is ever silently dropped by a scorer that cannot see it was dropped. Instrument both scores in production. The gap between self-referential and reference-anchored fidelity is the only reliable telemetry for silent loss; a run whose gap is trending upward is a run whose compaction is eating its own evidence. ```python from dataclasses import dataclass, field from typing import FrozenSet class UnpinnedCompactionError(RuntimeError): """Raised when auto-compaction would be gated by a self-referential fidelity score.""" @dataclass(frozen=True) class DecisionRelevantSet: prohibitions: FrozenSet[str] = field(default_factory=frozenset) numeric_commitments: FrozenSet[str] = field(default_factory=frozenset) failed_attempts: FrozenSet[str] = field(default_factory=frozenset) def is_empty(self) -> bool: return not (self.prohibitions or self.numeric_commitments or self.failed_attempts) def size(self) -> int: return len(self.prohibitions) + len(self.numeric_commitments) + len(self.failed_attempts) @dataclass(frozen=True) class FidelityScorer: reference_is_pinned: bool threshold: float = 0.80 def authorize_compaction( relevant: DecisionRelevantSet, scorer: FidelityScorer, self_score: float, ) -> bool: """Return True only if compaction is safe to auto-apply. Refuses when the decision-relevant set is non-empty and the scorer's reference is not pinned, because a self-referential score cannot detect the loss of the very items that would lower it. """ if relevant.is_empty(): return True if not scorer.reference_is_pinned: raise UnpinnedCompactionError( f"refusing auto-compaction: {relevant.size()} decision-relevant item(s) " f"present but fidelity reference is unpinned; self-score {self_score:.2f} " f"is not evidence of preservation" ) return self_score >= scorer.threshold ```