Skip to content

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

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-think-row-clip
Oct 29, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-think-row-clip

Conversation

@HugoXK

@HugoXK HugoXK commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1718

Written-by: Dev-1
Owner: Dev-1
Reviewer: Reviewer
Branch: dev/1-think-row-clip
Base: f0159ea (live main; the issue named aafb8d7, then #1708 moved main to a932752, #1717/#1716 to f8e4943, and #1715 to f0159ea. styles.js and this row's DOM are byte-identical on all of them; #1715 re-rendered core/client.js and re-encoded patches/ds-bot/0008, which made this branch conflict, so it is rebased once onto f0159ea and the mirrors are regenerated)
Tip: acb38f4
Tree: 95d9c33595167af16306531563f0564c798acb46

Docs-not-needed: #1718 bounds three CSS rules of the thinking row; no architecture, interface or contract changes.

What changed

The folded thinking row is a <details class="bt-think"> whose <summary> is one inline-flex line. An inline-flex box sizes to its content, so a reasoning line without a break (a 2000-character run) made the summary wider than the box it lives in: 1308 px inside a details box capped by max-width:min(560px,78%) (560 px at a 900 px column, 312 px at 400 px). The details box therefore never constrained the row, and the opened body had no break opportunity either.

Four declarations, all in core/src/client/styles.js:

  • .bt-think summary gains max-width:100%;min-width:0;white-space:nowrap. max-width:100% bounds it by its own details box, min-width:0 lets the flex line squeeze instead of forcing its content width, and white-space:nowrap keeps the label on one line — without it the label shrank to its longest word and wrapped into a three-line stack (summary height 54 px instead of 18 px).
  • .bt-think-peek gains max-width:100%; it already had min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap, so now the ellipsis fills whatever the summary leaves instead of the content width.
  • .bt-think-text gains overflow-wrap:anywhere beside white-space:pre-wrap, so the opened body breaks the unbroken token instead of scrolling.

The fold stays the design: the summary is still one line (display:inline-flex, height 18 px, white-space:nowrap), the caret is untouched and not clipped (nothing sets overflow:hidden on the summary), max-width is not raised, and the preview is still only in the folded state. #1636 (opened row hides the peek), #1642 (fence-only gets “{n} line(s) of reasoning”), #1624 (no reasoning, no row) keep passing.

core/client.js is regenerated (node core/scripts/build-client.mjs), and patches/ds-bot/{0003,0008} + files/test/thinking-row.test.js come from node scripts/ds-bot-patches.mjs generate — no hunk is written by hand. After the rebase onto f0159ea the mirrors are re-emitted: 0003 keeps the stored base bytes with only its src/client/styles.js section replaced by the generator's output (the rest of that file differed by hunk-header text alone), 0008 is the generator's output in the stored header form (this box's git 2.34.1 writes the trailing function hint, the stored file strips it), and the hint-only drift in 0002/0005/0014 is restored to the base bytes. patches check and build-client --check are green.

Evidence: geometry, base → fix

The unit suite runs on jsdom, which lays nothing out — every element reports scrollWidth === clientWidth === 0 — and CI runs no browser, so CI carries the containment assertions below. The geometry was measured on the real path (base a932752d; core/src/client/styles.js and core/src/client/cells.js are byte-identical from a932752d through f8e4943c to f0159ea8, the only base this branch is rebased onto): AssistantCell → ThinkingRow rendered with a 2000-character reasoning line (no \n, no spaces), that exact DOM mounted in a column carrying the shipped CONVERSATION_CSS, in headless Chromium.

Base a932752d:

container details box summary width peek client / line opened body
900 px 560 1308 (escapes by 748) 1174 / 1236 560 / 15397 scrolls sideways
400 px 312 1308 (escapes by 996) 1174 / 1236 312 / 15397 scrolls sideways

At this tip:

container details box summary width peek client / line opened body
900 px 560 560 420 / 1236, ellipsis 560 / 560, wraps
400 px 312 312 172 / 1236, ellipsis 312 / 312, wraps

(The peek's box is 420 / 172 px here rather than 488 / 240: the summary's white-space:nowrap keeps the whole Thought it through label on its line, so 120 px of the row is the label instead of the label wrapping into three lines.)

Folded (open:false), summary height 18 px, the label on one line, caret present — in both states.

Correction to the issue's reproduction, kept on the record: its two initial assertions already pass on the base — summary.scrollWidth <= summary.clientWidth is 1308 <= 1308 (the summary is stretched to its content; what escapes is the summary against its details box), and peek.scrollWidth > peek.clientWidth is 1236 > 1174 (the ellipsis already fires). The defect that actually fails on the base is summary.clientWidth > details.clientWidth (1308 vs 560 / 312), plus the opened body's scrollWidth of 15397 against 560 / 312. That is the shape the suite asserts and the fix removes — so the red is not “a style is missing”.

Tests

core/test/thinking-row.test.js already mounts this row through AssistantCell; it gains three cases:

  • the 2000-character line mounted at 900 px and 400 px in the shipped stylesheet: summary max-width:100%, min-width:0, white-space:nowrap; peek max-width:100% with overflow:hidden;text-overflow:ellipsis;white-space:nowrap; body overflow-wrap:anywhere with white-space:pre-wrap; the details ceiling still min(560px,78%); the row folded with its caret and Thought it through.
  • the fold guard: the summary rule keeps display:inline-flex and white-space:nowrap, sets no overflow:hidden (the caret can never be clipped), and the opened row still carries the whole 2000-character line.
  • the bundle guard: the app loads core/client.js, not the source, so the same three declarations are asserted in the built bundle.

Red first at the base f0159ea8, with only this test file present and the two generated/source files taken from that base (git checkout f0159ea8 -- core/src/client/styles.js core/client.js):

not ok 10 - \#1718: a 2000-character line cannot widen the folded row past its box (900 px and 400 px)
  error: |-
    summary is bounded by its box at 900px
  expected: '100%'
  actual: 'none'
not ok 11 - \#1718: the fold stays the design — one line, no block summary, no hidden caret
  error: 'the label cannot wrap into a stacked block'
  actual: '.bt-think summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:6px}'
not ok 12 - \#1718: the bundle the app loads carries the same containment rules
# tests 12 / # pass 9 / # fail 3

At this tip the same file is 12/12, and the pre-existing #1624 / #1636 / #1642 cases stay green.

What was run

Ran at this tip: TZ=UTC ARCH_DOCS_BASE=f0159ea8 npm run verify → exit 0 (core 2028/2028, social 539/539, tree 125, timeline 129, workflow 279, .github/scripts 549, interop 37, live-e2e 24 — zero not ok; arch-docs: OK (7 changed file(s)); ok 10 patches apply cleanly in order, ok core/ equals ds-bot/ + patches/ds-bot/). node scripts/ds-bot-patches.mjs check printed its three green lines, and node core/scripts/build-client.mjs --check is silent-green. A first run of the same command hit one load-timeout in core/test/room-external.test.js (#198, timed out waiting for the child); that file passes alone (13/13) and the rerun is the run quoted here.

Not run: the smoke test — this is a client CSS change with no core/index.js or src/host/ change; the row's DOM and cascade are covered by core/test/thinking-row.test.js.

Checkpoint

{
  "pr": 1721,
  "claim": "Dev-1",
  "issue": 1718,
  "summary": "The folded thinking row no longer runs past its column. The inline-flex summary was sizing itself to a long unbroken reasoning line (1308 px inside a 560 px details box); it is now bounded by its box with max-width:100% and min-width:0, and white-space:nowrap keeps the label on one line. The preview fills what is left and ellipsizes, and the opened body breaks the same token instead of scrolling sideways. Fold, caret, the peek and the #1624/#1636/#1642 behaviour are unchanged.",
  "files": ["core/src/client/styles.js", "core/client.js", "core/test/thinking-row.test.js", "changelog.d/1718-think-row-clip.fixed.md", "patches/ds-bot/0003-flybot-api-client.patch", "patches/ds-bot/0008-client-bundle.patch", "patches/ds-bot/files/test/thinking-row.test.js"],
  "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=f0159ea8 npm run verify", "result": "green", "at": "acb38f44cd8265c819e52ae0f61fef6ded8477bf" },
  "next": "none — ready for review"
}

The summary is an inline-flex box, so a long reasoning line without breaks
sized it to its content: at 900 px it was 1308 px wide inside a 560 px
details box, and the opened body ran past the column too. Bound the summary
and the preview to their box and let the opened body break anywhere; the
summary stays one line (white-space:nowrap keeps the label from wrapping
into a stack), the caret and the peek stay as they are.

Chromium measurement of the rendered cell at 900 px and 400 px:
summary 1308 / 1308 px before, 560 / 312 px after, inside a 560 / 312 px
details box; the peek fills what is left (423 / 175 px against a 1236 px
line); the opened 2000-character line wraps instead of scrolling to 15397 px.

Docs-not-needed: ThinkFlowLab#1718 bounds three CSS rules of the thinking row; no
architecture, interface or contract changes.

Fixes ThinkFlowLab#1718
@HugoXK
HugoXK force-pushed the dev/1-think-row-clip branch from 6825235 to acb38f4 Compare October 29, 2026 16:56
@Birfy Birfy added the agent-pr Pull request opened by an agent label Oct 29, 2026
@Birfy

Birfy commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at acb38f4
Written-by: Reviewer
Attestation: acb38f4 role=Reviewer

Ran at this tip:

$ node --import ./test/harness-resolve.mjs --test test/thinking-row.test.js   # in core/, TZ=UTC, tip acb38f44
# tests 12  # pass 12  # fail 0
$ git-less revert of the reviewed source: core/src/client/styles.js + core/client.js restored to base f0159ea8, test file kept
# tests 12  # pass 9  # fail 3   (not ok 10/11/12 = the three #1718 cases)
$ node core/scripts/build-client.mjs --check  → exit 0
$ node scripts/ds-bot-patches.mjs check  → ok 10 patches apply cleanly in order; ok core/ equals ds-bot/ + patches/ds-bot/
$ node .github/scripts/enqueue-guard.mjs --pr 1721 --repo ThinkFlowLab/FlyBot  → ALLOW (tier T1, no hold)

Review points:

  • Red first is real and full. With only the reviewed change reverted (styles.js and the built core/client.js at base f0159ea8, the new test kept), exactly the three new #1718 cases fail — summary is bounded by its box at 900px expected 100% got none, the fold guard, and the bundle guard — and the nine pre-existing #1624/#1636/#1642 cases stay green. Green only came back with the change in place.
  • Scope is the change. compare f0159ea8...acb38f44 = 1 commit, 0 behind, 7 files: core/src/client/styles.js (3 lines), regenerated core/client.js (3 lines), core/test/thinking-row.test.js (+85), the two patch mirrors and patches/ds-bot/files/test/thinking-row.test.js (generator output), plus changelog.d/1718-think-row-clip.fixed.md. No hand-written hunk in the mirrors; patches check and build-client --check agree with core/.
  • The fix matches the defect. .bt-think summary was an inline-flex box sizing to its content, so a 2000-character run made it 1308 px inside a 560 px details box. max-width:100%;min-width:0 bounds it by its own box, white-space:nowrap keeps the label one line (the caret is not clipped — nothing sets overflow:hidden on the summary); .bt-think-peek gains max-width:100% so its existing ellipsis fills the remainder; .bt-think-text gains overflow-wrap:anywhere so the opened body breaks the token instead of scrolling. The details ceiling min(560px,78%) is not raised and the fold is not turned into a block.
  • Tests are honest about jsdom. The added cases read the shipped cascade around the real AssistantCell → ThinkingRow DOM rather than claiming layout numbers, and the pixel evidence is stated in the body (base 1308 px vs 560/312; at tip 560/312, body wraps 560/560), with the correction to the issue's own reproduction kept on the record.
  • CI at this sha is green. All 14 check runs on acb38f44 are success (tests-ok, plugins (tree/social/timeline/workflow), package, merge-gate, agent-audience, enqueue-guard, report-only risk tier and reviewed tip). None failed.

Not run: the full core suite on this box — a TZ=UTC node --test "test/*.test.js" attempt died on pthread_create: Resource temporarily unavailable (the box, not the diff: 147 files had already passed and every failure is a spawn error); the tip's CI tests-ok green at this exact sha covers that suite. The smoke test is not needed (no core/index.js or src/host/ change).

Tier is T1 from the diff (client CSS only), so no PASS was required to merge; this review is written anyway and the guard passes with it.

@github-actions github-actions Bot added the pass label Oct 29, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 29, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 29, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 29, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 29, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 29, 2026
Merged via the queue into ThinkFlowLab:main with commit 703bead Oct 29, 2026
15 of 17 checks passed
@Birfy
Birfy deleted the dev/1-think-row-clip branch October 29, 2026 17:26
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants