Skip to content

Polish message and thread spacing, grouping, and typography - #364

Merged
wesbillman merged 16 commits into
mainfrom
am-message-polish
Sep 29, 2026
Merged

wesbillman merged 16 commits into
mainfrom
am-message-polish

Conversation

@mahanti

@mahanti mahanti commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Messages and thread replies had oversized gaps and repeated headers that interrupted reading. This change groups consecutive same-author messages within five minutes and shares typography and spacing across timelines and threads.

  • Respect author, channel, day, and membership boundaries when grouping.
  • Use medium author names, clock-only bylines with full accessible dates, centered continuation clocks, smaller reply counts, media spacing, and pretty wrapping for prose.
  • Keep dates visible with day/year dividers in timelines (including complete single-day DMs), threads, and media comments.
  • Float desktop hover/focus actions without reserving message height, including narrow mouse-driven windows. Keep full-header actions above the prose with their lower edge at the byline; place continuation actions above their prose. Touch actions remain visible below content.
  • Simplify the overflow menu: retain Copy link in the toolbar, remove its duplicate menu item and separators, add envelope read/unread icons, and shorten Report. Keep Copy link available in narrow rows.
  • Batch Virtua resize delivery outside native observer callbacks to avoid resize loops, with cancellation, retired-target, and remount coverage. Handle the IndexedDB timeout race when native transaction completion precedes its queued event.

Validation (earlier focused runs identified below):

  • Required hooks passed: TypeScript, 5,065 unit tests across 420 files, and design checks. All feature commits have DCO sign-offs; hosted DCO passes.
  • 24 focused Chromium/WebKit browser checks passed on an earlier merged snapshot: paging/reading anchors, actions and link hit testing, keyboard/touch menus, historical DM/thread dates, media-comment dates, and crowded nested branches.
  • Two browser cases added, none removed. They cover actual hover/focus geometry and hit testing, plus real virtualized DM/thread integration that jsdom cannot establish. Both new cases failed on the prior code in both engines and passed with the fixes. Existing media-comment coverage now asserts visible dates.
  • The complete new-message and presence files also passed in both engines (18 checks) after correcting a stale no-date expectation and reducing the presence-only fixture so its author header stays mounted. All presence assertions remain intact.
  • Fixed a traced bottom-follow race: the existing list-height observer records a native shrink/clamp before a rapid append can obscure it. The new controlled-order regression failed before the fix; all 86 timeline owner tests and all 6 membership browser cases pass. Initial-position and reader-input guards remain intact.
  • After merging current main’s attachment-layout update, all 20 attachment-strip, message-action, and membership browser checks passed in both engines. Main’s thumbnail strips retain their own spacing, and image keyboard focus outlines remain visible.
  • Independent review found no remaining code blockers. Current main was integrated, including its incoming message-control changes.
  • Fixed cold-reload restoration being discarded when a row refresh arrives before the first measured height. Preserve the original saved anchor across that refresh, while respecting reader input and remapped membership IDs. Controlled-order regression coverage failed before the fix; all 88 timeline owner tests, 10 isolated browser measurements, and 6 membership cases pass on the final code in Chromium and WebKit.
  • At 189c757a, all six hosted browser shards and browser measurements passed. JavaScript failed in the relay discovery suite’s fixture setup with a 10-second hook timeout; no assertion or timeout was weakened. Fresh CI is required for the latest UI update. Native acceptance remains untested; Windows validation is skipped by the automatic workflow.
  • The standalone WebKit wheel-input fixture now registers its existing blocking policy before hover establishes native input regions. Partial gestures and rejected blocked input pass in both engines; no assertion, tolerance, timeout, or retry was weakened.

Remaining review requirements:

  • Screenshot remediation remains open. Earlier live-community screenshots were published in a PR comment; review flagged private community content. Removing the embeds is pending the author's response, and removal of uploaded assets must be confirmed separately. No additional live-community captures will be published.
  • Final human acceptance and code-owner approval remain required. To try the latest change: hover or keyboard-focus a continuation in a narrow conversation and open its More menu; controls should float above continuation prose, remain clear of full-header prose, and never move neighboring messages. Open an old DM, its thread, or media comments and confirm the day/year is visible without hovering.

Latest UI follow-up (3f138548): 12 message-action browser cases pass across Chromium/WebKit, including narrow mouse layouts, continuation geometry/link hit testing, keyboard menus, and touch access. All 28 focused menu/report/management unit tests and 58 message-row tests pass. Mandatory push checks pass at this head: TypeScript, all 5,065 unit tests across 420 files, and design checks. Independent review: no remaining code blockers. No browser cases added or removed in this follow-up.

CI repair at 05284d94 (including current main):

  • Keep a full-header floating toolbar’s lower edge at the byline so even a wrapping toolbar cannot cover message prose; no row height is reserved. All four crowded nested-thread widths pass in both engines, including hover hit testing and collapse/reopen focus. Narrow mouse controls remain hidden until hover/focus, matching the agreed behavior; touch coverage remains intact.
  • Image loading setup now chooses an interior reading position from the actual scroll extent instead of an impossible fixed 5,000px offset after compact thumbnails. Explicitly verify the reading position is away from both clamped edges; retain image remount, decode, failure, and reading-anchor assertions.
  • All 62 checks in the complete image-scroll, nested-replies, message-actions, and layout files pass locally on macOS in Chromium/WebKit (two workers; 3.2 minutes wall time). No browser cases were added or removed in this repair. The earlier hosted run had ten failures across these two repaired contracts; hosted CI passed on the new head.
  • Local summed test execution: 335.1s. Slowest cases are the explicit partial/blocked input fixture (Chromium/WebKit; approximately 27s each), followed by nested send/collapse/reveal. These are validation timings, not a claim of application or hosted-CI performance improvement.
  • Mandatory push hooks passed on 05284d94: TypeScript, all 5,074 unit tests across 421 files, and design checks. Hosted run 36510057343 is green on this exact head: all six browser shards, browser measurements, JavaScript, Rust/tool integration, security, DCO, and CI required pass. Windows native validation is skipped by the automatic workflow. Human acceptance, code-owner approval, and screenshot remediation remain outstanding.

Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
@mahanti
mahanti marked this pull request as ready for review September 28, 2026 21:19
@mahanti
mahanti requested review from a team, comp615 and wesbillman as code owners September 28, 2026 21:19
…ions

Signed-off-by: Arjun Mahanti <arjun@squareup.com>
@mahanti
mahanti marked this pull request as draft September 28, 2026 21:43
@mahanti
mahanti marked this pull request as ready for review September 28, 2026 22:04

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Reviewed be46501deec54a61290227afbb499475bf4d4aca against 258c6d6b0b591e7ad478abea6c3cb255e9452ae6. Changes required: two user-facing regressions are detailed inline, plus this publication blocker.

P1 — Remove private community screenshots from this public PR. The screenshot comment embeds two images containing private community messages and the DM roster. This also contradicts the description’s claim that screenshots remained local. Remove the images from public presentation, arrange removal of the uploaded assets rather than assuming deleting the embed revokes access, and replace any visual evidence with synthetic/redacted fixtures. Do not reproduce the sensitive contents in the fix or discussion.

Merge criteria: address the screenshot exposure and both inline defects; add focused regression coverage for continuation action placement and date access without a pointer.

Validation: full diff, shared consumers, observer/transaction lifecycles, test adjustments, and PR media reviewed. Current hosted checks pass; no broad suites were rerun. This was source/media review, not a fresh native or browser acceptance run. No additional blockers found in the IndexedDB fix or observer cancellation/remount behavior. The observer change’s one-frame rendering tradeoff remains unmeasured here; native validation and final human acceptance remain outstanding as documented in the PR.

