The browser editor opts into disjoint-property merging. Two editors can save position and scale on the same object without discarding either change. Position, rotation, scale and other property values are atomic: separate coordinates of one vector still conflict. An edit followed by a revert also counts as an intervening write.
POST /api/authoring/commit accepts a format-1 transaction with merge: "disjoint" and the normal base revision/hash. It returns {document, intervening, changed}. intervening lists affected [scope, id, property] keys since that exact base. changed means this request changed the current server document; a stale no-op may return a newer document with changed: false.
Without the merge flag, saves remain strict. POST /api/authoring retains its document-only response. Publication always requires the exact current revision/hash. Both commit routes use the existing creator key, origin checks and request limits.
The server requires a complete retained lineage from the supplied revision and checksum. Overlapping writes return HTTP 409 with reason: "overlap" and conflict keys. Missing or expired lineage returns HTTP 409 with reason: "history-unavailable". Neither response changes the accepted draft. Structural operations fence object lifetime, source names and place ordering conservatively; model replacements fence their asset. Every merged candidate passes full world/compiler validation before persistence.
#Persistence and recovery
The journal retains at most 64 revision transitions and 4 MiB per metadata file. Files live under authoring/merge-state/<document-checksum>.json in the existing persistent volume. Metadata is checksummed, chain-validated and fsynced before the matching world.json advances. The current and previous metadata files can coexist; older files are pruned on the next write. A metadata file written before a failed world write cannot advance the draft. Storage errors stop further writes until restart.
An existing draft migrates by adding an empty journal without rewriting its world file. Old bases predating that migration cannot merge. Missing current metadata when other journal files exist, malformed chains and checksum failures fail closed. Back up and restore the entire authoring directory, including the world and its matching merge metadata. Published immutable snapshots remain independently readable and playable if draft metadata needs repair.
The server protects retained durable undo/redo entries, including entries older than the merge-lineage window. Reload restores history for the browser identity; see saved undo. Creator attribution and automatic remote scene replacement remain separate work. The service still requires a single writer process per volume.
The browser polls the protected /api/authoring/head endpoint for a lightweight revision/hash hint. A notice offers explicit loading; discovery never changes the local document or merge preconditions. Missed checks heal by reading the current head, and unsaved fields remain intact. See browser editor for timing and recovery behavior.
Ephemeral builder presence now reports selections, unsaved editing and revision-fenced transform previews separately. These advisory hints never bypass a merge conflict or add a lock to a transaction.
#Hierarchy dependencies
World-5 transform edits include read keys for the node's parent relationship and its ancestor transform frame. A read conflicts with a write to that entity/property, including entity lifetime changes, but two reads do not conflict. Position and scale remain independently mergeable. Reparenting also writes the old/new containers' child membership; deleting a group fences its complete identity. Group names share the place's object-name namespace. Every rebased transaction still validates the complete hierarchy and native-compatible transforms before committing.