Skip to content

test: pin the duplicated tail from concurrent same-spot splits - #3142

Merged
christianhg merged 1 commit into
mainfrom
test/shape-two-same-spot-split
Aug 24, 2026
Merged

test: pin the duplicated tail from concurrent same-spot splits#3142
christianhg merged 1 commit into
mainfrom
test/shape-two-same-spot-split

Conversation

@christianhg

@christianhg christianhg commented Aug 21, 2026

Copy link
Copy Markdown
Member

When two editors split the same block at the same offset at the same time, both converge on a document with the tail duplicated. Each editor performs the split locally as a text shortening plus an insert of a new tail block, and each mints its own _key for that tail. The two inserts carry nothing that relates them, so when the patches cross, both apply on both sides: three blocks, the tail twice. The nearest existing coverage (the two-client collision suite's block-split scenario) splits at different offsets and asserts only convergence and validity, so this outcome was unpinned.

This PR adds the pin: two independent editors in the collaborative-editing suite, seeded identically, both performing insert.break at the same offset, exchanging their emitted patches through a lossless relay. The test asserts the sane outcome (two blocks, the tail once, both editors agreeing) as test.fails: it passes while the defect exists and starts failing the day concurrent same-spot splits stop duplicating, at which point it flips to a plain test. test.fails is new in this repo; the alternative was a red test parked on a branch, and a living pin in CI seemed strictly better.

The run surfaced a second, separate defect, which shapes how the test asserts. The two editors do not even agree on the order of the duplicated tails: each editor placed its own tail after the original block when it split, and the other's tail then arrives as "insert after" the same original block, landing in front of it, so editor A ends with Ben's tail first and editor B with Ann's first. Because of that, the test compares the sequence of block texts (via getTersePt) rather than raw blocks: raw comparison would fail on the ordering defect and leave this pin red for reasons unrelated to duplication. The ordering defect is tracked separately as a follow-up, and this test doubles as its repro (flip the final comparison to raw toEqual).


Note

Low Risk
Test-only pin of an existing collab bug; no production code changes.

Overview
Pins a known collab defect: two editors that insert.break at the same offset currently duplicate the tail after patches cross.

Adds a test.fails scenario in collaborative-editing.test.tsx that relays local patches between two independent editors and asserts they converge on two blocks (foo / bar baz) via getTersePt. It stays green while the duplication exists and will fail once the split is fixed, at which point it should become a regular test. Text-only comparison avoids a separate tail-ordering bug.

Reviewed by Cursor Bugbot for commit a335ea4. Bugbot is set up for automated code reviews on this repo. Configure here.

Two editors seeded with the same block each perform `insert.break` at
offset 4 of the same span, then exchange their emitted local patches
through a lossless relay. Each editor mints its own `_key` for the new
tail block (`ea-k2`, `eb-k2`), both keyed inserts apply on both sides,
and the editors settle on a document with the tail duplicated: three
blocks, `bar baz` twice. Nothing in the patches relates the two
inserts, so no receiver can recognize them as the same intent.

The pin ships as `test.fails` asserting the sane outcome (two blocks,
tail once, both editors agreeing on the text projection): it passes
while the defect exists and starts failing the day concurrent
same-spot splits stop duplicating, at which point it flips to a plain
`test`.

The assertions compare `getTersePt` projections, not raw values,
deliberately: the raw documents also diverge in block order (each
editor sandwiches the foreign tail before its own, since both inserts
anchor after the same block). That order divergence is a second defect
in its own right, out of scope here.

Net behavior unchanged: test-only.
@vercel

vercel Bot commented Aug 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
portable-text-editor-documentation Building Building Preview Aug 21, 2026 12:56pm
portable-text-example-basic Ready Ready Preview Aug 21, 2026 12:56pm
portable-text-playground Ready Ready Preview Aug 21, 2026 12:56pm

Request Review

@changeset-bot

changeset-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a335ea4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Stats — @portabletext/editor

Compared against main (98d99698)

@portabletext/editor

Metric Value vs main (98d9969)
Internal (raw) 781.4 KB -
Internal (gzip) 174.0 KB -
Bundled (raw) 1.40 MB -
Bundled (gzip) 343.2 KB -
Import time 97ms -1ms, -1.4%

@portabletext/editor/behaviors

Metric Value vs main (98d9969)
Internal (raw) 4.2 KB -
Internal (gzip) 1.4 KB -
Bundled (raw) 3.9 KB -
Bundled (gzip) 1.3 KB -
Import time 2ms -0ms, -0.7%

@portabletext/editor/plugins

Metric Value vs main (98d9969)
Internal (raw) 5.2 KB -
Internal (gzip) 1.8 KB -
Bundled (raw) 5.0 KB -
Bundled (gzip) 1.7 KB -
Import time 7ms +0ms, +0.3%

@portabletext/editor/selectors

Metric Value vs main (98d9969)
Internal (raw) 96.4 KB -
Internal (gzip) 22.2 KB -
Bundled (raw) 92.6 KB -
Bundled (gzip) 21.0 KB -
Import time 8ms +0ms, +0.2%

@portabletext/editor/traversal

Metric Value vs main (98d9969)
Internal (raw) 40.7 KB -
Internal (gzip) 10.6 KB -
Bundled (raw) 41.1 KB -
Bundled (gzip) 10.6 KB -
Import time 6ms +0ms, +1.5%

@portabletext/editor/utils

Metric Value vs main (98d9969)
Internal (raw) 34.1 KB -
Internal (gzip) 8.7 KB -
Bundled (raw) 32.5 KB -
Bundled (gzip) 8.5 KB -
Import time 6ms +0ms, +0.5%

🗺️ . · ./behaviors · ./plugins · ./selectors · ./traversal · ./utils · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — @portabletext/markdown

Compared against main (98d99698)

Metric Value vs main (98d9969)
Internal (raw) 53.0 KB -
Internal (gzip) 11.6 KB -
Bundled (raw) 351.8 KB -
Bundled (gzip) 99.4 KB -
Import time 40ms +1ms, +2.0%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@christianhg
christianhg marked this pull request as ready for review August 24, 2026 10:54
@christianhg
christianhg merged commit 73f9db5 into main Aug 24, 2026
17 checks passed
@christianhg
christianhg deleted the test/shape-two-same-spot-split branch August 24, 2026 10:54
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