Status: explanatory map. The paper ((internal design notes)) describes a session-scoped shadow; the implementation runs shadow-primary. This document names every place they diverge and states why each divergence computes the same algebra. The algebra is the authority: CRDT operations commute, delta changesets add and subtract safely, and clientId gives the known precedence order — so two realizations are "the same" exactly when they produce the same op-log under the same register discipline.

The registers (paper §A.3 — shared by both realizations) #

[0, 2^51)         Regular    — normal operations        (p / b uuids)
[2^51, 2^52)      Liminal    — tentative session ops    (l uuids)
[2^52, 3×2^51)    Committed  — promoted commits         (never encoded; resolved
                                                          via the original l uuid)
[3×2^51, 2^53)    Genesis    — deterministic structure  (d uuids)

committedId = liminalId + 2^51. Resolution of an l uuid probes the committed ("bound") address first, then the liminal one — the paper's committed-preempts-tentative precedence, expressed as a probe order (deref.ts).

Divergence 1 — the shadow is the always-authoring surface #

Paper: normal writes land on main; the shadow exists only during a session, sparing peers the wire cost of ops that may be abandoned (§2.3). Code: every write, session or not, lands on the shadow; entities are homed there permanently (Plexus.ts root materialization on shadow).

Why it is the same thing: outside a session, every shadow transaction carries SHADOW_TO_MAIN and is forwarded to prime byte-identical, in the same tick, at the same (clientId, clock) addresses (Plexus.ts shadow→main listener). Algebraically the steady-state shadow is an identity buffer in front of prime: the op-log prime accumulates is indistinguishable from the paper's direct-to-main writes. The efficiency grounding — one authoring surface, one materialization path, undo isolation — changes where the pen sits, not what gets written. During a session the forwarder suppresses LIMINAL origins, which is precisely the paper's "held on shadow".

Divergence 2 — session boundaries restore, not reallocate #

Paper (A.4 commit, step 13): shadow.clientID ← limId + 1 — a fresh id after every boundary, because in the session-scoped model the shadow's id IS a session id. Code: commit/revert restore __shadowRegularId__, the shadow's resting regular-register id; enterLiminality advances a strictly-increasing liminal sequence (X + LIMINAL_BASE + n) instead.

Why it is the same thing: the paper's step 13 exists to prevent clock-gap reuse — "main never saw the liminal clocks". Both properties survive translation: the liminal id is never returned to (the next session takes n+1 — paper invariant 1, strictly increasing), and the resting id is gap-free by construction because main has seen every one of its clocks via the same-tick forwarder. A.5 invariant 4 ("setup operations use the regular clientId") holds in exactly the form the paper states it.

Divergence 3 — three identity planes, not one clientId #

Paper: speaks of "the peer's clientId" as one number per lifecycle stage. Code: one peer holds three ids at once — prime's doc.clientID (sync-wire and awareness identity; mints no entity structs), the shadow's resting id (steady-state struct authorship), and the per-session liminal id (tentative struct authorship).

Why it is the same thing: the paper's precedence argument only needs authorship ids to be register-partitioned and per-peer monotone within the liminal range — both hold. The extra separation is forced by the substrate: Yjs rerolls a doc whose own clientID is advanced by a non-local transaction, so prime and shadow can never share an id (yjs liminality research /two-doc.test.ts, REJECTED APPROACHES). Awareness identity riding prime's id is then free — presence and struct authorship never collide.

Divergence 4 — preview transport writes into the receiver's shadow #

Paper (Appendix C): previews reach the receiver's "tentative workspace". Code: applyPeerPreview applies the base64 delta into the receiver's shadow under a per-peer symbol origin that the forwarder blocks, with a per-peer UndoManager for un-application.

Why it is the same thing: the tentative workspace IS the shadow in shadow-primary; the forwarder's origin whitelist is what makes "tentative never reaches main" a structural property instead of a discipline.

History #

The register discipline was dropped, not designed away: the single-doc→shadow-primary migration (ce3f8ef272, 2026-03-28) carried the session-scratch shadow's born-liminal clientId into its new permanent role, which made every entity mint l and left the b binding unreachable. Restored 2026-08-05; the discipline is pinned by __tests__/8-liminality/register-discipline.test.ts (born red against the drifted state) and the reroll guard in __tests__/8-liminality/genesis-materialization-shadow-clientid.test.ts.