Skip to content

fix(goals): keep gateway goals alive across streaming and compression - #49743

Closed
MohamedRed wants to merge 2 commits into
NousResearch:mainfrom
MohamedRed:fix/goal-survives-compression
Closed

MohamedRed wants to merge 2 commits into
NousResearch:mainfrom
MohamedRed:fix/goal-survives-compression

Conversation

@MohamedRed

@MohamedRed MohamedRed commented Jun 20, 2026 •

Copy link
Copy Markdown

Summary

  • add a conservative migrate_goal(old_session_id, new_session_id) helper for active/paused /goal state
  • call it when context compression rotates the physical session id, while leaving in-place compaction unchanged
  • run the post-turn goal continuation hook before returning from already-streamed gateway replies, so Telegram/streamed sessions do not stay stuck at 0/N turns
  • do not overwrite an existing child-session goal and no-op for terminal goals

Fixes #33618. Related to #48956, #45059, and #18467.

Test plan

  • PYTHONPATH=. /opt/homebrew/bin/pytest tests/hermes_cli/test_goals.py::TestGoalManager::test_migrate_goal_preserves_unfinished_goal_after_compression_split tests/hermes_cli/test_goals.py::TestGoalManager::test_migrate_goal_noops_for_terminal_or_existing_destination -q -o 'addopts='
  • PYTHONPATH=. /opt/homebrew/bin/pytest tests/hermes_cli/test_goals.py -q -o 'addopts='
  • PYTHONPATH=. /opt/homebrew/bin/pytest tests/run_agent/test_compression_persistence.py tests/run_agent/test_compression_boundary.py tests/gateway/test_compression_session_id_persistence.py -q -o 'addopts='
  • PYTHONPATH=. python -m py_compile gateway/run.py
  • PYTHONPATH=. /opt/homebrew/bin/pytest tests/hermes_cli/test_goals.py tests/gateway/test_goal_verdict_send.py tests/gateway/test_goal_max_turns_config.py -q -o 'addopts=' (async gateway tests skipped locally because pytest-asyncio is not installed)

Copy active or paused /goal state when context compression rotates the physical session id, so the continuation session keeps the standing goal. Guard against overwriting an existing destination goal and add regression coverage for migration no-op cases.
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists labels Jun 20, 2026
@alt-glitch

Copy link
Copy Markdown

Duplicate of #29955 — same mechanism (a conservative migrate_goal*() helper in hermes_cli/goals.py invoked from the compression session-rotation path in agent/conversation_compression.py) for the same root cause: goal:<session_id> state is orphaned when context compression rotates the physical session id. #29955 is the earliest still-open PR using this exact helper + call-site approach.

Note: the original fix #23530 was merged then reverted by #23813, so this bug is genuinely still live on main and a fix is needed — this cluster just has several open competing PRs. Related: #33618 (issue), #18467, #18749, #33620, #33890, #34035.

Streamed gateway turns return None after final delivery to avoid duplicate sends. Run the post-turn goal continuation hook before that return so standing goals are judged and continuations are enqueued for streamed Telegram sessions.
@MohamedRed MohamedRed changed the title fix(goals): migrate active goal across compression rotation fix(goals): keep gateway goals alive across streaming and compression Jun 20, 2026
@alaamohanad169-ship-it

Copy link
Copy Markdown

Acknowledged: noted competing PR(s) #29955, #29955, #23530, #23813, #33618, #18467, #18749, #33620, #33890, #34035. My approach differs and is complementary, not mutually exclusive. Open to consolidating if reviewers prefer one direction.

@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/cli CLI entry point, hermes_cli/, setup wizard duplicate This issue or pull request already exists 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.

Persistent /goal is lost after context compression rotates session_id

4 participants