hermes peer dm reaches a hidden Bot Chat that rotated through compression (#106165, salvage #106365) - #106578
Merged
Conversation
…ough compression (#106165) Regression test from PR #106365 (one of its two tests kept: the full peer-dm e2e; the listing-shape test asserted the same row and was dropped). The handler-level fallback that shipped with the test is replaced by a SessionDB fix in the follow-up commit, so this commit carries only the test.
…the tip is untitled `hermes peer dm` resolves the target's canonical Bot Chat with GET /api/sessions?title=Bot%20Chat&include_hidden=1. list_sessions_rich admits the hidden root via the chain search, then _project_compression_tips overwrites every surfaced field — title included — with the live tip's. The title is carried root->tip by the agent AFTER publish_compression_child's transaction; a rotation cut off in between (crash, closed app, the tip's title write failing) leaves "Bot Chat" on the ended root and NULL on the tip, so the projected row carries title=None, the handler's exact-title filter drops it, the peer POSTs a duplicate and the UNIQUE(title) guard answers 400 "Title already in use" (#106165). Fix at the projection: fall back to the root's title only when the tip has none (a titled tip keeps winning). Same COALESCE in the bounded recent- sessions lister, the other place that projects a lineage onto its tip. This replaces the handler-level fallback in PR #106365 (a second lookup path bolted onto _handle_list_sessions with try/except: pass) with a 5-line fix at the one place the title is lost, so every list consumer sees the name. Salvage of #106365 by @Finn763.
Contributor
૮ >ﻌ< ა ci reviewran on 6a86c3c — fix(state): projected compression tip inherits the root's ti
|
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.
hermes peer dmreaches a target whose canonical Bot Chat is hidden and has rotated through compression, instead of failing with HTTP 400Title already in use.hermes_state_sessions.py::_project_compression_tips— when the live tip is untitled, the projected lineage row keeps the root's title instead of overwriting it withNone.hermes_state_sessions.py::list_recent_sessions_bounded— sameCOALESCE(tip.title, s.title)in the SQL projection (the other lineage→tip projector, used bysession_search).tests/gateway/test_peer_dm_hidden_e2e.py::test_peer_dm_reaches_compressed_hidden_bot_chat_e2e(stockpeer dmclient against a realAPIServerAdapter+ realstate.db, from fix(cli): resolve hidden canonical Bot Chat under compression in peer dm lookup (#106165) #106365) andtests/test_hermes_state.py::TestSessionTitleLineage::test_projected_tip_inherits_root_title_when_untitled(DB invariant + negative: a titled tip keeps its own title). Both red onorigin/main, green with the fix.Root cause
_project_compression_tipscopies the tip'stitleover the root's unconditionally; the title is carried root→tip by the agent afterpublish_compression_child's transaction, so a rotation interrupted in between leaves "Bot Chat" on the ended root andNULLon the tip — the projected row then fails the handler's exact-title filter, the peer mints a duplicate and theUNIQUE(title)guard 400s.Validation — live repro (real
APIServerAdapteron loopback TCP, real SQLitestate.dbunder a tempHERMES_HOME, stockhermes peer dmclient; only the model turn stubbed)python /tmp/peer_dm_repro.py <worktree> <label>— hiddenBot Chatroot ended withend_reason=compression, untitled hidden tip:Sabotage (fix reverted, tests kept):
2 failed, 4 passed→ with fix:6 passed.Premise check: with the normal rotation path (
publish_compression_child+_carry_session_state_to_child) the title does land on the tip and the listing already finds it on main; the bug needs the carry to have not run/failed — a real, reachable state (the user hit it), so the fix goes where the title is lost rather than at the HTTP handler.Salvage notes
Salvage of #106365 by @Finn763. Kept: the peer-dm e2e regression test (cherry-picked under their authorship). Replaced: the handler-level fallback in
gateway/platforms/api_server.py::_handle_list_sessions(a secondget_session_by_title+get_compression_tiplookup path withtry/except: passand nestedsuppress(Exception)) by the 5-line projection fix — one lookup path, every list consumer (API server, TUI gateway, dashboard,session_search) sees the name, no swallowed exceptions. Dropped: the listing-shape test (asserted the same row as the e2e test).Closes #106165
Infographic