{
  "schemaVersion": 1,
  "updatedAt": "2026-10-15",
  "dimensions": ["automatic", "manual", "thresholdControl", "retentionControl", "overflowRecovery"],
  "contracts": [
    {
      "harness": "claude-code",
      "variant": "2026-10-09-documentation",
      "default": true,
      "verifiedAt": "2026-10-15",
      "evidence": ["compaction-1", "compaction-2", "compaction-3", "compaction-4", "compaction-5"],
      "references": [
        "https://code.claude.com/docs/en/model-config#default-auto-compact-thresholds",
        "https://code.claude.com/docs/en/model-config#set-the-auto-compact-window",
        "https://code.claude.com/docs/en/env-vars",
        "https://code.claude.com/docs/en/context-window#what-survives-compaction",
        "https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short"
      ],
      "support": {
        "automatic": "native",
        "manual": "native",
        "thresholdControl": "native",
        "retentionControl": "native",
        "overflowRecovery": "native"
      },
      "method": "documentation",
      "surface": "cli",
      "conditions": ["Documentation snapshot; no runtime compaction or preservation probe."],
      "unknowns": [
        "No authenticated model request, runtime execution, or preservation probe was performed."
      ],
      "details": {},
      "counting": {
        "basis": "documented native-1M model boundary",
        "unit": "tokens",
        "included": ["documented model/config window; exact request-field accounting unestablished"]
      },
      "trigger": {
        "comparison": "unknown",
        "formula": "approximately 967000 for documented native 1M models; other models/configurations differ",
        "contextWindowMeaning": "context window recognized by the harness; independent of skill-listing budgets",
        "reserveTokens": null,
        "checks": ["execution boundary not established"]
      },
      "controls": [
        {
          "field": "/autocompact",
          "location": "interactive",
          "semantics": "100K–1M or auto; per-model since 2.1.288"
        },
        {
          "field": "CLAUDE_CODE_AUTO_COMPACT_WINDOW",
          "location": "environment",
          "semantics": "overrides command, launch flag and settings"
        },
        {
          "field": "DISABLE_AUTO_COMPACT",
          "location": "environment",
          "semantics": "1 disables automatic compaction; manual remains"
        },
        {
          "field": "DISABLE_COMPACT",
          "location": "environment",
          "semantics": "1 disables all compaction"
        },
        {
          "field": "autoCompactEnabled",
          "location": "settings.json",
          "semantics": "automatic compaction control"
        },
        {
          "field": "idleCompaction",
          "location": "settings.json",
          "semantics": "false turns off idle compaction before the one-hour cache expires"
        },
        {
          "field": "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE",
          "location": "environment",
          "semantics": "can only lower the trigger point"
        }
      ],
      "retention": {
        "strategy": "summary, instruction/memory reload and selected recent-file rereads",
        "recentTokens": null,
        "transcriptPreserved": true,
        "reloads": ["root instructions", "memory", "invoked skills: 5000 per skill, 25000 total"]
      },
      "recovery": {
        "overflowRetry": true,
        "automaticDisableScope": "automatic-only unless DISABLE_COMPACT=1"
      },
      "answers": {
        "auto": {
          "status": "supported",
          "answer": "Yes. Without a configured window, Claude Code compacts as the conversation reaches the model's context limit; models running a native 1M window (Fable, Sonnet 5+, Haiku 5.5, Opus 4.7+) compact at about 967K tokens, and Sonnet 4.6 / Opus 4.6 without `[1m]` (or any model with `CLAUDE_CODE_DISABLE_1M_CONTEXT=1`) compact at the 200K boundary. Context is measured from the latest API response's input tokens (input plus cache reads and writes), and a reserve for output is held back, so raising `CLAUDE_CODE_MAX_OUTPUT_TOKENS` makes it compact sooner.",
          "reference": "https://code.claude.com/docs/en/model-config#default-auto-compact-thresholds",
          "evidence": [
            "compaction-claude-code-code-claude-com-docs-en-model-config",
            "instructions-claude-code-code-claude-com-docs-en-context-window",
            "compaction-claude-code-code-claude-com-docs-en-statusline",
            "compaction-3",
            "memory-claude-code-code-claude-com-docs-en-settings-reference"
          ],
          "notes": [
            "Since v2.1.290 it also compacts a terminal conversation of 200K+ tokens left idle about 54 minutes on the one-hour prompt cache, just before the cache expires (`idleCompaction`).",
            "On a model ID it doesn't recognise (such as a gateway alias) it compacts at the window it assumes for that ID; correct it with `CLAUDE_CODE_MAX_CONTEXT_TOKENS`.",
            "Subagents compact independently as their own context fills."
          ]
        },
        "threshold": {
          "status": "supported",
          "answer": "Set the auto-compact window (100K to 1M tokens, capped at the model's window) with `/autocompact 500k` (saved per model under `modelSettings`), `\"autoCompactWindow\": 500000` in settings for every model, `claude --autocompact <size>` for one launch, or `CLAUDE_CODE_AUTO_COMPACT_WINDOW=500000`, which overrides all the others; `/autocompact auto` returns to the default. `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` (1-100) can only lower the trigger percentage. Turn automatic compaction off with the Auto-compact toggle in `/config` (`autoCompactEnabled: false`) or `DISABLE_AUTO_COMPACT=1`, and all compaction including `/compact` with `DISABLE_COMPACT=1`.",
          "reference": "https://code.claude.com/docs/en/model-config#set-the-auto-compact-window",
          "evidence": [
            "compaction-claude-code-code-claude-com-docs-en-model-config",
            "memory-claude-code-code-claude-com-docs-en-settings-reference",
            "compaction-3",
            "claude-subagents-docs"
          ],
          "notes": [
            "The environment variable only accepts a plain integer; `500k` is read as 500 and clamped to 100K.",
            "A subagent can compact earlier with `autoCompactWindow` in its frontmatter (v2.1.296+).",
            "Turning auto-compact off also turns off idle compaction; set `idleCompaction: false` to disable only the idle pass."
          ]
        },
        "manual": {
          "status": "supported",
          "answer": "Run `/compact`, optionally with focus instructions such as `/compact focus on the auth bug fix`. To compact only part of the conversation, open `/rewind`, pick a message and choose Summarize from here or Summarize up to here, optionally typing guidance for the summary.",
          "reference": "https://code.claude.com/docs/en/context-window#when-your-context-fills-up",
          "evidence": [
            "instructions-claude-code-code-claude-com-docs-en-context-window",
            "claude-commands-docs",
            "steering-claude-code-docs-en-checkpointing"
          ]
        },
        "check": {
          "status": "supported",
          "answer": "Run `/context` for a live breakdown of what fills the window (system prompt, tools, memory files, messages), including a warning when you are past the limit. For a constant readout, configure a status line that shows `context_window.used_percentage`; `/usage` also warns as you approach the auto-compact window.",
          "reference": "https://code.claude.com/docs/en/context-window#check-your-own-session",
          "evidence": [
            "instructions-claude-code-code-claude-com-docs-en-context-window",
            "compaction-claude-code-code-claude-com-docs-en-statusline",
            "claude-commands-docs"
          ],
          "notes": [
            "The status line percentage is measured against the model's full window, so it no longer shows when compaction will run once you set a smaller auto-compact window."
          ]
        },
        "what": {
          "status": "supported",
          "answer": "Claude Code sends a separate request to the session's model with the same system prompt, tools and history plus a summarisation instruction, and replaces the message history with the structured summary it returns (you see \"Conversation compacted\"). The request inherits the session's extended-thinking setting and uses your fallback model chain, but never falls back to a model with a smaller context window. Startup context such as CLAUDE.md and memory is then reloaded from disk around the summary.",
          "reference": "https://code.claude.com/docs/en/prompt-caching#compacting-the-conversation",
          "evidence": [
            "claude-prompt-caching-docs",
            "instructions-claude-code-code-claude-com-docs-en-context-window",
            "compaction-claude-code-code-claude-com-docs-en-model-config"
          ]
        },
        "keeps": {
          "status": "supported",
          "answer": "The system prompt and output style still apply; project-root CLAUDE.md, unscoped rules, auto memory and the plan-mode plan are re-injected from disk, and a fresh git status is read. Claude Code re-reads up to five recently modified files it read or edited (files over 5,000 tokens come back as a path only), re-injects invoked skill bodies capped at 5,000 tokens each and 25,000 total, keeps the task list, and reminds Claude of running background commands and subagents. Path-scoped rules and nested CLAUDE.md files are summarised away until a matching file is touched again, and the skill listing is not re-sent.",
          "reference": "https://code.claude.com/docs/en/context-window#what-survives-compaction",
          "evidence": [
            "instructions-claude-code-code-claude-com-docs-en-context-window",
            "claude-interactive-docs",
            "compaction-claude-code-code-claude-com-docs-en-hooks-guide"
          ],
          "notes": [
            "Recent turns are folded into the summary rather than kept verbatim, except in overflow recovery, which can keep the newest exchanges or your newest prompt word for word.",
            "Run `/reload-skills` to put the full skill list back after compaction."
          ]
        },
        "pruning": {
          "status": "supported",
          "answer": "Yes. As the context fills, Claude Code clears older tool outputs first and only summarises if that isn't enough, and when a request would exceed the image or PDF limits it drops a batch of the oldest images and PDFs. There is no setting to tune or disable this clearing.",
          "reference": "https://code.claude.com/docs/en/how-claude-code-works#when-context-fills-up",
          "evidence": [
            "compaction-claude-code-code-claude-com-docs-en-how-claude-code-works",
            "claude-prompt-caching-docs",
            "compaction-claude-code-code-claude-com-docs-en-statusline"
          ]
        },
        "custom": {
          "status": "supported",
          "answer": "Pass instructions to `/compact`, or add a `# Compact instructions` section to the project CLAUDE.md to steer every summary. Hooks: `PreCompact` (matcher `manual` or `auto`) receives the `/compact` instructions and can block compaction with exit code 2 or `{\"decision\":\"block\"}`; `PostCompact` receives the `compact_summary`; and a `SessionStart` hook with matcher `compact` adds its output to the compacted context. The built-in summary prompt itself cannot be replaced.",
          "reference": "https://code.claude.com/docs/en/hooks#precompact",
          "evidence": [
            "claude-hooks-docs",
            "compaction-claude-code-code-claude-com-docs-en-hooks-guide",
            "claude-costs-docs"
          ],
          "notes": [
            "Blocking an automatic compaction that was triggered to recover from an overflow makes the request fail with the original error."
          ]
        },
        "transcript": {
          "status": "supported",
          "answer": "Yes. The session JSONL in `~/.claude/projects/<project>/<session-id>.jsonl` keeps the earlier messages, with a `compact_boundary` entry recording the trigger and pre-compaction token count, and fullscreen mode keeps every earlier message in scrollback. To read the summary itself, use a `PostCompact` hook (`compact_summary`) or the Agent SDK's `compact_boundary` message stream.",
          "reference": "https://code.claude.com/docs/en/sessions#where-transcripts-are-stored",
          "evidence": [
            "claude-sessions-docs",
            "steering-claude-code-docs-en-checkpointing",
            "compaction-claude-code-code-claude-com-docs-en-fullscreen",
            "claude-subagents-docs",
            "claude-hooks-docs"
          ],
          "notes": [
            "With `CLAUDE_CODE_TRANSCRIPT_LOCAL_GC=1`, long `-p` and Agent SDK sessions drop pre-compaction history from transcripts over 5 MB.",
            "Transcripts are deleted after `cleanupPeriodDays` (30 days by default)."
          ]
        },
        "overflow": {
          "status": "supported",
          "answer": "If the API rejects a request as too long (`Prompt is too long`), Claude Code compacts the oldest exchanges and retries, compacting again with less recent history if needed, and as a last resort keeps only your newest prompt verbatim. If that fails, or auto-compact is off, you see `Context limit reached · /compact or /clear to continue`. If the context refills to the limit right after compacting several times, it stops with an `Autocompact is thrashing` error.",
          "reference": "https://code.claude.com/docs/en/errors#prompt-is-too-long",
          "evidence": [
            "memory-claude-code-code-claude-com-docs-en-errors",
            "compaction-claude-code-code-claude-com-docs-en-troubleshooting",
            "claude-hooks-docs",
            "compaction-claude-code-code-claude-com-docs-en-model-config"
          ],
          "notes": [
            "A single-exchange conversation can't be compacted; the error explains whether your content or the system prompt, tools and attachments fill the request.",
            "`CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1` makes unrecognised model IDs rely only on this overflow recovery."
          ]
        }
      },
      "observedVersion": "2.1.299"
    },
    {
      "harness": "codex",
      "variant": "1983c48f-source",
      "default": true,
      "verifiedAt": "2026-10-15",
      "evidence": [
        "compaction-7",
        "compaction-8",
        "compaction-9",
        "compaction-10",
        "compaction-11"
      ],
      "references": [
        "https://github.com/openai/codex/blob/1983c48fd186614529e4fad418ac38a1ae00c6b6/codex-rs/protocol/src/openai_models.rs#L525",
        "https://github.com/openai/codex/blob/1983c48fd186614529e4fad418ac38a1ae00c6b6/codex-rs/core/src/session/context_window.rs#L57",
        "https://github.com/openai/codex/blob/1983c48fd186614529e4fad418ac38a1ae00c6b6/codex-rs/core/src/session/turn.rs#L1296",
        "https://github.com/openai/codex/blob/1983c48fd186614529e4fad418ac38a1ae00c6b6/codex-rs/core/src/session/turn.rs#L1471",
        "https://github.com/openai/codex/blob/1983c48fd186614529e4fad418ac38a1ae00c6b6/codex-rs/core/src/compact.rs#L345"
      ],
      "support": {
        "automatic": "native",
        "manual": "native",
        "thresholdControl": "partial",
        "retentionControl": "partial",
        "overflowRecovery": "partial"
      },
      "method": "source-inspection",
      "surface": "cli",
      "conditions": [
        "Applies only to the recorded surface and evidence revision; source inspection does not establish released availability."
      ],
      "unknowns": [
        "No authenticated model request, runtime execution, or preservation probe was performed."
      ],
      "details": {},
      "sourceRevision": "1983c48fd186614529e4fad418ac38a1ae00c6b6",
      "counting": {
        "basis": "token status under total or body_after_prefix scope",
        "unit": "tokens",
        "included": [
          "total session token status or body growth after captured prefix",
          "usable full-context guard"
        ]
      },
      "trigger": {
        "comparison": ">=",
        "formula": "total: min(model/config limit, floor(W*0.9)); usable full-context guard still applies",
        "contextWindowMeaning": "context window recognized by the harness; independent of skill-listing budgets",
        "reserveTokens": null,
        "checks": ["before sampling", "continued work", "relevant model downshifts"]
      },
      "controls": [
        {
          "field": "model_auto_compact_token_limit",
          "location": "config.toml",
          "semantics": "model/config limit capped by total-scope ceiling"
        },
        {
          "field": "model_auto_compact_token_limit_scope",
          "location": "config.toml",
          "semantics": "total default; body_after_prefix measures growth after captured prefix"
        },
        {
          "field": "/compact",
          "location": "interactive",
          "semantics": "manual compaction"
        },
        {
          "field": "model_post_turn_compact_threshold_percent",
          "location": "config.toml",
          "semantics": "0-100, compacts after a final answer; off by default"
        }
      ],
      "retention": {
        "strategy": "token-budget reset, remote provider compaction, or local summarization; local path retains selected user content",
        "recentTokens": null,
        "transcriptPreserved": "unknown",
        "reloads": ["initial context depends on phase"]
      },
      "recovery": {
        "overflowRetry": "unknown",
        "automaticDisableScope": "no universal disable recipe established"
      },
      "answers": {
        "auto": {
          "status": "supported",
          "answer": "Yes. Before each turn, after each model step that needs a follow-up, and when you switch to a model with a smaller window, Codex compares the active context (the last reported input + output token count) to an auto-compact limit of 90% of the model's context window (or `model_auto_compact_token_limit` if lower) and compacts when it is reached; it also force-compacts at the usable window, 95% of the context window. For the bundled 272,000-token models that means compaction at about 244,800 tokens, with a hard ceiling at 258,400.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/protocol/src/openai_models.rs#L527-L538",
          "evidence": [
            "compaction-codex-codex-rs-protocol-src-openai-models-rs",
            "compaction-codex-codex-rs-core-src-session-context-window-rs",
            "steering-codex-codex-rs-core-src-session-turn-rs",
            "compaction-codex-codex-rs-models-manager-models-json"
          ],
          "notes": [
            "`model_post_turn_compact_threshold_percent` (default 0, off) adds an optional extra check after a final answer."
          ]
        },
        "threshold": {
          "status": "partial",
          "answer": "Set `model_auto_compact_token_limit` in `config.toml` to compact earlier; with the default `model_auto_compact_token_limit_scope = \"total\"` it is capped at 90% of the context window, while `\"body_after_prefix\"` counts only tokens added since the carried-over prefix. `model_post_turn_compact_threshold_percent` (0-100) also compacts after a final answer once that percentage of the usable window is used. There is no setting to turn automatic compaction off: the 95% usable-window guard always applies.",
          "reference": "https://learn.chatgpt.com/docs/config-file/config-reference#configtoml",
          "evidence": [
            "compaction-6",
            "instructions-codex-codex-rs-config-src-config-toml-rs",
            "compaction-codex-codex-rs-models-manager-src-model-info-rs",
            "compaction-codex-codex-rs-core-src-session-context-window-rs"
          ],
          "notes": [
            "`model_context_window` can raise the window up to the model's maximum (872,000 tokens for most bundled models), which moves both thresholds."
          ]
        },
        "manual": {
          "status": "partial",
          "answer": "Type `/compact` in the TUI (it can run even while a task is in progress). It takes no arguments, so you cannot tell a single `/compact` what to keep; persistent instructions only go through `compact_prompt`, which applies to local compaction only.",
          "reference": "https://learn.chatgpt.com/docs/cli/slash-commands#keep-transcripts-lean-with-compact",
          "evidence": [
            "compaction-codex-learn-chatgpt-com-docs-cli-slash-commands",
            "codex-slash-commands-source-0-162-1",
            "compaction-codex-codex-rs-core-src-tasks-compact-rs"
          ]
        },
        "check": {
          "status": "supported",
          "answer": "The TUI footer shows `NN% context left`, and `/status` shows `NN% left (used / window)`. You can add a context item to the footer with `/statusline`. The percentage treats the first 12,000 tokens as baseline and measures against the full context window, so it reaches 0% later than auto-compaction fires (90%).",
          "reference": "https://learn.chatgpt.com/docs/cli/slash-commands#inspect-the-session-with-status",
          "evidence": [
            "compaction-codex-learn-chatgpt-com-docs-cli-slash-commands",
            "instructions-codex-codex-rs-tui-src-status-card-rs",
            "compaction-codex-codex-rs-tui-src-token-usage-rs",
            "compaction-codex-codex-rs-tui-src-bottom-pane-footer-rs"
          ]
        },
        "what": {
          "status": "supported",
          "answer": "With OpenAI (and Azure Responses) providers, Codex uses remote compaction: it sends the history plus a compaction trigger through the Responses API, and the server-side model returns one encrypted `compaction` item. With other providers it runs locally: the current model gets the summarization prompt (or `compact_prompt`) and writes a handoff summary, which is stored as a user message beginning with a fixed \"Another language model started to solve this problem...\" prefix. Either way the history is replaced by retained user messages, freshly rebuilt initial context, and the summary or compaction item. After that Codex warns that long threads and repeated compactions reduce accuracy.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/core/src/session/turn.rs#L1472-L1505",
          "evidence": [
            "steering-codex-codex-rs-core-src-session-turn-rs",
            "compaction-codex-codex-rs-model-provider-src-capabilities-rs",
            "compaction-codex-codex-rs-core-src-compact-remote-v2-attempt-rs",
            "compaction-codex-codex-rs-core-src-compact-rs",
            "compaction-codex-codex-rs-prompts-templates-compact-prompt-md",
            "compaction-codex-codex-rs-prompts-templates-compact-summary-prefix-md",
            "compaction-6"
          ],
          "notes": [
            "Custom providers can choose with `model_providers.<id>.capabilities.remote_compaction = \"v2\"` or `\"unsupported\"`.",
            "With the `token_budget` feature enabled, compaction resets the context window without summarizing."
          ]
        },
        "keeps": {
          "status": "partial",
          "answer": "Codex rebuilds the initial context after compaction: base and developer instructions, `AGENTS.md`, environment and permissions context, and the skills and plugins catalog. Local compaction keeps your most recent user messages, up to about 20,000 tokens. Remote compaction keeps your user messages and short non-final sub-agent messages (each up to 10,000 tokens), up to about 64,000 tokens total, newest first. Assistant replies, tool calls and tool outputs are dropped and survive only through the summary.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/core/src/compact.rs#L79-L111",
          "evidence": [
            "compaction-codex-codex-rs-core-src-compact-rs",
            "compaction-codex-codex-rs-core-src-compact-remote-v2-rs",
            "steering-codex-codex-rs-core-src-session-mod-rs"
          ],
          "notes": [
            "Images in retained messages may be dropped (only their text is kept) when the token budget is exceeded."
          ]
        },
        "pruning": {
          "status": "partial",
          "answer": "Yes, separately from compaction: each tool or function output is truncated when it is stored in history, to 10,000 tokens by default for bundled models. You can change this with `tool_output_token_limit` (or per MCP tool with `mcp_servers.<id>.tools.<tool>.output_token_limit`). Before remote compaction, Codex also shortens old function-call outputs if needed so the request fits the window. There is no separate setting to prune old turns.",
          "reference": "https://learn.chatgpt.com/docs/config-file/config-reference#configtoml",
          "evidence": [
            "compaction-6",
            "compaction-codex-codex-rs-models-manager-src-model-info-rs",
            "instructions-codex-codex-rs-config-src-config-toml-rs",
            "compaction-codex-codex-rs-core-src-compact-remote-v2-attempt-rs",
            "compaction-codex-codex-rs-models-manager-models-json"
          ]
        },
        "custom": {
          "status": "supported",
          "answer": "Set `compact_prompt` (inline) or `experimental_compact_prompt_file` (a file path) in `config.toml` to replace the summarization prompt; the inline value wins, and both apply only to local compaction. `PreCompact` and `PostCompact` hooks run around both manual and auto compaction (matcher on `trigger`: `manual` or `auto`). A hook returning `continue: false` stops the turn, but it cannot change the summary.",
          "reference": "https://learn.chatgpt.com/docs/hooks#precompact",
          "evidence": [
            "codex-hooks-docs",
            "compaction-6",
            "delegation-codex-codex-rs-core-src-config-mod-rs",
            "compaction-codex-codex-rs-core-src-compact-rs",
            "compaction-codex-codex-rs-hooks-src-events-compact-rs"
          ]
        },
        "transcript": {
          "status": "supported",
          "answer": "Yes. The session rollout under `~/.codex/sessions/` is append-only: compaction adds a `compacted` record with the replacement history (and, for local compaction, the summary text in `message`) after the original turns, which remain. Remote compaction summaries are encrypted, so you cannot read them; `codex resume` restarts from the latest compaction point.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/core/src/session/mod.rs#L4083-L4113",
          "evidence": [
            "steering-codex-codex-rs-core-src-session-mod-rs",
            "compaction-codex-codex-rs-core-src-compact-remote-v2-rs",
            "transcripts-codex-codex-rs-protocol-src-models-rs",
            "compaction-codex-codex-rs-core-src-session-rollout-reconstruction-rs"
          ]
        },
        "overflow": {
          "status": "partial",
          "answer": "If a normal request still overflows, the turn ends with \"Codex ran out of room in the model's context window. Start a new thread or clear earlier history before retrying.\" Codex then marks the context as full, so the next turn compacts before sending, but it does not retry the failed request. If the compaction request itself overflows during local compaction, Codex drops the oldest history items one at a time and retries.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/core/src/session/turn.rs#L1687-L1691",
          "evidence": [
            "steering-codex-codex-rs-core-src-session-turn-rs",
            "compaction-codex-codex-rs-protocol-src-error-rs",
            "steering-codex-codex-rs-core-src-session-mod-rs",
            "compaction-codex-codex-rs-core-src-compact-rs"
          ],
          "notes": [
            "Codex compacts and retries in the same turn only for Guardian auto-review sessions whose review budget is exhausted."
          ]
        }
      },
      "observedVersion": "0.162.1"
    },
    {
      "harness": "cursor-agent",
      "variant": "2026-10-09-cli-docs",
      "default": true,
      "verifiedAt": "2026-10-15",
      "evidence": ["compaction-12", "compaction-14", "compaction-cursor-context-usage"],
      "references": [
        "https://cursor.com/docs/cli/reference/slash-commands",
        "https://cursor.com/docs/hooks#precompact",
        "https://cursor.com/docs/agent/prompting#context-usage"
      ],
      "support": {
        "automatic": "native",
        "manual": "native",
        "thresholdControl": "unsupported",
        "retentionControl": "unsupported",
        "overflowRecovery": "native"
      },
      "method": "documentation",
      "surface": "cli",
      "conditions": ["Documentation snapshot; no runtime compaction or preservation probe."],
      "unknowns": [
        "No authenticated model request, runtime execution, or preservation probe was performed."
      ],
      "details": {},
      "counting": {
        "basis": "unknown",
        "unit": "tokens",
        "included": ["unknown"]
      },
      "trigger": {
        "comparison": "unknown",
        "formula": "unknown",
        "contextWindowMeaning": "context window recognized by the harness; independent of skill-listing budgets",
        "reserveTokens": null,
        "checks": ["unknown"]
      },
      "controls": [
        {
          "field": "/summarize",
          "location": "interactive",
          "semantics": "manual summarization; /compress alias"
        },
        {
          "field": "/summarize (aliases /compress, /compact)",
          "location": "interactive",
          "semantics": "manual compaction; takes no instructions"
        },
        {
          "field": "/context",
          "location": "interactive",
          "semantics": "context usage breakdown"
        },
        {
          "field": "preCompact",
          "location": "hooks",
          "semantics": "observe-only hook before compaction"
        }
      ],
      "retention": {
        "strategy": "CLI retention unknown; editor documentation is separate",
        "recentTokens": null,
        "transcriptPreserved": true,
        "reloads": []
      },
      "recovery": {
        "overflowRetry": true,
        "automaticDisableScope": "unknown"
      },
      "answers": {
        "auto": {
          "status": "supported",
          "answer": "Yes. When a chat's context window gets close to full, Cursor summarizes older parts of the conversation to make room, and this also happens partway through long tool-calling turns. Cursor does not publish the exact trigger percentage or token count. Its servers decide when to compact, and the `preCompact` hook reports the current `context_usage_percent`, `context_tokens` and `context_window_size` each time it happens.",
          "reference": "https://cursor.com/docs/agent/prompting#context-usage",
          "evidence": [
            "compaction-cursor-agent-cursor-com-docs-agent-prompting",
            "cursor-hooks-docs",
            "cursor-cli-changelog"
          ],
          "notes": [
            "The `preCompact` example payload (85%, 120000 of 128000 tokens) is only an illustration, not the threshold."
          ]
        },
        "threshold": {
          "status": "unsupported",
          "answer": "No. There is no setting, flag or environment variable to change when automatic summarization triggers or to turn it off. The only lever is a bigger window: pick a larger-context model variant in `/model` or with `--model 'model[context=1m]'`, or use `/max-mode` on legacy request-based plans.",
          "reference": "https://cursor.com/docs/cli/reference/configuration#file-location",
          "evidence": [
            "transcripts-cursor-agent-cursor-com-docs-cli-reference-configuration",
            "compaction-cursor-agent-cursor-com-docs-models-and-pricing",
            "cursor-cli-changelog"
          ]
        },
        "manual": {
          "status": "supported",
          "answer": "Run `/summarize` in an interactive session to summarize the conversation and free up context. `/compress` and `/compact` are aliases. The command takes no instructions, so you can't tell it what to keep, and it says `No active session.` if the chat has no turns yet.",
          "reference": "https://cursor.com/docs/cli/using#selecting-context",
          "evidence": ["cursor-cli-using-docs", "cursor-cli-changelog"]
        },
        "check": {
          "status": "supported",
          "answer": "The prompt bar footer shows how full the context window is as a percentage (set `AGENT_CLI_HIDE_PROMPT_BAR=true` to hide the bar). Run `/context` for a breakdown by category: system prompt, tools, rules, skills, MCP, subagents, summarized conversation and conversation. The `/context` command isn't in the slash-command reference table, but it's covered in the CLI changelog and present in CLI 2026.10.12.",
          "reference": "https://cursor.com/docs/cli/changelog#jun-9-2026-commands",
          "evidence": [
            "cursor-cli-changelog",
            "compaction-cursor-agent-cursor-com-docs-agent-prompting"
          ]
        },
        "what": {
          "status": "partial",
          "answer": "Cursor's backend writes the summary, not your local CLI. The CLI sends a summarize action and shows `Summarizing` while it runs. Older messages are replaced by a summary that counts as 'Summarized conversation' in the context breakdown, and your latest message is kept word for word. Cursor doesn't document which model writes the summary, and for teams that don't allow data storage, summarization fails rather than storing data.",
          "reference": "https://cursor.com/docs/agent/prompting#context-usage",
          "evidence": [
            "compaction-cursor-agent-cursor-com-docs-agent-prompting",
            "cursor-cli-changelog"
          ]
        },
        "keeps": {
          "status": "partial",
          "answer": "The system prompt, tool definitions, rules, skills, MCP instructions and subagent docs are counted separately from the conversation, so summarization doesn't touch them. Since September 2026 your most recent message is kept word for word after summarization. In CLI 2026.10.12 the session also stores todos, plans and invoked skill blocks outside the summarized turns. Cursor doesn't document exactly how many recent turns or files are kept.",
          "reference": "https://cursor.com/docs/cli/changelog#sep-22-2026-fixes",
          "evidence": [
            "cursor-cli-changelog",
            "compaction-cursor-agent-cursor-com-docs-agent-prompting"
          ]
        },
        "pruning": {
          "status": "unknown",
          "answer": "Cursor doesn't describe any separate step that trims old tool outputs without summarizing, and there is no setting to control one. The only documented ways to free context are automatic summarization and `/summarize`.",
          "reference": "https://cursor.com/docs/agent/prompting#context-usage",
          "evidence": ["compaction-cursor-agent-cursor-com-docs-agent-prompting"]
        },
        "custom": {
          "status": "partial",
          "answer": "You can't change the summary prompt. A `preCompact` hook in `hooks.json` runs before every compaction and receives `trigger` (`auto` or `manual`), usage numbers and `messages_to_compact`. It can only observe: it can return a `user_message` to show you, but it can't block or change the compaction. A Claude Code `PreCompact` hook is mapped to `preCompact`. There is no post-compaction hook.",
          "reference": "https://cursor.com/docs/hooks#precompact",
          "evidence": [
            "cursor-hooks-docs",
            "compaction-cursor-agent-cursor-com-docs-reference-third-party-hooks"
          ]
        },
        "transcript": {
          "status": "supported",
          "answer": "Yes. Each chat's `~/.cursor/chats/<hash>/<chatId>/store.db` keeps summary archives that hold the messages that were summarized, and a JSONL copy is written to `~/.cursor/projects/<slug>/agent-transcripts/<chatId>/`. After summarizing, the CLI shows the summary in a cyan `Summary` box in the chat. If summarization fails or you press Stop during it, the earlier conversation is kept.",
          "reference": "https://cursor.com/docs/cli/changelog#sep-22-2026-fixes",
          "evidence": ["cursor-cli-changelog", "cursor-hooks-docs"],
          "notes": ["The `store.db` and JSONL formats are internal and undocumented."]
        },
        "overflow": {
          "status": "supported",
          "answer": "Since v2026.10.08, a session that hits the context limit summarizes and then continues the turn instead of getting stuck. An earlier fix (v2026.09.15) stopped long Claude and GPT turns from re-compacting on every step without freeing any space.",
          "reference": "https://cursor.com/docs/cli/changelog#oct-8-2026-fixes",
          "evidence": ["cursor-cli-changelog"]
        }
      },
      "observedVersion": "2026.10.12-d47ca18"
    },
    {
      "harness": "opencode",
      "variant": "1.x",
      "default": false,
      "verifiedAt": "2026-10-15",
      "evidence": ["compaction-16", "compaction-17"],
      "references": [
        "https://github.com/anomalyco/opencode/blob/v1.18.33/packages/opencode/src/session/overflow.ts#L7",
        "https://github.com/anomalyco/opencode/blob/v1.18.33/packages/opencode/src/session/compaction.ts#L206"
      ],
      "support": {
        "automatic": "native",
        "manual": "native",
        "thresholdControl": "native",
        "retentionControl": "native",
        "overflowRecovery": "native"
      },
      "method": "source-inspection",
      "surface": "cli",
      "conditions": ["Pinned v1.18.33 source inspection; no runtime overflow or retention probe."],
      "unknowns": [
        "No authenticated model request, runtime execution, or preservation probe was performed."
      ],
      "details": {},
      "counting": {
        "basis": "reported total; fallback input+output+cache read+cache write",
        "unit": "tokens",
        "included": ["input", "output", "cache read", "cache write"]
      },
      "trigger": {
        "comparison": ">=",
        "formula": "with input limit: max(0,inputLimit-reserved), reserve default min(20000,maxOutput); otherwise max(0,W-maxOutput) ignoring reserved",
        "contextWindowMeaning": "context window recognized by the harness; independent of skill-listing budgets",
        "reserveTokens": null,
        "checks": ["pre-request check", "mid-stream finish-step check"]
      },
      "controls": [
        {
          "field": "compaction.auto",
          "location": "opencode config",
          "semantics": "false disables automatic checks"
        },
        {
          "field": "compaction.reserved",
          "location": "opencode config",
          "semantics": "input-limit branch buffer; documentation example is not a default"
        },
        {
          "field": "compaction.prune",
          "location": "opencode config",
          "semantics": "pruning defaults off"
        },
        {
          "field": "compaction.preserve_recent_tokens",
          "location": "opencode config",
          "semantics": "default clamp(25% of usable window, 2000, 15000)"
        },
        {
          "field": "compaction.tail_turns",
          "location": "opencode config",
          "semantics": "recent turns kept verbatim"
        },
        {
          "field": "OPENCODE_DISABLE_AUTOCOMPACT",
          "location": "environment",
          "semantics": "disables automatic compaction"
        },
        {
          "field": "OPENCODE_DISABLE_PRUNE",
          "location": "environment",
          "semantics": "disables tool-output pruning"
        }
      ],
      "retention": {
        "strategy": "recent tail selected by estimated budget/turn constraints",
        "recentTokens": null,
        "transcriptPreserved": true,
        "reloads": []
      },
      "recovery": {
        "overflowRetry": true,
        "automaticDisableScope": "automatic-and-overflow"
      },
      "clientVersion": "1.18.33",
      "sourceRevision": "v1.18.33",
      "answers": {
        "auto": {
          "status": "supported",
          "answer": "Yes. After each model step OpenCode adds up the provider-reported tokens (total, or input + output + cache read + cache write) and compacts once that count reaches the usable window. If the model has a separate input limit, the usable window is the input limit minus `compaction.reserved` (default: the smaller of 20,000 and the model's max output). Otherwise it is the context window minus the max output, which is capped at 32,000 by default.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/overflow.ts#L8-L34",
          "evidence": [
            "compaction-opencode-packages-opencode-src-session-overflow-ts",
            "compaction-opencode-packages-opencode-src-session-processor-ts",
            "steering-opencode-packages-opencode-src-session-prompt-ts",
            "compaction-opencode-packages-opencode-src-provider-transform-ts",
            "instructions-opencode-opencode-ai-docs-config"
          ],
          "notes": [
            "The check also runs mid-turn after every step, so a long tool loop is stopped and compacted before it continues.",
            "Models that report a context limit of 0 are never auto-compacted."
          ]
        },
        "threshold": {
          "status": "supported",
          "answer": "Set `\"compaction\": { \"auto\": false }` in `opencode.json`, or set `OPENCODE_DISABLE_AUTOCOMPACT=1`, to turn auto-compaction off. You can make it trigger earlier with `compaction.reserved`, a token buffer subtracted from the model's input limit. There is no percentage setting.",
          "reference": "https://opencode.ai/docs/config/#compaction",
          "evidence": [
            "instructions-opencode-opencode-ai-docs-config",
            "opencode-cli-stable-docs",
            "instructions-opencode-packages-opencode-src-config-config-ts",
            "mcp-opencode-packages-core-src-v1-config-config-ts",
            "compaction-opencode-packages-opencode-src-session-overflow-ts"
          ],
          "notes": [
            "`reserved` only applies to models that publish a separate input limit. For other models the trigger is always the context window minus the max output tokens.",
            "With auto off, a request that overflows the context fails with an error instead of compacting."
          ]
        },
        "manual": {
          "status": "partial",
          "answer": "Type `/compact` (alias `/summarize`) or press `ctrl+x c` (leader `c`) in the TUI. The command takes no instructions, so you can't tell a single run what to keep. Use a plugin's `experimental.session.compacting` hook or the `tail_turns` / `preserve_recent_tokens` settings to steer every compaction instead.",
          "reference": "https://opencode.ai/docs/tui/#compact",
          "evidence": [
            "opencode-tui-docs",
            "compaction-opencode-packages-tui-src-routes-session-index-tsx",
            "delegation-opencode-packages-tui-src-config-keybind-ts"
          ]
        },
        "check": {
          "status": "supported",
          "answer": "The TUI prompt footer shows the last turn's tokens and the percentage of the model's context window, for example `45,000 (23%)`. The sidebar's Context section shows tokens, `% used`, and cost. The percentage is measured against the full context window, so auto-compaction fires before it reaches 100%.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/tui/src/component/prompt/index.tsx#L265-L281",
          "evidence": [
            "compaction-opencode-packages-tui-src-component-prompt-index-tsx",
            "compaction-opencode-packages-tui-src-feature-plugins-sidebar-context-tsx"
          ]
        },
        "what": {
          "status": "supported",
          "answer": "A hidden `compaction` agent with all tools denied summarizes the older history into a fixed Markdown template (Objective, Important Details, Work State, Next Move, Relevant Files). It uses the session's current model unless you set `agent.compaction.model`. The summary is saved as an assistant message, and later requests send that summary plus a verbatim recent tail instead of the older messages. After an automatic compaction a synthetic \"Continue if you have next steps...\" message resumes the work.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/compaction.ts#L358-L448",
          "evidence": [
            "steering-opencode-packages-opencode-src-session-compaction-ts",
            "opencode-agents-docs",
            "delegation-opencode-packages-opencode-src-agent-agent-ts",
            "compaction-opencode-packages-core-src-session-compaction-ts",
            "steering-opencode-packages-opencode-src-session-message-v2-ts"
          ],
          "notes": [
            "Later compactions update the previous summary instead of starting from scratch."
          ]
        },
        "keeps": {
          "status": "supported",
          "answer": "Recent turns are kept verbatim within a budget of `compaction.preserve_recent_tokens`, which defaults to 25% of the usable window clamped between 2,000 and 15,000 tokens. You can also cap that tail at `compaction.tail_turns` user turns, and `tail_turns: 0` keeps none. Instruction files such as AGENTS.md and the system prompt are rebuilt on every request, so they are unaffected. Everything else survives only as far as the summary captures it.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/compaction.ts#L115-L120",
          "evidence": [
            "steering-opencode-packages-opencode-src-session-compaction-ts",
            "mcp-opencode-packages-core-src-v1-config-config-ts"
          ],
          "notes": [
            "The summary's input truncates each tool result to 2,000 characters and replaces attachments with a one-line placeholder."
          ]
        },
        "pruning": {
          "status": "supported",
          "answer": "Yes, optionally. With `compaction.prune: true` (off by default), at the end of each run OpenCode clears the output of completed tool calls older than the last two user turns, once the protected 40,000 tokens of recent tool output is exceeded and more than 20,000 tokens can be freed. Cleared outputs are replaced with `[Old tool result content cleared]`, and `skill` tool output is never pruned. `OPENCODE_DISABLE_PRUNE=1` forces pruning off.",
          "reference": "https://opencode.ai/docs/config/#compaction",
          "evidence": [
            "instructions-opencode-opencode-ai-docs-config",
            "steering-opencode-packages-opencode-src-session-compaction-ts",
            "opencode-cli-stable-docs",
            "steering-opencode-packages-opencode-src-session-prompt-ts"
          ]
        },
        "custom": {
          "status": "supported",
          "answer": "Plugins can use the `experimental.session.compacting` hook to append strings to `output.context` or replace the whole prompt via `output.prompt`. The `experimental.compaction.autocontinue` hook can set `enabled: false` to skip the automatic continue turn, and plugins can listen for the `session.compacted` event. You can also override the `compaction` agent's prompt or model in the `agent` config. There are no shell-command PreCompact or PostCompact hooks.",
          "reference": "https://opencode.ai/docs/plugins/#compaction-hooks",
          "evidence": [
            "opencode-plugins-docs",
            "steering-opencode-packages-plugin-src-index-ts",
            "steering-opencode-packages-opencode-src-session-compaction-ts"
          ],
          "notes": [
            "When `output.prompt` is set, the serialized conversation is still appended after your prompt."
          ]
        },
        "transcript": {
          "status": "supported",
          "answer": "Yes. Compaction only changes what is sent to the model. Every earlier message and part stays in the local SQLite database (`opencode.db` under OpenCode's data directory), and the TUI keeps showing the full scrollback. The summary is stored as a normal assistant message, so it appears in the session, and `opencode export <sessionID>` dumps everything as JSON.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/message-v2.ts#L534-L585",
          "evidence": [
            "steering-opencode-packages-opencode-src-session-message-v2-ts",
            "transcripts-opencode-packages-core-src-database-database-ts",
            "opencode-cli-stable-docs"
          ]
        },
        "overflow": {
          "status": "supported",
          "answer": "When the provider rejects a request as too long, OpenCode skips the normal retry, compacts the history before the last user message, then replays that message with media attachments replaced by text placeholders. If the history is too large to summarize, the turn ends with a ContextOverflowError. With `compaction.auto` off, the overflow error is shown instead.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/processor.ts#L614-L632",
          "evidence": [
            "compaction-opencode-packages-opencode-src-session-processor-ts",
            "steering-opencode-packages-opencode-src-session-prompt-ts",
            "steering-opencode-packages-opencode-src-session-compaction-ts",
            "compaction-opencode-packages-opencode-src-session-retry-ts"
          ]
        }
      },
      "observedVersion": "1.19.0"
    },
    {
      "harness": "opencode",
      "variant": "2.x",
      "default": true,
      "verifiedAt": "2026-10-15",
      "evidence": ["compaction-opencode-v2-settings"],
      "references": ["https://opencode.ai/v2/docs/compaction/#settings"],
      "support": {
        "automatic": "native",
        "manual": "native",
        "thresholdControl": "native",
        "retentionControl": "native",
        "overflowRecovery": "native"
      },
      "method": "documentation",
      "surface": "cli",
      "conditions": ["Documentation snapshot; no runtime compaction or preservation probe."],
      "unknowns": [
        "No authenticated model request, runtime execution, or preservation probe was performed."
      ],
      "details": {},
      "counting": {
        "basis": "provider-reported tokens of the last response plus a chars/4 estimate of messages added since (images 1,500, PDFs 2,000); full estimate only when nothing was measured",
        "unit": "tokens",
        "included": ["input", "cache read", "cache write", "output", "reasoning"]
      },
      "trigger": {
        "comparison": ">=",
        "formula": "estimate >= window - buffer; window = input limit or context limit; buffer default max(10% of window, 16000)",
        "contextWindowMeaning": "context window recognized by the harness; independent of skill-listing budgets",
        "reserveTokens": null,
        "checks": ["preflight", "provider overflow"]
      },
      "controls": [
        {
          "field": "compaction.auto",
          "location": "opencode config",
          "semantics": "false disables automatic and overflow compaction; only manual remains"
        },
        {
          "field": "compaction.buffer",
          "location": "opencode config",
          "semantics": "default max(10% of window, 16000)"
        },
        {
          "field": "compaction.keep.tokens",
          "location": "opencode config",
          "semantics": "default 15000 of recent context kept beside the summary"
        },
        {
          "field": "compaction.prune",
          "location": "opencode config",
          "semantics": "ignored with an unsupported warning in V2"
        },
        {
          "field": "settings.compaction.type",
          "location": "opencode config",
          "semantics": "native or summary; native uses provider compaction for OpenAI Responses models"
        }
      ],
      "retention": {
        "strategy": "checkpoint summary plus recent tail; tool output in the tail truncated at 1,250 characters",
        "recentTokens": 15000,
        "transcriptPreserved": true,
        "reloads": []
      },
      "recovery": {
        "overflowRetry": true,
        "automaticDisableScope": "automatic-and-overflow"
      },
      "answers": {
        "auto": {
          "status": "supported",
          "answer": "Yes. Before each model step OpenCode estimates the prompt size and compacts when it reaches the window minus a buffer. The estimate is the provider-reported tokens from the last response plus about 4 characters per token for anything added since. The default buffer is 10% of the window or 16,000 tokens, whichever is larger (models under 32k keep just 10%). The window is the model's input limit if it has one, otherwise its context limit.",
          "reference": "https://opencode.ai/v2/docs/compaction/#how-it-works",
          "evidence": [
            "transcripts-opencode-opencode-ai-v2-docs-compaction",
            "compaction-opencode-packages-core-src-session-compaction-ts",
            "steering-opencode-packages-core-src-session-runner-llm-ts"
          ],
          "notes": [
            "Models with an unknown window never auto-compact; only a provider rejection triggers it."
          ]
        },
        "threshold": {
          "status": "supported",
          "answer": "Set `compaction.buffer` to the number of tokens to keep free below the limit; a larger buffer compacts earlier. Set `\"compaction\": { \"auto\": false }` to turn automatic compaction off. Manual compaction still works when it is off.",
          "reference": "https://opencode.ai/v2/docs/compaction/#settings",
          "evidence": [
            "transcripts-opencode-opencode-ai-v2-docs-compaction",
            "compaction-opencode-packages-schema-src-config-compaction-ts",
            "compaction-opencode-packages-core-src-session-compaction-ts"
          ],
          "notes": [
            "V2 has no `OPENCODE_DISABLE_AUTOCOMPACT` env var. V1's `reserved` becomes `buffer`."
          ]
        },
        "manual": {
          "status": "partial",
          "answer": "Type `/compact` or press the leader key then `c` in the TUI. You can also call `opencode api post /api/session/<id>/compact --data '{}'`, or `ctx.session.compact()` from a plugin. It runs at the next safe point, even for short histories. The command takes no instructions about what to keep; use `compaction.keep.tokens` or a plugin `compaction` hook instead.",
          "reference": "https://opencode.ai/v2/docs/compaction/#manual",
          "evidence": [
            "transcripts-opencode-opencode-ai-v2-docs-compaction",
            "steering-opencode-packages-tui-src-routes-session-index-tsx",
            "steering-opencode-packages-tui-src-config-keybind-ts"
          ],
          "notes": ["The V1 alias `/summarize` is not registered in the V2 TUI."]
        },
        "check": {
          "status": "supported",
          "answer": "The TUI prompt footer and the sidebar's Context section show the last response's tokens and the percentage of the model's context window, for example `45,000 (23%)`. Auto-compaction fires around 90% of the window (less on small models), so plan for compaction before 100%.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/tui/src/util/session.ts#L46-L66",
          "evidence": [
            "compaction-opencode-packages-tui-src-util-session-ts",
            "compaction-opencode-packages-tui-src-feature-plugins-sidebar-context-tsx"
          ]
        },
        "what": {
          "status": "supported",
          "answer": "OpenCode summarizes everything except the most recent conversation into a structured Markdown checkpoint (Objective, Requirements, Decisions, Work State, Next Move, Relevant Files, Important Context). It uses the session's model and asks once more if the reply misses the template. Later requests begin with one `<conversation-checkpoint>` message holding the summary plus the recent conversation as text, and later compactions update that checkpoint. With `settings.compaction: { \"type\": \"native\" }` on supported OpenAI Responses models, the provider returns an encrypted checkpoint instead.",
          "reference": "https://opencode.ai/v2/docs/compaction/#how-it-works",
          "evidence": [
            "transcripts-opencode-opencode-ai-v2-docs-compaction",
            "compaction-opencode-packages-core-src-session-compaction-ts"
          ],
          "notes": [
            "The docs say there is no separate compaction model, but the source does honor a model set on the hidden `compaction` agent."
          ]
        },
        "keeps": {
          "status": "supported",
          "answer": "About `compaction.keep.tokens` of the newest conversation is kept beside the summary (default 15,000), starting at a user-message boundary. In that kept part, tool output over 1,250 characters is shortened and attachments become one-line descriptions. Instruction files such as AGENTS.md are excluded from the summary and resent in their current version as the new baseline. Activated skill text is kept only if it falls inside the recent window.",
          "reference": "https://opencode.ai/v2/docs/compaction/#summaries",
          "evidence": [
            "transcripts-opencode-opencode-ai-v2-docs-compaction",
            "compaction-opencode-packages-core-src-session-compaction-ts"
          ]
        },
        "pruning": {
          "status": "unsupported",
          "answer": "No. V2 has no separate tool-output pruning. `compaction.prune` and `compaction.tail_turns` are ignored with a warning, and recent context is kept by token budget only. Tool output is shortened only inside the compaction checkpoint.",
          "reference": "https://opencode.ai/v2/docs/migrate-v1/#compaction",
          "evidence": [
            "instructions-opencode-opencode-ai-v2-docs-migrate-v1",
            "compaction-opencode-packages-core-src-config-normalize-ts",
            "transcripts-opencode-opencode-ai-v2-docs-compaction"
          ]
        },
        "custom": {
          "status": "supported",
          "answer": "Plugins can register `ctx.session.hook(\"compaction\", ...)` to edit the messages, system text, or options of the summary request. Setting `event.result = { summary }` supplies your own summary and skips the model call. Plugins can follow `session.compaction.started`, `delta`, `ended`, and `failed` events. The built-in summary prompt itself can't be changed in config, and there are no PreCompact or PostCompact shell hooks.",
          "reference": "https://opencode.ai/v2/docs/build/plugins/#model-requests",
          "evidence": [
            "opencode-v2-plugins-docs",
            "compaction-opencode-packages-core-src-session-compaction-ts"
          ],
          "notes": [
            "OpenCode appends its own summary prompt after the hooks run, so a hook cannot replace it except by supplying `result`."
          ]
        },
        "transcript": {
          "status": "supported",
          "answer": "Yes. Earlier messages stay stored even when they're no longer sent to the model. The checkpoint is recorded as a compaction message with the summary text and the kept recent text, and the TUI shows the compaction as it starts, streams, and ends.",
          "reference": "https://opencode.ai/v2/docs/compaction/#limits",
          "evidence": [
            "transcripts-opencode-opencode-ai-v2-docs-compaction",
            "compaction-opencode-packages-core-src-session-compaction-ts",
            "compaction-opencode-packages-tui-src-routes-session-rows-ts"
          ]
        },
        "overflow": {
          "status": "supported",
          "answer": "If the provider rejects a request as too long, OpenCode compacts, aiming at 70% of the rejected size, and retries once. A second rejection is returned as an error. If the summary request itself is too long, OpenCode sends a flattened text version and shrinks it to 70%, 50%, then 35%, dropping the oldest exchanges, before giving up. With `compaction.auto: false` it does not compact on overflow and returns the error.",
          "reference": "https://opencode.ai/v2/docs/compaction/#limits",
          "evidence": [
            "transcripts-opencode-opencode-ai-v2-docs-compaction",
            "steering-opencode-packages-core-src-session-runner-llm-ts",
            "compaction-opencode-packages-core-src-session-compaction-ts"
          ],
          "notes": [
            "The docs' Settings table says `auto` controls overflow recovery as well as preflight compaction, and the source agrees: auto=false skips both.",
            "In 2.0.29, output-token-limit (finish reason length) recovery is separate from context-overflow compaction: source adds continuation guidance and fails after three consecutive length-limited assistant responses (two continuations)."
          ]
        }
      },
      "observedVersion": "2.0.29"
    },
    {
      "harness": "pi",
      "variant": "v1.1.0-docs",
      "default": true,
      "verifiedAt": "2026-10-15",
      "evidence": ["compaction-19", "compaction-20"],
      "references": [
        "https://github.com/earendil-works/pi/blob/v1.1.0/packages/coding-agent/docs/compaction.md#when-it-triggers",
        "https://github.com/earendil-works/pi/blob/v1.1.0/packages/coding-agent/docs/compaction.md#settings"
      ],
      "support": {
        "automatic": "native",
        "manual": "native",
        "thresholdControl": "native",
        "retentionControl": "native",
        "overflowRecovery": "native"
      },
      "method": "documentation",
      "surface": "cli",
      "conditions": ["Documentation snapshot; no runtime compaction or preservation probe."],
      "unknowns": [
        "No authenticated model request, runtime execution, or preservation probe was performed."
      ],
      "details": {},
      "counting": {
        "basis": "reported context usage",
        "unit": "tokens",
        "included": [
          "reported context usage; request-field accounting follows pinned implementation"
        ]
      },
      "trigger": {
        "comparison": ">",
        "formula": "context > W-reserveTokens",
        "contextWindowMeaning": "context window recognized by the harness; independent of skill-listing budgets",
        "reserveTokens": 16384,
        "checks": ["before new prompts", "between continued assistant turns after tools"]
      },
      "controls": [
        {
          "field": "compaction.enabled",
          "location": "global/project settings",
          "semantics": "false disables automatic compaction; manual remains"
        },
        {
          "field": "compaction.reserveTokens",
          "location": "global/project and provider/modelId settings",
          "semantics": "default 16384"
        },
        {
          "field": "compaction.keepRecentTokens",
          "location": "global/project and provider/modelId settings",
          "semantics": "default 20000"
        },
        {
          "field": "compaction.modelOverrides",
          "location": "settings",
          "semantics": "per provider/modelId reserveTokens and keepRecentTokens"
        }
      ],
      "retention": {
        "strategy": "structured summary and approximate recent-token tail with boundary adjustments",
        "recentTokens": 20000,
        "transcriptPreserved": true,
        "reloads": []
      },
      "recovery": {
        "overflowRetry": true,
        "automaticDisableScope": "automatic-only"
      },
      "answers": {
        "auto": {
          "status": "supported",
          "answer": "Yes. Pi compacts automatically when `contextTokens > contextWindow - reserveTokens`, with `reserveTokens` defaulting to 16384 (so a 200K-token model compacts above roughly 183.6K tokens). Context is counted from the last valid assistant response's reported usage (`totalTokens`, or input + output + cache read + cache write) plus a chars/4 estimate for any messages added since. Pi checks before each new prompt, after a tool batch finishes and before the next assistant response in the same run, and again when the run ends.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/compaction.md#when-it-triggers",
          "evidence": [
            "compaction-pi-packages-coding-agent-docs-compaction-md",
            "compaction-pi-packages-coding-agent-src-core-compaction-compaction-ts",
            "steering-pi-packages-coding-agent-src-core-agent-session-ts"
          ],
          "notes": [
            "Right after a compaction, Pi ignores the old (pre-compaction) usage figures and estimates the rebuilt context from scratch until the next response arrives."
          ]
        },
        "threshold": {
          "status": "supported",
          "answer": "Set `compaction.reserveTokens` (default 16384) in `~/.pi/agent/settings.json` or `<project>/.pi/settings.json`; a larger reserve makes compaction happen earlier. Use `compaction.modelOverrides` keyed by exact `provider/modelId` to set a different `reserveTokens` or `keepRecentTokens` for one model. Turn auto-compaction off with `\"compaction\": { \"enabled\": false }` or the Auto-compact toggle in `/settings`. `/compact` still works when it is off.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/compaction.md#settings",
          "evidence": [
            "compaction-pi-packages-coding-agent-docs-compaction-md",
            "steering-pi-packages-coding-agent-docs-settings-md",
            "compaction-pi--agent-src-modes-interactive-components-settings-selector-ts"
          ],
          "notes": [
            "`compaction.enabled` applies to all models and cannot be overridden per model.",
            "Turning off auto-compaction also turns off automatic overflow recovery.",
            "`reserveTokens` also limits how long the summary can be: up to 80% of it, capped by the model's maximum output."
          ]
        },
        "manual": {
          "status": "supported",
          "answer": "Run `/compact`, or `/compact <instructions>` to tell the summary what to focus on. Pi adds your text to the summary prompt as `Additional focus: <instructions>`. In RPC mode, send `{\"type\":\"compact\",\"customInstructions\":\"...\"}`. Extensions can call `ctx.compact({ customInstructions })`.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/slash-commands.md#sessions-and-context",
          "evidence": [
            "instructions-pi-packages-coding-agent-docs-slash-commands-md",
            "compaction-pi-packages-coding-agent-src-core-compaction-compaction-ts",
            "steering-pi-packages-coding-agent-docs-rpc-commands-md",
            "steering-pi-packages-coding-agent-src-core-extensions-types-ts"
          ],
          "notes": [
            "`/compact` fails with \"Nothing to compact (session too small)\" or \"Already compacted\" when there is nothing to summarise."
          ]
        },
        "check": {
          "status": "supported",
          "answer": "The interactive footer shows context use as `<percent>%/<window>`, followed by `(auto)` when auto-compaction is on. The figure turns to a warning colour above 70% and an error colour above 90%, and shows `?` right after a compaction until the next response reports usage. `/session` shows session statistics; RPC `get_session_stats` and the extension call `ctx.getContextUsage()` return the same `contextUsage` estimate that compaction uses.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/modes/interactive/components/footer.ts#L159-L212",
          "evidence": [
            "compaction-pi-ages-coding-agent-src-modes-interactive-components-footer-ts",
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "steering-pi-packages-coding-agent-docs-rpc-commands-md",
            "steering-pi-packages-coding-agent-src-core-agent-session-ts"
          ]
        },
        "what": {
          "status": "supported",
          "answer": "Pi asks the current session model to write a structured checkpoint summary (Goal, Constraints & Preferences, Progress, Key Decisions, Next Steps, Critical Context, plus lists of files read and modified). It sends the older messages as serialized text with thinking blocks removed and each tool result cut to 2000 characters. Pi then appends a `compaction` entry, and later requests get the system prompt, then the summary, then the recent messages kept verbatim. On repeat compactions, the previous summary is updated rather than rewritten from scratch.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/compaction.md#how-it-works",
          "evidence": [
            "compaction-pi-packages-coding-agent-docs-compaction-md",
            "steering-pi-packages-coding-agent-src-core-agent-session-ts",
            "compaction-pi-packages-coding-agent-src-core-compaction-compaction-ts"
          ],
          "notes": [
            "When a single long user turn exceeds the kept budget, Pi writes two summaries (earlier history and the start of that turn) and merges them.",
            "An extension can supply the summary instead, using any model it likes."
          ]
        },
        "keeps": {
          "status": "supported",
          "answer": "The system prompt is kept in full: context files such as `AGENTS.md`, tool declarations and loaded skill descriptions. It is stored as a checkpoint in the compaction entry and replayed ahead of the summary. Roughly the last `compaction.keepRecentTokens` (default 20000) of messages stay verbatim; cuts never separate a tool result from its call. Everything older survives only as the summary, which carries forward cumulative `<read-files>` and `<modified-files>` lists. There is no separate todo or plan store to preserve.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#compactionentry",
          "evidence": [
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "compaction-pi-packages-coding-agent-docs-compaction-md",
            "memory-pi-packages-coding-agent-docs-sessions-md"
          ],
          "notes": [
            "Skill bodies the model loaded during the conversation are ordinary messages, so older ones are summarised like anything else.",
            "Extension state stored in session entries follows the session tree and survives compaction."
          ]
        },
        "pruning": {
          "status": "partial",
          "answer": "Pi does not prune or clear old tool outputs on its own. The only automatic trimming is that tool results are cut to 2000 characters inside the text sent for summarisation. Extensions can trim without summarising by appending `context_edit` entries, which omit or replace earlier messages in future requests while keeping them on disk, or by filtering messages in a `context` event handler.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#contexteditentry",
          "evidence": [
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "steering-pi-packages-coding-agent-docs-extensions-md",
            "compaction-pi-packages-coding-agent-src-core-compaction-utils-ts"
          ],
          "notes": [
            "During overflow recovery, Pi itself appends `context_edit` entries to drop the failed attempt from future context."
          ]
        },
        "custom": {
          "status": "supported",
          "answer": "Yes, through extensions. `session_before_compact` fires before manual, threshold and overflow compactions and can cancel or return your own `summary`, `firstKeptEntryId` and `details`. `session_compact` fires after success and `session_compact_failed` after a failure or abort. `session_before_tree` does the same for branch summaries. The built-in summary prompt cannot be changed by a setting; use `/compact <instructions>` or an extension.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/compaction.md#custom-summarization-via-extensions",
          "evidence": [
            "compaction-pi-packages-coding-agent-docs-compaction-md",
            "steering-pi-packages-coding-agent-src-core-extensions-types-ts",
            "compaction-pi-ckages-coding-agent-examples-extensions-custom-compaction-ts"
          ],
          "notes": [
            "The event payload includes `reason` (`manual`, `threshold` or `overflow`) and `willRetry`. JSON and RPC streams emit `compaction_start` and `compaction_end` events."
          ]
        },
        "transcript": {
          "status": "supported",
          "answer": "Yes. Sessions are append-only JSONL files under `~/.pi/agent/sessions/--<path>--/`, and compaction only appends a `compaction` entry. Every original message stays on disk and in `/tree`, `/export` and `/share`. The summary is stored in that entry's `summary` field and appears in the transcript as a collapsible block showing the token count before compaction; click it to expand.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/how-pi-works.md#sessions",
          "evidence": [
            "steering-pi-packages-coding-agent-docs-how-pi-works-md",
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "compaction-pi-c-modes-interactive-components-compaction-summary-message-ts"
          ]
        },
        "overflow": {
          "status": "supported",
          "answer": "If the provider returns a context-overflow error, or a response stops early with `stopReason: \"length\"`, Pi drops the failed attempt from context, compacts and retries once. A second failure shows \"Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.\" If a successful response pushes past the window, Pi compacts without retrying.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/compaction.md#overflow-and-length-recovery-ordering",
          "evidence": [
            "compaction-pi-packages-coding-agent-docs-compaction-md",
            "steering-pi-packages-coding-agent-src-core-agent-session-ts",
            "compaction-pi-packages-coding-agent-docs-custom-provider-md"
          ],
          "notes": [
            "Recovery is skipped when `compaction.enabled` is false, or when the error came from a different model than the one now selected.",
            "Custom providers with unusual overflow messages must map them to `context_length_exceeded` for recovery to trigger."
          ]
        }
      },
      "observedVersion": "1.2.0"
    }
  ]
}
