Commit Graph
10 Commits
Author SHA1 Message Date
amosblomqvist d5c4c3bf9f ui: the chat comeback — side-based authorship, restored quotes, tucked whys
Blockquotes: the callout override had displaced Streamdown's own styled
blockquote component, so plain quotes rendered as bare unstyled text
since that commit. The pass-through branch now restores Streamdown's
verbatim classes (border-l-4, muted italic).

Explanations tucked for ALL questions (owner): the prediction's Why /
Hide-why toggle is universal — every quiz answered card sits its
explanation behind the same collapsed button. Same pattern, one law.

The thinking row's rhythm: my-1 -> my-3. The 4px margin hugged the
options on non-graded answered cards (owner report); 12px matches the
card's mt-2/mt-3 spacing grammar everywhere the row renders.

Side-based authorship (owner round, 2026-10-07): the document shape
blurred user into agent — three left-rail idioms (user text, user
thinking, quoted prose) collided once quotes rendered. User rows go
RIGHT: 'You' messages and practice thinking cards hug the right edge at
85% width with the rail mirrored (border-r), text still reading
left-to-right. In-card thinking (inside the answered card, the agent's
context) stays left. Transcript thinking rows arrive EXPANDED — the
thinking was clearly sent. Cmd+T (toggle-user-thinking, chat scope,
cheat-sheet row) sets every user-thinking row to one state via a module
store: explicit sets stomp individual toggles, late mounts honor the
last set (the state initializer reads the store, so static render
reflects it too).
2026-10-08 02:29:05 +03:00
amosblomqvist 4eeb05b3c4 practice: the metadata popover — the node-card info-box register, not a drawer (round 17 refinement)
Owner corrections (2026-10-06): no expand/collapse; a quiet METADATA
trigger sits at the card's bottom (no divider — it just sits there);
click opens the info box in the graph-view node card's exact register
(rounded-xl border bg-card p-4 shadow-lg, w-80, floating ABOVE the
trigger so the transcript scroller never clips it); ANY scroll
(capture-phase — every scroller in the tree) or click outside closes
it, plus Esc claimed from the layered chain (usePopoverDismiss, the
popover law). Values match the model solution's font size
(text-[15px], verified — the drawer's text-xs did not); labels keep
the eyebrow register.
2026-10-06 04:26:34 +03:00
amosblomqvist 793638d6ce practice: the agent's data drawer — full transparency on every conclude card (round 17)
Owner ask (2026-10-06): reveal everything the agent filled in when
writing the problem and concluding it, at the very bottom of the
conclude card, collapsible, arriving collapsed.

The fields, both calls:
- problem: mode (recall/discrimination/composition), target
  proposition ids, statement, modelSolution (the last two ARE the
  visible card — the drawer shows the metadata only)
- conclude: outcome, hint rung (R0–R5/null), miss class
  (cue/discrimination/execution/careless/structural/null), retest.

Seams: problemInputForConclude (native-messages) walks the reveal's
walk and folds the WHOLE problem-call input onto the conclude part
(projectView join; same refused-pose law — an unacked pose folds
nothing); ArtifactPartProps grows problemInput. Targets resolve to
proposition NAMES at render (one lazy module-cached /api/graph fetch;
failure degrades to raw ids — observability never breaks the card).
The drawer: divider + chevron 'AGENT'S DATA' toggle (mono-caps
eyebrow register), definition rows with mono values, 'untagged'/
'none' honest empties, absent entirely when the calls filled nothing
(the dismissal line, legacy bare records).
2026-10-06 04:18:26 +03:00
amosblomqvist 05f083748b ui: conclude card — quiz-chip outcomes, verdict-first; YOUR THINKING / AGENT THINKING
Owner round 3 (2026-10-05):

- CONCLUDE CARD: the stacked same-weight headings are gone. Plain
  'Concluded' eyebrow + the outcome in the quiz cards' EXACT chip
  register. Colors per outcome: solved green (the 'correct' twin),
  solvedWithHints amber (succeeded with cost), surrendered red (the
  problem won), movedOn muted (the agent's call, not a verdict against
  the learner). Verdict as plain 50% prose under the heading — the
  'Verdict:' label is gone — then a divider, then the labeled model
  solution.
- ALL-CAPS: 'YOUR THINKING' and 'AGENT THINKING' — display strings only
  (the model-facing marker label stays sentence-case). The two rows are
  equal-length over the shared rail, so the chevrons align vertically.
  Dock field labels match.
2026-10-05 04:14:21 +03:00
amosblomqvist 0bd3236af0 practice: ONE send lane — the register is read from the text
Owner round 2 (2026-10-05), Slice H: the Nudge/Commit two-lane buttons
are gone. One Send; Enter sends, Shift+Enter is a newline. Whether a
submission claims an answer is apparent from the thinking itself — the
agent reads it (hint ladder for traces, moves+verdict for claims).

- The thinking input loses the commit field end-to-end: ChatInput,
  parseChatInput, newThinkingMessage (details and the model-facing label
  both collapse to the single 'Your thinking'), the optimistic marker.
- Legacy records' commit flags are deliberately unread.
- Doctrine: the two labeled channels become one read instruction; 'answer
  commits' section retitled 'Claimed answers' — a claim is not a
  progress signal.
