fix(compression): /compress refusal no longer reports a successful rewrite

This commit is contained in:
Teknium
2026-08-19 20:02:30 -07:00
parent cce0427905
commit 7bf66ec39b
5 changed files with 97 additions and 3 deletions

View File

@@ -1885,6 +1885,7 @@ class ContextCompressor(ContextEngine):
self._cooldown_persist_failed = False
self._last_summary_error = None
self._last_compress_aborted = False
self._last_compress_refused_would_grow = False
self.last_real_prompt_tokens = 0
self.last_compression_rough_tokens = 0
self.last_rough_tokens_when_real_prompt_fit = 0
@@ -2167,6 +2168,7 @@ class ContextCompressor(ContextEngine):
self._summary_failure_cooldown_until = 0.0
self._cooldown_persist_failed = False
self._last_compress_aborted = False
self._last_compress_refused_would_grow = False
self._context_probed = False
self._context_probe_persistable = False
self.last_real_prompt_tokens = 0
@@ -6927,6 +6929,7 @@ This compaction should PRIORITISE preserving all information related to the focu
self._last_aux_model_failure_error = None
self._last_aux_model_failure_model = None
self._last_compress_aborted = False
self._last_compress_refused_would_grow = False
self._last_compression_made_progress = False
# NOTE: do NOT reset _last_summary_auth_failure or
# _last_summary_network_failure here. These flags are set by

View File

@@ -3395,6 +3395,17 @@ def compress_context(
f"{_rough_in:,}",
f"{_rough_out:,}",
)
# Flag the refusal on the compressor state so manual
# /compress feedback can report it honestly. Without this,
# the CLI compared the returned list against its pre-call
# snapshot, saw a difference (durable-snapshot adoption can
# legitimately change the count), and printed
# "✅ Compressed: 8 → 14 messages" directly under the
# refusal warning (Aug 2026 full-surface CLI QA sweep).
try:
agent.context_compressor._last_compress_refused_would_grow = True
except Exception:
pass
try:
agent._emit_warning(
"⚠️ Compression refused: the generated summary "

View File

@@ -53,6 +53,11 @@ def summarize_manual_compression(
compression_state is not None
and getattr(compression_state, "_last_compress_aborted", False) is True
)
refused_would_grow = (
compression_state is not None
and getattr(compression_state, "_last_compress_refused_would_grow", False)
is True
)
fallback_used = (
compression_state is not None
and getattr(compression_state, "_last_summary_fallback_used", False) is True
@@ -65,7 +70,12 @@ def summarize_manual_compression(
if not isinstance(failure_reason, str) or not failure_reason.strip():
failure_reason = None
if aborted:
if refused_would_grow:
headline = (
f"Compression refused (summary would grow the conversation): "
f"{before_count} messages preserved"
)
elif aborted:
headline = f"Compression aborted: {before_count} messages preserved"
elif fallback_used:
headline = (
@@ -78,6 +88,8 @@ def summarize_manual_compression(
if noop and after_tokens == before_tokens:
token_line = f"Approx request size: ~{before_tokens:,} tokens (unchanged)"
elif refused_would_grow:
token_line = f"Approx request size: ~{before_tokens:,} tokens (unchanged)"
else:
token_line = (
f"Approx request size: ~{before_tokens:,} → "
@@ -85,7 +97,12 @@ def summarize_manual_compression(
)
note = None
if aborted:
if refused_would_grow:
note = (
"The generated summary was larger than what it would replace; "
"no messages were removed."
)
elif aborted:
note = "Summary generation failed; no messages were removed."
elif fallback_used:
dropped_count = getattr(
@@ -113,6 +130,7 @@ def summarize_manual_compression(
return {
"noop": noop,
"aborted": aborted,
"refused_would_grow": refused_would_grow,
"fallback_used": fallback_used,
"headline": headline,
"token_line": token_line,

6
cli.py
View File

@@ -12970,7 +12970,11 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
self.agent, "context_compressor", None
),
)
if summary.get("aborted") or summary.get("fallback_used"):
if (
summary.get("aborted")
or summary.get("fallback_used")
or summary.get("refused_would_grow")
):
icon = "⚠️"
else:
icon = "🗜️" if summary["noop"] else "✅"

View File

@@ -0,0 +1,58 @@
"""Regression tests: manual /compress feedback for a would-grow refusal.
The anti-growth guard (#83339 / PR #86700) can refuse the commit AFTER the
compressor produced a candidate. The CLI's feedback previously compared the
returned list against its pre-call snapshot; durable-snapshot adoption can
legitimately change that list, so a REFUSED compression printed
"✅ Compressed: 8 → 14 messages" directly under the refusal warning
(Aug 2026 full-surface CLI QA sweep). The refusal must surface as its own
honest headline.
"""
from types import SimpleNamespace
from agent.manual_compression_feedback import summarize_manual_compression
def _msgs(n):
return [{"role": "user", "content": f"m{n_i}"} for n_i in range(n)]
def _state(**flags):
base = {
"_last_compress_aborted": False,
"_last_compress_refused_would_grow": False,
"_last_summary_fallback_used": False,
"_last_summary_error": None,
"_last_summary_dropped_count": 0,
}
base.update(flags)
return SimpleNamespace(**base)
class TestWouldGrowRefusalFeedback:
def test_refusal_reports_preserved_not_compressed(self):
summary = summarize_manual_compression(
_msgs(8), _msgs(14), 22025, 22453,
compression_state=_state(_last_compress_refused_would_grow=True),
)
assert summary["refused_would_grow"] is True
assert "refused" in summary["headline"].lower()
assert "→" not in summary["headline"] # never claims a message rewrite
assert "unchanged" in summary["token_line"]
assert "no messages were removed" in summary["note"]
def test_normal_compression_unchanged(self):
summary = summarize_manual_compression(
_msgs(10), _msgs(4), 30000, 12000, compression_state=_state(),
)
assert summary["refused_would_grow"] is False
assert summary["headline"].startswith("Compressed: 10 → 4")
def test_abort_still_wins_its_own_headline(self):
summary = summarize_manual_compression(
_msgs(6), _msgs(6), 9000, 9000,
compression_state=_state(_last_compress_aborted=True),
)
assert summary["aborted"] is True
assert summary["headline"].startswith("Compression aborted")