Skip to content

fix(gateway): forward-resolve compressed session to tip on resident non-Telegram platforms - #48911

Closed
RoySRose wants to merge 1 commit into
NousResearch:mainfrom
RoySRose:fix/discord-compression-tip-resolution
Closed

fix(gateway): forward-resolve compressed session to tip on resident non-Telegram platforms#48911
RoySRose wants to merge 1 commit into
NousResearch:mainfrom
RoySRose:fix/discord-compression-tip-resolution

Conversation

@RoySRose

Copy link
Copy Markdown

Summary

Fixes the resident-gateway (Discord/Slack) slice of the compaction session-fork bug (#44004): on a self-hosted Discord/Slack gateway, a long conversation keeps rotating its session_id on every auto-compression, forking orphan child sessions and reloading the oversized pre-compression parent on each turn — an endless preflight-compression loop where one session was observed climbing past the model's context cap and spawning multiple orphan lineages in minutes.

Why existing fixes don't cover this path

The same #44004 root cause has three distinct intake paths, each needing its own forward-resolution to the compression tip:

The resident gateway path never calls resolve_resume_session_id() (only slash-commands / TUI / api_server do), and get_or_create_session() returns the stored session_key → session_id mapping verbatim without following the compression chain. The only forward-resolution in gateway/run.py lived inside the Telegram-topic-lane branch, so Discord/Slack resident lanes reloaded the pre-compression parent after every rotation.

Change

Right after get_or_create_session(), apply the same lineage-aware get_compression_tip() walk the Telegram lane already uses — for all non-Telegram resident platforms — and switch_session() the session_key forward to the tip. Telegram keeps its own binding-based healing. get_compression_tip() only follows end_reason='compression' chains and returns the input unchanged otherwise, so it's a no-op for fresh/branch/delegate sessions.

Verification

  • tests/test_hermes_state.py -k compression_tip (4 passed) — the primitive.
  • tests/gateway/test_telegram_topic_mode.py (44 passed) — the mirrored healing pattern, no regression.
  • Live: on a Discord gateway exhibiting the fork loop, after this patch a compaction split now continues on the child tip (subsequent turns route to the child), the parent ends and stops re-growing, orphan-session count stays flat across repeated compactions, and no session exceeds the context cap.

Refs #44004, complements #48633 and #44103.

…nt platforms

Compaction rotates session_id (ends parent with end_reason=compression, creates
child). The forward-resolution that heals stale session_key->session_id mappings
existed only inside the Telegram-topic-lane branch, so Discord/Slack resident
gateways reloaded the pre-compression parent on the next message -> the stale
oversized parent re-grows past the context cap and forks orphan child sessions
in an endless preflight-compression loop (observed on hermes-main: one session
reached 283K tokens > cap, 3 orphan children in ~80min).

Apply the same get_compression_tip() walk (already used by the Telegram lane and
proven by tests) to the general non-Telegram path right after
get_or_create_session, so the next message resumes the compressed child. Idempotent
and safe: get_compression_tip only follows end_reason='compression' chains and
returns the input unchanged otherwise. Refs NousResearch#44004 NousResearch#38763 NousResearch#25921.
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for identifying the resident-gateway compression-routing failure mode. This is now implemented on current main through a centralized SessionStore repair rather than a second gateway-runner branch.

  • gateway/session.py:1840-1853 resolves every existing, non-force_new routing entry to its compression tip before the normal session decision path.
  • gateway/session.py:1897-1901 writes that canonical id back into the stored entry before returning it, covering resident non-Telegram platforms as well as the existing Telegram-specific binding repair.
  • tests/gateway/test_restart_resume_pending.py:387-406 covers a Weixin platform source and asserts that get_or_create_session() advances a compressed parent mapping to its child.
  • The implementation landed in 52d0d671e79ec1d5727881a6e8519332d04c1a07 and is included in v2026.7.7.

This is an automated hermes-sweeper review.

@teknium1 teknium1 closed this Jul 14, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants