fix(rag): stop the per-run blocks from folding — the container is the one disclosure
Build and Push Containers / build-and-push-app (push) Successful in 1m43s
Build and Push Containers / build-and-push-db (push) Successful in 15s

The owner refinement (2026-10-06): the per-run thinking and tool-call
blocks inside the Reasoning bubble were individually collapsible
details elements — a fold inside the fold. A tool frame closed the
previous thinking block, so the visible thinking vanished mid-turn;
and the pinned-tail follow died on the append of every run after the
first (the pin was captured AFTER the new block's height growth
contaminated the 32px reading).

- app.js: the in-container runs are now plain divs —
  createThinkingRunEl (div.thinking + static .thinking-summary label +
  .thinking-text) and createToolRunEl (div.tool-calls-disclosure +
  static .tool-calls-summary label + the .tool-calls list); they never
  open or fold (the container is the ONE open/fold control, open
  through the turn, folded at settle — unchanged); the pin capture
  moves BEFORE ensureThinkingRun/ensureToolRun append (plus the
  first-frame edge: no container yet -> always pinned);
  closeCurrentRun just ends the run; closeAllRuns stays the defensive
  legacy guard; restoreTimeline/addSegments (shared.js) use the div
  builders; the legacy no-segments restore path keeps the old
  details-based blocks byte-identical
- styles.css: the in-container runs are distinct by label + rail
  (brand-ink Thinking label on a brand-soft rail; accent-ink
  Tool call(s) (N) label on a neutral rail); the interactive
  treatment (cursor + chevron) is scoped to the legacy <summary>; the
  inner windows stay disabled (the container's .reasoning-body is the
  ONE live scroll surface)
- unit + E2E: the D5-refinement contract is pinned — one
  details.reasoning disclosure, per-run blocks as plain divs, zero
  nested <details> inside the container, the container as the only
  open/fold control, the .reasoning-body window auto-follows the
  tail while streaming

unit+integration 3738 passed (coverage 99%), ruff + pyright clean, all
five affected E2E suites pass in isolation (reasoning_bubble 6,
thinking_timeline 6, thinking_display 5, thinking_scroll 8,
tool_call_compact 4), verified live: the follow holds through a long
thinking stream, the tool-frame transition, and the second thinking
run; restore renders the div structure without client-side errors

LLM-Generated: true
This commit is contained in:
2026-10-06 14:44:41 -04:00
parent 051f62deb7
commit 690fd98036
15 changed files with 941 additions and 609 deletions
+11 -9
View File
@@ -457,17 +457,19 @@ open, its summary carries a live status ("Thinking…" /
settles; a turn with no thinking and no tools renders no bubble at all
(the answer layout is byte-identical to pre-phase).
The per-run blocks keep their own open/fold behavior: each block opens
and fills in live while its run streams, and the runs tuck themselves
away when the first answer token lands, when the turn ends, or when the
turn is stopped/failed — and every block and tool-call disclosure stays
click-toggleable afterwards (the bubble's summary is the at-rest entry
point).
The per-run blocks are plain and always visible inside the open
bubble: each block appears and fills in live while its run streams,
and the runs simply stop accumulating frames when the first answer
token lands, when the turn ends, or when the turn is
stopped/failed. They are distinct from each other by label + rail:
the brand-ink "Thinking" label on a brand rail, the accent-ink
"Tool call(s) (N)" label on a neutral rail.
The tool calls ride the same timeline: each contiguous run of tool
calls gets its own collapsed-when-idle "Tool call(s) (N)" disclosure
(one per run, in arrival order), and the per-line elapsed-seconds
suffix targets the newest line of the active run.
calls gets its own "Tool call(s) (N)" block (one per run, in
arrival order; always visible while the bubble is open), and the
per-line elapsed-seconds suffix targets the newest line of the
active run.
The timeline is persisted with the saved turn (an optional `segments`
array — the per-run order; the concatenated `thinking` and the `tools`