.messageBody {
/* Thread controls keep their own row so hover never obscures reply text
or shifts neighboring branch controls. */
.threadHistory .messageBody {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P2 — Keep timeline continuation actions clear of message text. The reserved toolbar row now applies only inside .threadHistory, but this PR also makes ChannelTimeline render same-author messages as layout="continuation". Those rows hide their byline and start prose at the top (MessageRow.tsx:250-253,390-405); desktop actions still use position: absolute; top: 0. In a narrow conversation column, hovering a continuation or keyboard-focusing its actions puts the toolbar over the first line, obscuring text and intercepting pointer selection/link clicks. A one-line continuation can also be shorter than the toolbar.

Give timeline continuations non-overlapping action placement without moving neighboring rows on hover/focus. Cover two consecutive same-author timeline messages at a narrow column width with actual hover/focus geometry and text/link hit testing. The existing action journey exercises a full-header message, not this new layout.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🤖 Addressed in the latest UI follow-up. Continuation actions float above their prose without reserving height or moving adjacent rows; full-header actions are centered on the byline per the author’s design feedback. Mouse behavior now applies below 640px too. The Chromium/WebKit action file passes all 12 cases, including continuation geometry, link hit testing, hover/focus, and narrow toolbar access.

.join("")
.trim()
: `${day} at ${clock.format(date)}`;
: clock.format(date);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P2 — Preserve date access on surfaces without day separators. Clock-only bylines work with visible day context, but ThreadPanel passes day={false} for both its root and every reply (ThreadPanel.tsx:551,664), and a fully loaded single-day DM suppresses its first day separator (ChannelTimeline.tsx:526-534). Opening an old thread or such a DM therefore shows only times, with no visible indication of which day/year the messages belong to. The remaining full date is screen-reader-only text or a hover tooltip on a non-focusable <time>, so sighted keyboard and touch users cannot recover it.

Keep the compact clock design while providing visible date context on these surfaces, or another keyboard/touch-accessible date affordance. Cover a historical thread and a complete single-day DM; media comments also pass day={false} and share this component.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🤖 Addressed: timelines (including complete single-day DMs), thread roots/replies, and media comments now expose day/year separators while retaining compact clock bylines. Historical DM/thread browser coverage passes in Chromium and WebKit; media-comment coverage also checks date context.

@mahanti
mahanti marked this pull request as draft September 28, 2026 23:25
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>

# Conflicts:
#	src/features/messages/Messages.module.css
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
@mahanti

mahanti commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

🤖 @wesbillman The toolbar/menu follow-up is pushed at 3f138548, with replies on both inline findings. Could you take another look?

Hover actions no longer reserve message space; full-header actions align to the byline, while continuation controls remain above prose. The overflow menu is simplified and Copy link remains available at narrow widths.

Validation: 12 Chromium/WebKit action cases, 28 focused menu/report tests, 58 message-row tests, and mandatory hooks (TypeScript, all 5,065 unit tests, design checks) pass. Fresh hosted CI is running; the previous head passed all browser lanes but hit a relay fixture setup timeout in JavaScript.

The screenshot publication finding remains open pending the author’s response; uploaded-asset removal has not been confirmed. The PR remains draft and is not represented as merge-ready.

Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
@mahanti
mahanti marked this pull request as ready for review September 29, 2026 11:51
@mahanti
mahanti requested a review from wesbillman September 29, 2026 11:57

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Follow-up reviewed at 05284d94b8400d75734b80b398b2fb797b27c058 against merge-base 0c3a601bfee641d58bf3d8806730ffa398398464.

The two prior UI blockers are addressed; the P1 privacy blocker remains. The screenshot comment is now removed (API returns 404), but both original uploaded assets still serve PNG bytes without authentication. On 2026-09-29 at 13:35 UTC, independent ranged GETs returned 206 image/png for each. Removing the embeds did not revoke access. Arrange removal of both uploaded assets, involving GitHub Support if necessary, then verify the original URLs no longer return the images without authentication. Do not repost their URLs or contents.

The action-placement finding and visible-date finding are addressed in source and covered by the green Chromium/WebKit journeys. No new blocking code defect found. The inline date-divider suggestion is optional.

Validation: reviewed the follow-up source, scroll-restoration ordering, and changed assertions; hosted run 36510057343 passes on this head. Broad suites were not rerun. No fresh native/browser acceptance run was performed for this review; native/human acceptance remains outstanding. GitHub currently reports merge conflicts, separately from the privacy finding; the integrated head will need fresh CI.

const day =
!previousReply ||
new Date(previousReply.createdAt * 1000).toDateString() !==
new Date(row.createdAt * 1000).toDateString();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P3, optional — Separate date context from grouping context. After a reply with collapsed children, previousReply is deliberately cleared to break author grouping. Reusing it here makes the next sibling receive another full date separator even when root, parent, and sibling are all on the same day. The displayed date is correct, so this does not block the accessibility fix. Consider tracking the last displayed row separately for the date comparison (including expanded descendants), with a same-day collapsed-branch regression.

Signed-off-by: Arjun Mahanti <arjun@squareup.com>
@wesbillman
wesbillman merged commit ae687c7 into main Sep 29, 2026
20 checks passed
@wesbillman
wesbillman deleted the am-message-polish branch September 29, 2026 14:36
johnmatthewtennant pushed a commit that referenced this pull request Sep 29, 2026
…t-update-drafts

* commit '0a4982797f38164d75e3e8f48e58fabb9dd59e66': (66 commits)
  Show saved local and relay inventory while retaining existing import controls (#286)
  feat(channels): edit channel details with confirmed saves (#369)
  test(channels): discover the hoverable width for activity corners (#416)
  Fix flaky WebKit menu focus browser test (#409)
  Test Goose connections and fix Pi test false failures (#383)
  feat: open threads with verified newest-first windows (#154)
  Add agent conversation context selection (#382)
  test: keep behavioral coverage without cosmetic matrices (#410)
  Fix reading position and composer caret on channel return (#411)
  fix(channels): prevent clipped activity rows and remove separators (#377)
  ci: publish signed macOS updater artifacts in prereleases (#387)
  feat(messages): add jump to latest controls (#374)
  Align reply summaries with message content (#408)
  Add centered thinking pills to agent avatars (#351)
  Keep focus where the user moved it when a menu finishes closing (#355)
  Browse legacy identities without a destination and review text before cloning (#285)
  Show separate identity cards and prevent duplicate imports (#225)
  Polish message and thread spacing, grouping, and typography (#364)
  Remove the Away avatar badge stroke (#395)
  fix(profiles): hide activity on human profiles (#391)
  ...

Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>
johnmatthewtennant pushed a commit that referenced this pull request Sep 29, 2026
* origin/main: (25 commits)
  Show saved local and relay inventory while retaining existing import controls (#286)
  feat(channels): edit channel details with confirmed saves (#369)
  test(channels): discover the hoverable width for activity corners (#416)
  Fix flaky WebKit menu focus browser test (#409)
  Test Goose connections and fix Pi test false failures (#383)
  feat: open threads with verified newest-first windows (#154)
  Add agent conversation context selection (#382)
  test: keep behavioral coverage without cosmetic matrices (#410)
  Fix reading position and composer caret on channel return (#411)
  fix(channels): prevent clipped activity rows and remove separators (#377)
  ci: publish signed macOS updater artifacts in prereleases (#387)
  feat(messages): add jump to latest controls (#374)
  Align reply summaries with message content (#408)
  Add centered thinking pills to agent avatars (#351)
  Keep focus where the user moved it when a menu finishes closing (#355)
  Browse legacy identities without a destination and review text before cloning (#285)
  Show separate identity cards and prevent duplicate imports (#225)
  Polish message and thread spacing, grouping, and typography (#364)
  Remove the Away avatar badge stroke (#395)
  fix(profiles): hide activity on human profiles (#391)
  ...

Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>

# Conflicts:
#	src/bundled/agents/AgentsPage.test.tsx
#	src/bundled/agents/AgentsPage.tsx
matt2e added a commit that referenced this pull request Oct 1, 2026
…s are measured

A reader at the top of history who loaded older messages could see their
content move about 76px on Linux WebKit: live.spec.mjs:194 ("post-reconnect
finite catch-up keeps paged history, cursor and reading position") failed 4
of 10 CI re-runs of PR #456's head ac40051 with an identical 76.109375px
displacement, and passed 10 of 10 on Chromium.

Mechanism, from the attempt 7, 8 and 10 traces

Before the gesture the window is rows 620 to 639 (1586.859375px); edge()
scrolls to the top, the fixture holds the older page, and anchor() records
row 620's paragraph at scrollTop 0. Releasing the page prepends 20 rows in
one React commit: ChannelTimeline computes `day` (index 0 only) and `layout`
(continuesMessageGroup against the previous row) during render, and
MessageRow renders both synchronously, so the same commit that mounts the 20
new rows turns row 620 into a continuation without its day divider and
author header. The 12.38s snapshot shows exactly that: 40 rows, scrollTop
1478, the new rows at the 73.9453px estimate and still `visibility: hidden`,
row 620 already without its divider. Those 21 size changes reach the
ResizeObserver together (one layout, one depth) and Virtua's batched
observer delivers them in one frame.

Virtua's store enters SCROLL_BY_SHIFT on the prepend and compensates every
resize in that mode ("keep distance from end during shifting"). The mode
ends at ACTION_SCROLL_END, which the element driver dispatches 150ms after
the last scroll event, here the shift jump's own scroll to 1478. When the
measuring frame runs later than that timer, the batch meets native policy,
which keeps the viewport start: a row is compensated only if its bottom lies
at or above scrollTop. Row 620 (offset 1478.906) is not, so its 87.96875px
shrink is dropped; row 619's estimated bottom 1478.906 is read against
WebKit's integer scrollTop 1478, so its 9.9922px growth is dropped too. The
settled snapshot confirms the arithmetic: rows 0 to 18 contribute
1478 + 97.96 = 1575.96, reported as 1575, row 620's li sits at 1586.859375
and its paragraph has moved 87.97px up inside the box: 11.86 - 87.97 =
-76.11px. A displacement of 87 would have meant the new rows were
compensated and only row 620's shrink lost; 76 means the whole batch landed
after scroll-end. On a timely frame (every Chromium run and macOS WebKit
here) the batch arrives inside the 150ms window and the shift covers it.

Attribution

origin/main has the same compensation behaviour. The hunks da81370 added to
patches/virtua@0.51.0.patch (git diff 1a692d5 da81370 -- that file) touch
the element driver only: the absolute-path condition near the end of the
list, the exposed cancel, cancelScrollToIndex in the handle and the typings.
The store's ACTION_ITEMS_LENGTH_CHANGE, ACTION_SCROLL_END and
ACTION_ITEM_RESIZE paths are stock in both bundles, and the observer's
requestAnimationFrame batching predates it (ae687c7, #364). f5c7d35's
removal of the fake clock lets the real frame timing reach this test, which
is why the branch surfaces it; the race is the product's.

Directions considered

(a) Landing row 620's re-layout in the prepend's commit is already the case.
(b) Measuring the anchored row before the prepend and re-pinning after
layout would duplicate Virtua's shift with an imperative scroll that Virtua
then holds for 150ms and re-applies on size updates, the loop da81370 had
to cancel, and the row-top anchor recordPosition keeps would still move the
paragraph by the header's height. (c) Extending the shift until its own
measurements arrive is the smallest change that is correct on both engines,
and it is what Virtua already does when the frame is on time.

Virtua patch (store)

ACTION_ITEMS_LENGTH_CHANGE with shift records how many rows it prepends.
ACTION_SCROLL_END keeps SCROLL_BY_SHIFT while any of those rows inside the
rendered range is still unmeasured, and otherwise resets as before. The
ACTION_ITEM_RESIZE batch that measures them applies shift policy to the
whole batch, as a timely frame would have, and then performs the deferred
reset. A shift whose prepended rows are not mounted still ends at
scroll-end, a batch inside the window is unchanged, and a visible row that
grows after the shift (an image loading) keeps the viewport start exactly as
today: the hold lasts only until the first measurement batch after the
prepend, which is the batch that would carry such a growth anyway. The
element driver, window scroller and typings are unchanged.

Regenerated with pnpm patch / patch-commit, blank context lines converted
to -/+ pairs as before, the patchedDependencies hash updated and pnpm 11.8's
stray `libc: [musl]` line dropped. patches/README.md gains a section and
notes that the store is now patched too.

Tests

virtua-compensation.test.mjs: the prepend() helper computes the rendered
range between the length change and the flush, as the Virtualizer's render
does (buffer 1600, ChannelTimeline's). Three new installed-store cases:
a prepend whose rows measure after scroll-end keeps the former first row's
paragraph at the same viewport position (88px) and then returns to native
policy; a prepend measured inside the window keeps stock shift policy until
scroll-end; a prepend whose rows are not mounted ends its shift at
scroll-end. The first failed against the previous bundle with scrollBy 200
instead of 112 (the 88px shrink dropped) and passes now; the other two pass
on both bundles as controls. live.spec.mjs is unchanged: its expectAnchor
after the release is the check.

Verified

bin/pnpm install --frozen-lockfile rebuilds node_modules/virtua/lib/index.js
byte-identical to the edit dir; bin/pnpm typecheck; biome check on the
changed test file; vitest virtua-compensation.test.mjs plus the three
ChannelTimeline suites, 150 passed. live.spec.mjs on WebKit with
--repeat-each 5: 15 passed, 0 failed; on Chromium with --repeat-each 5:
15 passed, 0 failed. The README's patch checks, history-loading.spec.mjs,
image-scroll.spec.mjs and initial-position.spec.mjs, once per engine:
20 passed on Chromium, 20 passed on WebKit.

The mechanism does not reproduce on macOS WebKit (the branch recorded 15 of
15 before this change), so these local passes are necessary but not
sufficient; Linux CI re-runs will verify the fix in a follow-up session.

Cherry-pick check

Built on #481's bundle (origin/main at fefbfd0, "buffer both sides while
the scroll direction is frozen"), which had regenerated the same Virtua
patch. Rebasing onto it conflicted in patches/virtua@0.51.0.patch and
pnpm-lock.yaml only; patches/README.md and the test file auto-merged once
da81370 had moved their insertion points. The patch was regenerated rather
than merged by hand: main's patch and lockfile were taken, the package was
extracted with the rebased da81370 patch applied (bin/pnpm patch
virtua@0.51.0 --edit-dir), this commit's four store edits were applied to
it as the diff between its previous bundle and da81370's, and bin/pnpm
patch-commit rewrote the patch; blank context lines were converted to -/+
pairs, a plain install refreshed the patchedDependencies hash and pnpm
11.8's stray `libc: [musl]` line was dropped, as before. The store lines
this commit edits are stock in #481's bundle, so the regenerated patch is
the #481 hunks plus da81370's driver hunks plus these, and the #481
shift-mode resize policy (rows wholly below the viewport end are not
corrected) now governs the held batch too. bin/pnpm install
--frozen-lockfile reproduces the edit dir byte for byte, and
virtua-compensation.test.mjs passes with the two #481 shift-buffer tests,
da81370's driver tests and the three cases here (34 tests).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
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.

2 participants