diff --git a/packages/thread-view/src/completed-turn-grouping.ts b/packages/thread-view/src/completed-turn-grouping.ts
index df6a8e6a2d..e4e0eafdbb 100644
--- a/packages/thread-view/src/completed-turn-grouping.ts
+++ b/packages/thread-view/src/completed-turn-grouping.ts
@@ -7,7 +7,9 @@ import { getMessageStartedAt } from "./format-helpers.js";
 import {
   findLastTerminalTimelineMessage,
   isSingletonContextManagementOperation,
+  isTimelineTerminalMessage,
   isTimelineUngroupableMessage,
+  isTimelineUserInputBoundaryMessage,
 } from "./timeline-message-helpers.js";
 
 export interface CompletedTurnSummaryGroup {
@@ -167,6 +169,7 @@ function groupCompletedTurnSummaryMessages(
   let groupedMessages: EventProjectionMessage[] = [];
   let segmentIndex = 0;
   let externalBoundaryIndex = 0;
+  let preserveNextTerminalMessage = false;
 
   function appendSummaryGroup(sourceMessages: EventProjectionMessage[]): void {
     if (sourceMessages.length === 0) {
@@ -193,6 +196,8 @@ function groupCompletedTurnSummaryMessages(
     // Human follow-ups split one provider turn into multiple visible exchange
     // segments. Keep each segment's last assistant/error message beside the
     // user row instead of burying it inside that segment's collapsed summary.
+    // The first assistant/error message after user input is kept too — it is
+    // the direct reply the user already read while the turn was streaming.
     const sourceMessages = groupedMessages;
     groupedMessages = [];
     const terminalMessage = preserveLastTerminalMessage
@@ -222,19 +227,31 @@ function groupCompletedTurnSummaryMessages(
     ) {
       flushGroupedMessages(true);
       externalBoundaryIndex += 1;
+      preserveNextTerminalMessage = true;
     }
   }
 
   for (const message of summaryMessages) {
     flushExternalBoundariesBefore(message);
     if (isTimelineUngroupableMessage(message)) {
-      flushGroupedMessages(
-        message.kind === "user" && message.initiator === "user",
-      );
+      const isUserInputBoundary = isTimelineUserInputBoundaryMessage(message);
+      flushGroupedMessages(isUserInputBoundary);
       items.push({
         kind: "ungrouped-message",
         message,
       });
+      if (isUserInputBoundary) {
+        preserveNextTerminalMessage = true;
+      }
+      continue;
+    }
+    if (preserveNextTerminalMessage && isTimelineTerminalMessage(message)) {
+      flushGroupedMessages();
+      items.push({
+        kind: "ungrouped-message",
+        message,
+      });
+      preserveNextTerminalMessage = false;
       continue;
     }
     groupedMessages.push(message);
@@ -244,7 +261,7 @@ function groupCompletedTurnSummaryMessages(
     flushGroupedMessages(true);
     externalBoundaryIndex += 1;
   }
-  flushGroupedMessages();
+  flushGroupedMessages(true);
   return applySingleSummaryTurnBounds(turn, items);
 }
 
diff --git a/packages/thread-view/src/timeline-message-helpers.ts b/packages/thread-view/src/timeline-message-helpers.ts
index 8e3d2c989a..d65a911997 100644
--- a/packages/thread-view/src/timeline-message-helpers.ts
+++ b/packages/thread-view/src/timeline-message-helpers.ts
@@ -25,9 +25,24 @@ export function isTimelineUngroupableMessage(
   if (message.kind === "assistant-text") {
     return message.isLegacyUserMessage === true;
   }
+  if (message.kind === "user-question-lifecycle") {
+    return message.lifecycle === "answered";
+  }
   return message.kind === "debug/raw-event";
 }
 
+export function isTimelineUserInputBoundaryMessage(
+  message: EventProjectionMessage,
+): boolean {
+  if (message.kind === "user") {
+    return message.initiator === "user";
+  }
+  return (
+    message.kind === "user-question-lifecycle" &&
+    message.lifecycle === "answered"
+  );
+}
+
 export function isTimelineSummaryCountedMessage(
   message: EventProjectionMessage,
 ): boolean {
diff --git a/packages/thread-view/test/completed-turn-grouping.test.ts b/packages/thread-view/test/completed-turn-grouping.test.ts
index aa24884073..b0279fbaf0 100644
--- a/packages/thread-view/test/completed-turn-grouping.test.ts
+++ b/packages/thread-view/test/completed-turn-grouping.test.ts
@@ -266,7 +266,7 @@ describe("groupCompletedTurnMessages", () => {
       {
         kind: "summary",
         startedAt: 1,
-        completedAt: null,
+        completedAt: 3,
         segmentIndex: 0,
         summaryCount: 1,
       },
@@ -277,17 +277,13 @@ describe("groupCompletedTurnMessages", () => {
         },
       },
       {
-        kind: "summary",
-        startedAt: 3,
-        completedAt: null,
-        segmentIndex: 1,
-        summaryCount: 1,
+        kind: "ungrouped-message",
+        message: {
+          id: "assistant-after",
+        },
       },
     ]);
-    expect(summarySourceMessageIds(groups)).toEqual([
-      ["assistant-before"],
-      ["assistant-after"],
-    ]);
+    expect(summarySourceMessageIds(groups)).toEqual([["assistant-before"]]);
   });
 
   it("slices terminal and trailing messages out of the summary groups", () => {
diff --git a/packages/thread-view/test/completed-turn-user-input-visibility.test.ts b/packages/thread-view/test/completed-turn-user-input-visibility.test.ts
new file mode 100644
index 0000000000..94370f4592
--- /dev/null
+++ b/packages/thread-view/test/completed-turn-user-input-visibility.test.ts
@@ -0,0 +1,158 @@
+import type { ThreadEventRow } from "@bb/domain";
+import { turnScope } from "@bb/domain";
+import { describe, expect, it } from "vitest";
+import {
+  createTimelineEventFactory,
+  renderTimelineFixture,
+} from "./timeline-test-harness.js";
+import type { TimelineEventFactory } from "./timeline-test-harness.js";
+
+function topLevelAssistantTexts(
+  rows: ReturnType<typeof renderTimelineFixture>["rows"],
+): string[] {
+  return rows.flatMap((row) =>
+    row.kind === "conversation" && row.role === "assistant" ? [row.text] : [],
+  );
+}
+
+function renderTimeline(
+  events: ThreadEventRow[],
+  threadStatus: "active" | "idle",
+) {
+  return renderTimelineFixture({
+    events,
+    projectionOptions: {
+      threadStatus,
+      turnMessageDetail: "summary",
+    },
+  });
+}
+
+function answeredUserQuestionEvent(seq: number): ThreadEventRow {
+  return {
+    id: `evt-user-question-${seq}`,
+    threadId: "thread-1",
+    seq,
+    createdAt: seq,
+    scope: turnScope("turn-1"),
+    type: "system/userQuestion/lifecycle",
+    data: {
+      interactionId: "pint_question_1",
+      providerId: "claude-code",
+      providerRequestId: "request-question-1",
+      status: "resolved",
+      resolution: {
+        kind: "user_answer",
+        answers: {
+          "question-1": { selected: ["all"] },
+        },
+      },
+      statusReason: null,
+      payload: {
+        kind: "user_question",
+        questions: [
+          {
+            id: "question-1",
+            prompt: "Which changes should I include?",
+            shortLabel: "Scope",
+            multiSelect: false,
+            options: [
+              { value: "all", label: "All of them" },
+              { value: "none", label: "None" },
+            ],
+            allowFreeText: false,
+          },
+        ],
+      },
+    },
+  } as ThreadEventRow;
+}
+
+describe("completed turn user input visibility", () => {
+  function buildSteerEvents(event: TimelineEventFactory, completed: boolean) {
+    const request = event.clientTurnRequested({
+      target: { kind: "new-turn" },
+      text: "Check my router setup",
+    });
+    const steer = event.clientTurnRequested({
+      target: { kind: "steer", expectedTurnId: "turn-1" },
+      source: "tell",
+      text: "explore but do not apply changes",
+      requestId: "creq_steersteer" as never,
+    });
+    const events: ThreadEventRow[] = [
+      request,
+      event.turnStarted(),
+      event.inputAccepted({ clientRequestId: request.data.requestId }),
+      event.assistantCompleted({ itemId: "a1", text: "Starting the audit." }),
+      steer,
+      event.inputAccepted({ clientRequestId: steer.data.requestId }),
+      event.assistantCompleted({
+        itemId: "a2",
+        text: "Understood - read-only only.",
+      }),
+      event.commandCompleted({ itemId: "tool-1", command: "ssh router" }),
+      event.assistantCompleted({ itemId: "a3", text: "Login works." }),
+      event.assistantCompleted({
+        itemId: "a4",
+        text: "Audit complete. Nothing was changed.",
+      }),
+      event.assistantCompleted({ itemId: "a5", text: "Final runbook." }),
+    ];
+    if (completed) {
+      events.push(event.turnCompleted());
+    }
+    return events;
+  }
+
+  it("keeps the direct reply and the segment-final message visible after a steered turn completes", () => {
+    const event = createTimelineEventFactory({ threadId: "thread-1" });
+    const runningTexts = topLevelAssistantTexts(
+      renderTimeline(buildSteerEvents(event, false), "active").rows,
+    );
+    expect(runningTexts).toContain("Understood - read-only only.");
+    expect(runningTexts).toContain("Audit complete. Nothing was changed.");
+
+    const completedEvent = createTimelineEventFactory({ threadId: "thread-1" });
+    const completedTexts = topLevelAssistantTexts(
+      renderTimeline(buildSteerEvents(completedEvent, true), "idle").rows,
+    );
+    expect(completedTexts).toContain("Understood - read-only only.");
+    expect(completedTexts).toContain("Audit complete. Nothing was changed.");
+    expect(completedTexts).toContain("Final runbook.");
+    expect(completedTexts).not.toContain("Login works.");
+  });
+
+  it("keeps an answered question and the report preceding it visible after the turn completes", () => {
+    const event = createTimelineEventFactory({ threadId: "thread-1" });
+    const request = event.clientTurnRequested({
+      target: { kind: "new-turn" },
+      text: "Audit the router",
+    });
+    const timeline = renderTimeline(
+      [
+        request,
+        event.turnStarted(),
+        event.inputAccepted({ clientRequestId: request.data.requestId }),
+        event.commandCompleted({ itemId: "tool-1", command: "ssh router" }),
+        event.assistantCompleted({
+          itemId: "a1",
+          text: "Audit complete. Which changes should I include?",
+        }),
+        answeredUserQuestionEvent(6),
+        event.assistantCompleted({ itemId: "a2", text: "Final runbook." }),
+        event.turnCompleted(),
+      ],
+      "idle",
+    );
+
+    const texts = topLevelAssistantTexts(timeline.rows);
+    expect(texts).toContain("Audit complete. Which changes should I include?");
+    expect(texts).toContain("Final runbook.");
+    expect(
+      timeline.rows.some(
+        (row) => row.kind === "work" && row.workKind === "question",
+      ),
+    ).toBe(true);
+  });
+});
