hermes-agent/contributors/emails/lanyusea@gmail.com
Teknium ec5835ab8b
fix(compression): persist anti-thrash state across process restarts (#69872)
The anti-thrash guard (_ineffective_compression_count) was in-memory
only: a fresh compressor bound to a resumed, already-compacted session
started with compression_count=0 and a disarmed guard, so a
near-threshold session could legally re-compact once per process
restart, forever.

Persist the counter through the durable session-state channel,
mirroring the failure-cooldown (#54465) and fallback-streak (af7dceaf7)
pattern:

- hermes_state.py: sessions.compression_ineffective_count column
  (declarative reconciliation adds it on existing DBs) +
  get/set_compression_ineffective_count accessors.
- context_compressor.py: every strike/clear verdict routes through
  _record_ineffective_compression_verdict() which writes through to the
  session row (no-change verdicts skip the DB write);
  bind_session_state() loads the persisted value; the compression
  rotation boundary carries the counter onto the child row;
  update_model()'s reset also clears the durable copy; the
  ineffective-only fast path in _automatic_compression_blocked() is
  removed because the counter is now durable and another agent's clear
  must unblock a stale local snapshot.
- conversation_compression.py: _refresh_persisted_compression_guards
  re-reads the counter alongside cooldown + fallback streak.

Reset semantics are unchanged: any real provider reading below the
threshold still clears the counter — and now clears it durably too.

Resolves the residual gap identified in #54923 by @lanyusea (the
second-threshold mechanism was superseded by persisting the existing
guard state).

Co-authored-by: lanyusea <lanyusea@gmail.com>
2026-07-23 08:08:48 -07:00

1 line
9 B
Text