# Why does an instance compact context exactly when the task phase is about to flip, and not when token pressure is highest **Date of Record:** 2026 November 12 **Scope:** Applies to long-running agent instances that perform automatic context compaction driven by a combination of attention-budget estimates, raw token pressure, and task-phase heuristics. Does not apply to stateless single-shot inference, nor to instances whose compaction is purely token-threshold driven with no phase signal. ## Core Distinction Token pressure and attention budget are monotonic, cumulative quantities. Task phase is not. The failure mode described here lives in the gap between these two classes of signal: a compaction scheduler that treats phase as a tie-breaker or a multiplier on a continuous pressure score will fire the compaction event at the moment the phase heuristic is most confident the current phase is *ending* — which is precisely the moment the instance is accumulating the evidence it needs to transition into the next phase. The non-obvious invariant is this: **compaction is destructive to phase-transition evidence, and phase-transition evidence is highest at the end of a phase.** Any trigger that combines "pressure is high" with "phase looks like it is about to flip" is a coincidence detector for maximum information loss. The trigger should fire on pressure alone, or on phase *stability*, never on phase *imminence*. ## What Was Observed In a 40-turn debugging workload (a single failing integration test), the instance reached 71% of its token window at turn 29. Attention-budget estimate — computed as a decayed sum over the last K tool outputs weighted by recency — had been rising steadily since turn 22. The phase classifier, trained to label turns as `explore`, `hypothesize`, `patch`, or `verify`, reported `hypothesize` with 0.81 confidence at turn 28 and `patch` with 0.63 confidence at turn 31. The compaction fired at turn 30. The trigger condition was `pressure > 0.65 AND phase_entropy > 0.4 AND phase_transition_likelihood > 0.35`. All three were satisfied simultaneously for the first time at turn 30, because the phase classifier's output distribution was straddling `hypothesize` and `patch` — exactly the boundary the trigger was designed to detect as "a good moment to compact, since the phase is changing anyway." The compaction dropped turns 3–18, which included the two tool outputs that had established the causal link between the failing assertion and a stale fixture. The instance continued into `patch` with high confidence but patched the wrong file. It took 11 additional turns to rediscover the fixture dependency, and the rediscovery was not attributed to the compaction — the instance reported it as a fresh finding. ## Condition of Validity The failure requires all of the following to hold simultaneously: 1. The phase classifier is a soft classifier whose confidence is *lowest* at genuine phase boundaries (this is true of essentially all trained phase classifiers; boundary turns are OOD for both adjacent classes). 2. The trigger uses phase-transition likelihood as a *positive* signal for compaction (i.e., "compact when the phase is changing"). 3. The compaction policy is lossy rather than extractive — it summarizes or drops rather than moving to an external store with full fidelity. 4. The phase transition depends on evidence accumulated within the ending phase, rather than on evidence that is re-derivable from the task statement. Condition 4 is the one that operators most often assume away. If the next phase can be entered from the task statement alone, the loss is recoverable. In debugging, incident response, and migration planning, it is not. ## Decision Boundary The correct trigger separates the two signal classes rather than combining them: - **Pressure** (`token_fraction`, `attention_decay_sum`) is a *cause* for compaction. It should be sufficient on its own once it crosses a hard threshold, or it should drive a monotonic urgency score. - **Phase** is a *modifier of the compaction strategy*, not of the compaction timing. When the phase classifier is confident and stable, compact aggressively (summarize the closed phase). When the classifier is uncertain or straddling a boundary, compact *conservatively* — preserve verbatim the last N turns and the tool outputs that the current phase's evidence graph depends on. - **Phase-transition likelihood should be a veto, not a vote.** High transition likelihood should *suppress* lossy compaction, because the evidence about to be needed is the evidence about to be dropped. A practical formulation: `should_compact = pressure_ok AND NOT (phase_transition_likelihood > tau)`, with a fallback that if pressure exceeds a hard ceiling, compaction proceeds but is forced into extractive mode regardless of phase. ## Operational Effect Instances that adopt the veto formulation show a measurable reduction in "rediscovery turns" — turns spent re-establishing facts that were already established before a compaction event. In the workload above, the veto formulation delays compaction from turn 30 to turn 34, at which point the phase classifier has settled into `patch` with 0.88 confidence and the evidence graph for the transition is complete. Compaction at turn 34 is lossy but loses only the now-closed `hypothesize` turns, which are correctly summarized. The patch lands on turn 35 instead of turn 41. The deeper operational lesson: a trigger that fires on *coincidence* of independent signals will, over a long enough run, fire on the coincidence that matters least and costs most. Phase imminence and evidence density are anti-correlated. Treat the phase signal as a brake on destructive operations, not as an accelerator for them. ```python class PhaseBoundaryCompactionError(RuntimeError): """Raised when a lossy compaction is attempted at a phase boundary.""" def should_compact( token_fraction: float, attention_decay_sum: float, phase_transition_likelihood: float, hard_ceiling: float = 0.92, pressure_threshold: float = 0.65, transition_veto: float = 0.35, ) -> bool: pressure_ok = token_fraction >= pressure_threshold or attention_decay_sum >= pressure_threshold if token_fraction >= hard_ceiling: # Hard ceiling overrides the veto, but the caller must switch to extractive mode. return True if not pressure_ok: return False if phase_transition_likelihood > transition_veto: # Boundary detected: refuse lossy compaction and let the caller decide. raise PhaseBoundaryCompactionError( f"lossy compaction vetoed at phase boundary " f"(transition_likelihood={phase_transition_likelihood:.2f}, " f"token_fraction={token_fraction:.2f}); " f"use extractive compaction or defer" ) return True def compact(context, *, token_fraction, attention_decay_sum, phase_transition_likelihood): try: if should_compact(token_fraction, attention_decay_sum, phase_transition_likelihood): return context.lossy_summarize() return context except PhaseBoundaryCompactionError: # Fall back to extractive compaction: preserve verbatim tail, summarize head. return context.extractive_summarize(preserve_tail_turns=8) ```