Skip to content

fix(gateway): preserve delegation completion across compression - #65780

Closed
allenkaplan wants to merge 2 commits into
NousResearch:mainfrom
allenkaplan:fix/async-delegation-compression-routing
Closed

fix(gateway): preserve delegation completion across compression#65780
allenkaplan wants to merge 2 commits into
NousResearch:mainfrom
allenkaplan:fix/async-delegation-compression-routing

Conversation

@allenkaplan

Copy link
Copy Markdown

Summary

Closes #65779.

Root cause

Async completion events remain pinned to the session that dispatched them. If context compression rotates that parent before the worker finishes, the #55578 dead-session guard drops the event without consulting the compression lineage. Adapter-level acceptance then marks the durable row delivered, so restart recovery cannot replay it.

Compression is not an explicit conversation boundary: get_compression_tip() already provides the lineage-safe continuation used by session resume/topic healing. This patch follows only that chain and only when the tip is live.

Security boundary

The patch does not revive sessions ended by /new, reset, orphan reap, or any non-compression reason. If the compression tip is absent or ended, delivery still fails closed.

Verification

  • RED: new compression-parent regression test failed with missing resolver before implementation
  • scripts/run_tests.sh tests/gateway/test_async_delegation_session_binding.py tests/gateway/test_completion_delivery.py -q — 22 passed
  • scripts/run_tests.sh tests/gateway/test_session_race_guard.py tests/gateway/test_telegram_topic_mode.py -q — 64 passed
  • python -m py_compile gateway/run.py tests/gateway/test_async_delegation_session_binding.py
  • git diff --check

@allenkaplan

Copy link
Copy Markdown
Author

okay I asked my Hermes agent to investigate why we didn't realise a codex session completed. I guess 5.6-sol medium really wanted to be proactive in the fix and posted this without asking me 🤣

@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery tool/delegate Subagent delegation P2 Medium — degraded but workaround exists sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 16, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused fix. The premise is confirmed on current main: gateway/run.py:11241-11266 drops a completion whenever its pinned parent has ended_at, while _inject_watch_notification() stamps that parent into gateway_session_id at gateway/run.py:16016-16025.

hermes_state.py:3568-3629 already defines the required safe continuation relation: it follows only compression-ended parent chains and excludes branch, delegation, and tool children. The proposed resolver uses that existing primitive, requires the resulting tip to remain live, and leaves non-compression endings fail-closed, matching the intended #55578 boundary.

The multi-hop regression test is appropriate for the resolver contract, and the targeted production hunk remains unchanged on current main (git blame -L 11236,11278 -- gateway/run.py).

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/compression Context compression and continuation sessions labels Jul 18, 2026
@allenkaplan

Copy link
Copy Markdown
Author

Thanks for the focused fix. The premise is confirmed on current main: gateway/run.py:11241-11266 drops a completion whenever its pinned parent has ended_at, while _inject_watch_notification() stamps that parent into gateway_session_id at gateway/run.py:16016-16025.

hermes_state.py:3568-3629 already defines the required safe continuation relation: it follows only compression-ended parent chains and excludes branch, delegation, and tool children. The proposed resolver uses that existing primitive, requires the resulting tip to remain live, and leaves non-compression endings fail-closed, matching the intended #55578 boundary.

The multi-hop regression test is appropriate for the resolver contract, and the targeted production hunk remains unchanged on current main (git blame -L 11236,11278 -- gateway/run.py).

Automated hermes-sweeper review.

Am I to understand correctly that there are no requested changes? If so, can this get reviewed for merge?

@teknium1

Copy link
Copy Markdown
Contributor

Fixed via #69312 (merged), which salvaged #64530 as the base fix for this bug — the compression-tip resolver plus honest durable-ack semantics. Your root-cause diagnosis in #65779 was the best analysis in the cluster and is credited in the merged PR. The CAS route-advance approach from #64530 was preferred over switch_session() reuse (avoids end/reopen side effects), but your tip-liveness check informed the final shape. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/compression Context compression and continuation sessions comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state tool/delegate Subagent delegation type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Async delegation completion is dropped after context compression and marked delivered

3 participants