Skip to content

fix(trajectory_compressor): fix inverted compressible region on short trajectories - #7248

Open
mztteo wants to merge 1 commit into
NousResearch:mainfrom
mztteo:patch-1
Open

fix(trajectory_compressor): fix inverted compressible region on short trajectories#7248
mztteo wants to merge 1 commit into
NousResearch:mainfrom
mztteo:patch-1

Conversation

@mztteo

@mztteo mztteo commented Apr 10, 2026

Copy link
Copy Markdown

Problem

_find_protected_indices used an n // 2 heuristic to split protected indices
into head/tail buckets:

head_protected = [i for i in protected if i < n // 2]
tail_protected = [i for i in protected if i >= n // 2]

On short trajectories this produces a wrong compressible window:

Example — 8 turns, protect_last_n=5:

  • first_tool is at index 3, which is < 8 // 2 = 4 → goes into head_protected
  • tail_start = 8 - 5 = 3
  • compressible_start = 3 + 1 = 4
  • compressible_end = min(tail_protected) = 3
  • Result: compressible_end (3) < compressible_start (4) → the region is inverted

The code then hits the early-return guard (compress_start >= compress_end) and
returns the trajectory unchanged, setting still_over_limit = True silently.
Over-budget short trajectories are never compressed.

Fix

Track head-protected indices in a dedicated set during the protect-first-turns
loop, and derive compressible_start from that set directly. Use the explicit
tail_start variable for compressible_end. Add a final clamp to guarantee
compressible_end >= compressible_start for all inputs including empty trajectories.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels Apr 29, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for identifying the midpoint-based boundary bug. Current main still uses the positional n // 2 split in trajectory_compressor.py:517-521, so tracking head protection separately is a useful fix for late first-tool trajectories.

Problems

  • The stated 8-turn / protect_last_n_turns=5 example remains non-compressible after this patch: the proposed head boundary is 4 and tail_start is 3, so the clamp produces an empty [4, 4) window. The sync and async paths then return unchanged at trajectory_compressor.py:789-794 and trajectory_compressor.py:912-916. Those turns are all protected, so this should be framed as an overlap case rather than a missed compression opportunity.
  • The PR changes only trajectory_compressor.py; it adds no regression coverage. Existing boundary tests end at tests/test_trajectory_compressor.py:403. Linked duplicate PR fix(research): split compressor protected turns by role, not midpoint #50411 contains targeted late-first-tool and protected-window-invariant tests that fit this change.

Suggested changes

  • Reframe the bug around the verified late-first-tool misclassification and add those focused regression tests.
  • Preserve current _snap_boundary handling when salvaging the boundary change.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users area/compression Context compression and continuation sessions labels Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/compression Context compression and continuation sessions comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants