From 4490c7cf8de4aef8abb61e5e4cb748bbd960e5c2 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 10 Jun 2026 17:37:34 -0700 Subject: [PATCH] fix: in-memory transcript blocks empty-session prune CI caught tests/cli/test_cli_new_session.py asserting that /new keeps the old session row when conversation history exists in memory. The live transcript is authoritative: a session whose messages haven't flushed to the DB yet (or whose flush failed) must not be pruned. Guard _discard_session_if_empty on self.conversation_history and pin the behavior with a test. --- cli.py | 6 ++++++ tests/test_empty_session_hygiene.py | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/cli.py b/cli.py index 2cc1a8f16db..126d0a1038a 100644 --- a/cli.py +++ b/cli.py @@ -5833,6 +5833,12 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin): """ if not self._session_db or not session_id: return False + # In-memory transcript is authoritative: if this CLI object holds + # conversation messages (flushed to the DB or not), the session is + # not empty. Protects against pruning a real conversation whose DB + # flush failed or hasn't happened yet. + if getattr(self, "conversation_history", None): + return False try: from hermes_constants import get_hermes_home as _ghh return self._session_db.delete_session_if_empty( diff --git a/tests/test_empty_session_hygiene.py b/tests/test_empty_session_hygiene.py index 7166ce936e1..3576e7dce72 100644 --- a/tests/test_empty_session_hygiene.py +++ b/tests/test_empty_session_hygiene.py @@ -113,6 +113,7 @@ class TestCLIDiscardSessionIfEmpty: cli = HermesCLI.__new__(HermesCLI) cli._session_db = db + cli.conversation_history = [] return cli def test_discards_empty(self, db): @@ -146,3 +147,15 @@ class TestCLIDiscardSessionIfEmpty: cli = self._make_cli(Boom()) assert cli._discard_session_if_empty("x") is False + + def test_in_memory_history_blocks_prune(self, db): + """The live transcript is authoritative: even if the DB row has no + flushed messages yet, a CLI holding conversation history must not + prune the session (covers flush-failed / not-yet-flushed turns).""" + db.create_session(session_id="unflushed", source="cli", model="test") + db.end_session("unflushed", "new_session") + + cli = self._make_cli(db) + cli.conversation_history = [{"role": "user", "content": "hello"}] + assert cli._discard_session_if_empty("unflushed") is False + assert db.get_session("unflushed") is not None