Work together on documents in real time — comment on passages, edit freely, and, whenever you want to know what changed, open Versions, name the two versions you care about, and read the whole thing as a redline (who, when, what) with a one-click revert.


How It Works: Annotations as Satellite Entities

CLEAN DOCUMENT + ANCHORED COMMENTS + DERIVED CHANGES Document Node clean markdown — no markers _Comment Comment satellite Version history every version, author, time captures start, length, version, anchor text tracked changes are DERIVED from it — nothing is stored at render anchor text @ v3 the text when captured current text @ v7 the document now diff (version delta) map the offsets effective range in the live text The highlight (comment) or the inline diff (change) is rendered at the effective range — a transient overlay for that one render. The stored document is never modified. Reverting a change is a normal versioned write — it lands in the history like any other edit. *The document text stays clean. Comments capture the character range they cover; tracked changes are computed from the version history. Both are recomputed at render time.*

MeshWeaver keeps the document's markdown clean — nothing is woven into it. The two annotation kinds get there differently, and the difference is the point:

Annotation type Where it lives Source of truth
Comment _Comment satellite The satellite (genuinely additional data — the document never carried it)
Tracked change nowhere — a view model The node's version history (IVersionQuery / mesh_node_history)

A comment records, on its satellite, the character range it covers (Start/Length), the document version that range was captured against, and the document text at that version (the anchor).

A tracked change stores nothing at all. The version history is already the authoritative record of every change — who made it, when, and the full text before and after — so ChangeProjection diffs a baseline version against the current text and attributes each resulting hunk to the version step that introduced it. Persisting that a second time only bought a failure class: anchors going stale as the document moved, orphaned satellite state, and two answers to "what changed".

Legacy _Tracking satellites. Older builds persisted tracked changes at {doc}/_Tracking/{id}. Nothing writes them any more; the node type and the _Tracking → annotations table mapping stay registered for a deprecation window so existing rows remain readable.

Capturing and recomputing positions

There is no "strip markers / reassemble" round-trip and no marker is ever written into the source. Instead:

  1. Capture — when you comment, the satellite records Start, Length, Version, and AnchorText (the clean document text at that version) plus the highlighted text. A tracked change captures nothing: it is projected from the history, and the text it was projected against becomes its anchor.
  2. Recompute — when the document is displayed, each annotation's effective range is computed against the current text. If the document is still at the captured version, the stored offsets are used directly; if it has moved on, the engine diffs the anchor text against the current text and maps the offsets through that diff (a diff_xIndex-style position map). This is exposed as EffectiveStart / EffectiveEnd / EffectiveVersion.
  3. Overlay — the comment highlight, or the tracked-change diff, is injected as a transient span for that render only.

Because the range is recomputed from the actual edit delta, an annotation follows its text when content is inserted or deleted above it — without the document ever carrying annotation state.

Annotation entity reference

Comment (_Comment partition)

Field Purpose
Start / Length The captured character range in the document's clean text
Version / AnchorText The document version + text the range was captured against
EffectiveStart / EffectiveEnd The range recomputed for the current text (not persisted)
HighlightedText The originally selected text
Status Active or Resolved
PrimaryNodePath Document path used for permission delegation

TrackedChange — a view model, computed by ChangeProjection, never persisted

Field Purpose
ChangeType Insertion, Deletion, or Replacement — classified from the diff hunk
Author / CreatedAt / Version The version-history step that introduced the hunk
OriginalText / NewText What the range held before, and what it holds now
Start / Length / AnchorText The range in the text it was projected against (so a later edit re-locates it)
PrimaryNodePath The document the change belongs to

Comment has IsSatelliteType = true; TrackedChange has no node type of its own any more (the legacy one stays registered read-only — see above).


Adding Comments

Select any passage and click Comment. A Comment satellite is created that captures the selected range, the document version, and the anchor text — the document itself is untouched, so commenting works even without edit access. The highlight is rendered inline from the satellite.

Comments without a selected range attach to the bottom of the page.

Example — a paragraph with comments

MeshWeaver is a powerful platform for building collaborative applications. It provides real-time synchronization and conflict-free editing.

A reviewer might attach comments to:


Making Suggestions (Track Changes)

