You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixes /goal state drift across context-compression session splits.
Hermes can end an oversized parent session and continue in a child session after context compression. Before this change, active /goal state could remain attached to the old parent session while the live conversation continued under the child session. That made post-turn goal continuation/status desynchronize from the active chat, and some paths could revive stale terminal goal rows.
This PR fixes the migration at both important seams:
the core compression boundary in agent/conversation_compression.py, so CLI/gateway/other callers of _compress_context() inherit the migration;
gateway session-routing in gateway/run.py, so session-store persistence, Telegram topic binding repair, and /goal state migration stay aligned when a verified compression relationship changes the active session id.
Goal migration is intentionally narrow:
only verified compression continuations migrate;
active/paused goals move to the child session;
the old goal row is preserved as cleared/non-resumable;
missing, done, cleared, and non-compression child relationships are no-ops;
Compared with those, this PR combines a core compression-boundary hook with gateway-specific routing/topic/session-store guardrails. It includes regression coverage for compression-only migration, non-compression child no-leak behavior, Telegram topic compression-tip repair, manual /compress, hygiene compression, and a guard against future direct session_entry.session_id mutation outside the shared gateway helper.
Type of Change
🐛 Bug fix (non-breaking change that fixes an issue)
✨ New feature (non-breaking change that adds functionality)
🔒 Security fix
📝 Documentation update
✅ Tests (adding or improving test coverage)
♻️ Refactor (no behavior change)
🎯 New skill (bundled or hub)
Changes Made
agent/conversation_compression.py
migrates active/paused /goal state at the core compression session split after the child session is created.
hermes_state.py
adds atomic state-meta compare/move support;
adds verified compression-chain walking helpers.
hermes_cli/goals.py
adds compression-validated goal migration;
prevents /goal resume from reviving cleared/done/migrated goals.
cli.py
adds a manual /compress fallback migration call at the CLI session-id rebind seam.
gateway/run.py
routes agent-result compression, Telegram topic compression-tip repair, hygiene compression, manual /compress, and late session-split detection through a shared compression session-switch helper;
keeps session-store persistence, Telegram topic binding, and /goal migration aligned.
Result: no conflict markers in changed files, whitespace check passed, and py_compile passed.
Full-suite status:
The full-suite checkbox remains unchecked. On this Android/Termux phone, a clean full-suite proof currently depends on the separate Termux/test-portability PRs. Without those companion changes, a full-suite run on this phone cannot honestly be marked green for this branch alone.
Thanks for this — the diagnosis and fix are correct for the rotation path.
Context on why we're closing it: as of #52658 (#38763), compression.in_place now defaults to True. Compaction keeps ONE durable session id for the conversation's whole life — it no longer ends the session and forks a continuation id. Because the id no longer rotates, the active /goal stays attached to the same session automatically — there is no rotation boundary to migrate the goal across.
Rotation now only runs as an explicit opt-out (compression.in_place: false), and the direction is to treat that path as legacy. So this fix hardens a code path that no longer executes by default and that we're not investing further in. Closing as superseded by the in-place default — not a reflection on the code, which was a correct fix for the behavior at the time. Credit preserved in the issue/PR history. Appreciate the contribution.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Fixes
/goalstate drift across context-compression session splits.Hermes can end an oversized parent session and continue in a child session after context compression. Before this change, active
/goalstate could remain attached to the old parent session while the live conversation continued under the child session. That made post-turn goal continuation/status desynchronize from the active chat, and some paths could revive stale terminal goal rows.This PR fixes the migration at both important seams:
agent/conversation_compression.py, so CLI/gateway/other callers of_compress_context()inherit the migration;gateway/run.py, so session-store persistence, Telegram topic binding repair, and/goalstate migration stay aligned when a verified compression relationship changes the active session id.Goal migration is intentionally narrow:
/goal resumecannot revive migrated/cleared terminal rows.Related Issue
N/A — bug found during local gateway/session-routing work.
Existing overlap checked
I searched existing open PRs before and after opening this review surface. This overlaps with the broader goal-compression area, especially:
fix(cli, gateway): migrate /goal across all session_id rebind sitesfix: preserve goals across compression session splitsfix(agent): migrate goal state across compression session rotationfix: preserve goals across compression sessionsCompared with those, this PR combines a core compression-boundary hook with gateway-specific routing/topic/session-store guardrails. It includes regression coverage for compression-only migration, non-compression child no-leak behavior, Telegram topic compression-tip repair, manual
/compress, hygiene compression, and a guard against future directsession_entry.session_idmutation outside the shared gateway helper.Type of Change
Changes Made
agent/conversation_compression.py/goalstate at the core compression session split after the child session is created.hermes_state.pyhermes_cli/goals.py/goal resumefrom reviving cleared/done/migrated goals.cli.py/compressfallback migration call at the CLI session-id rebind seam.gateway/run.py/compress, and late session-split detection through a shared compression session-switch helper;/goalmigration aligned./compressfallback coverage;/compress;How to Test
Focused verification on Android 16 / Termux after rebasing onto current
upstream/main:Result:
Additional local checks:
Result: no conflict markers in changed files, whitespace check passed, and
py_compilepassed.Full-suite status:
The full-suite checkbox remains unchecked. On this Android/Termux phone, a clean full-suite proof currently depends on the separate Termux/test-portability PRs. Without those companion changes, a full-suite run on this phone cannot honestly be marked green for this branch alone.
Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots / Logs
N/A — behavior covered by regression tests.