- ThinkingCard: one label, collapsed arrival (the unified row).
- The dock placeholder no longer explains lanes that no longer exist.
2026-10-05 03:46:32 +03:00
amosblomqvist f460a90be9 ui: labeled conclusion sections — 'Model solution' hero, 'Verdict' below
Owner round 2 (2026-10-05), Slice G: 'Solved' alone over unlabeled prose
didn't read as the model solution. The hero now carries its own 'Model
solution' section label (the quiz cards' register), and the verdict
section mirrors it — label muted, text at the same 50% register as quiz
explanations.
2026-10-05 03:42:12 +03:00
amosblomqvist a5a554582e ui: intent-gated fold, measured height caps, the Problem eyebrow, fold fade
Owner round (2026-10-05), Slice D — the dock mechanics:

- INTENT-GATED FOLD: a ResizeObserver on the scroller's content stamps
  the existing 400ms mute whenever the transcript GROWS — growth frames
  (a live turn streaming under stick-to-bottom's chase) can never fold
  the dock; and a fold now needs the distance AND stick-to-bottom's
  isAtBottom agreeing the learner left. Fixes the generation churn
  (dock disappearing and reappearing while the agent works). Shrinks
  stamp nothing (the fold's own morph must not self-mute re-expand).
- MEASURED HEIGHT CAPS: the question (55dvh) and problem (40vh) areas
  now cap at the available column (scroller clientHeight − 2rem,
  re-measured on resize) via --dock-max-h — questions stretch to the
  top bar with sensible padding and scroll internally only when
  genuinely huge.
- The practice dock's statement area carries the 'Problem' eyebrow —
  the quiz cards' label row, mirrored (dock and transcript card read
  identically).
- The fold's CONTENT fade: a 160ms WAAPI fade/rise on the bar↔form
  toggle — no remount, so the question form's state survives; the
  shell height morph was already animated.
2026-10-05 02:31:55 +03:00
amosblomqvist 5d253a933c ui: ProblemCard/ConcludeCard redesigned — the solution is the hero
Owner round (2026-10-05), Slice C:

- ProblemCard: ALWAYS OPEN — the answered card's container + eyebrow
  discipline ('Problem' label, lh-prose statement), no chevron, no
  collapsed bar. The dock mirrors it in Slice D.
- ConcludeCard: the reveal is the modelSolution committed at POSE time,
  shown verbatim as the hero — never re-authored (the slim schema's
  law). The verdict rides below in the quiz-explanation register
  (small, muted 'Verdict:' row). Nothing collapsible. Legacy inputs
  with their own solutionReveal fall back to it.
- The reveal join: modelSolutionForConclude (native-messages.ts) — the
  newest cleanly-posed problem before the conclude call; refused poses
  reveal nothing. projectView enriches tool-conclude parts with
  part.reveal at projection; ArtifactPartProps carries the field
  (contracts/chat.ts).

Pinned: always-open problem card; hero-first conclude layout with the
verdict after it; legacy fallback; the join (clean pose, refused pose,
multi-problem records) and the view enrichment.
2026-10-05 02:29:16 +03:00
amosblomqvist 90893ae236 graph context: a separate marker message before the first user turn
The map picks no longer glue into the opening prompt as seed text
(owner, 2026-10-04 late). POST /api/chats accepts graphContext
{propositions}; the route resolves the picks against the live graph,
derives the reasoning chains among them (chainsForSelection →
formatChainLine), and writes a graph-context custom marker as
message[0] — before the learner's first user message, in either mode.

- Core: newGraphContextMessage (model-facing content = the
  contextualization framing + proposition lines + chain lines;
  details = the structured pick); toLlmMessages flattens it to a user
  message like every marker, so the model reads it for free.
- View: projects to a user-side data-graph-context part.
- UI: GraphContextCard — minimal, muted, dashed, collapsed by default
  (counts only); expand reveals name — statement rows and the chain
  lines. Same compact-expandable pattern as the practice cards.
- Home: sends graphContext with the creation whenever picks exist;
  the prompt param carries the learner's own words only.
2026-10-04 23:07:13 +03:00
amosblomqvist 59bf5bf219 practice UI: the dock, the transcript cards, layered-Esc discard
- PracticeDock (components/practice-dock.tsx): the active problem
  replaces the composer — statement (markdown+LaTeX) above, the 'Your
  thinking' composer-twin below with the two submit lanes (Nudge =
  thinking without a commit; Commit = answer commit; ⌘/Ctrl+Enter
  commits). Dictation claims the thinking field.
- Transcript cards (practice-cards.tsx + the artifact registry): the
  problem card (compact-expandable statement — the commitment NEVER
  renders), the conclude card (outcome + verdict + reveal; the
  dismissal synthesis is one muted line), and the user-side thinking
  register cards (Your thinking / Your solution).
- view.ts: the problem pose joins the placeholder fork (the ack never
  flips the part); practice-thinking markers project as data parts;
  problem-dismissed markers project nothing.
- chat.tsx: activeProblemOf drives the dock branch (question > problem
  > composer), the esc layering gains the problem rung (below question,
  above turn) with its discard confirm + the silent marker route; the
  thinking submissions POST through the session's optimistic appends.
2026-10-04 21:55:54 +03:00