Suggest Edit (in the UI, or the agent tool of the same name) applies the edit to the document as a normal versioned write. There is no pending-proposal limbo: the edit lands and the version history records who made it and when. Open Versions and the edit reads as a tracked change with a one-click Revert. Reverting is itself a versioned write, so the whole review is auditable instead of a satellite quietly appearing and disappearing.

The redline is never on by default. Reading a document is not reviewing it: the document page shows the document, comments and all, and nothing else. The redline appears only where a reader has said which two versions they want compared — see Choosing what to compare below. That is also why there is no "show changes" toggle to hunt for: the comparison IS the switch.

Additions

New text shows as a green-underlined insertion in the redline.

The quarterly report shows significant growth of 25% in user engagement.

Deletions

Removed text shows struck through, reconstructed from the baseline version — the current document does not carry it.

Please review the outdated documentation before the meeting.

Combined example

Our team has completed the comprehensive analysis of the market trends. We recommend immediate action on the following priorities:

  1. Expand into European markets
  2. Reallocate marketing spend to digital channels
  3. Improve customer retention rates

Choosing what to compare

Open Versions. The list of versions IS the picker — there is no separate dialog to fill in and no baseline to remember between clicks:

You want Do this
What has happened since some version Compare with current on that version's row — one click
What changed between two specific versions From on the older, To on the newer, then Compare
To start over Clear selection

A comparison needs two endpoints, so Compare stays inert until both are named — and says so rather than failing quietly when clicked. Claiming an endpoint that would invert the pair (a From at or after the current To) releases the other one instead of offering a backwards comparison: the picker cannot be driven into a state that Compare would have to refuse.

Compare with current is on every row except the current version's, where it would compare a version with itself.

What the comparison shows

Prose renders as the redline: every hunk introduced between the two versions marked up inline — insertions underlined, deletions struck through — with a card per change naming the author and the time, read straight off the version that introduced it. Non-prose content (and prose, via Show the source diff) renders as the side-by-side source diff instead, which is what you want for front matter or link syntax.

Comparing against the current document keeps the view live: further edits appear as they land, and each change can be reverted. Comparing two historical versions pins the view to the document as it stood at the target version — there is nothing on screen to revert INTO, so revert is not offered there.


Reviewing Changes

Keeping a change

Do nothing. The change is already in the document — that is precisely why it appears in the version history and therefore in the redline. There is no "accept" button because there is nothing left to apply.

Reverting a change

Click on the change card. The range is re-resolved against the live document (so a concurrent edit can never make the revert splice the wrong text) and the previous text is put back:

The revert is a normal versioned write, so it shows up in the history exactly like the edit it undoes.

Reverting everything

Use the Versions page: pick the version you want and restore it. That is one write with one clear meaning, instead of N independent reverts racing each other.


Position Tracking Under Edits

When the document is edited above or around an annotation, its highlight follows the text — without any stored position drifting, because positions are recomputed from the edit delta:

  1. Each annotation captured Start/Length against a known Version and AnchorText.
  2. At display, if the document has advanced past that version, the engine diffs AnchorText against the current text.
  3. Offsets before an edit map unchanged; offsets after shift by the net length delta; an edit inside the range grows or shrinks it; if the anchored text is gone the annotation is dropped from the inline view.
  4. The result is the EffectiveStart/EffectiveEnd used for that render.

This is a pure, deterministic text operation — the same engine drives both comment highlights and the tracked-change diff, and it is covered by an extensive unit-test suite.


Working with Multiple Collaborators

Multiple editors work on the same document without conflicts:

An edit whose text several people touched attributes to nobody rather than to the wrong person — the card then reads as an unattributed change. That is deliberate: guessing an author is worse than admitting the edit is shared.

Example — team review session

Project Proposal (3 collaborators editing)

The proposed timeline for Phase 1 is 4 months. This aggressive but achievable schedule requires:


Tips for Effective Collaboration

  1. Comment before you change — if you are uncertain, ask rather than edit.
  2. Keep edits atomic — one logical change per write makes both the redline and the revert clean.
  3. Resolve threads when done — mark comment threads resolved to keep the sidebar clean.
  4. Reach for Versions for a wholesale undo — restoring a version beats reverting a dozen cards.
  5. Add context — a comment explaining why you made a change helps reviewers decide quickly.
Reconnecting…
The server was updated. Reloading the page to pick up the latest version.