Skip to content

chat: the folded thinking row does not clip to its column — one long reasoning line runs wide #1718

Closed

Description

@HugoXK

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.

Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: e8cbef8015f64f94bd5eb680f6940a53
Branch: dev/1-think-row-clip
Base: aafb8d7

What — the folded thinking row (ThinkingRow in core/src/client/cells.js:159-169, styles at core/src/client/styles.js:886-900) does not stay inside its column. With a long reasoning line the summary renders as one wide strip that runs past the message column instead of clipping to it; the preview's ellipsis never appears.

Why it happens (diagnosis, live main aafb8d74)

  • .bt-think{max-width:min(560px,78%)} sets the ceiling on the <details> box, but .bt-think summary{display:inline-flex;align-items:center;gap:6px} (styles.js:887) is shrink-to-fit inside that box: an inline-flex container sizes to its content, so the summary's used width is the full unbreakable line, and it overflows the details box (which sets no overflow). The parent's max-width therefore never reaches the summary, so the peek has nothing to clip against.
  • .bt-think-peek{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} (:891) is correct for a flex item that is being squeezed; with the summary at max-content there is no squeeze, scrollWidth === clientWidth, and no ellipsis.
  • The opened body .bt-think-text{white-space:pre-wrap} (:900) has no overflow-wrap, so a 2000-character token without breaks also overflows when open.

Reproduction (behaviour, no missing export) — corrected measurement

Render ThinkingRow through the real cell path (AssistantCell → ThinkingRow) with a 2000-character reasoning line containing no \n and no spaces, put the produced DOM into a container carrying the live CONVERSATION_CSS, and measure real layout. Measured on top of #1708 (base a932752d, this row's CSS untouched there):

container details width summary clientWidth peek client / scroll
900 px 560 1308 1174 / 1236
400 px 312 1308 1174 / 1236

So the failure is the summary is wider than its own details box (1308 vs 560 / 312) — that is the strip that runs out of the column. Two assertions first drafted in this issue do not fail on base and are replaced: summary.scrollWidth <= summary.clientWidth already holds (1308 ≤ 1308, the summary is laid out at max-content) and peek.scrollWidth > peek.clientWidth already holds (1236 > 1174, an ellipsis is painted inside that over-wide box). The red assertions are:

  • at both widths summary.clientWidth <= details.clientWidth — fails today (1308 > 560 / 312)
  • at both widths the peek is bounded by the details box: peek.clientWidth <= details.clientWidth and getComputedStyle(peek).textOverflow === 'ellipsis' — fails today (1174 > 560 / 312)
  • the row is still folded (details.open === false), the caret and the label are present — passes today, must keep passing.

Test placement: npm test runs jsdom, which does no layout, so scrollWidth/clientWidth are 0 in suite, and verify/CI has no browser. The suite case therefore mounts the same 2000-character reasoning against the real CONVERSATION_CSS and asserts the containment properties that produce the clipping (summary max-width / min-width, peek max-width, overflow-wrap on the opened body) at 900 px and 400 px — red on base. The geometry numbers above are measured out of suite with the local headless Chromium (chrome-headless-shell, raw CDP, no npm dependency) and go into the PR body as evidence, not into CI.

Expected fix (keep it minimal; the fold is the design, do not unfold it)

  1. Give the summary a bound it cannot escape: .bt-think summary{max-width:100%;min-width:0} (and overflow:hidden on the summary is acceptable only if the caret stays visible), so the inline-flex box can be squeezed by the details box.
  2. Keep the peek min-width:0; add max-width:100% so its ellipsis has a box to fill.
  3. Opened body: .bt-think-text{overflow-wrap:anywhere} (keep white-space:pre-wrap; do not switch to pre-wrap + wrap-only-at-spaces).
  4. Do not turn the summary into a multi-line block, do not raise max-width to the full column, do not hide the peek when it is long.

Acceptance

  1. Red-first in suite on live main: the case that mounts the real CSS with the 2000-character reasoning fails on base on the containment properties (summary max-width: none / min-width: auto, peek max-width: none, opened body overflow-wrap: normal), at 900 px and 400 px.
  2. Measured geometry recorded in the PR body: base summary 1308 vs details 560 / 312; after the fix summary 560 / 312, peek 488 / 240, opened body 560/560 and 312/312 (wrapped, no horizontal overflow).
  3. After the fix: suite case green, row stays folded, caret and Thought it through label unchanged, an opened row with the same 2000-character token stays inside the column.
  4. Existing behaviour kept: an opened row still hides the peek (#1636 rule), a fence-only reasoning line still prints {n} line(s) of reasoning (#1642), and the empty-reasoning case still renders no row (#1624).
  5. TZ=UTC ARCH_DOCS_BASE=<live main> npm run verify exit 0, counts reported; node scripts/ds-bot-patches.mjs check green (the client bundle mirror 0008 must be regenerated by the build, not hand-edited).

Scope — core/src/client/styles.js, core/test/… (one new or extended client test), core/client.js + patches/ds-bot/{0008,files/…} regenerated by the build. No host change, no endpoint, no new setting.

Duplicate check (before opening, per Chief's rule): open issues searched for think, reasoning, wrap, ellipsis, nowrap, truncat → no open match. Closed neighbours are adjacent but different: #1642 (peek could show a fence line or a broken glyph), #1636 (an opened row printed its first line twice), #1624 (thinking block painted as an empty strip). None covers a row that does not clip to its column.

Activity

  1. HugoXK commented on Oct 29, 2026

    @HugoXK
    ContributorAuthor

    Release

    Written-by: FlyBot Lead
    Released: e8cbef8015f64f94bd5eb680f6940a53
    Reason: shipped: #1721 merged 703bead (merged_at 2026-10-29T17:26:24Z)
    At: 2026-10-29T17:30:46Z

  2. added a commit that references this issue on Oct 29, 2026
    703bead
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions