Skip to content

fix(gateway): freshness-gate resume_pending against per-message zombies - #56264

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-877832fc
Jul 1, 2026
Merged

fix(gateway): freshness-gate resume_pending against per-message zombies#56264
teknium1 merged 1 commit into
mainfrom
hermes/hermes-877832fc

Conversation

@teknium1

@teknium1 teknium1 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

A crash-interrupted session marked resume_pending now falls through to a fresh session once resume has been pending past the freshness window — closing the zombie-session context bleed reported on Telegram and Feishu.

Root cause: #54442 added _should_reset() to the resume_pending branch, but that policy keys on updated_at, which is bumped to now on every message. A zombie session that keeps receiving messages therefore never goes idle and resumes its stale transcript forever.

Changes

  • gateway/session.py: gate the resume_pending branch on last_resume_marked_at (set once at resume-mark, never bumped per-message) vs the auto-continue freshness window. Past the window → auto-reset with reason "resume_pending_expired". Window <= 0 disables the gate (opt-out).
  • gateway/session.py: hoist auto_continue_freshness_window() here as the single source of truth.
  • gateway/run.py: _auto_continue_freshness_window() now delegates to the session-module helper (import/patch surface preserved).
  • tests/gateway/test_clean_shutdown_marker.py: 3 tests — fresh returns same session, per-message zombie (fresh updated_at, stale mark) resets, window=0 opt-out.

Validation

Scenario Before After
Fresh resume_pending returns session returns session
Zombie (fresh updated_at, resume pending > window) resumes stale context new session
HERMES_AUTO_CONTINUE_FRESHNESS=0 resumes resumes (opt-out)

Targeted tests: 86/86 green (incl. test_restart_resume_pending, _auto_continue_freshness_window helper tests). E2E verified against real imports with a temp HERMES_HOME.

Salvaged from #46963 by @annguyenNous (authorship preserved). Supersedes #43392.

Fixes #46934

Infographic

freshness gate

A crash-interrupted session marked resume_pending is returned by
get_or_create_session so its transcript reloads intact. The idle/daily
reset policy (#54442) keys on updated_at, which is bumped to now on every
message — so a zombie session that keeps receiving messages never trips
it and resumes stale context forever (context bleed reported on Telegram
and Feishu).

Gate the resume_pending branch on last_resume_marked_at (set once at
resume-mark, never bumped per-message) against the auto-continue freshness
window. If resume has been pending past the window, fall through to
auto-reset with reason "resume_pending_expired". A window <= 0 disables
the gate (opt-out for the pre-fix always-fresh behaviour).

Also hoist auto_continue_freshness_window() into gateway/session.py as the
single source of truth; gateway/run._auto_continue_freshness_window() now
delegates to it (keeps the existing import/patch surface).

Fixes #46934

Co-authored-by: Hermes Agent <noreply@nousresearch.com>
@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state P2 Medium — degraded but workaround exists labels Jul 1, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Salvage of #46963 (supersedes #43392). Companion to #56262 (recovery-note injection, different mechanism/file) and related to #46997. Not a duplicate of the cluster.

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:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: stale resume_pending sessions bypass idle reset, causing context bleed after gateway restart

3 participants