From 8b7b074df9506d512b80ab6855f9773041314e0e Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Thu, 30 Apr 2026 19:59:36 -0700 Subject: [PATCH] test(context_compressor): regression test for PR #17025 tail-protection off-by-one When len(messages) <= protect_tail_count and a token budget is set, the previous formula min(protect_tail_count, len(result) - 1) under-protected the tail by one, allowing the oldest message to be summarized. The test fails on the buggy formula (pruned == 1) and passes on the fix (pruned == 0, tool content preserved verbatim). --- tests/agent/test_context_compressor.py | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/agent/test_context_compressor.py b/tests/agent/test_context_compressor.py index 8f5d6c4d1..8d1de377b 100644 --- a/tests/agent/test_context_compressor.py +++ b/tests/agent/test_context_compressor.py @@ -1143,6 +1143,34 @@ class TestTokenBudgetTailProtection: # At least one old tool result should have been pruned assert pruned >= 1 + def test_prune_short_conv_protects_entire_tail(self, budget_compressor): + """Regression guard for PR #17025. + + When ``len(messages) <= protect_tail_count`` and a token budget is + also set, every message must be protected. The previous code used + ``min(protect_tail_count, len(result) - 1)`` which capped the floor + one below the full length, leaving the oldest message eligible for + pruning. + """ + c = budget_compressor + # 4 messages, protect_tail_count=4 -- nothing should be pruned. + # Oldest message is a large tool result; on the buggy path it falls + # outside the protected window and gets summarized. + messages = [ + {"role": "tool", "content": "x" * 5000, "tool_call_id": "c0"}, + {"role": "assistant", "content": "ack"}, + {"role": "user", "content": "recent"}, + {"role": "assistant", "content": "reply"}, + ] + result, pruned = c._prune_old_tool_results( + messages, + protect_tail_count=4, + protect_tail_tokens=1_000_000, # budget large enough to protect all + ) + assert pruned == 0 + # Tool result at index 0 must be preserved verbatim + assert result[0]["content"] == "x" * 5000 + def test_prune_without_token_budget_uses_message_count(self, budget_compressor): """Without protect_tail_tokens, falls back to message-count behavior.""" c = budget_compressor