Editor history storm can persist duplicate block IDs #262

Closed
opened 2026-09-27 19:29:43 +00:00 by kayg · 1 comment
Owner

Evidence

The one-time adversarial round (tests/adversarial/run.sh) reported a reproducible editor consistency failure in tests/adversarial/editor.mjs:324–460.

  • Seed: 25608414
  • Probe: hostile HTML/plain-text paste, IME input, then 500 undo and 500 redo actions.
  • The probe waited for the copied block anchors to reach the server. The saved Note then contained duplicate block IDs: duplicate-id and icjf8j each appeared more than once. The uniqueness assertion failed with 4 !== 7.
  • The saved Markdown contained repeated ^duplicate-id and ^icjf8j anchors after history replay.

Duplicate block IDs make stable block links ambiguous and can attach block actions to the wrong block. Please reproduce the seed in the real-browser adversarial probe and preserve the existing uniqueness assertion as the regression check.

## Evidence The one-time adversarial round (`tests/adversarial/run.sh`) reported a reproducible editor consistency failure in `tests/adversarial/editor.mjs:324–460`. - Seed: `25608414` - Probe: hostile HTML/plain-text paste, IME input, then 500 undo and 500 redo actions. - The probe waited for the copied block anchors to reach the server. The saved Note then contained duplicate block IDs: `duplicate-id` and `icjf8j` each appeared more than once. The uniqueness assertion failed with `4 !== 7`. - The saved Markdown contained repeated `^duplicate-id` and `^icjf8j` anchors after history replay. Duplicate block IDs make stable block links ambiguous and can attach block actions to the wrong block. Please reproduce the seed in the real-browser adversarial probe and preserve the existing uniqueness assertion as the regression check.
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:57 +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#262
No description provided.