From 4cb85fb7fc9a6848cec45985a3534d2ddf78b46f Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Thu, 23 Jul 2026 08:08:06 -0700 Subject: [PATCH] fix(compress): type-pin the lock-skip signal check at every consumer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bare truthiness test on _compression_skipped_due_to_lock is fooled by MagicMock auto-attributes on test-double agents (skill pitfall: MagicMock defeats hasattr/truthiness duck-typing) — the type-ahead CLI test's MagicMock agent took the lock-skip branch and skipped the transcript commit. Real values are None/True/holder-string; pin the check to 'is True or isinstance(str)' at all three consumer sites. --- cli.py | 9 ++++++++- gateway/slash_commands.py | 2 +- tui_gateway/server.py | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) 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).