fix(gateway): carry origin_json/display_name into /branch child sessions too

Complete the /branch routing-identity fix (salvaged from PR #62278 by
@jcjc81): in addition to user_id/session_key/chat_id/chat_type/thread_id,
forward origin_json and display_name at create_session() time, matching
the reset-path db_create_kwargs pattern (#82633) so the branch row is
born with full identity — no backfill gap for state.db consumers
(mcp_serve, mirror, channel directory) if a crash lands before
switch_session().

The obsolete compression-rotation half of #62278 was dropped: rotation
now goes exclusively through publish_compression_child, which already
copies all identity columns in-transaction.
This commit is contained in:
Teknium
2026-08-09 14:08:49 -07:00
parent 4f0531c972
commit 59f1aa8bf6
2 changed files with 35 additions and 1 deletions
+22 -1
View File
@@ -4774,6 +4774,20 @@ class GatewaySlashCommandsMixin:
parent_session_id = current_entry.session_id
# Serialize the parent's full origin (same shape as the reset path's
# db_create_kwargs in gateway/session.py, #82633) so the branch row
# carries complete identity from birth. Prefer the live entry's origin
# (it may hold richer metadata than the triggering event's source).
_branch_origin = current_entry.origin or source
_branch_origin_json = None
if _branch_origin is not None:
try:
import json as _json
_branch_origin_json = _json.dumps(_branch_origin.to_dict())
except Exception:
_branch_origin_json = None
# Create the new session with parent link.
# Persist a stable ``_branched_from`` marker in model_config so
# list_sessions_rich() keeps the branch visible in /resume and
@@ -4798,12 +4812,19 @@ class GatewaySlashCommandsMixin:
# IDOR guard too (which requires the row's chat_id/thread_id to
# match the caller's). user_id is critical for the fallback lookup
# path (hermes_state.py:1994-2009) that searches by the complete
# peer tuple when session_key doesn't match.
# peer tuple when session_key doesn't match. origin_json and
# display_name complete the identity (same shape as the reset
# path's db_create_kwargs in gateway/session.py, #82633) so
# consumers that read routing/presentation data from state.db
# (mcp_serve, mirror, channel directory) see the branch row
# fully formed with zero backfill gap.
user_id=source.user_id,
session_key=session_key,
chat_id=source.chat_id,
chat_type=source.chat_type,
thread_id=source.thread_id,
origin_json=_branch_origin_json,
display_name=current_entry.display_name,
)
except Exception as e:
logger.error("Failed to create branch session: %s", e)
@@ -137,6 +137,19 @@ class TestBranchRoutingColumns:
assert row["session_key"] is not None, (
"branched session lost session_key — primary lookup path fails"
)
# origin_json completes the identity (#82633 reset-path pattern):
# consumers reading routing/presentation data from state.db
# (mcp_serve, mirror, channel directory) need the full origin on
# the branch row without waiting for any backfill.
assert row["origin_json"], (
"branched session lost origin_json — state.db consumers see an "
"identity-less branch row until a peer refresh backfills it"
)
import json as _json
origin = _json.loads(row["origin_json"])
assert origin.get("chat_id") == "170829464"
assert origin.get("thread_id") == "544520"
_ = real_switch_session # silence unused