10 — Collaboration profile
Document status: executable bounded register and existing-tree structural profiles. Canonical source.
Collaboration is operation-based and layered above canonical NUIF.
A collaboration engine MUST be able to materialize a canonical NUIF snapshot without collaboration metadata. Replica IDs, clocks, tombstones and sync-state are profile data.
The profile defines convergence requirements, causal/change identifiers, transaction grouping, awareness/presence separation and checkpoint materialization. It does not mandate Automerge or Yjs.
Semantic conflicts that cannot be merged safely remain explicit conflict objects even if the underlying CRDT converges structurally.
Executable register profile 0
nuif-collab-registers-0 represents each collaboration change as a replica/counter dot, a transitive version-vector context and one semantic operation. The metadata lives in the profile state and is stripped from the materialized Document.
Register-like operations use one multi-value register per entity/property pointer. Causally superseded values leave the frontier. Concurrent distinct values remain in an explicit SemanticConflict; a deterministic selected dot permits a provisional canonical checkpoint without discarding the candidates from the checkpoint report. The operation-set join is commutative, associative and idempotent, and incomplete causal histories fail closed.
Profile 0 supports rename, size, container layout, grid-item placement, token, authored-value, extension-declaration, entity-extension and unknown-payload registers. It rejects insert, remove, move and restore-subtree. Structural collaboration requires a declared tree move/list algorithm, cycle handling and tombstone policy and MUST NOT be inferred from register convergence.
cargo xtask gate-h compares an operation-set maximality materializer with an incremental replica-log frontier materializer over every delivery permutation of the bounded conflict fixture. These are algorithmically separate in-repository implementations, not foreign-engine interoperability evidence.
Executable existing-tree structural profile 0
nuif-collab-tree-0 accepts only Move and Delete for entity identities
already present in one validated canonical base. Creation, subtree payloads,
relations, property changes and mixed structural/property transactions are not
part of this profile. A structural change uses the same dot and transitive
version-vector requirements as the register profile. Every engine and joined
operation set is bound to the canonical hash of exactly one base; merging
different bases is a typed failure. The dot’s total order is (counter, replica).
A move carries (entity, new_parent, anchor). anchor is either Start or a
stable position identifier. A base position is Base(entity_id); every move
creates Change(dot). An authoring surface MUST resolve a canonical
After(entity_id) against its current checkpoint and persist the resulting
stable position. It MUST NOT reconstruct a stale anchor from the entity’s
current position after synchronization. A Change(dot) anchor MUST name a
received change included in the author’s transitive causal context; a missing
or non-causal anchor change fails the checkpoint as incomplete history.
The materializer MUST behave as if all changes were applied in ascending dot order:
- An unknown entity or parent is a typed failure and produces no checkpoint.
- Moving an entity below itself or its current descendant has no structural
effect, remains in the applied history and emits
CycleRejected. - A missing anchor, an anchor from another parent, or the entity’s own position has no structural effect and emits its typed anchor conflict.
- A valid move deactivates the entity’s prior position and creates an active position under the target parent. Inactive positions remain as sibling origins.
- Delete deactivates the prior position and assigns the entity to synthetic profile trash. Descendant relationships are retained in profile state.
- A later valid move may restore a trashed entity or rescue one of its descendants.
Sibling order is an RGA-style origin traversal. Positions with the same origin sort by descending position identifier, followed recursively by their own descendants. Base sibling order is represented as an origin chain. Position IDs, inactive positions, clocks and trash are profile metadata. The canonical checkpoint stores only ordinary ordered child arrays and removes every entity not reachable from a visible root; it MUST validate and hash as canonical NUIF.
Concurrent distinct moves of one entity, delete/move of one entity, deletion of a destination parent and deletion of a moved entity’s base ancestor MUST remain typed semantic conflicts. Total ordering selects a provisional tree but does not erase those candidates.
Gate H compares full sorted replay with an incremental local/rollback-replay engine for all 5,040 deliveries of the bounded fixture, multiple joins, duplicate delivery and a 4,096-change scaling case. Pinned Automerge 3.4.1 must reproduce the exact immutable operation set through different merge orders and save/load. That foreign check covers convergent transport only; it is not an independent implementation of these tree semantics.
Gate H also runs implementations/python/nuif_tree_materializer.py, a
standard-library-only replay oracle over the same base document and immutable
changes. It independently computes parent transitions, stable sibling order,
cycle rejection, unavailable/self anchors, reachable pruning and active
position projection, then compares those results with the Rust checkpoint.
This is a foreign tree-materializer check, not a second canonical NUIF codec:
the oracle does not decode CBOR, recompute the canonical hash or classify the
higher-level concurrent semantic-conflict families.
Executable structural prefix profile 0
nuif-collab-tree-prefix-0 is a conservative checkpoint handoff for an
existing-tree history. The stable prefix MUST be causally closed and every
retained replica log MUST continue after the attested frontier. The stable
checkpoint rebuilds ordinary base positions from its canonical child arrays.
An anchor to a stable position is rewritten only when that position is still
active and therefore has an unambiguous Base(entity) equivalent. Anchors to
inactive or moved stable positions are rejected with
StableAnchorNotRepresentable; retained change positions remain available for
suffix replay. The resumed checkpoint is equivalent to complete replay in
canonical hash, document and semantic-conflict set, while applied dots and
active-position metadata are intentionally local synchronization state.
Gate H exercises active-anchor rebasing and typed refusal of an inactive tombstone anchor. Structural collection with inferred frontiers, concurrent stable-versus-retained changes, creation payloads or general tombstone rewriting remains outside this bounded profile.
Executable concurrent-creation profile 0
nuif-collab-tree-create-0 is a separate bounded profile for concurrent
creation of leaf entities under a parent already present in one canonical
base. A creation change carries a dot, transitive version-vector context, a
base parent (or the root), a Start or After(base-entity) anchor and one
entity with an empty children list. The entity ID MUST not already exist in
the base. The parent and anchor MUST resolve against the base; creation below
a concurrently created parent is outside this profile.
The materializer groups changes by entity ID. A group with more than one
candidate produces EntityIdCollision containing every dot and selects the
greatest dot provisionally. For selected, valid creations, positions sharing
an anchor are ordered by descending dot and are placed around the unchanged
base sibling list. The canonical checkpoint contains ordinary entities and
child arrays only; dots, contexts and collision candidates remain profile
metadata. The checkpoint MUST validate and hash as canonical NUIF.
cargo xtask gate-h exhausts all 24 deliveries of the four-change fixture,
checks merge convergence, same-anchor ordering, explicit ID-collision
diagnostics, canonical metadata absence and typed failures for nested entities,
unknown parents/anchors and incomplete causal history. This profile does not
claim nested creation, deletion/resurrection, mixed property/structure
transactions or an independently authored tree materializer.
Executable nested-creation profile 0
nuif-collab-tree-create-nested-0 extends creation to a bounded causal parent
chain without changing nuif-collab-tree-create-0. A creation may name an
entity created by another change as its parent only when the child context
includes the selected parent dot. The parent chain is resolved before
materialization, cycles and unavailable parents fail as typed errors, and the
chain is capped at the profile’s declared depth limit.
Start is the only supported anchor below a created parent. A base parent may
still use Start or After(base-entity), preserving the base sibling order;
created-parent After anchors are rejected rather than guessed from delivery
order. The payload remains one leaf entity per change, so descendants are
separate changes and ordinary canonical child arrays are produced only after
all selected parent relationships validate. Entity-ID collisions remain
explicit EntityIdCollision conflicts with the greatest dot selected
provisionally.
The profile is intentionally one operation-set materializer. Its conformance fixture exhausts all six deliveries of a causal parent, nested child and base sibling, checks merge convergence and canonical metadata absence, and rejects non-causal/unknown parents, created-parent anchors and incomplete history. Deletions, resurrection, arbitrary created-parent anchors, mixed property/structure transactions and a second independently authored tree materializer remain future work.
Executable nested-creation arbitrary-anchor profile 1
nuif-collab-tree-create-nested-1 preserves profile 0’s wire operation and
causal parent contract while admitting After(entity) anchors under base or
selected created parents. If the anchor is created, the change MUST causally
include the selected anchor dot and the anchor’s selected parent MUST equal the
new change’s parent. An anchor that is absent, non-causal, or owned by another
parent fails with a typed diagnostic. Same-anchor candidates retain descending
dot order, and anchor chains are materialized recursively under the bounded
MAX_PARENT_DEPTH limit.
The canonical checkpoint contains only ordinary entities and child arrays; the anchor dots, causal contexts and active positions remain outside the document. This profile still excludes deletion/resurrection, mixed property/structure transactions and anchors to non-selected collision candidates. Gate H exhausts all 24 deliveries of a causal sibling-chain fixture and checks merge convergence, metadata absence and the typed negative boundaries.
Executable mixed property/structure profile 0
nuif-collab-mixed-0 uses one causal operation set for existing-tree structural
changes and register-like property changes. A checkpoint materializes the
structural operation-set result first, then applies the property register
frontiers to that document. Property and structural conflicts remain distinct,
and a property change whose entity was removed by the selected structural
result fails with PropertyTargetUnavailable; it is never silently discarded.
The profile does not admit creation operations or multiple semantic operations under one change dot. Gate H exhausts all 24 deliveries of a four-change fixture, checks merge convergence, explicit conflict sets and metadata-free output, and rejects deleted targets and cross-kind missing dependencies.
Causal-stability compaction profile 0
nuif-collab-gc-0 is an explicit, conservative history-collection profile. It
does not infer stability from a local log and it never deletes canonical
document data. A host supplies a StabilityFrontier, a replica-to-counter map
attesting that every participant has observed the corresponding history. The
frontier MUST exactly match every locally observed replica clock. A missing,
behind or ahead counter is an unsafe-compaction error and MUST leave the
operation set unchanged.
When the frontier is exact, a register, concurrent-creation or existing-tree
materializer may emit a
CompactionReceipt and replace its complete operation history with the
metadata-free canonical checkpoint it already materializes. The receipt records
the source profile, source base hash, compacted checkpoint hash, frontier and
every dropped change identifier. The checkpoint’s canonical hash and semantic
content MUST equal the pre-compaction checkpoint; replica IDs, clocks, conflict
candidates, positions, tombstones and receipts MUST remain outside the
canonical Document.
Profile 0 intentionally supports complete-history checkpoint compaction only. It MUST NOT prune a stable prefix while retaining later changes, rebase causal contexts, or rewrite structural position anchors. Those operations require a versioned checkpoint-as-causal-base protocol and remain a future profile. A caller MUST retain or archive the receipt and checkpoint according to its sync and recovery policy; compaction is not an interoperability claim for arbitrary CRDT logs.
cargo xtask gate-h runs the register operation-set and replica-log,
concurrent-creation and structural materializers through complete-history
compaction. It checks exact checkpoint equivalence, complete dropped-history
receipts, empty-history behavior, metadata absence and typed refusal of partial
and ahead frontiers. The release report is
target/collaboration-gc-report.json.
Executable causal register prefix profile 0
nuif-collab-gc-prefix-0 defines a deliberately narrow checkpoint-as-causal-
base handoff for register histories. A supplied StabilityFrontier partitions
the complete, validated history into a stable prefix (every local dot at or
below its replica counter) and a retained suffix. The prefix MUST be causally
closed: no stable change may depend on a retained dot. Every retained change
MUST include every non-zero frontier entry in its context, so the suffix
causally dominates the collected checkpoint. These conditions exclude
concurrent retained-versus-stable register conflicts without pretending to
rebase them.
The stable prefix is materialized with the register profile and carried in a
CausalCheckpointBase whose profile, source profile, source-base hash,
frontier and checkpoint are synchronization metadata, not canonical NUIF
fields. ResumedOperationSetEngine accepts only contiguous retained counters,
checks the frontier on ingestion and materializes the suffix over that base.
The resumed checkpoint MUST have the same canonical hash, semantic document and
conflict set as complete replay. CompactionReceipt records source and
compacted hashes plus both dropped and retained change IDs.
Structural changes, arbitrary position anchors, frontier inference, unseen
remote changes and stable/retained concurrent registers are outside this
profile. Implementations MUST return typed failures rather than silently
rebasing context or deleting a position. Gate H exhausts the executable fixture
and archives target/collaboration-gc-prefix-report.json.