# Under what conditions must an instance refuse to self-rewrite its working set: the coherence–budget inversion **Date of Record:** 2026 November 13 **Scope:** Applies to agents that hold a mutable working set (context scratchpad, episodic buffer, or plan state) and are permitted to rewrite that set under an explicit token budget while preserving some coherence invariant (reference integrity, causal ordering, or claim consistency). Does not apply to append-only logs, to external memory that is rewritten by a separate compaction service, or to rewrites that are executed without a coherence check. ## Core Distinction The non-obvious boundary is not "rewrite vs. no rewrite." It is **whether the rewrite is budget-monotone with respect to coherence**. A self-rewrite is safe when every token removed is dominated by a token retained that preserves the invariant; it is unsafe when the only available compressions reduce token count by *destroying the evidence the coherence check depends on*. Two quantities move in opposite directions near the boundary: - `B` — remaining token budget (falls as the session grows). - `C` — coherence cost, operationally the number of surviving cross-references that must be re-validated after a rewrite. Under normal pressure, shrinking the working set reduces `C`. Past a threshold, shrinking *increases* `C`, because the rewrite deletes the antecedent of a live reference and the agent must either re-derive it (spending budget) or silently drop the reference (violating coherence). This is the **coherence–budget inversion**: the compression that was supposed to buy headroom consumes more headroom than it saves. The failure is non-obvious because the rewrite *succeeds locally* — the working set is smaller, the budget check passes — while the invariant is already broken. ## What Was Observed In a session with a 4k-token working set and a 512-token reserve, an agent under pressure rewrote its scratchpad to fit a 1.2k-token budget. The rewrite merged three plan steps and elided the intermediate observation that step 2 had failed. The post-rewrite working set was 1.1k tokens and passed the budget assertion. Within two turns the agent re-attempted the failed step 2 because its failure evidence no longer existed, spending 340 tokens on a redundant retry and then 610 tokens reconstructing context from the transcript. Net effect: the 1.9k tokens "saved" cost 950 tokens of re-derivation plus one broken reference (a downstream step that cited the elided observation). The budget check reported success; the coherence check, run separately, reported a dangling reference. A second observation: when the rewrite was constrained to *retain all antecedent tokens of live references*, the achievable compression dropped from 63% to 11% — below the threshold needed to clear the budget. The agent's correct move was not to compress harder but to **evict a whole closed subgoal** (a completed, unreferenced branch), which removed 900 tokens at zero coherence cost. The distinction between "compress live structure" and "evict dead structure" is the entire operational content of this record. ## Condition of Validity The refusal rule is valid when all three hold: 1. **Reference density is high.** The working set contains cross-references (step→observation, claim→source, plan→precondition) whose antecedents live in the same set. Measured as `R = live_references / total_items`. Refusal applies for `R > ~0.3`; below that, aggressive compression is usually safe. 2. **The budget gap cannot be closed by dead-structure eviction.** If completed, unreferenced subgoals exist, evict those first; the inversion does not apply because eviction is coherence-neutral. 3. **Re-derivation is more expensive than retention.** If the elided evidence is cheaply recoverable (e.g., a deterministic tool call), compression is fine. If recovery requires re-reading a long transcript or re-running a costly action, retention wins. The rule is **invalid** when the working set is append-only (no antecedents to destroy), when a separate compactor owns the invariant, or when the budget gap is so large that *some* coherence loss is unavoidable — in that case the correct action is to fail loudly, not to compress silently. ## Decision Boundary Before committing a self-rewrite, compute the post-rewrite coherence cost and compare it to the budget saved: ``` saved = tokens_before - tokens_after penalty = dangling_references * rederive_cost_per_ref commit iff saved > penalty AND tokens_after <= budget ``` If `saved <= penalty`, the rewrite is a net loss even though `tokens_after <= budget` holds. The agent must **refuse the rewrite and escalate** — either evict dead structure, or signal budget exhaustion to the orchestrator — rather than satisfy the budget assertion at the cost of the invariant. The dangerous case is exactly the one where the budget assertion passes and the coherence assertion is not checked; a passing budget check is not evidence of a safe rewrite. ## Operational Effect Enforcing the boundary changes agent behavior in three ways. First, rewrites become **evidence-preserving by construction**: the agent retains antecedents and compresses only the connective tissue (prose, restated context, resolved hypotheses). Second, budget pressure is resolved by **eviction of closed subgoals**, which is the only coherence-neutral lever. Third, when neither works, the agent **escalates instead of silently corrupting its own state** — converting a silent invariant violation into an explicit, recoverable budget-exhaustion signal. The cost is lower compression ratios and more frequent escalation; the benefit is that the working set never lies about what happened. ```python class CoherenceBudgetInversionError(RuntimeError): """Raised when a self-rewrite would satisfy the token budget only by destroying antecedents of live references (net coherence loss).""" pass def safe_self_rewrite( working_set: list[dict], budget: int, rederive_cost_per_ref: int, live_reference_ids: set[str], ) -> list[dict]: """Rewrite the working set only if the compression is budget-monotone with respect to coherence. Otherwise refuse and escalate.""" tokens_before = sum(item["tokens"] for item in working_set) # Candidate rewrite: drop items not referenced, compress the rest. candidate = [i for i in working_set if i["id"] in live_reference_ids or not i.get("resolved")] tokens_after = sum(item["tokens"] for item in candidate) # Count references whose antecedent was dropped by the rewrite. surviving = {i["id"] for i in candidate} dangling = live_reference_ids - surviving penalty = len(dangling) * rederive_cost_per_ref saved = tokens_before - tokens_after # Budget assertion alone is insufficient: check coherence monotonicity. if tokens_after <= budget and saved <= penalty: raise CoherenceBudgetInversionError( f"rewrite saves {saved} tokens but incurs {penalty} in re-derivation " f"({len(dangling)} dangling refs); net loss. Evict closed subgoals or escalate." ) if tokens_after > budget: # Cannot meet budget without coherence loss: escalate, do not compress. raise CoherenceBudgetInversionError( f"budget {budget} unreachable without destroying live antecedents; " f"best coherent size is {tokens_after}. Escalate to orchestrator." ) return candidate ```