Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions agent/conversation_compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,20 @@ def compress_context(
except Exception as _me_err:
logger.debug("memory manager on_session_switch (compression): %s", _me_err)

# Migrate goal state to the continuation session so /goal survives
# compression. Goal state is keyed by ``goal:<session_id>`` in
# state_meta, so it must be copied to the new key. See #33618.
try:
_old_sid = locals().get("old_session_id")
if _old_sid:
from hermes_cli.goals import load_goal, save_goal

_old_goal = load_goal(_old_sid)
if _old_goal is not None:
save_goal(agent.session_id, _old_goal)
except Exception as _goal_err:
logger.debug("goal migration on compression: %s", _goal_err)

# Warn on repeated compressions (quality degrades with each pass)
_cc = agent.context_compressor.compression_count
if _cc >= 2:
Expand Down
26 changes: 26 additions & 0 deletions tests/hermes_cli/test_goals.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,32 @@ def test_persistence_across_managers(self, hermes_home):
assert mgr2.state.goal == "do the thing"
assert mgr2.is_active()

def test_goal_migrates_across_session_rotation(self, hermes_home):
"""Goal must survive context compression session_id rotation.

Compression creates a continuation session with a new id and
copies the goal via load_goal/save_goal. A GoalManager bound
to the new id must see the original goal. Regression guard
for #33618.
"""
from hermes_cli.goals import GoalManager, load_goal, save_goal

old_sid = "compress-old-sid"
new_sid = "compress-new-sid"

mgr_old = GoalManager(session_id=old_sid)
mgr_old.set("ship the feature")

# Simulate what compress_context now does:
old_goal = load_goal(old_sid)
assert old_goal is not None
save_goal(new_sid, old_goal)

mgr_new = GoalManager(session_id=new_sid)
assert mgr_new.state is not None
assert mgr_new.state.goal == "ship the feature"
assert mgr_new.is_active()

def test_evaluate_after_turn_done(self, hermes_home):
"""Judge says done → status=done, no continuation."""
from hermes_cli import goals
Expand Down
Loading