The redline pipeline
From "change clause 9" to native Word tracked changes — proposal, review, and the accept that bakes the edit into the canonical .docx.
4 · The redline lifecycle
The DOCX engine is Docxodus 6.4.0 (a .NET-8 OOXML engine compiled to WASM, patched in three lockfiles to strip debug symbols). Proposals are recorded, never applied directly:
stateDiagram-v2
[*] --> pending : redline (clause rewrite) /\ntracked-changes (phrase swap)\n— both ask permission first
pending --> superseded : newer conflicting proposal\n(same anchor, clause scope or overlap)
pending --> accepted : POST …/redlines/:rid/accept\n→ bake() into canonical .docx → re-ingest
pending --> rejected : POST …/redlines/:rid/reject
accepted --> [*]
rejected --> [*]
superseded --> [*]
- The viewer never mutates the canonical file:
GET /matters/:id/documents/redlinedrebuilds a copy withcompareDocuments(original, modified)so pending proposals render as native Word tracked changes (redline.ts:44), and the same bytes are what "Download" hands to Word. - Accepting bakes: proposals are applied all-or-nothing (throws if an
anchor no longer resolves), the canonical
.docxis rewritten, and the document is re-ingested so offsets stay true (redline.ts:64,server.ts:148). - A third tool,
word-integration, performs silent (untracked) edits — permission-gated, and no redline row is recorded. - Conflict semantics live in
lib/redlines.ts:86–108: proposals collide when they share an anchor and either is clause-scoped or their find-texts overlap; the newer proposal supersedes, independent phrase edits coexist.