Skip to content

fix(gateway): relay semantic thread rename — register eagerly, poll send-result feedback at fire time - #75581

Merged
benbarclay merged 1 commit into
mainfrom
fix/relay-rename-registration-ordering
Jul 31, 2026
Merged

fix(gateway): relay semantic thread rename — register eagerly, poll send-result feedback at fire time#75581
benbarclay merged 1 commit into
mainfrom
fix/relay-rename-registration-ordering

Conversation

@benbarclay

Copy link
Copy Markdown
Collaborator

Relay semantic thread rename — register eagerly, poll send-result feedback at fire time

Staging re-test (2026-07-31, after the fleet box rolled to an image containing #74482): auto-created threads still stuck on their initial "first few words" titles; connector telemetry shows zero thread_rename ops ever sent.

Root cause — an ordering flaw in #74482's consume path. Both gates that decide whether the semantic-rename callback runs read the connector's send-result feedback cache (_relay_auto_thread_info):

  1. the title-callback registration gate (run_sync, pre-delivery), and
  2. the schedule gate (auto-title background thread, racing delivery).

But the cache is only populated when the connector answers the send — which happens after registration on the non-streaming lane, and typically after the title generator has already fired. The rename lane deterministically disqualified itself on exactly the turn it exists for. (#74482's unit tests exercised the cache and the rename in isolation; the gap was the cross-component ordering, which needed the live lane to expose.)

Fix — decide shape early, facts late

  • New _is_relay_discord_channel_lane: shape-only predicate (relay-delivered Discord channel event, not already threaded) for the registration + schedule gates. No cache read before delivery can have happened.
  • _rename_discord_auto_thread_for_session_title: on the relay lane, poll the adapter's feedback cache (0.5s ticks, ≤10s) — delivery lands right behind the title in practice. A true miss (connector didn't auto-thread: delivery policy off, DM, already threaded, send failed) no-ops exactly as before.
  • Native marker lane untouched; only_if_current_name no-clobber guard (human rename wins) preserved — fed from the connector's reported initial name.

Tests

  • shape-gate matrix (thread events / DMs / native events excluded)
  • late-arriving feedback → rename fires with the guard (the race, reproduced)
  • never-arriving feedback → no-op, no rename call

Relay + Discord-adjacent suites 174 passed · ruff clean · Windows-footguns clean.

No ops flags. Connector half (gg#188) is already deployed; this completes the pair for real this time — verified against the actual live-lane ordering rather than component tests alone.

…end-result feedback at fire time

Staging re-test (2026-07-31, post-74482 image roll): auto-created
threads still stuck on their initial titles; connector telemetry shows
zero thread_rename ops. Root cause is an ordering flaw in the 74482
consume path: BOTH the title-callback registration gate and the
schedule gate read the send-result feedback cache
(_relay_auto_thread_info) — but registration runs BEFORE delivery on
the non-streaming lane, and the auto-title thread races delivery even
when registration survives. The cache read can only succeed AFTER the
connector answers the send, so the rename lane deterministically
disqualified itself on the title turn.

Fix — decide shape early, facts late:
- New _is_relay_discord_channel_lane: SHAPE-only predicate (relay
  Discord channel event, no thread) used by the registration and
  schedule gates; no cache read before delivery.
- _rename_discord_auto_thread_for_session_title: on the relay lane,
  poll the adapter's feedback cache (0.5s ticks, ≤10s) — delivery is
  typically right behind the title. True miss (connector didn't
  auto-thread: policy off, DM, send failed) no-ops exactly as before.

Tests: shape-gate matrix; late-arriving feedback -> rename fires with
only_if_current_name guard; never-arriving feedback -> no-op. Relay
suite 174 passed.
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 0672c8f

ℹ️ Info

Desktop E2E visual evidence · View test artifacts · View job

3 visual diffs.

inline evidence is publishing...

@benbarclay
benbarclay merged commit 4a8eeb5 into main Jul 31, 2026
35 checks passed
@benbarclay
benbarclay deleted the fix/relay-rename-registration-ordering branch July 31, 2026 18:55
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/discord Discord bot adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 31, 2026
benbarclay added a commit that referenced this pull request Aug 1, 2026
…ename + trace logs (#75912)

Live staging (2026-08-01): relay semantic thread rename still declined
silently despite both #74482 and #75581 deployed — thread kept its
initial-words name, session title generated fine. Root cause is the
no-clobber guard string mismatch (see paired gateway-gateway PR): the
gateway can't reproduce the thread's initial name byte-for-byte, so the
connector's only_if_current_name check always failed.

- relay rename lane now passes prefer_connector_created=True instead of
  the fragile initial-name string; the connector resolves the guard from
  its own created-name memory. Native-marker lane keeps the legacy
  only_if_current_name string (source carries the real initial name).
- rename_thread: prefer_connector_created param -> only_if_connector_created
  on the wire, precedence over the legacy string.
- INFO logs at rename dispatch (thread/lane/new_title) and result
  (applied=bool): the whole failure hunt needed telemetry the gateway
  never emitted — this makes the outcome visible in fly logs.

Tests: connector-guard wire shape + precedence over legacy string; the
title-turn race test updated to assert the connector-owned guard. Relay
suite 149 passed; ruff + footguns clean.
bbasketballer75 added a commit to bbasketballer75/hermes-agent that referenced this pull request Aug 10, 2026
The memo was keyed on (path, st_mtime_ns), so an edit to honcho.json
landing inside one mtime tick on a coarse-mtime filesystem kept serving
the previously parsed identity config. Add st_size to the key — it comes
from the single stat() call the memo already makes, so any same-tick
rewrite that changes the file's size is now detected at zero added I/O
on this hot path (it feeds the per-turn agent-cache signature).

Deliberately NOT content-hashed. An equal-size rewrite inside one mtime
tick can still reuse stale parsed state for one cache generation; that
edge is vanishingly rare and self-heals on the next change. Hashing the
file on every lookup would defeat the memo's no-I/O purpose — this is
the exact design the maintainer resolution on NousResearch#46385 declined, naming
st_size as the right-shaped discriminator. A test pins the documented
tradeoff so a future change that silently adds per-lookup I/O surfaces
as a deliberate decision rather than an accident.

Tests cover: same-mtime size-changing rewrite invalidates (verified to
fail against the old key), identical stat reuses the memo without
re-parsing, the equal-size edge stays memoized by design, and stat
failure still returns a parsed config.

Supersedes the earlier content-hash version of this branch, which also
accidentally reverted NousResearch#75581's relay rename behavior via a whole-file
checkout across divergent bases — this rewrite touches only the memo.
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…end-result feedback at fire time (NousResearch#75581)

Staging re-test (2026-07-31, post-74482 image roll): auto-created
threads still stuck on their initial titles; connector telemetry shows
zero thread_rename ops. Root cause is an ordering flaw in the 74482
consume path: BOTH the title-callback registration gate and the
schedule gate read the send-result feedback cache
(_relay_auto_thread_info) — but registration runs BEFORE delivery on
the non-streaming lane, and the auto-title thread races delivery even
when registration survives. The cache read can only succeed AFTER the
connector answers the send, so the rename lane deterministically
disqualified itself on the title turn.

Fix — decide shape early, facts late:
- New _is_relay_discord_channel_lane: SHAPE-only predicate (relay
  Discord channel event, no thread) used by the registration and
  schedule gates; no cache read before delivery.
- _rename_discord_auto_thread_for_session_title: on the relay lane,
  poll the adapter's feedback cache (0.5s ticks, ≤10s) — delivery is
  typically right behind the title. True miss (connector didn't
  auto-thread: policy off, DM, send failed) no-ops exactly as before.

Tests: shape-gate matrix; late-arriving feedback -> rename fires with
only_if_current_name guard; never-arriving feedback -> no-op. Relay
suite 174 passed.
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…ename + trace logs (NousResearch#75912)

Live staging (2026-08-01): relay semantic thread rename still declined
silently despite both NousResearch#74482 and NousResearch#75581 deployed — thread kept its
initial-words name, session title generated fine. Root cause is the
no-clobber guard string mismatch (see paired gateway-gateway PR): the
gateway can't reproduce the thread's initial name byte-for-byte, so the
connector's only_if_current_name check always failed.

- relay rename lane now passes prefer_connector_created=True instead of
  the fragile initial-name string; the connector resolves the guard from
  its own created-name memory. Native-marker lane keeps the legacy
  only_if_current_name string (source carries the real initial name).
- rename_thread: prefer_connector_created param -> only_if_connector_created
  on the wire, precedence over the legacy string.
- INFO logs at rename dispatch (thread/lane/new_title) and result
  (applied=bool): the whole failure hunt needed telemetry the gateway
  never emitted — this makes the outcome visible in fly logs.

Tests: connector-guard wire shape + precedence over legacy string; the
title-turn race test updated to assert the connector-owned guard. Relay
suite 149 passed; ruff + footguns clean.
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 platform/discord Discord bot adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants