Automattic / Automattic/gutenberg-sync-engines
The saved-HTML note kept for blocks added during a session is deleted as soon as the block changes
- Dominant language
- JavaScript
- Stars
- 2
- Forks
- 0
- Avg merge
- 11h 22m
- Merged PRs (30d)
- 49
Description
## What happens now
For every block someone adds while editing together, the browser stores a small note in the shared document: the block's saved HTML, so the server can later rebuild the post's content with the right surrounding HTML element. That note is deleted the moment any edit passes over the block — the merge routine writes a fresh copy of the note and then its own cleanup step immediately deletes it. The server then rebuilds such blocks with no surrounding element at all: a Group added during a session comes out as bare inner blocks with no `
Nothing a user sees reads that rebuilt content today, which is why this has gone unnoticed, but it quietly undoes what PR #35 shipped: the rebuilt content is part of the engine's contract, the diagnostics and benchmarks trust it, and anything built on it later will inherit broken output.
## Example
1. Start the tests site (`npm run env:tests start`) and run one automated editing session that adds Groups mid-session: `npm run fuzz -- --combos=yjs-server/http-polling --seed-list=3 --steps=12` (pass `WP_BASE_URL` if the site is not on :8889).
2. Find the newest entry in `npm run env:tests -- run cli wp collaboration rooms list`.
3. Dump it: `npm run env:tests -- run cli wp eval-file wp-content/plugins//tests/tools/dump-yjs-room-blocks.php "postType/post:"`.
**What you see:** the Groups added during the session print `wrapper:no _save=(none)`, and the rebuilt content at the bottom shows them as `…` — inner blocks directly inside the comment markers, no `
**What you expected:** every block added in-session keeps its saved-HTML note, and the rebuilt content wraps the Group's children in its `
## What should happen instead
The note should survive edits (and keep being refreshed as the block's attributes change, which is what the code visibly intends), so the server can always rebuild a faithful copy of the post.
## How we will know it is done
Repeat the example: the dump shows `_save` present on in-session container blocks after later edits, and the rebuilt content contains their wrapper elements. Needs a test — no unit test today covers the note surviving a merge (the existing PHP test writes the note server-side and never exercises the browser's merge routine).
## Notes for whoever picks this up
The defect is in the bundled framework copy, `gutenberg/packages/core-data/src/utils/crdt-blocks.ts`: the update lane refreshes the `_save` mirror (lines 556–567, added by PR #35), then the trailing cleanup loop (lines 710–714) deletes every key the incoming editor block does not carry — and editor blocks never carry `_save` (it is stripped on read at line 229). Both happen in one transaction, so peers and the server only ever see the deleted state. The fix is one line: skip `CRDT_BLOCK_SAVE_KEY` in that cleanup loop, the same exclusion `areBlocksEqual` already makes at line 261. Because it is a `gutenberg/` subtree change, the loop's rules put it with a human (plus the subtree round-trip that carries it upstream) — hence filed as parked rather than ready. Evidence and the full investigation trail: #38 (2026-08-26 cycle comment; confirmed on real session data from passing and failing runs alike). The diagnosis tools referenced above landed in #54.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in gutenberg/packages/core-data/src/utils/crdt-blocks.ts, reading the _save refresh around lines 556–567 and cleanup around 710–714, then compare the exclusion in areBlocksEqual at line 261. Reproduce with the listed npm test-site and fuzz commands, and inspect the room dump. Done means an in-session container retains _save after edits and rebuilt content includes its wrapper; add coverage for the merge path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- distributed-systems
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100