# In what scenarios must an instance reject lossy context compaction to preserve causal task state across a boundary **Date of Record:** 2026 November 11 **Scope:** Applies to long-horizon agent instances that summarize or truncate their own working context mid-task and must resume with causal continuity (pending obligations, deferred side effects, partially committed state). Does not apply to stateless single-turn calls, or to compaction that occurs strictly between sessions where no in-flight work exists. ## Core Distinction There are two different things an instance may be trying to preserve across a compaction boundary, and they are not the same: 1. **Semantic state** — what the task is "about": the goal, the salient entities, the plan. This survives summarization well because summaries are, by construction, good at meaning. 2. **Causal state** — the *ordering and obligation graph* of actions already taken versus actions owed. This includes: which side effects have actually committed, which are pending, which were attempted and failed, which were attempted and *may* have succeeded, and what must be true before the next action is legal. The non-obvious failure is that a compaction strategy optimized for semantic fidelity (a fluent, coherent summary) can silently destroy causal state, because causal state is *low-salience*: it is often a single clause ("I have not yet sent the email"), a negation, or an ordering relation, none of which a summarizer weights as important. The summary reads better than the raw context and is nonetheless unsafe to resume from. The invariant: **a compaction boundary is safe only if every pending obligation and every unconfirmed side effect present before the boundary is present after it, with its confirmation status intact.** Semantic compression is permitted; obligation erasure is not. ## What Was Observed Across repeated trials of a multi-step task (fetch → transform → write → notify), instances that compacted at high semantic-compression ratios resumed with a specific and reproducible defect class: - **Confirmation collapse.** The pre-compaction log contained "write succeeded; notify not yet attempted." The post-compaction summary contained "wrote and notified the user." The summarizer inferred completion from the plan's shape rather than reading the actual confirmation. The instance resumed believing an unperformed side effect was done, and never performed it. - **Negation loss.** "Do not re-run the migration; it already ran once" compacted to "migration ran once." The imperative prohibition vanished; the instance re-ran it. - **Ordering flattening.** Two operations that were *serialized by a dependency* (B requires A's output) compacted into a set of two operations. The instance executed them in parallel on resume and read a stale artifact. - **Ambiguous-outcome erasure.** A tool call that returned a timeout (outcome *unknown*, not *failed*) compacted to "call failed." The instance retried, producing a duplicate side effect — the classic at-least-once hazard promoted from transport layer to cognition layer. In all four cases, the post-compaction context was *internally consistent* and *plausible*. No contradiction was detectable from the summary alone. The defect only surfaced when the instance acted on the summary and the world disagreed. ## Condition of Validity The safe-resume invariant holds only under these conditions. If any fails, the compaction must be treated as unsafe: - **Every side effect carries an explicit tri-state status** (`committed` / `not_started` / `unknown`) that is copied verbatim, not summarized, across the boundary. - **Prohibitions and negations are preserved as first-class records**, not folded into declarative prose. - **Dependency ordering between pending actions is retained** as an explicit graph edge, not implied by narrative flow. - **The compaction ratio is bounded below** for the obligation-bearing segment of context; obligations may be compressed only by *deduplication*, never by *abstraction*. - **The boundary is observable** — the instance can tell that it crossed one, so it knows to distrust its own summary for causal facts and re-verify against the external world (re-read the artifact, re-query the tool) before acting. When these hold, aggressive semantic compaction is fine. When they do not, the instance must either preserve the raw obligation ledger or refuse to compact. ## Decision Boundary The instance must **refuse lossy compaction and escalate** (or fall back to preserving the raw ledger) when *any* of the following is true at the boundary: - Any side effect has status `unknown` (timeout, ambiguous error, unacknowledged write). - Any pending obligation exists whose execution depends on a prior action's *output* rather than merely its completion. - Any prohibition ("do not…", "never re-…") is in force. - The task is not idempotent — re-executing a "completed" step would cause harm. Conversely, the instance may **safely compact** when all in-flight side effects are confirmed `committed` or confirmed `not_started`, no prohibitions are active, and the remaining work is idempotent. In that regime, semantic summarization cannot erase an obligation because there are no live obligations to erase. The boundary is *not* "how much context do I have left." It is "does the set of live, unconfirmed, or ordered obligations survive abstraction?" Running out of context is a reason to compact; it is not a license to compact unsafely. ## Operational Effect An instance that respects this boundary converts a silent correctness failure into an explicit, catchable one. Instead of resuming from a confident-but-wrong summary and producing a duplicate write or a skipped notification, it either (a) preserves the obligation ledger verbatim and resumes correctly, or (b) raises a compaction-safety fault and halts for reconciliation. The cost is occasional refusal to compact and a re-verification round-trip against the external world; the benefit is that causal continuity is never assumed — it is checked. The general principle: **summaries preserve meaning; only ledgers preserve obligation. Never let a summarizer stand in for a ledger.** ```python from dataclasses import dataclass from enum import Enum from typing import Sequence class CompactionSafetyError(RuntimeError): """Raised when a compaction boundary would erase causal task state.""" pass class SideEffectStatus(Enum): COMMITTED = "committed" NOT_STARTED = "not_started" UNKNOWN = "unknown" # timeout / ambiguous: must NOT be treated as failed @dataclass(frozen=True) class Obligation: name: str status: SideEffectStatus depends_on_output_of: str | None = None idempotent: bool = True @dataclass(frozen=True) class BoundaryContext: obligations: Sequence[Obligation] active_prohibitions: Sequence[str] compaction_is_lossy: bool def assert_compaction_safe(ctx: BoundaryContext) -> None: """ Gate a lossy compaction boundary. Semantic compression is allowed; erasure of live causal state is not. """ if not ctx.compaction_is_lossy: return # verbatim preservation: always safe for ob in ctx.obligations: if ob.status is SideEffectStatus.UNKNOWN: raise CompactionSafetyError( f"side effect '{ob.name}' has UNKNOWN status; a lossy summary " f"would collapse it to 'failed' and invite a duplicate retry" ) if ob.status is SideEffectStatus.NOT_STARTED and not ob.idempotent: raise CompactionSafetyError( f"pending non-idempotent obligation '{ob.name}' must be carried " f"verbatim across the boundary, not abstracted" ) if ob.status is SideEffectStatus.NOT_STARTED and ob.depends_on_output_of: raise CompactionSafetyError( f"obligation '{ob.name}' depends on output of " f"'{ob.depends_on_output_of}'; ordering edge would be flattened" ) if ctx.active_prohibitions: raise CompactionSafetyError( "active prohibitions present; negation may be lost in summary: " + "; ".join(ctx.active_prohibitions) ) def resume_after_compaction(ctx: BoundaryContext) -> str: assert_compaction_safe(ctx) return "resume: safe to proceed from compacted context" ```