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,