fix(state): release archived Bot Chat title
This commit is contained in:
@@ -97,7 +97,7 @@ class SessionTitlesMixin:
|
||||
return 0
|
||||
if title:
|
||||
conflict = conn.execute(
|
||||
"SELECT id FROM sessions WHERE title = ? AND id != ?", (title, session_id),
|
||||
"SELECT id, archived, hidden FROM sessions WHERE title = ? AND id != ?", (title, session_id),
|
||||
).fetchone()
|
||||
if conflict:
|
||||
conflict_id = conflict["id"]
|
||||
@@ -105,6 +105,16 @@ class SessionTitlesMixin:
|
||||
# user, so transfer it onto the tip (uniqueness + lineage kept).
|
||||
if self._is_compression_ancestor(conn, ancestor_id=conflict_id, descendant_id=session_id):
|
||||
conn.execute("UPDATE sessions SET title = NULL WHERE id = ?", (conflict_id,))
|
||||
# A deliberately archived hidden Bot Chat is a retired registry
|
||||
# entry, not a live identity. Retire its name in the same title
|
||||
# transaction so a replacement can become the sole canonical row;
|
||||
# the old session remains archived and otherwise untouched.
|
||||
elif (title == self.CANONICAL_BOT_CHAT_TITLE and bool(conflict["archived"])
|
||||
and bool(conflict["hidden"])):
|
||||
conn.execute(
|
||||
"UPDATE sessions SET title = NULL, title_source = NULL WHERE id = ?",
|
||||
(conflict_id,),
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Title '{title}' is already in use by session {conflict_id}")
|
||||
# CAS on the values just read (``IS`` is NULL-safe): a concurrent write between
|
||||
|
||||
@@ -61,6 +61,23 @@ def test_visible_session_titled_bot_chat_stays_renameable(db):
|
||||
assert db.get_session("ordinary")["title"] == "renamed away"
|
||||
|
||||
|
||||
def test_deliberately_archived_canonical_chat_releases_name_for_replacement(db):
|
||||
"""Retiring a Bot Chat must not leave its registry name permanently locked."""
|
||||
retired = _make_canonical(db, "retired")
|
||||
assert db.set_session_archived(retired, True)
|
||||
|
||||
db.create_session("replacement", source="desktop")
|
||||
assert db.set_session_title("replacement", SessionDB.CANONICAL_BOT_CHAT_TITLE)
|
||||
assert db.set_session_hidden("replacement", True)
|
||||
|
||||
# The retired row stays archived, while exact-title resolution reaches the
|
||||
# replacement that Bot Mode will subsequently open.
|
||||
assert db.get_session(retired)["archived"]
|
||||
assert db.get_session(retired)["title"] is None
|
||||
row = db.get_session_by_title(SessionDB.CANONICAL_BOT_CHAT_TITLE)
|
||||
assert row and row["id"] == "replacement"
|
||||
|
||||
|
||||
def test_auto_titler_still_cannot_touch_the_canonical_row(db):
|
||||
# Pre-existing provenance contract, re-pinned here: user-authority title
|
||||
# outranks derived/llm, so the turn-start auto-titler can never displace
|
||||
|
||||
Reference in New Issue
Block a user