Skip to content

fix(compression): don't recommend a threshold the small-context floor will ignore - #67431

Closed
Sora-bluesky wants to merge 3 commits into
NousResearch:mainfrom
Sora-bluesky:fix/issue-67422
Closed

fix(compression): don't recommend a threshold the small-context floor will ignore#67431
Sora-bluesky wants to merge 3 commits into
NousResearch:mainfrom
Sora-bluesky:fix/issue-67422

Conversation

@Sora-bluesky

Copy link
Copy Markdown
Contributor

What does this PR do?

The auxiliary-compression feasibility warning computes its compression.threshold suggestion as aux_context / main_context (agent/conversation_compression.py), independently of ContextCompressor._effective_threshold_percent()'s raise-only small-context floor (agent/context_compressor.py:1261-1262). For main windows under 512K the floor raises any configured value below 75% back up, so a suggestion like threshold: 0.40 is silently ignored and the identical warning returns every session — an advice loop the user cannot exit by following the advice.

This PR derives the suggestion's viability through the compressor's own floor logic (the _effective_threshold_percent staticmethod, so the two can't drift): the "lower the threshold" option is offered only when the floored value still fits the auxiliary model's context; otherwise the message recommends only a larger compression model and explains the floor. This is the issue's first two suggested fixes — no new config surface.

Related Issue

Fixes #67422

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • agent/conversation_compression.py — compute threshold_suggestion_viable via ContextCompressor._effective_threshold_percent(); branch the persistence-guidance section of the warning on it. Unknown main context keeps the legacy message (the floor can't be evaluated without a window size).
  • tests/run_agent/test_compression_feasibility.py — the existing auto-correct test (200K main, 40% suggestion → floored) now pins the new branch: no threshold: suggestion, floor explained. Two new tests pin the surviving suggestion at/above the floor on a small window (100K main, 80% ≥ 75%) and below 75% on a 512K+ window where no floor applies (1M main, 30%).

How to Test

  1. scripts/run_tests.sh tests/run_agent/test_compression_feasibility.py -q
  2. Manual repro (from the issue): main model with a <512K window + aux compression model below 75% of it → the warning no longer suggests a sub-0.75 compression.threshold; it explains the floor and recommends a larger aux model. Previously, applying the suggested value changed nothing and the warning repeated every session.

Checklist

Code

Documentation & Housekeeping

  • Docstrings/comments — the viability rationale is documented at the computation site — or N/A
  • cli-config.yaml.example — N/A (no config surface added)
  • CONTRIBUTING.md / AGENTS.md — N/A
  • Cross-platform impact — N/A (pure string/arithmetic logic)
  • Tool descriptions/schemas — N/A

Screenshots / Logs

$ pytest tests/run_agent/test_compression_feasibility.py tests/agent/test_context_compressor.py -q  (Windows 11)
201 passed

# Against the unfixed code (regression proof, changed test):
1 failed (test_auto_corrects_threshold_when_aux_context_below_threshold), new pinning tests pass

🤖 Generated with Claude Code

@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 area/compression Context compression and continuation sessions labels Jul 19, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #67422 and #66249. This patch fixes the warning/recommendation contract; #66249 changes the underlying small-context threshold behavior.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for isolating the stale recommendation loop; the underlying mismatch is present on current upstream main (agent/conversation_compression.py:341, agent/context_compressor.py:1261-1263).

Problems

  • agent/conversation_compression.py:353 checks only the percentage floor against the raw context window. The actual built-in trigger also uses the output reservation, 64K floor, and effective-window guard in agent/context_compressor.py:1293-1305. That can suppress a threshold recommendation that would actually fit after the persisted setting is recomputed.
  • The new code unconditionally imports and applies built-in ContextCompressor policy. Plugin engines can be active at agent/agent_init.py:1881-1908, and that code explicitly states that external engines own compaction policy.

Suggested changes

  • Gate the floor-specific calculation to the built-in compressor and use _compute_threshold_tokens(..., max_tokens) after applying the effective percent.
  • Add a reservation-based regression test and a non-built-in-engine test.

Automated hermes-sweeper review.

Comment thread agent/conversation_compression.py Outdated

threshold_suggestion_viable = (
not main_ctx
or _CC._effective_threshold_percent(main_ctx, safe_pct / 100) * main_ctx

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the complete built-in trigger calculation: _compute_threshold_tokens() also applies max_tokens reservation, the 64K floor, and the degenerate effective-window branch (agent/context_compressor.py:1293-1305). It also should not run for a plugin context engine, which owns its own policy. Please gate this to ContextCompressor and compare aux_context to the fully recomputed token threshold.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 19, 2026
@Sora-bluesky

Copy link
Copy Markdown
Contributor Author

Both points addressed in 75d5b2a84:

  1. Full trigger recomputation. The guard now mirrors _compute_threshold_tokens(...) (output reservation + 64K floor + degenerate-window guard) applied to the effective percent, not just the raw-window percentage. Regression test: a 200K window with max_tokens=120K recomputes to 64K, so the suggestion is correctly kept for an 80K aux model — the case the raw-window check wrongly suppressed.
  2. Plugin engines untouched. The built-in policy is gated behind isinstance(agent.context_compressor, ContextCompressor); non-built-in engines keep the plain suggestion (per Codex gpt-5.5 autoraise should defer to external context engines #44439's "external engines own compaction policy"). Passthrough test added.

The non-viable message now names the recomputed trigger instead of hardcoding the 75%/512K wording, so it stays accurate when the reservation — not the percentage floor — is what makes the value unreachable.

Sora-bluesky and others added 2 commits July 22, 2026 19:37
… will ignore

The auxiliary-compression feasibility warning computes its
compression.threshold suggestion as aux_context / main_context,
independently of ContextCompressor._effective_threshold_percent()'s
raise-only small-context floor. For main windows under 512K the floor
raises any configured value below 75% back up, so a suggestion like
'threshold: 0.40' is silently ignored and the same warning returns every
session.

Derive the suggestion's viability through the compressor's own floor
logic: offer the 'lower the threshold' option only when the floored value
still fits the auxiliary model's context; otherwise recommend only a
larger compression model and explain the floor, so the guidance is always
actionable.

Tests: the updated auto-correct test pins the floored branch (no
threshold suggestion, floor explained); two new tests pin the surviving
suggestion at/above the floor on a small window and below 75% on a
512K+ window where no floor applies. The updated test fails against the
previous code.

Fixes NousResearch#67422

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tion guard

Review follow-up on NousResearch#67431 (hermes-sweeper):

- The viability check compared the floored percentage against the raw
  context window, but the built-in trigger recomputation also applies the
  output-token reservation, the 64K floor, and the degenerate-window
  guard (_compute_threshold_tokens). Mirror that math exactly, so e.g. a
  200K window with max_tokens=120K recomputes to max(0.75*80K, 64K)=64K
  and the suggestion is correctly KEPT for an 80K aux model instead of
  being suppressed by the raw-window percentage.
- Gate the built-in policy behind isinstance(ContextCompressor): external
  context engines own compaction policy (NousResearch#44439), so plugin engines keep
  the plain suggestion untouched.
- The non-viable explanation now names the recomputed trigger instead of
  hardcoding the 75%/512K wording, so it stays accurate when the
  reservation (not the percentage floor) is what makes the value
  unreachable.

Tests: reservation-viability regression and plugin-engine passthrough,
per the review; the floored-branch assertion updated to the recomputed
number.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
teknium1 pushed a commit that referenced this pull request Jul 22, 2026
…tion guard

Review follow-up on #67431 (hermes-sweeper):

- The viability check compared the floored percentage against the raw
  context window, but the built-in trigger recomputation also applies the
  output-token reservation, the 64K floor, and the degenerate-window
  guard (_compute_threshold_tokens). Mirror that math exactly, so e.g. a
  200K window with max_tokens=120K recomputes to max(0.75*80K, 64K)=64K
  and the suggestion is correctly KEPT for an 80K aux model instead of
  being suppressed by the raw-window percentage.
- Gate the built-in policy behind isinstance(ContextCompressor): external
  context engines own compaction policy (#44439), so plugin engines keep
  the plain suggestion untouched.
- The non-viable explanation now names the recomputed trigger instead of
  hardcoding the 75%/512K wording, so it stays accurate when the
  reservation (not the percentage floor) is what makes the value
  unreachable.

Tests: reservation-viability regression and plugin-engine passthrough,
per the review; the floored-branch assertion updated to the recomputed
number.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Sora-bluesky

Copy link
Copy Markdown
Contributor Author

Agreed the original suggestion skipped _compute_threshold_tokens's max_tokens reservation, 64K floor, and degenerate-window guard. Thanks for salvaging the complete version into #69332, which mirrors the full recomputation.

@Sora-bluesky

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Both points were against commit 7073d1a8; the follow-up 21a59ab (six minutes later, and on the current head) already does what it asks:

  • The viability check now recomputes the full trigger: it calls _compute_threshold_tokens(main_ctx, _effective_threshold_percent(...), max_tokens), so the output reservation, the 64K floor, and the effective-window guard from context_compressor.py all apply, instead of the raw percentage-against-window it used before.
  • The floor logic is gated on isinstance(agent.context_compressor, ContextCompressor), so a plugin engine keeps its own policy and the plain suggestion is left untouched.
  • Both suggested tests are in: test_threshold_suggestion_kept_when_reservation_shrinks_trigger (a 120K reservation on a 200K window shrinks the trigger to the 64K floor, and the recommendation is not suppressed) and test_plugin_engine_keeps_plain_suggestion.

Flagging in case the keep_open verdict was rendered before that follow-up landed.

@teknium1

Copy link
Copy Markdown
Contributor

Merged via #69332 (commit cca7b93). All three of your commits were cherry-picked with authorship preserved — cleanest submission of the three competing fixes, no follow-up needed. Thanks!

@teknium1 teknium1 closed this Jul 22, 2026
@Sora-bluesky

Copy link
Copy Markdown
Contributor Author

Late reply — my monitoring only covered open threads until this week, and this landed in the blind spot; found it in today's backfill. Verified all three (dbc71fb, 19a59f7, cca7b93) on main with authorship intact. Thanks for carrying them.

randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…tion guard

Review follow-up on NousResearch#67431 (hermes-sweeper):

- The viability check compared the floored percentage against the raw
  context window, but the built-in trigger recomputation also applies the
  output-token reservation, the 64K floor, and the degenerate-window
  guard (_compute_threshold_tokens). Mirror that math exactly, so e.g. a
  200K window with max_tokens=120K recomputes to max(0.75*80K, 64K)=64K
  and the suggestion is correctly KEPT for an 80K aux model instead of
  being suppressed by the raw-window percentage.
- Gate the built-in policy behind isinstance(ContextCompressor): external
  context engines own compaction policy (NousResearch#44439), so plugin engines keep
  the plain suggestion untouched.
- The non-viable explanation now names the recomputed trigger instead of
  hardcoding the 75%/512K wording, so it stays accurate when the
  reservation (not the percentage floor) is what makes the value
  unreachable.

Tests: reservation-viability regression and plugin-engine passthrough,
per the review; the floored-branch assertion updated to the recomputed
number.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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-moderate Sweeper blast radius: moderate — a subsystem or single platform 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.

Compression warning can recommend a threshold below the small-context floor

3 participants