Skip to content

fix: migrate goals across compression sessions - #41478

Closed
kortylokai-web wants to merge 3 commits into
NousResearch:mainfrom
kortylokai-web:fix/goal-compression-session-migration
Closed

kortylokai-web wants to merge 3 commits into
NousResearch:mainfrom
kortylokai-web:fix/goal-compression-session-migration

Conversation

@kortylokai-web

@kortylokai-web kortylokai-web commented Jun 7, 2026

Copy link
Copy Markdown

What does this PR do?

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;
  • /goal resume cannot 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:

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.
  • Tests
    • adds core compression-boundary regression coverage;
    • adds CLI manual /compress fallback coverage;
    • adds gateway regressions for goal migration across compression splits/tip-walks;
    • covers non-compression child no-leak behavior;
    • covers hygiene compression and manual gateway /compress;
    • updates the session-id persistence guard so future direct session-id mutation outside the helper is caught.

How to Test

Focused verification on Android 16 / Termux after rebasing onto current upstream/main:

PY="$HOME/.hermes/hermes-agent/venv/bin/python"
PATH="$PATH:/bin" "$PY" -m pytest \
  tests/run_agent/test_compression_boundary_hook.py \
  tests/cli/test_manual_compress.py \
  tests/hermes_cli/test_goals.py \
  tests/gateway/test_goal_compression_split.py \
  tests/gateway/test_compression_session_id_persistence.py \
  tests/gateway/test_telegram_topic_mode.py::test_managed_topic_binding_reuses_restored_session_over_static_lane_session \
  tests/gateway/test_telegram_topic_mode.py::test_topic_binding_follows_compression_tip_on_read \
  tests/gateway/test_compress_plugin_engine.py \
  tests/test_hermes_state.py::TestStateMeta \
  -q -o 'addopts=' --tb=short

Result:

90 passed in 38.20s

Additional local checks:

git grep -n '<<<<<<<\|>>>>>>>\|=======' -- <changed files> || true
git diff --check upstream/main...HEAD
"$PY" -m py_compile <changed Python files and focused tests>

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.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Android 16 / Termux

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

N/A — behavior covered by regression tests.

@kortylokai-web
kortylokai-web marked this pull request as draft June 7, 2026 19:57
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/gateway Gateway runner, session dispatch, delivery labels Jun 7, 2026
@kortylokai-web
kortylokai-web force-pushed the fix/goal-compression-session-migration branch from 899d7fd to 3cc706c Compare June 8, 2026 02:09
@kortylokai-web
kortylokai-web marked this pull request as ready for review June 8, 2026 02:10
@kortylokai-web
kortylokai-web force-pushed the fix/goal-compression-session-migration branch 3 times, most recently from de7f7eb to 87fa68b Compare June 8, 2026 09:30
@kortylokai-web
kortylokai-web force-pushed the fix/goal-compression-session-migration branch from 87fa68b to 7556ddc Compare June 21, 2026 21:40
@teknium1

Copy link
Copy Markdown
Collaborator

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.

@teknium1 teknium1 closed this Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants