"Your thinking": the learner's voice, first-class in the question dock

The note was the transfer channel of the whole product presented as an
afterthought: an unlabeled one-line slot whispering "optional". Now:

- A labeled composer-TWIN field ("Your thinking") between the options
  and Submit, docked with the submit button inside it exactly like the
  chat composer's send. The placeholder invites dumping ("Why this
  answer? What are you unsure about? Say as much as you like — the
  teacher reads all of this."); the word "optional" is banished.
- Enter makes a NEWLINE in the thinking field (it is for dumping, soon
  dictated); the button submits. Text-mode answers keep Enter-to-submit.
- Phase-scaled prominence: teaching = a generous dump area, probing =
  one quick row (threaded from the session phase via DockOverlay).
- "Other…" (ask questions) is now an editable OPTION ROW — radio circle
  that fills on selection + inline input, styled like its siblings — so
  picking Other never displaces the thinking field; typed text survives
  deselection.
- The answered card promotes the thinking to a quoted first-class
  block above the verdict, labeled "Your thinking" — the transcript
  reads as a dialogue of thinking, not a buried "Note:" footnote.

The frozen core is untouched (the teacher-facing "Note:" transcript
line in question-core.ts is protocol text, flagged to master).
This commit is contained in:
amosblomqvist
2026-09-09 01:57:44 +03:00
parent c061d11fd7
commit d057a5a616
4 changed files with 211 additions and 61 deletions
+6 -1
View File
@@ -24,7 +24,7 @@ import { QuestionDock } from "@/components/question-dock";
import { SidebarToggle } from "@/components/sidebar";
import { SubAgentsPanel } from "@/components/sub-agents-panel";
import { TreePanel } from "@/components/tree-panel";
import type { ArtifactPartProps, JobRecord, QuestionAnswerData, TeacherUIMessage } from "@/src/core";
import type { ArtifactPartProps, JobRecord, Phase3, QuestionAnswerData, TeacherUIMessage } from "@/src/core";
import { PhaseChip, PhaseDivider, planNodeCount } from "@/components/phase-divider";
import { findPendingToolCall, phaseAt3, phaseTimeline } from "@/src/core";
@@ -376,6 +376,7 @@ export function Chat({
<DockOverlay
pending={pending}
requiresReveal={requiresReveal}
phase={phases.at(-1) ?? "probe"}
composer={
<Composer
// Stop applies only to a LOCAL stream: a server-side turn has no
@@ -428,12 +429,15 @@ export function Chat({
function DockOverlay({
pending,
requiresReveal,
phase,
composer,
onSubmitAnswer,
}: {
pending: ReturnType<typeof findPendingToolCall>;
/** Teach-phase pending question: arrives collapsed behind the reveal button (W5). */
requiresReveal: boolean;
/** Session phase at the pending question — scales the thinking field. */
phase: Phase3;
composer: React.ReactNode;
onSubmitAnswer: (output: QuestionAnswerData) => void;
}) {
@@ -587,6 +591,7 @@ function DockOverlay({
input={pending.input as never}
expanded={expanded}
reveal={revealPending}
phase={phase}
onExpand={expandAndReveal}
onSubmit={onSubmitAnswer}
/>