the chat panel's header names a new conversation too
The list learned the name and the panel header did not, which narrowed it to one lookup: the panel records its session id, and ChatHeader resolves the title by finding that id in the sessions LIST. The panel was recording `chat.sessionId` — OFFICER's session key — and the list is keyed on Claude's TRANSCRIPT id. Two id spaces on either side of one `find`, so it never matched: a new chat's header read "New chat" for the whole life of the conversation and offered no rename, because rename is a per-row action on a list the session was not found in. Selecting the conversation from the list fixed it, which is exactly why navigating away and back looked like the cure. Same trap as the Command HQ pane on 2026-08-21, third time this pair has caused a bug: officer's handle and the harness's transcript id are not interchangeable, and every place that keys one lookup on the other fails silently rather than loudly. The "only a REAL id, never null" rule is unchanged and still needed — both ids are null for a moment while a resumed session connects, and writing that null would turn "this panel has never chosen" into "the user asked for a new chat", so the next reload would open blank. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -84,16 +84,23 @@ const ChatPanelInner = ({
|
||||
|
||||
useEffect(() => {
|
||||
setActiveSession(chat.sessionId);
|
||||
// Only a REAL id, never null.
|
||||
//
|
||||
// A new chat is nameless until the harness names it on the first turn, and recording that id is what
|
||||
// makes "New chat, say something, reload" return to that conversation instead of a third one. But
|
||||
// `chat.sessionId` is also null for a moment while a resumed session connects — and writing that null
|
||||
// would turn "this panel has never chosen" into "the user asked for a new chat", so the next reload
|
||||
// would open blank. Asking for a new conversation is something the header says explicitly; this
|
||||
// effect only ever reports what the harness decided.
|
||||
if (chat.sessionId) onSessionId?.(chat.sessionId);
|
||||
}, [chat.sessionId]);
|
||||
/*
|
||||
`claudeSessionId`, NOT `sessionId`. The panel's stored id is looked up in the sessions LIST — see
|
||||
`ChatHeader`'s `sessions.find((s) => s.id === sessionId)` — and that list is keyed on Claude's
|
||||
transcript id. Recording officer's own session key here put two id spaces on either side of one
|
||||
lookup: it never matched, so a new chat's header read "New chat" for the life of the conversation and
|
||||
offered no rename, because rename is a per-row action on a list the session was not found in.
|
||||
Selecting the conversation from the list fixed it, which is why navigating away and back appeared to
|
||||
be the cure.
|
||||
|
||||
Only a REAL id, never null. A new chat has none until the harness names its transcript on the first
|
||||
turn, and recording it is what makes "new chat, say something, reload" return to that conversation
|
||||
rather than a third one. Both ids are also null for a moment while a resumed session connects, and
|
||||
writing that null would turn "this panel has never chosen" into "the user asked for a new chat", so
|
||||
the next reload would open blank.
|
||||
*/
|
||||
if (chat.claudeSessionId) onSessionId?.(chat.claudeSessionId);
|
||||
}, [chat.sessionId, chat.claudeSessionId]);
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 flex-col">
|
||||
|
||||
Reference in New Issue
Block a user