diff --git a/cli.py b/cli.py index f89adec37803..1502521a213f 100644 --- a/cli.py +++ b/cli.py @@ -10183,7 +10183,14 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin): # "No changes from compression" no-op text. The wording # distinguishes a confirmed holder from an unconfirmed # acquisition failure (describe_compression_lock_skip). - if getattr(self.agent, "_compression_skipped_due_to_lock", None): + # Type-pinned check (is True / str): the flag's only real + # values are None/True/holder-string, and a bare getattr + # truthiness test is fooled by MagicMock auto-attributes on + # test-double agents (skill pitfall: MagicMock vs hasattr). + _lock_skip_signal = getattr( + self.agent, "_compression_skipped_due_to_lock", None + ) + if _lock_skip_signal is True or isinstance(_lock_skip_signal, str): from agent.manual_compression_feedback import ( describe_compression_lock_skip, ) diff --git a/gateway/slash_commands.py b/gateway/slash_commands.py index d10baa56f8d7..9b6f989ff8b8 100644 --- a/gateway/slash_commands.py +++ b/gateway/slash_commands.py @@ -3573,7 +3573,7 @@ class GatewaySlashCommandsMixin: # The deferred context-engine notification is discarded by # the finally block below (finalize committed=False). _lock_skipped = getattr(tmp_agent, "_compression_skipped_due_to_lock", None) - if _lock_skipped: + if _lock_skipped is True or isinstance(_lock_skipped, str): from agent.manual_compression_feedback import ( describe_compression_lock_skip, ) diff --git a/tui_gateway/server.py b/tui_gateway/server.py index cc0d8a1e5dd0..176239b2ba52 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -3745,8 +3745,10 @@ def _compress_session_history( # If _compress_context returned unchanged because a concurrent # compression lock is held, raise so callers can surface a clear # message instead of the misleading "No changes from compression" text. + # Type-pinned (is True / str): real values are None/True/holder-string; + # bare truthiness is fooled by MagicMock auto-attrs on test doubles. _lock_skipped = getattr(agent, "_compression_skipped_due_to_lock", None) - if _lock_skipped: + if _lock_skipped is True or isinstance(_lock_skipped, str): agent._compression_skipped_due_to_lock = None # No boundary was committed on a lock-skip; discard any pending # deferred context-engine notification (exactly-once, no-op safe).