Skip to content

fix(gateway): resume follows the compression tip so post-compression replies render - #48633

Merged
OutThisLife merged 2 commits into
mainfrom
fix/resume-follows-compression-tip
Jun 18, 2026
Merged

fix(gateway): resume follows the compression tip so post-compression replies render#48633
OutThisLife merged 2 commits into
mainfrom
fix/resume-follows-compression-tip

Conversation

@OutThisLife

Copy link
Copy Markdown
Collaborator

Summary

Fixes the recurring desktop report: "I send a message, it starts working, I look away, and when I come back the reply isn't there" — on large sessions, the response is generated and persisted but never shows up under the user's message.

Root cause is session rotation on auto-compression, not a render bug:

  • Auto-compression ends the live session and forks a continuation child (linked via parent_session_id); the turns generated after compression — including the assistant's response — land in the continuation, not the original session.
  • SessionDB.resolve_resume_session_id() only redirected an empty head to a descendant (the --resume loads empty chat after context compression; exit banner points at wrong session id #15000 case). A long-lived parent keeps its own flushed message rows, so it was never redirected — and every resume path anchored on the parent id reloaded the pre-compression transcript, missing the response.
  • The desktop's chat is routed on the pre-rotation id (the id when the chat was opened), so both the gateway session.resume RPC and the REST /messages read missed the continuation.

Changes

  • hermes_state.resolve_resume_session_id() now follows the compression-continuation chain forward via the existing get_compression_tip() before its empty-head walk. get_compression_tip() is lineage-aware (only follows children whose parent ended with end_reason='compression', created after the parent was ended), so delegation/branch children never hijack a resume. This fixes every resume caller at the chokepoint: REST /messages, CLI --resume, gateway /resume.
  • tui_gateway session.resume was the one resume path that bypassed the resolver (it used the raw target id). It now routes through resolve_resume_session_id() (non-lazy only — lazy watch windows must stay on their exact child branch). Resolving up front also re-anchors the live-session fast path, so a still-live rotated session is reused by its new key instead of rebuilding a duplicate agent on the stale parent.

Premise verification

tests/hermes_state/test_resolve_resume_session_id.py::test_follows_compression_tip_when_parent_retains_messages fails on current main (resolve_resume_session_id("root") returns "root", the pre-compression parent) and passes with this change.

Test plan

  • resolve_resume_session_id follows the tip even when the parent retains messages; not confused by a delegation child
  • session.resume binds the agent to the continuation tip and returns the post-compression reply
  • Existing resume callers green: tests/hermes_cli/test_web_server.py, tests/cli/test_cli_resume_command.py, tests/cli/test_resume_display.py, tests/cli/test_resume_quiet_stderr.py, tests/gateway/test_resume_command.py, tests/test_lazy_session_regressions.py, tests/test_hermes_state.py, tests/test_tui_gateway_server.py (only the unrelated, environment-dependent test_browser_manage_connect_default_local_reports_launch_hint fails locally — no Chromium on the box)

Follow-up (not in this PR, to keep it one idea)

The desktop prefers the REST /messages snapshot over the resume payload when non-empty; with the resolver fixed both now agree. A separate cleanup could make the gateway re-anchor _find_live_session_by_key to also match a session's pre-rotation id directly, but resolving the tip up front already covers the reuse path.

…replies render

Auto-compression ends the live session and forks a continuation child
(linked via parent_session_id). A long-lived parent keeps its own flushed
message rows, so resolve_resume_session_id()'s empty-head walk never
redirected it — resuming the parent id reloaded the pre-compression
transcript and dropped every turn generated after compression, including
the assistant's response. On the desktop this is the recurring "I sent a
message, came back, and the reply isn't there" report on large sessions:
the chat's routed id is the pre-rotation id, and both the gateway
session.resume RPC and the REST /messages read anchored on it.

Fix the resolver at the chokepoint: resolve_resume_session_id() now
follows the compression-continuation chain forward via get_compression_tip()
before its existing empty-head descendant walk. get_compression_tip() only
follows children whose parent ended with end_reason='compression' (created
after the parent was ended), so delegation/branch children never hijack a
resume. This fixes every resume caller at once (REST /messages, CLI
--resume, gateway /resume).

session.resume in tui_gateway was the one resume path that never called the
resolver — it used the raw target id directly. Route it through
resolve_resume_session_id() too (non-lazy only; lazy watch windows must
stay on their exact child branch). Resolving up front also re-anchors the
live-session fast path so a still-live rotated session is reused by its new
key instead of rebuilding a duplicate agent on the stale parent.

Tests:
- resolve_resume_session_id follows the tip even when the parent retains
  messages, and is not confused by a delegation child.
- session.resume binds the agent to the continuation tip and returns the
  post-compression reply.
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: fix/resume-follows-compression-tip vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11030 on HEAD, 11028 on base (🆕 +2)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5780 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

…access

The new compression-tip tests poke started_at/ended_at directly via
db._conn to force deterministic lineage ordering. _conn is typed
Optional[Connection], so ty flagged .execute/.commit as unresolved on
None. Bind a local and assert it's non-None first to narrow the union.
@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/gateway Gateway runner, session dispatch, delivery comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists labels Jun 18, 2026
@OutThisLife
OutThisLife enabled auto-merge June 18, 2026 21:08
@OutThisLife
OutThisLife merged commit 1ea2b27 into main Jun 18, 2026
34 checks passed
@OutThisLife
OutThisLife deleted the fix/resume-follows-compression-tip branch June 18, 2026 21:09
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…llows-compression-tip

fix(gateway): resume follows the compression tip so post-compression replies render
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…llows-compression-tip

fix(gateway): resume follows the compression tip so post-compression replies render
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…llows-compression-tip

fix(gateway): resume follows the compression tip so post-compression replies render
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…llows-compression-tip

fix(gateway): resume follows the compression tip so post-compression replies render
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…llows-compression-tip

fix(gateway): resume follows the compression tip so post-compression replies render
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 comp/tui Terminal UI (ui-tui/ + tui_gateway/) 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.

2 participants