From 96b83ac6b3af713b9669173ff0710436670e52c5 Mon Sep 17 00:00:00 2001 From: Daniil Perkin Date: Wed, 7 Oct 2026 11:33:57 +0200 Subject: [PATCH] fix(buddy): say what actually disables the new-conversation control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three doc blocks still described the round before the mid-answer stop: the new-conversation button's header said it is disabled mid-turn because newConversation "cannot call back a request already streaming into it", and the conversation list's prop doc and binning paragraph said picking or binning mid-turn is refused and the controls stand down for that window. None of that is true anymore — the move stops the running answer itself (see `stopRunningTurn`) and stays on offer mid-answer; the list is disabled only for an open, a greeting, or a decision in flight (and in team mode), never for a running answer. - The button's header now lists the caller's actual disable terms: team mode, empty conversation, an open or greeting in flight, a proposal decision in flight — and says mid-answer it stays live. - The list's prop doc matches the caller's condition and points at stopRunningTurn for what happens to a running answer. - The binning paragraph now says the session stops a reply still streaming into the conversation being binned, and leaves a running answer in another conversation alone. Comment-only; no behavior change. --- .../buddy/components/BuddyConversationList.tsx | 13 +++++++------ .../buddy/components/BuddyNewConversationButton.tsx | 9 +++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/features/buddy/components/BuddyConversationList.tsx b/src/features/buddy/components/BuddyConversationList.tsx index 66e8ee20..057fede9 100644 --- a/src/features/buddy/components/BuddyConversationList.tsx +++ b/src/features/buddy/components/BuddyConversationList.tsx @@ -14,9 +14,11 @@ type BuddyConversationListProps = { /** Which one is on screen — marked with `aria-current` and the brand tone. */ currentSessionId: string | null; /** - * True while a turn or an open is in flight: picking another conversation would clear the - * thread out from under a reply still streaming into it (the session's guards back this up), - * and binning is refused for the same reason — so its controls stand down with it. + * True while an open, a greeting, or a decision is in flight — and in team mode, whose list is + * there to look at but not to switch away with. The session refuses those moves; this is the + * same state kept here so the list does not offer what the session will bounce. A running + * answer does not disable it: picking or binning the conversation it streams into stops it + * first (see `stopRunningTurn`). */ disabled?: boolean; onSelect: (sessionId: string) => void; @@ -108,9 +110,8 @@ function groupSessions(sessions: BuddySessionSummary[]): SessionGroup[] { * **Binning is a confirmation, not a click.** The trash stands beside the row on hover or * focus (always, on touch), and the dialog spells out what happens before anything does — the * same deal the chat's sidebar struck, because it is the same kind of act. The row is removed - * by the session, which is also what refuses mid-turn: a conversation cannot be binned out - * from under a reply that is still streaming into it, so the controls stand down for that - * window rather than failing after the fact. + * by the session, which stops a reply still streaming into that conversation before the bin + * goes through (see `stopRunningTurn`); binning another row leaves a running answer alone. * * Search filters by title and rows sit under date buckets — the shape the chat's sidebar had, * kept because a list that only grows is a wall by the tenth conversation. Both are client-side diff --git a/src/features/buddy/components/BuddyNewConversationButton.tsx b/src/features/buddy/components/BuddyNewConversationButton.tsx index 864ab4c0..751dcab0 100644 --- a/src/features/buddy/components/BuddyNewConversationButton.tsx +++ b/src/features/buddy/components/BuddyNewConversationButton.tsx @@ -13,10 +13,11 @@ import { MessageSquarePlus } from "lucide-react"; * would undo what one shared header is for. Same chrome and same corner treatment as * `RailToggle`, on the opposite side, so the two never meet. * - * Always on screen, disabled by its caller while starting one is not possible — mid-turn, for the - * reason `BuddyDock` withdraws its own copy (`newConversation` clears the thread, but cannot call - * back a request already streaming into it), or while the conversation is still empty. A control - * that came and went read as a missing button. + * Always on screen, disabled by its caller while starting one is not possible: in a team + * conversation, while the conversation is still empty, while a conversation is opening or being + * greeted, or while a proposal decision is in flight. Mid-answer it stays live — the move stops + * the running answer itself (see `stopRunningTurn`). A control that came and went read as a + * missing button. */ export function BuddyNewConversationButton({ onClick,