Skip to content
Back to skills

530 Core Compaction 76ab60bd

ASecurity

Context window management and tool output pruning

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added June 1, 2026
developmentpythongoreact

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned June 1, 2026

npx -y skills add tools-only/X-Skills --skill 530-core-compaction_76ab60bd --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 530 Core Compaction 76ab60bd?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 530 Core Compaction 76ab60bd
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-530-core-compaction-76ab60bd/badge)](https://www.skillsdirectory.com/skills/tools-only-530-core-compaction-76ab60bd)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
title: Core Compaction
path: src/tunacode/core/compaction.py
type: file
depth: 1
description: Context window management and tool output pruning
exports: [prune_old_tool_outputs, get_prune_thresholds, is_tool_return_part, count_user_turns, estimate_part_tokens, prune_part_content]
seams: [M]
---

# Core Compaction

## Purpose

Manages context window limits by pruning old tool outputs from conversation history while preserving recent context. Uses a backward-scanning algorithm to identify and replace old tool outputs with placeholders.

## When Pruning Occurs

Pruning is triggered **proactively** at the start of each agent request, before the agent iteration loop begins:

```
Location: core/agents/main.py:367-372
```

```python
# In RequestOrchestrator._run_impl()
session_messages = self.state_manager.session.conversation.messages
_, tokens_reclaimed = prune_old_tool_outputs(session_messages, self.model)
message_history = list(session_messages)
```

This ensures context is compacted before sending to the provider, not reactively after overflow.

## Pruning Algorithm

The `prune_old_tool_outputs()` function at lines 160-238 implements a 4-phase algorithm:

### Phase 1: Backward Scanning (lines 187-204)

Iterates through messages **newest to oldest**:
- Identifies tool return parts using `is_tool_return_part()`
- Estimates token count for each using `estimate_part_tokens()`
- Builds list of `(message_index, part_index, part, token_count)` tuples

### Phase 2: Protection Boundary (lines 209-221)

Determines which outputs to protect:
- Accumulates tokens from newest to oldest
- When accumulated tokens exceed `protect_tokens` threshold, marks pruning boundary
- All outputs within protection window remain untouched

### Phase 3: Threshold Check (lines 223-229)

Validates pruning is worthwhile:
- Calculates total tokens reclaimable from old outputs
- Only proceeds if savings exceed `minimum_threshold`
- Prevents unnecessary work for minimal gains

### Phase 4: Content Replacement (lines 231-236)

Performs in-place mutation:
- Replaces old tool output content with placeholder
- Uses `prune_part_content()` for safe mutation
- Returns total tokens reclaimed

## Key Functions

### prune_old_tool_outputs(messages, model)

Main entry point. Returns `(pruned_count, tokens_reclaimed)`.

### get_prune_thresholds()

Returns `(protect_tokens, minimum_threshold)`.

### is_tool_return_part(part)

Returns `True` if part has `part_kind == "tool-return"`.

### count_user_turns(messages)

Counts user messages. Pruning requires `>= 2` user turns (`PRUNE_MIN_USER_TURNS`).

### estimate_part_tokens(part)

Estimates tokens in a message part using 4-char heuristic.

### prune_part_content(part)

Replaces part content with placeholder. Returns tokens reclaimed or 0 if immutable.

## Safety Guards

| Guard | Location | Purpose |
|-------|----------|---------|
| Min user turns | line 183-185 | Requires 2+ turns before pruning |
| Immutability handling | line 151-156 | Gracefully handles frozen parts |
| Already-pruned check | line 138-139 | Skips parts with placeholder |
| Empty messages | line 179-180 | Early return for empty list |

## Pruning Thresholds

| Mode | protect_tokens | minimum_threshold | Behavior |
|------|----------------|-------------------|----------|
| Standard | 40,000 | 20,000 | Keep ~40k recent tokens |

Thresholds are defined at lines 14-18 and are not user-configurable.

## Placeholder

Pruned content is replaced with:

```
[Old tool result content cleared]
```

Defined as `PRUNE_PLACEHOLDER` at line 21.

## What Gets Pruned

**Targets:**
- Tool return parts (`part_kind == "tool-return"`)
- Content older than protection window

**Never Pruned:**
- User messages
- Recent tool outputs (within protection window)
- System prompts
- Tool call requests (only returns are pruned)

## Integration Points

| Component | File | Integration |
|-----------|------|-------------|
| Trigger point | `core/agents/main.py` | Called at request start |
| Token counting | `utils/messaging` | `estimate_tokens()` |
| Message types | `pydantic_ai` | `ToolReturnPart`, `ModelRequest` |
| State | `core/state.py` | `session.conversation.messages` storage |

## Constants

```python
PRUNE_PROTECT_TOKENS = 40_000
PRUNE_MINIMUM_THRESHOLD = 20_000
PRUNE_MIN_USER_TURNS = 2
PRUNE_PLACEHOLDER = "[Old tool result content cleared]"
```

## Seams (M)

**Modification Points:**
- Adjust thresholds in constants (lines 14-18)
- Customize placeholder format (line 21)
- Add selective preservation rules in phase 2
- Implement content-aware pruning (e.g., preserve error messages)

Files in this skill

  • README.md1 KB
  • skill.md4.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.