fix(gateway): never double-deliver background output; drain /goal continuations - #70197
Merged
Conversation
… watcher messages process(wait) marks a completion consumed and returns the exit code + output inline. The gateway process watcher's agent-notify branch honored that (skipping the synthetic agent turn), but its skip FELL THROUGH to the plain text-notification branch, which re-sent the same completion to the chat as a raw '[Background process ... finished with exit code ...]' message — a duplicate delivery of output the agent had already read and was summarizing (observed on Slack with display.background_process_notifications: all, but platform-agnostic). Guard the raw-notification branch on is_completion_consumed(), same as the agent-notify branch. poll() stays read-only and never marks consumed (#10156), so status checks still can't suppress autonomous delivery. Fixes #65379. Reported-by: hergert
… required Issue #47699 reported Slack /goal continuations being enqueued by _post_turn_goal_continuation -> _enqueue_fifo but never drained until the next real inbound message woke the session. On the current tree the continuation lands in the adapter pending slot while the _process_message_background frame is still live, so the in-band pending drain (and the finally-block late-arrival drain) spawns the follow-up turn automatically — the reported stall is not reproducible on main. Pin the two halves of that contract so it can't silently regress: 1. a continuation placed in the FIFO during the handler frame is consumed as a second turn without any new user message, and 2. the runner's goal hook enqueues under the same session key the adapter drain resolves (key mismatch would orphan the event). Refs #47699. Reported-by: joesu-angible
…ong turns Salvaged from PR #45702 (heartbeat half). A multi-minute turn showed a static 'is thinking...' assistant status that reads as stuck and provokes mid-turn 'you there?' pings. Derive the fallback status label from the turn's elapsed time (>=30s → 'still working… (NmSSs)'), riding the existing _keep_typing refresh — zero extra API calls. Ported onto the current plugin adapter: the start time rides the tracked _active_status_threads entry (workspace-scoped key), so it shares the existing bounds/eviction and resets when stop_typing clears the status. Explicit live-status phrases (set_status_text) and configured typing_status_text always win; only the built-in default label changes. The PR's other half (top-level channel follow-up coalescing) is NOT included — dispatch semantics changed on main (busy-input active-turn redirect, #30170 demotion) and need a fresh design pass. Refs #45702. Co-authored-by: MrAbsaroka <mrabsaroka@gmail.com>
…sion Salvaged from PR #36220, ported onto the current SessionStore (SQLite- backed get_or_create_session; activity check is last_prompt_tokens) and the sidecar-note reset path (context notes now ride turn_sidecar_notes instead of prepending to context_prompt). Long-lived Slack/Discord channels/threads lose their context on daily/idle session resets, and the agent can bind a new request to an unrelated recent session (observed: a Discord thread reset caused a PR in the wrong repository). Record prev_session_id when an auto-reset replaces a session with real activity, persist it, and append a deterministic one-line hint to the auto-reset context note pointing the agent at session_search for that specific prior session. No LLM calls, no channel-history APIs, no extra DB lookups; other platforms and activity-free resets are untouched. Refs #36220. Co-authored-by: metamon <269728612+metamon-p@users.noreply.github.com>
Contributor
૮ >ﻌ< ა ci reviewran on ee79334 ℹ️ InfoDesktop E2E visual evidence · View test artifacts · View job1 visual diff. inline evidence upload failed. Failed to upload diff-665a0833239e-onboarding-overlay-diff.png with gh image (exit code 1): Error uploading /home/runner/work/_temp/e2e-evidence/diff-665a0833239e-onboarding-overlay-diff.png: step 0 (get upload token): uploadToken not found on repo page — do you have write access to NousResearch/hermes-agent? (or, if NousResearch enforces SAML SSO, authorize at https://github.com/orgs/NousResearch/sso) |
This was referenced Jul 23, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three cross-cutting bugs fixed, headlined by: background process output is never delivered twice — the watcher's raw text-notification branch no longer re-sends output that
process(wait)already consumed.Fixes #65379, #47699.
Changes
gateway/run.py::_run_process_watcher: the agent-notify branch honoredis_completion_consumed()but its skip FELL THROUGH to the raw text-notification branch, re-sending "[Background process … finished]" via adapter.send(). Fixed at the watcher (ownership) layer — platform-agnostic. Regression tests proven red-without-fix.Credits
Salvaged with authorship: #36220 (@metamon-p), #45702 (@MrAbsaroka, partial).
Verdicts: #13126 (voice reply) — premise dead on current main, voice subsystem rewrote the path (evidence in report); #31214 (shared group sessions) — DEFERRED, intentional-design question about the per-user session model, needs a maintainer call.
Validation
tests/gateway/ tests/tools/ -q -k 'slack or process or background'Infographic