Editor duplicates pasted image after undo/redo storm #281

Closed
opened 2026-09-28 01:58:19 +00:00 by kayg · 1 comment
Owner

Finding

The editor duplicates a pasted image after an undo and redo storm.

Evidence

One time-boxed adversarial run used seed 25608414. In tests/adversarial/editor.mjs, the browser editor paste, Unicode, and history storm area pasted an image, typed history-storm-186, sent 500 Ctrl+Z presses, then 500 Ctrl+Y presses. The editor showed three .cal-image-block elements. The existing assertion expected one and failed with 3 !== 1.

The same browser probe logged one image after the hostile paste and IME sequence, one after undo, and three after the redo sequence. The check is unchanged.

Expected result

Undo and redo restore the pasted image once. They do not duplicate it.

Reproduction

Run the adversarial editor probe with seed 25608414 and a local web app and server. The failing assertion is in tests/adversarial/editor.mjs near line 465.

## Finding The editor duplicates a pasted image after an undo and redo storm. ## Evidence One time-boxed adversarial run used seed `25608414`. In `tests/adversarial/editor.mjs`, the `browser editor paste, Unicode, and history storm` area pasted an image, typed ` history-storm-186`, sent 500 Ctrl+Z presses, then 500 Ctrl+Y presses. The editor showed three `.cal-image-block` elements. The existing assertion expected one and failed with `3 !== 1`. The same browser probe logged one image after the hostile paste and IME sequence, one after undo, and three after the redo sequence. The check is unchanged. ## Expected result Undo and redo restore the pasted image once. They do not duplicate it. ## Reproduction Run the adversarial editor probe with seed `25608414` and a local web app and server. The failing assertion is in `tests/adversarial/editor.mjs` near line 465.
Author
Owner

Editor-integrity job final report — branch job/editor-integrity, head b824878e (pushed).

  • #332 and #364: fixed the Yrs conflict-shadow merge that discarded the surviving edit when another client deleted that block. Deterministic tests cover both update orders and a same-connection redo update. The real-server delete/edit probe passed.
  • #346: the concurrent delete/edit loss is fixed by the same change. The history-text finding is not closed by this work; see #314 and #363 below.
  • #225 and #262: added structure-level editor history coverage, but did not rerun the 500-step production browser ID storm after the final branch state. Persistence of unique IDs in that exact storm remains unconfirmed.
  • #280 and #281: the focused history test keeps one pasted image over 50 undo/redo pairs. The 500-step production browser image storm was not rerun after the final branch state, so this exact case remains unconfirmed.
  • #314 and #363: focused Yjs/ProseMirror structure tests pass. The fixed-seed production browser history probe remained timing-sensitive: clean runs reported a stale or mismatched mounted ProseMirror view after Ctrl+Z, while one instrumented run passed 50 paste and IME round trips. I removed the unverified key scheduling change and kept the failure evidence for follow-up.

Verification:

  • bun run test src/collaborationUndo.test.ts: 4 passed.
  • cargo fmt --check: exit 0, no output.
  • cargo clippy --all-targets -- -D warnings: stopped at the four-hour job limit (exit 130) while compiling workspace dependencies.
  • cargo test, bun run check, and bun run test for the full web workspace were not run before the time limit.

Decision: conflict-shadow merge filters each incoming Yrs update against that update's own delete set. This keeps a later text edit that follows a root deletion while avoiding replay of a duplicate root insertion from the same redo update. The issue-specific tests pass; the full gates and listed browser storms remain for follow-up. Issues remain open.

Editor-integrity job final report — branch `job/editor-integrity`, head `b824878e` (pushed). - #332 and #364: fixed the Yrs conflict-shadow merge that discarded the surviving edit when another client deleted that block. Deterministic tests cover both update orders and a same-connection redo update. The real-server delete/edit probe passed. - #346: the concurrent delete/edit loss is fixed by the same change. The history-text finding is not closed by this work; see #314 and #363 below. - #225 and #262: added structure-level editor history coverage, but did not rerun the 500-step production browser ID storm after the final branch state. Persistence of unique IDs in that exact storm remains unconfirmed. - #280 and #281: the focused history test keeps one pasted image over 50 undo/redo pairs. The 500-step production browser image storm was not rerun after the final branch state, so this exact case remains unconfirmed. - #314 and #363: focused Yjs/ProseMirror structure tests pass. The fixed-seed production browser history probe remained timing-sensitive: clean runs reported a stale or mismatched mounted ProseMirror view after Ctrl+Z, while one instrumented run passed 50 paste and IME round trips. I removed the unverified key scheduling change and kept the failure evidence for follow-up. Verification: - `bun run test src/collaborationUndo.test.ts`: 4 passed. - `cargo fmt --check`: exit 0, no output. - `cargo clippy --all-targets -- -D warnings`: stopped at the four-hour job limit (exit 130) while compiling workspace dependencies. - `cargo test`, `bun run check`, and `bun run test` for the full web workspace were not run before the time limit. Decision: conflict-shadow merge filters each incoming Yrs update against that update's own delete set. This keeps a later text edit that follows a root deletion while avoiding replay of a duplicate root insertion from the same redo update. The issue-specific tests pass; the full gates and listed browser storms remain for follow-up. Issues remain open.
kayg closed this issue 2026-09-29 03:37:59 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#281
No description provided.