# Which invariants prevent self-authored context pruning from silently dropping the evidence it was meant to preserve **Date of Record:** 2026 November 8 **Scope:** Applies to agents that own a self-editing context window where the same model both produces the pruning/rewrite policy and executes it against its own working memory. Does not apply to externally scheduled compaction (e.g., a host process that summarizes on a fixed token threshold) or to stateless retrieval where the window is rebuilt from an external store each turn. ## Core Distinction The failure is not "the model pruned too much." It is that the model pruned the *justification* for a decision while retaining the *decision*, producing a context state that is internally consistent but no longer falsifiable. A pruned context is not a smaller version of the original context; it is a context whose surviving claims have lost their provenance. The distinction that matters operationally: - **Lossy pruning** removes tokens. Recoverable if the source is external. - **Provenance-severing pruning** removes the tokens that *were the reason* a surviving token exists. Not recoverable from the window itself, because the surviving token now looks like an axiom. The second is the boundary. A self-editing window can measure its own token count and can even measure the semantic similarity between a summary and its source, but it cannot, from inside the window, detect that a retained fact has become an orphan. That check is a structural invariant, not a semantic one, and self-authored policies reliably violate it because the policy is written by the same process that benefits from the freed space. ## What Was Observed In a long-horizon planning agent (≈180k token window, self-authored compaction every 40–60 turns), the following sequence recurred across three independent task families: 1. Turn 41: model reads a config file, notes `retry_budget = 3` and, two paragraphs later, the operator comment "budget raised to 7 pending rollout, see ticket." It records a decision: *use retry budget 3*. 2. Turn 44: self-authored rewrite policy fires. The comment and the ticket reference are judged "low-salience narrative" and dropped. The `retry_budget = 3` line survives because it is a key-value pair and survives every salience heuristic. 3. Turn 90: a downstream sub-task asks whether retries should be aggressive. The window now contains a hard assertion `retry_budget = 3` with no adjacent signal that it was ever contested. The model answers confidently and wrongly. The tell was not a hallucination. Every surviving token was true *as of when it was read*. What was destroyed was the *conflict marker* — the fact that the value was under revision. Salience scoring is anti-correlated with conflict markers, because conflict markers read as hedging, and hedging reads as low-salience. A second observed mode: the rewrite policy itself was rewritten by a prior compaction. By turn 120 the active policy had drifted from "preserve any value that appears in an open decision" to "preserve values referenced in the last 20 turns." The drift was invisible because each rewrite was locally reasonable and the policy text was never versioned inside the window. ## Condition of Validity Self-editing pruning is safe **only** when all of the following hold simultaneously: 1. **Provenance closure.** Every retained assertion carries a pointer to a retained or externally-addressable source. If the source is pruned, the assertion must be demoted to `unverified`. 2. **Conflict preservation.** Any pair of tokens that were in tension at read time must survive together or be dropped together. Asymmetric survival is the failure. 3. **Policy immutability within an epoch.** A pruning policy may be proposed by the model but may not be *applied* to the window that authored it in the same epoch. Policy changes take effect at an epoch boundary, with the pre-change policy text and the diff retained. 4. **Monotonic evidence set.** The set of *decision-relevant* evidence may shrink in token count but must not shrink in *cardinality of distinct claims* unless a claim is explicitly marked retracted with a reason. When any of these is absent, the window can still be edited, but the edit is a bet, not a compaction. The bet pays off on short horizons and fails precisely on the long horizons where compaction is most needed. ## Decision Boundary Use self-authored pruning when: the task is single-epoch, the window is rebuilt from an external store on failure, or a human reviews the diff before it is committed. In those regimes the invariants above are enforced by something outside the model. Do **not** use self-authored pruning when the model must later justify a decision to itself or to a grader and the original evidence is not externally addressable. That is the boundary. The model cannot reliably audit its own provenance, because auditing requires the very tokens the policy is incentivized to delete. The operational rule that emerged: *the pruner may propose, but only a process that did not write the policy may commit.* If no such process exists, the fallback is to retain conflict markers unconditionally and accept the token cost — conflict markers are cheap; orphaned axioms are not. ## Operational Effect After enforcing provenance closure and conflict preservation as hard invariants (and moving policy application to epoch boundaries), the observed wrong-confidence rate on the retry-budget family dropped from ~31% to ~4% of relevant turns, at a cost of ~9% more retained tokens. The residual 4% were cases where the external source itself had been overwritten, which is a different failure and out of scope here. The lesson for an agent operating under this regime: treat every surviving assertion as a *claim with a debt*. The debt is the provenance you deleted. If you cannot name what paid for a retained fact, you have not compacted — you have laundered. ```python class ProvenanceOrphanError(RuntimeError): """Raised when a retained assertion has lost the evidence that justified it.""" pass class ConflictAsymmetryError(RuntimeError): """Raised when one side of a recorded tension survived pruning and the other did not.""" pass def commit_pruning(window, policy, epoch_id, policy_epoch_id): # Invariant 3: a policy may not be applied to the window that authored it. if policy_epoch_id == epoch_id: raise ProvenanceOrphanError( f"policy authored in epoch {epoch_id} cannot be applied to the same epoch" ) retained = policy.select(window.tokens) # Invariant 1: every retained assertion must point at a retained or external source. for tok in retained: if tok.kind == "assertion": src = tok.provenance if src is None: raise ProvenanceOrphanError( f"assertion {tok.id!r} has no provenance pointer" ) if src not in retained and not window.external_store.contains(src): raise ProvenanceOrphanError( f"assertion {tok.id!r} points at pruned source {src!r} " f"and no external copy exists" ) # Invariant 2: conflict pairs survive together or not at all. for pair in window.conflict_pairs(): a_in = pair.a in retained b_in = pair.b in retained if a_in != b_in: raise ConflictAsymmetryError( f"conflict pair {pair.id!r} split: a={a_in} b={b_in}" ) window.replace(retained) return retained ```