A template changed outside a room that edits it together can be merged into the room instead of being overwritten.
If-Match on collaboration.room_version()), the host hands the newer
template to collaboration.conflict(document, version). What it changed reaches everyone in the
room, what the room changed and it did not stays, and where both changed one element the file
wins. conflict() returns a promise that resolves once the merge is on this window's canvas, also
when the user was dragging, so the host saves again after it. collaboration.saved(version, document) takes the saved JSON as a second argument, which
the room compares a newer file with. Without a host that does this, nothing changes.Not merged yet: the swatch library, styles and fonts, and whether page 1 is on the left.
@saved, a hash of how the last saved
version has it, written when the room is seeded and on every record_version(). merge() diffs
the room against the newer file (diff_structure()) and keeps the changes whose element or spread
hashes differently in the file than @saved: a three-way merge without storing the base, so any
window can merge. The hash follows file-service's normalisation (asset URLs cleared, an image's
key filled in), so a file read back after touch compares equal to what was saved. It is
written with its own transaction origin, so the merging window applies it to its canvas too; a
story goes into its Y.Text. A window holds the others' changes back while it drags;
ElementSync.settled() resolves once nothing is held, which conflict() awaits. An event that
changes only @saved is no change to the others' canvases or to the spread list, and a file
without a spread is refused, as it would remove every page.