Skip to content

cmux-next agent pane: don't snap a small scroll-up back to the latest row - #16498

Merged
teamleaderleo merged 5 commits into
feat-cmux-nextfrom
nx-pane-no-snapback
Oct 1, 2026
Merged

teamleaderleo merged 5 commits into
feat-cmux-nextfrom
nx-pane-no-snapback

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

If a reader at the latest row of the agent pane scrolls up slightly while a row below finishes drawing shorter, they now stay where they scrolled. Until now the transcript could snap them back to the latest row.

The anchor effect detects when the browser has clamped the scroll offset after the content shrank. Before this change it treated any offset within 1px of the layout's fractional end as clamped, because the browser rounds scrollHeight. That 1px also caught a real scroll-up of U when the shrink S satisfied S < U ≤ S + 1. A clamped offset lands exactly on the scroller's own end, scrollHeight - clientHeight, so the check now compares against that with a 0.5px allowance. This is a follow-up from the #16491 review.

Stacked on #16497 (same layout effect). Once that merges, this branch takes feat-cmux-next and the diff narrows to the two commits below.

Validation

cd webviews && bun test src/agent-session/

  • Red at 4db8286: a small scroll-up at the latest row survives a row below drawing shorter fails. The reader scrolls up 10.75px, then the latest row draws 10px shorter. The view snaps to the new end, 8474, instead of staying at 8473.25. The fake viewport now reports scrollHeight.
  • Green at 469359e: 147 of 147 pass. bunx tsc --noEmit -p . and oxlint --deny-warnings are clean, and build-agent-pane-web.sh --check says the bundle is current.

Not checked in a running app. The test's fake viewport assumes a clamp lands exactly on scrollHeight - clientHeight. WebKit keeps element scroll positions on whole pixels, so that should hold, but nobody has checked it live.

Changelog

none (cmux-next is unreleased)

🤖 Generated with Claude Code

https://claude.ai/code/session_01RYQHfug1ZVQDp4eWgwVUtD


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixes the agent pane snapping a small scroll-up back to the latest row when a row below draws shorter, and keeps the latest row in view when the viewport shrinks.

Bug Fixes

  • A small scroll-up at the latest row no longer snaps back when a row below draws shorter; the clamp check now uses the scroller's own end rather than a fractional layout height.
  • Shrinking the viewport (e.g., a permission card appearing) keeps the latest row in view; an offset that hasn't moved keeps its recorded at-latest state.
  • Merged the latest feat-cmux-next changes to keep this branch current.

Written for commit e72c736. Summary will update on new commits.

Review in cubic

teamleaderleo and others added 4 commits October 1, 2026 17:14
Red: at the latest row of 200 rows, shrinking the viewport from 600 to
400 leaves scrollTop at 8400 against a new end of 8600, so the latest
row's last 200px fall below the fold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RYQHfug1ZVQDp4eWgwVUtD
A shorter viewport doesn't move or clamp the offset, so the at-latest
check against the new client height read a reader at the latest row as
scrolled up. An offset that hasn't moved since it was recorded now
keeps the recorded at-latest state.

Green: bun test src/agent-session/ passes 146 of 146.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RYQHfug1ZVQDp4eWgwVUtD
…horter

The fake viewport now reports scrollHeight. Red: at the latest row,
scrolling up 10.75px and then having the latest row draw 10px shorter
before the scroll event leaves the reader 0.75px above the new end. The
clamp check's 1px tolerance reads that as a clamp and snaps to 8474
instead of keeping 8473.25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RYQHfug1ZVQDp4eWgwVUtD
The clamp check allowed 1px under the layout's fractional end, to cover
the browser rounding scrollHeight. That also caught a reader who had
scrolled up within 1px of a new end that a row below had just
shortened, and snapped them back to the latest row. A clamped offset
lands exactly on scrollHeight - clientHeight, so the check now compares
with that and allows half a pixel.

Green: bun test src/agent-session/ passes 147 of 147.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RYQHfug1ZVQDp4eWgwVUtD
@cursor

cursor Bot commented Oct 1, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 2eb942da-7043-44a5-9ee4-595a601d105d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

…snapback

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/Resources/agent-pane/index.html
#	webviews/src/agent-session/acpmux/App.tsx
#	webviews/src/agent-session/acpmux/transcript.test.tsx
@cursor

cursor Bot commented Oct 1, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Subagent review at e72c736: LGTM.

  • WebKit clamps an overflow scroller to scrollableContentsSize - visibleSize. That's the same rounded integer scrollHeight returns, and overflow scroll positions are whole pixels even at DPR 2. So a real clamp lands exactly on scrollHeight - clientHeight, and the 0.5 allowance catches it.
  • scrollHeight is the browser's real scroll extent. It's more accurate than the model's totalHeight.
  • Reading scrollTop first already forces layout, so scrollHeight reflects the spacer that was just committed.
  • Residual risk, not checked on a device and not new: a clamp is missed only if WebKit's visible height rounded differently from clientHeight. The old -1 tolerance on an unrounded total had a similar edge.
  • Test nits: the repro scrolls up a fractional 10.75px, and the fake scrollHeight isn't rounded. The logic is still modelled correctly.
  • 147/147 bun test, tsc and oxlint clean, bundle current. The new test fails on base App.tsx (8474 against 8473.25) and passes at the head.

@teamleaderleo
teamleaderleo merged commit c1f2212 into feat-cmux-next Oct 1, 2026
46 checks passed
@teamleaderleo
teamleaderleo deleted the nx-pane-no-snapback branch October 1, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant