Module groups
Expand description
Where a version’s name lives: in the document, with the changes it names.
A name that lived in the widget would vanish on close, and one beside the document would never reach a collaborator. So a name is written into the same CRDT as the content it describes — one record at the document root per named range, keyed by the range it covers:
ROOT
"tilo:group:<hex of the range's first change>" <- the key IS the range
label : "Intro rewrite"
end : "<hex of the range's last change>" (absent while open)
by : "<actor hex of whoever wrote the name>"
at : <unix millis>The key is the range’s first change, not minted per writer, so two people naming the same run collide on one map key and automerge’s conflict rule resolves it identically on every peer. Records sit at the root rather than under one container map for the same reason at a coarser grain: a container created independently by two peers naming different ranges would have one discarded whole, silently losing a name.
Naming a version is a change like any other, but deliberately gets no row of its own in the
history surfaces — see is_group_marker.
Structs§
- Displayed
Session - One work session beside a seam, as the person saw it: its named record,
or
Nonewhile it is still an automatic projection with these bounds and title.
Constants§
- GENERATED_
BY - The
byof a name a model wrote, in place of a person’s actor hex. A generated name is the document’s guess at what a run of changes was: it is replaced by anyone who names the same range, and it is never shown as somebody’s words (NamedRange::named_bystays empty for it). - GROUPS_
KEY - Namespaced so it cannot collide with an app’s own schema:
tilo-docusescontent/comments/props, and the shell’s workspace document usesworkspaces/active. - MAX_
LABEL_ LEN - A version name is a label, not a paragraph; past this it stops fitting anywhere it is rendered and starts being a way to make another user’s timeline unreadable.
Functions§
- apply_
name_ request - Write what a
GroupNameRequestasks for: name its range, or, with an empty label, remove the name it replaces. A range named again from another first change drops the record it replaces, so one run of changes carries one name.falsewhen there was nothing to write. The transaction is left open for the host to commit. - clear_
name - Remove a name. The changes it covered stay; only the band goes.
- close_
range - Close an open range at
end.falsewhen no such record exists. - is_
group_ marker - True when every patch in
patcheslands inside the named-range map — used by the producer to keep naming out of the row list. An empty patch set is not a marker: a change that did nothing visible is still a change, and hiding it would be incorrect behaviour. - materialize_
and_ move_ boundary - Correct a seam even when one or both work sessions are still automatic projections. Missing records are materialized with the titles and bounds the person saw, then the bordering action is moved in the same document transaction. The atomic history entries themselves are never rewritten.
- merge_
named_ ranges - Merge named bands into one caller-resolved range. Every old record must exist before anything is changed, so a stale UI cannot partially merge a set that a collaborator has already edited.
- move_
named_ boundary - Move the boundary between two named bands while preserving both labels. As with split, the caller resolves the two sides from its displayed causal order and sends exact ids.
- name_
is_ generated - Whether the name at
record_idwas written by a model rather than a person. A record this device cannot read counts as a person’s: never overwrite what another writer may have said. - name_
range - Names the run of changes from
starttoend, or opens an unbounded run whenendisNone. Returns the record id (also the document key). The transaction is left open — the host commits, so the naming lands stamped and attributed like any other edit. - name_
range_ by name_range, with thebywritten into the record: a person’s actor hex, orGENERATED_BYfor a name a model wrote.- read_
named_ ranges - Records that do not parse (a corrupted key, a missing label) are skipped rather than guessed at — a band in the wrong place is worse than no band.
- split_
named_ range - Split one named band into two adjacent named bands in the current transaction. The caller supplies both boundary ids because a CRDT history is not inherently linear at concurrent branches; guessing adjacency here would make the operation non-deterministic across peers.