Skip to content

Reconciliation-generated nodes have no defined path to collaborators #586

Description

@Aymericr

Problem

Nodes that space-detection reconciliation generates — auto slabs, auto ceilings, auto zones, frontSide/backSide surface flips, and the level.children growth that comes with them — have no defined way to reach collaborators. Anything that moves reconciliation after the commit snapshot silently stops replicating.

Today it works by accident of ordering. initSpaceDetectionSync subscribes to the store, so its writes land before zundo's onSave snapshots the transaction, and the hosted editor's

// apps/community — use-project-scene-collaboration.ts:552
const diff = deriveSceneOperationChanges(commit.before, commit.current)

picks them up inside commit.current. Nothing states this as a contract, and nothing tests it.

Why it needs writing down

#554 restructured reconciliation to run from subscribeSceneCommits instead — a reasonable design in isolation, since it gives reconciliation the before/after pair it needs for delta work. But commit listeners run after both snapshots are taken, and reconciliation writes under pauseSceneHistory, so they emit no commit of their own. Measured on that branch versus main, same four-walls-closing-a-room scenario:

commit current.nodes live store never in any commit
main 8 8
#554 6 8 the auto slab + ceiling

The author gets a floor and a ceiling; collaborators get a bare wall and a divergent level.children. That drift doesn't self-heal.

What would resolve it

  1. State the contract. Either "reconciliation must write within the triggering commit's transaction" or "reconciliation must emit its own commit that collaboration can transmit." Then document it in wiki/architecture/ next to the space-detection notes.
  2. Test it at the boundary. A core-level test asserting that reconciliation-generated nodes appear in the emitted commit would have caught editor: keep room surfaces in sync with wall topology #554 automatically. The check is cheap: close a room, capture commits, assert every live node id appears in some current.nodes.
  3. Decide about pauseSceneHistory. Reconciliation pauses history so its writes don't become a separate undo step, which is correct for undo but is also what suppresses the commit. Whether "one undo step" and "one transmittable commit" can be the same thing is the crux.

Option 2 is worth doing regardless of which way 1 goes — right now the invariant is enforced only by call ordering that any refactor can reverse without a single test turning red.

Context: #554 (closed; the TopologyIndex half is expected to return as a focused PR).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingready-for-humanNeeds human input during execution

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions