@ai-matrx/office 0.8.13 → 0.8.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/univer/collab/index.ts","../src/univer/collab/WorkbookCollabSession.ts","../src/univer/collab/covered.ts","../src/univer/collab/docs-ot/transform.ts","../src/univer/collab/docs-ot/state-hash.ts","../src/univer/collab/docs-ot/room.ts","../src/docs/document-ot-room.ts","../src/docs/document-model.ts","../src/univer/openEditorContent.ts","../src/docs/remote-carets.ts","../src/docs/document-service.ts","../src/docs/ports.ts","../src/docs/document-restore.ts"],"sourcesContent":["/**\n * The collab session shared by `/sheets` and `/docs` (was matrx-frontend `features/workbooks/collab`): the\n * Univer <-> Yjs bridge. It owns the Yjs import, so it is loaded on demand (`import()` when a workbook\n * or document goes live). The snapshot-insert subscription hook is its own entry,\n * `@ai-matrx/office/univer/realtime`, so a static import of the hook never carries Yjs into the editor\n * chunk. A transitional subpath, like `./univer`: it goes internal when the editors move.\n */\nexport * from \"./WorkbookCollabSession\";\nexport * from \"./docs-ot\";\nexport * from \"../../docs/document-ot-room\";\nexport * from \"../../docs/document-restore\";\n","/**\n * WorkbookCollabSession — the Univer ↔ Yjs bridge.\n *\n * Subscribes to Univer's public `commandService.onMutationExecutedForCollab`\n * hook for local mutations and pushes them onto a `Y.Array<MutationOp>` shared\n * via `SupabaseYjsProvider`. Inbound Yjs updates produce `IMutationInfo` ops\n * that are applied through `commandService.syncExecuteCommand` with the\n * `fromCollab` execution option flagged so the outbound listener short-\n * circuits and we don't echo our own apply.\n *\n * See `FEATURE.md` in this directory for the architecture, the \"do NOT use\n * the Pro preset\" verdict, and the host-election rule. This class is the\n * runtime side of that plan.\n *\n * Lifecycle:\n * - constructor: wire references, no side effects\n * - start(): create Y.Doc + Awareness, instantiate provider, subscribe to\n * command stream, subscribe to Yjs Array observer\n * - stop(): detach all listeners, dispose provider\n *\n * The session is one-shot per workbook open. Reload = stop() + new instance.\n */\n\"use client\";\n\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport { electCollabHost, remoteOriginOf, REMOTE_PARAM_TAG } from \"@ai-matrx/data/realtime/collab\";\n\nexport { COLLAB_COVERED_KEY, stampCovered, takeCovered } from \"./covered\";\n\n/**\n * Structural transport contract. `SupabaseYjsProvider` satisfies it in\n * production; the verification harness injects an in-memory loopback\n * transport through the same seam. Keeping this structural (not the concrete\n * class) is what makes the session testable without network.\n */\nexport type CollabProviderLike = {\n connect(): Promise<void>;\n disconnect(): void;\n ready(): Promise<void>;\n /**\n * True when this is the only holder of its room in this tab allowed to act as\n * host (autosave). Same-tab holders share one client id and one uid, so\n * awareness cannot tell them apart. Absent = a lone holder = leader.\n */\n isTabLeader?(): boolean;\n};\n\n// Univer types are loose at the public hook boundary; we narrow with a\n// structural interface so we don't have to import the full Univer surface.\ntype MutationParams = Record<string, unknown> | unknown[] | null;\n\nexport type CollabMutationInfo = {\n id: string;\n type: number; // CommandType.MUTATION = 2 in Univer's enum\n params: MutationParams;\n /** Who made it (the person's uid), so a peer can tell its own other tab's edit from a stranger's. */\n uid?: string;\n /**\n * The entry's identity in the room (`<clientId>:<seq>`). A saved snapshot names the entries it holds\n * (`stampCovered`), so a seat that boots from that snapshot never replays them a second time.\n */\n eid?: string;\n};\n\n/**\n * What a seat booted from: the saved snapshot's row id and the room entries that snapshot already holds.\n * The session never replays a covered entry, and a seat that booted from an OLDER snapshot than the\n * room's newest checkpoint first reloads (the entries that checkpoint trimmed are only in that snapshot).\n */\nexport type CollabBase = {\n snapshotId: () => string | null;\n covered: () => ReadonlySet<string>;\n /** Show the newest saved snapshot (and make it the base). */\n reload: () => Promise<void>;\n};\n\ntype ExecuteOptions = {\n /** Per-Univer convention: when true, the command runs locally only and is\n * NOT broadcast to other plugins. We set this on inbound-apply so the\n * subsequent onMutationExecutedForCollab does NOT re-fire on our peer. */\n onlyLocal?: boolean;\n fromCollab?: boolean;\n};\n\nexport type CommandServiceLike = {\n onMutationExecutedForCollab(\n listener: (info: CollabMutationInfo, options?: ExecuteOptions) => void,\n ): {\n dispose: () => void;\n };\n syncExecuteCommand(\n id: string,\n params: MutationParams,\n options?: ExecuteOptions,\n ): unknown;\n};\n\nexport type WorkbookCollabSessionOptions = {\n workbookId: string;\n uid: string;\n clientId: string;\n commandService: CommandServiceLike;\n /** Factory so this file does not statically depend on the provider. */\n makeProvider: (args: {\n workbookId: string;\n clientId: string;\n doc: Y.Doc;\n awareness: Awareness;\n /** Wire to the provider so a host handover re-runs the election. */\n onLeaderChange: () => void;\n }) => CollabProviderLike;\n /** Called when the awareness set changes (peers join / leave / move cursor). */\n onAwarenessChange?: (awareness: Awareness) => void;\n /**\n * A peer replaced the whole content (history restore, Google update): the\n * newest saved snapshot is the content now. Reload it in place; never\n * re-announce. See `announceReplaced`.\n */\n onReplaced?: (snapshotId: string) => void;\n /**\n * TRUE when the room is bound to a Univer DOCUMENT unit (the Docs editor): there the `doc.mutation.*`\n * stream IS the content, so it must travel. Leave unset for a workbook, where `doc.mutation.*` is the\n * in-cell editor's scratch document and never travels (see `isCellEditorScratch`).\n */\n forwardDocumentMutations?: boolean;\n /**\n * The Univer unit id this seat mounted. Each seat can mount its own unit, so a peer's mutation\n * (addressed to the SENDER's unit) is re-addressed to this one before it is applied.\n */\n unitId?: () => string | null;\n /** A peer's mutation could not be applied here: the seat says so and re-syncs; never only a console line. */\n onApplyFailed?: (mutationId: string, error: unknown) => void;\n /**\n * The saved snapshot this seat booted from. Without it a reloading seat replays every entry still in\n * the room's log on top of a snapshot that already holds them: the text shows twice, and the next save\n * stores it twice (2026-10-16).\n */\n base?: CollabBase;\n};\n\n/** What `checkpoint` writes into the room's control map: the newest saved snapshot whose entries left the log. */\ntype CheckpointSignal = { snapshotId: string; by: string };\n\n/** What `announceReplaced` writes into the room's control map. */\ntype ReplacedSignal = { snapshotId: string; by: string; nonce: string };\n\nconst MUTATIONS_ARRAY_KEY = \"mutations\";\nconst CONTROL_MAP_KEY = \"control\";\nconst REPLACED_KEY = \"replaced\";\nconst CHECKPOINT_KEY = \"checkpoint\";\n\nexport class WorkbookCollabSession {\n private readonly options: WorkbookCollabSessionOptions;\n private doc: Y.Doc | null = null;\n private awareness: Awareness | null = null;\n private provider: CollabProviderLike | null = null;\n private commandDisposer: { dispose: () => void } | null = null;\n private yArrayObserver:\n ((event: Y.YArrayEvent<CollabMutationInfo>) => void) | null = null;\n private awarenessObserver: (() => void) | null = null;\n private controlObserver: ((event: Y.YMapEvent<unknown>) => void) | null = null;\n /** >0 while this client swaps its own content: its mutations are not edits. */\n private muted = 0;\n private started = false;\n private disposed = false;\n /** Room entries this seat holds in its content: applied from a peer, or made here. */\n private readonly applied = new Set<string>();\n /** Entries without an id (a peer on an older build) are applied once, by identity. */\n private readonly appliedRefs = new WeakSet<object>();\n private seq = 0;\n /** False until this seat has seen the room's content once (the join-time check runs then). */\n private joined = false;\n /** The base is being reloaded: entries wait in the log until it is shown. */\n private reloadingBase = false;\n\n constructor(options: WorkbookCollabSessionOptions) {\n this.options = options;\n }\n\n async start(): Promise<void> {\n if (this.started || this.disposed) return;\n this.started = true;\n\n this.doc = new Y.Doc();\n this.awareness = new Awareness(this.doc);\n\n // Seed local awareness with the user identity. Cursor (sheetId/row/col)\n // is set later via setCursor().\n this.awareness.setLocalState({\n uid: this.options.uid,\n clientId: this.options.clientId,\n name: this.options.uid.slice(0, 8),\n color: pickColor(this.options.uid),\n sheetId: null,\n row: null,\n col: null,\n ts: Date.now(),\n });\n\n this.provider = this.options.makeProvider({\n workbookId: this.options.workbookId,\n clientId: this.options.clientId,\n doc: this.doc,\n awareness: this.awareness,\n onLeaderChange: () => {\n if (this.awareness) this.options.onAwarenessChange?.(this.awareness);\n },\n });\n\n // Subscribe to inbound Yjs array changes BEFORE connecting the provider,\n // so the initial-state replay (if any) hits our observer.\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n this.yArrayObserver = (event) => {\n // Local transactions are OUR OWN pushes from handleLocalMutation —\n // Univer already executed those mutations. Re-applying them here would\n // double-apply every local edit on the originator. Only act on\n // transactions that arrived via Y.applyUpdate (origin 'remote').\n if (event.transaction.local) return;\n if (!event.changes.delta.some((change) => Array.isArray(change.insert) && change.insert.length > 0)) return;\n this.drain();\n };\n yArray.observe(this.yArrayObserver as Parameters<typeof yArray.observe>[0]);\n\n // Awareness change passthrough.\n if (this.options.onAwarenessChange) {\n const cb = this.options.onAwarenessChange;\n this.awarenessObserver = () => {\n if (this.awareness) cb(this.awareness);\n };\n this.awareness.on(\"change\", this.awarenessObserver);\n }\n\n // Subscribe to Univer's collab-grain mutation stream.\n this.commandDisposer =\n this.options.commandService.onMutationExecutedForCollab((info, options) =>\n this.handleLocalMutation(info, options),\n );\n\n await this.provider.connect();\n await this.provider.ready();\n this.drain();\n\n // Whole-content replacement from a peer. Bound AFTER the initial sync: a\n // joiner already loaded the newest snapshot, so the signal it finds in\n // the room's state is history, not news (the editor also skips a\n // snapshot it already shows).\n if (this.disposed || !this.doc) return;\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const seen = (control.get(REPLACED_KEY) as ReplacedSignal | undefined)?.nonce ?? null;\n this.controlObserver = (event) => {\n if (event.transaction.local || !event.keysChanged.has(REPLACED_KEY)) return;\n const signal = control.get(REPLACED_KEY) as ReplacedSignal | undefined;\n if (!signal?.snapshotId || signal.nonce === seen) return;\n this.options.onReplaced?.(signal.snapshotId);\n };\n control.observe(this.controlObserver);\n }\n\n stop(): void {\n if (this.disposed) return;\n this.disposed = true;\n\n this.commandDisposer?.dispose();\n this.commandDisposer = null;\n\n if (this.doc && this.yArrayObserver) {\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n yArray.unobserve(\n this.yArrayObserver as Parameters<typeof yArray.unobserve>[0],\n );\n this.yArrayObserver = null;\n }\n\n if (this.doc && this.controlObserver) {\n this.doc.getMap<unknown>(CONTROL_MAP_KEY).unobserve(this.controlObserver);\n this.controlObserver = null;\n }\n\n if (this.awareness && this.awarenessObserver) {\n this.awareness.off(\"change\", this.awarenessObserver);\n this.awarenessObserver = null;\n }\n\n this.provider?.disconnect();\n this.provider = null;\n\n if (this.awareness) {\n this.awareness.destroy();\n this.awareness = null;\n }\n\n if (this.doc) {\n this.doc.destroy();\n this.doc = null;\n }\n }\n\n /** How many mutations the shared log holds right now. */\n logLength(): number {\n return this.doc?.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY).length ?? 0;\n }\n\n /**\n * The room entries this seat's content holds RIGHT NOW. Read it in the same synchronous step as the\n * content you are about to save, and save it with that content (`stampCovered`); after the save lands,\n * pass it to `checkpoint`.\n */\n coveredNow(): string[] {\n if (!this.doc) return [];\n const covered = this.options.base?.covered();\n const out: string[] = [];\n for (const op of this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY).toArray()) {\n if (op.eid && (this.applied.has(op.eid) || covered?.has(op.eid))) out.push(op.eid);\n }\n return out;\n }\n\n /**\n * The snapshot `snapshotId` was SAVED holding `covered` (from `coveredNow`): those entries leave the\n * shared log, and the room records the snapshot as its newest checkpoint. Removal is by entry id, never\n * by position — an entry that arrived while the save was in flight is not in the snapshot and stays.\n * Only the elected saver calls this; peers receive it as a delete (never replayed).\n */\n checkpoint(snapshotId: string, covered: readonly string[]): void {\n if (!this.doc) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const drop = new Set(covered);\n const signal: CheckpointSignal = { snapshotId, by: this.options.clientId };\n this.doc.transact(() => {\n const entries = yArray.toArray();\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const eid = entries[i]?.eid;\n if (eid && drop.has(eid)) yArray.delete(i, 1);\n }\n control.set(CHECKPOINT_KEY, signal);\n });\n }\n\n /**\n * This client replaced the whole content and SAVED it as `snapshotId`.\n * One transaction empties the shared mutation log (every entry targets the\n * content that is gone — a joiner must never replay them onto the new\n * snapshot) and tells every peer to reload the newest snapshot.\n */\n announceReplaced(snapshotId: string): void {\n if (!this.doc) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const signal: ReplacedSignal = {\n snapshotId,\n by: this.options.clientId,\n nonce: `${this.options.clientId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`,\n };\n this.doc.transact(() => {\n if (yArray.length > 0) yArray.delete(0, yArray.length);\n control.set(REPLACED_KEY, signal);\n control.set(CHECKPOINT_KEY, { snapshotId, by: this.options.clientId } satisfies CheckpointSignal);\n });\n }\n\n /**\n * Run `swap` (this client tearing its content down and mounting the new\n * one) without broadcasting what Univer emits while it does: those are not\n * edits, and peers reload the same snapshot themselves.\n */\n muteWhile<T>(swap: () => T): T {\n this.muted += 1;\n try {\n return swap();\n } finally {\n this.muted -= 1;\n }\n }\n\n /**\n * Update the local awareness cursor. Call this from Univer's selection\n * listener (`worksheet.onSelectionChange(...)`). Throttle at the call site\n * (~50ms is plenty); the provider broadcasts on its own debounced cycle.\n */\n setCursor(input: {\n sheetId: string | null;\n row: number | null;\n col: number | null;\n }): void {\n if (!this.awareness) return;\n const current = this.awareness.getLocalState() ?? {};\n this.awareness.setLocalState({\n ...current,\n sheetId: input.sheetId,\n row: input.row,\n col: input.col,\n ts: Date.now(),\n });\n }\n\n /**\n * Returns the deterministic host: the connected peer with the lowest uid\n * (lexicographic). Host is the only client that writes canonical snapshots.\n * No election protocol; recompute whenever awareness changes.\n */\n electHost(opts: { tabTieBreak?: boolean } = {}): { isHost: boolean; hostUid: string | null } {\n if (!this.awareness) return { isHost: false, hostUid: null };\n const states = Array.from(this.awareness.getStates().values()) as Array<\n Record<string, unknown>\n >;\n // Lowest uid wins ACROSS tabs; inside this tab only the room's tab leader\n // may be host, because every same-tab holder carries the same uid.\n const leader = this.provider?.isTabLeader?.() ?? true;\n return electCollabHost(states, this.options.uid, this.options.clientId, leader, opts.tabTieBreak ?? false);\n }\n\n // ─── internals ────────────────────────────────────────────────────────\n\n private handleLocalMutation(info: CollabMutationInfo, options?: ExecuteOptions): void {\n if (this.muted > 0) return;\n // Univer marks a mutation `onlyLocal` when every seat derives it itself (formula-engine recalculation,\n // layout results): relaying it turns every recalculation into network traffic and a logged op.\n if (options?.onlyLocal) return;\n if (!this.options.forwardDocumentMutations && isCellEditorScratch(info)) return;\n // Inbound-applied mutations re-fire this listener because Univer's\n // syncExecuteCommand legitimately processes them through the full\n // pipeline. Skip by sniffing the sentinel we stamped on apply.\n if (\n info.params &&\n typeof info.params === \"object\" &&\n !Array.isArray(info.params) &&\n remoteOriginOf(info.params) !== null\n ) {\n return;\n }\n if (!this.doc) return;\n\n // Normalize params through a JSON round-trip BEFORE pushing into Yjs.\n // Yjs (and the Broadcast transport) only carry JSON-encodable values;\n // Univer types its mutation params as \"serializable\" but JS objects can\n // smuggle Date / Map / class instances through that promise. The\n // round-trip makes the failure mode deterministic: a non-encodable\n // mutation is skipped with a warning instead of corrupting the shared\n // doc or desyncing peers mid-session. What we push here is byte-for-byte\n // what remote peers will apply, so local-apply == remote-apply.\n let safeParams: MutationParams;\n try {\n safeParams =\n info.params === undefined || info.params === null\n ? null\n : stripSenderView(JSON.parse(JSON.stringify(info.params)) as MutationParams);\n } catch (err) {\n console.warn(\n `[collab] skipping non-serializable mutation \"${info.id}\" — peers will not receive it`,\n err,\n );\n return;\n }\n\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const eid = `${this.options.clientId}:${++this.seq}`;\n this.applied.add(eid);\n // An edit made here is made on what this seat shows: the join-time check is over.\n this.joined = true;\n yArray.push([{ id: info.id, type: info.type, params: safeParams, uid: this.options.uid, eid }]);\n }\n\n /**\n * Apply every log entry this seat's content does not hold yet, in the log's order. The first time the\n * room shows content, the join-time check runs: a seat that booted from a snapshot OLDER than the\n * room's newest checkpoint reloads first (the entries that checkpoint trimmed exist only in it).\n */\n private drain(): void {\n if (!this.doc || this.disposed || this.reloadingBase) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const entries = yArray.toArray();\n const base = this.options.base;\n if (!this.joined) {\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const checkpoint = control.get(CHECKPOINT_KEY) as CheckpointSignal | undefined;\n if (entries.length === 0 && !checkpoint) return;\n this.joined = true;\n if (base && checkpoint?.snapshotId && checkpoint.snapshotId !== base.snapshotId()) {\n this.reloadingBase = true;\n void base\n .reload()\n .catch((error: unknown) => {\n console.warn(\"[collab] could not load the newest saved version on joining\", error);\n this.options.onApplyFailed?.(\"collab.join\", error);\n })\n .finally(() => {\n this.reloadingBase = false;\n this.drain();\n });\n return;\n }\n }\n const covered = base?.covered();\n for (const op of entries) {\n if (op.eid) {\n if (this.applied.has(op.eid) || covered?.has(op.eid)) continue;\n this.applied.add(op.eid);\n } else {\n if (this.appliedRefs.has(op)) continue;\n this.appliedRefs.add(op);\n }\n this.applyRemoteMutation(op);\n }\n }\n\n private applyRemoteMutation(op: CollabMutationInfo): void {\n // Wrap params with the sentinel so handleLocalMutation knows not to\n // echo the apply back into Yjs.\n const ownUnit = this.options.unitId?.() ?? null;\n const taggedParams: MutationParams =\n op.params && typeof op.params === \"object\" && !Array.isArray(op.params)\n ? {\n ...(op.params as Record<string, unknown>),\n ...(ownUnit && typeof (op.params as { unitId?: unknown }).unitId === \"string\" ? { unitId: ownUnit } : {}),\n [REMOTE_PARAM_TAG]: op.uid ?? true,\n }\n : op.params;\n\n try {\n this.options.commandService.syncExecuteCommand(op.id, taggedParams, {\n onlyLocal: true,\n fromCollab: true,\n });\n } catch (err) {\n // One unappliable op (already baked into the loaded snapshot, or a\n // stale target) must not throw into the realtime channel handler and\n // abort the rest of the catch-up. Said, never swallowed.\n console.warn(\n `[collab] could not apply remote mutation \"${op.id}\" — skipped`,\n err,\n );\n this.options.onApplyFailed?.(op.id, err);\n }\n }\n}\n\n// ─── helpers ────────────────────────────────────────────────────────────\n\n/**\n * A workbook holds no Univer DOCUMENT units of its own: the `doc.mutation.*` stream a sheet emits is\n * the in-cell editor's scratch document (typing into a cell). The finished text reaches the sheet as\n * `sheet.mutation.set-range-values`, which does travel. Sending the scratch edits made a joiner replay\n * them against an editor unit it does not have (\"Trying to overwrite value at key\").\n */\nexport const SENDER_VIEW_PARAMS: readonly string[] = [\"layoutState\", \"textRanges\", \"prevTextRanges\"];\n\n/**\n * Remove what describes the SENDER'S view (the editor's layout cache, caret and selection ranges) from a\n * mutation's params before it travels: a receiver would otherwise restore the sender's layout and caret.\n * Everything else (the content-changing `actions`, ids, addresses) is left as is.\n */\nexport function stripSenderView(params: MutationParams): MutationParams {\n if (!params || typeof params !== \"object\" || Array.isArray(params)) return params;\n const out: Record<string, unknown> = { ...params };\n for (const key of SENDER_VIEW_PARAMS) delete out[key];\n return out;\n}\n\nexport function isCellEditorScratch(info: Pick<CollabMutationInfo, \"id\">): boolean {\n return typeof info.id === \"string\" && info.id.startsWith(\"doc.mutation.\");\n}\n\nconst CURSOR_PALETTE = [\n \"#3b82f6\", // blue\n \"#10b981\", // emerald\n \"#f59e0b\", // amber\n \"#ef4444\", // red\n \"#8b5cf6\", // violet\n \"#06b6d4\", // cyan\n \"#ec4899\", // pink\n \"#84cc16\", // lime\n];\n\nfunction pickColor(uid: string): string {\n // Deterministic FNV-1a-ish hash so the same user is always the same color\n // across sessions and across other users' screens.\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return CURSOR_PALETTE[Math.abs(h) % CURSOR_PALETTE.length] ?? \"#ec4899\";\n}\n","/**\n * A saved snapshot names the collab-room entries it already holds, so a seat that boots from it never\n * replays them (2026-10-16: a reload showed the text twice). Pure — no Yjs — so the editors' model can\n * stamp and read it without loading the room.\n */\n\n/** The key a saved snapshot carries its covered room entries under (`stampCovered` / `takeCovered`). */\nexport const COLLAB_COVERED_KEY = \"__matrxCollabCovered\";\n\n/** The snapshot to SAVE: `snapshot` plus the room entries it holds (`WorkbookCollabSession.coveredNow`). */\nexport function stampCovered<T extends object>(snapshot: T, covered: readonly string[]): T {\n return { ...snapshot, [COLLAB_COVERED_KEY]: [...covered] };\n}\n\n/** A LOADED snapshot split into the content to mount and the room entries it already holds. */\nexport function takeCovered<T>(snapshot: T): { snapshot: T; covered: Set<string> } {\n if (!snapshot || typeof snapshot !== \"object\" || !(COLLAB_COVERED_KEY in (snapshot as object))) {\n return { snapshot, covered: new Set() };\n }\n const { [COLLAB_COVERED_KEY]: list, ...rest } = snapshot as Record<string, unknown>;\n return {\n snapshot: rest as T,\n covered: new Set(Array.isArray(list) ? list.filter((e): e is string => typeof e === \"string\") : []),\n };\n}\n","/**\n * The Docs operational transform (COLLAB-DESIGN §6.4, §6.5; C0b rules R1–R5 plus the C2 retain rule R6).\n *\n * Pure and DOM-free. ot-json1 walks the JSON tree; only the `text-x` edit transform is ours. It is a port of\n * Univer 1.0.4's `TextX._transform` / `transformBody` (Apache-2.0, dream-num/univer, core\n * src/docs/data-model/text-x) with these cases changed or added (evidence: C0-REPORT, C0b):\n *\n * R1 a whole-table delete swallows typing inside it; the typist gets a `lost` entry.\n * R2 a REPLACE (coverType 1) retain keeps a concurrent comment decoration whole.\n * R3 a REPLACE paragraph with no paragraphStyle means \"no style\" ({}), on both sides.\n * R4 style keys are tested for presence (`!== undefined`), never truthiness (a winning `bl: 0`).\n * R5 a non-monotonic op (a negative retain) is rewritten as the composition of its forward segments.\n * R6 a merge (not REPLACE) retain whose style lost every key comes back as a PLAIN retain. Without it `textRuns: [{ts:{}}]` and\n * `textRuns: []` apply differently and two-edit chains diverge (C2: 462 of 20,000; with it 0).\n *\n * Ops carrying `rangeUpdates` go to Univer's `TextX.transform` unchanged (no free 1.0.4 command emits them).\n * `T(x, y, side)` returns x rewritten to apply after y; `side` is x's side and the later-committed op takes\n * `'left'` (§6.4). A transform that throws is a barrier for that pair (the session treats a throw as one).\n */\n/* eslint-disable @typescript-eslint/no-explicit-any -- Univer's text-x action shapes are open JSON */\nimport { JSONX, TextX, getBodySliceForSplitTextXAction, normalizeTextRuns, merge as univerMerge } from \"@univerjs/core\";\nimport * as json1 from \"ot-json1\";\n\ntype Act = Record<string, any> & { t: \"i\" | \"r\" | \"d\"; len: number };\ntype Body = Record<string, any>;\ntype Zone = [number, number];\n/** One `lost` entry: what a transform dropped from either side (R1), for the author's notice. */\nexport interface DocsLost {\n rule: string;\n side: \"insert\" | \"delete\";\n len: number;\n text?: string;\n}\n\nconst isTextX = (c: unknown): c is { et: string; e: Act[] } =>\n !!c && typeof c === \"object\" && (c as { et?: unknown }).et === \"text-x\" && Array.isArray((c as { e?: unknown }).e);\nconst clone = <T>(v: T): T => (v == null ? v : structuredClone(v));\n\n// ── normalization: the traveling shape ──────────────────────────────────────────────────────────────\n\nfunction tableZones(a: Act): Zone[] {\n const out: Zone[] = [];\n for (const t of (a.body?.tables ?? []) as Array<{ startIndex: number; endIndex: number }>) {\n if (t.startIndex >= 0 && t.endIndex <= a.len && t.endIndex > t.startIndex) out.push([t.startIndex, t.endIndex - 1]);\n }\n return out;\n}\n\n/** R5: an op whose cursor goes backwards becomes the composition of its forward-only segments. */\nfunction unrewind(actions: Act[]): Act[] {\n if (!actions.some((a) => a.len < 0)) return actions;\n const segs: Act[][] = [];\n let cur: Act[] = [];\n let cursor = 0;\n for (const a of actions) {\n if (a.len < 0) {\n if (a.t !== \"r\") return actions;\n segs.push(cur);\n cursor += a.len;\n cur = cursor > 0 ? [{ t: \"r\", len: cursor }] : [];\n continue;\n }\n cur.push(a);\n if (a.t !== \"d\") cursor += a.len;\n }\n segs.push(cur);\n const out = segs.reduce((acc, s) => TextX.compose(acc as any, s as any) as unknown as Act[]);\n return out.some((a) => a.len < 0) ? actions : out;\n}\n\nfunction normText(actions: Act[]): Act[] {\n const out: Act[] = [];\n for (const a of unrewind(actions)) {\n if (a.t === \"d\") {\n if (!(a.len > 0)) continue;\n const d: Act = { t: \"d\", len: a.len };\n if (a.valueRangeId !== undefined) d.valueRangeId = a.valueRangeId;\n const tz = (a.tz as Zone[] | undefined) ?? tableZones(a);\n if (tz.length) d.tz = tz;\n out.push(d);\n continue;\n }\n if (a.t === \"r\") {\n const { oldBody: _oldBody, ...rest } = a;\n out.push(rest as Act);\n continue;\n }\n out.push(a);\n }\n return out;\n}\n\n/** The traveling shape of a Docs JSON op: text-x edits normalized (R1 zones, R5, no oldBody). */\nexport function normalizeDocsOp<T>(op: T): T {\n if (op == null) return op;\n const walk = (v: unknown): unknown => {\n if (Array.isArray(v)) return v.map(walk);\n if (isTextX(v)) return { ...v, e: normText(v.e) };\n return v;\n };\n return walk(op) as T;\n}\n\n/** R6: a retain whose style lost every key to the other side is a plain retain. */\nexport function dropEmptyStyleRetains<T>(op: T): T {\n if (op == null) return op;\n const walk = (v: unknown): unknown => {\n if (Array.isArray(v)) return v.map(walk);\n if (isTextX(v)) {\n return {\n ...v,\n e: v.e.map((a) => {\n const b = a.body as Body | undefined;\n if (a.t !== \"r\" || !b || a.coverType === 1) return a;\n const runs = ((b.textRuns as Array<{ ts?: Record<string, unknown> }>) ?? []).filter((r) => r.ts && Object.keys(r.ts).length);\n const other = Object.keys(b).filter(\n (k) => k !== \"textRuns\" && k !== \"dataStream\" && !(Array.isArray(b[k]) && (b[k] as unknown[]).length === 0),\n );\n if (!runs.length && !other.length && !b.dataStream && !a.rangeUpdates?.length) return { t: \"r\", len: a.len };\n if (b.textRuns === undefined || runs.length === (b.textRuns as unknown[]).length) return a;\n return { ...a, body: { ...b, textRuns: runs } };\n }),\n };\n }\n return v;\n };\n return walk(op) as T;\n}\n\n// ── action list helpers (Univer's TextX.push / trimEndUselessRetainAction, plus zone merging) ────────\n\nconst onlyDataStream = (body: Body) => Object.keys(body).length === 1;\nconst shiftZones = (tz: Zone[], by: number): Zone[] => tz.map(([s, e]) => [s + by, e + by]);\nfunction mergeZones(tz: Zone[]): Zone[] {\n const s = [...tz].sort((x, y) => x[0] - y[0]);\n const out: Zone[] = [];\n for (const z of s) {\n const l = out[out.length - 1];\n if (l && l[1] + 1 >= z[0]) l[1] = Math.max(l[1], z[1]);\n else out.push([z[0], z[1]]);\n }\n return out;\n}\nfunction push(list: Act[], action: Act): void {\n let index = list.length;\n let last = list[index - 1];\n const a = clone(action);\n if (a.t === \"r\" && a.len === 0 && a.body == null && !a.rangeUpdates) return;\n if (last) {\n if (last.t === \"d\" && a.t === \"d\" && last.valueRangeId === a.valueRangeId) {\n const tz = [...((last.tz as Zone[]) ?? []), ...shiftZones((a.tz as Zone[]) ?? [], last.len)];\n last.len += a.len;\n if (tz.length) last.tz = mergeZones(tz);\n return;\n }\n if (last.t === \"d\" && a.t === \"i\") {\n index -= 1;\n last = list[index - 1];\n if (last == null) {\n list.unshift(a);\n return;\n }\n }\n if (last.t === \"r\" && a.t === \"r\" && last.body == null && a.body == null && !last.rangeUpdates && !a.rangeUpdates) {\n last.len += a.len;\n return;\n }\n if (last.t === \"i\" && onlyDataStream(last.body) && a.t === \"i\" && onlyDataStream(a.body) && last.valueRangeId === a.valueRangeId) {\n last.len += a.len;\n last.body.dataStream += a.body.dataStream;\n return;\n }\n }\n if (index === list.length) list.push(a);\n else list.splice(index, 0, a);\n}\nconst BODY_FIELDS = [\n \"textRuns\", \"paragraphs\", \"customRanges\", \"customBlocks\", \"docxRawCustomBlocks\", \"docxRawBlocks\",\n \"docxExportExcludedRanges\", \"customDecorations\", \"tables\", \"columnGroups\", \"blockRanges\",\n];\nconst uselessRetain = (a: Act) => !a.rangeUpdates?.length && (a.body == null || BODY_FIELDS.every((k) => a.body[k] == null));\nfunction trimEnd(list: Act[]): Act[] {\n while (list.length && list[list.length - 1]!.t === \"r\" && uselessRetain(list[list.length - 1]!)) list.pop();\n return list;\n}\n\n/** Univer's ActionIterator, plus the offset inside the current action and table zones sliced on split. */\nclass It {\n private i = 0;\n private off = 0;\n constructor(private readonly a: Act[]) {}\n peekType(): Act[\"t\"] {\n return this.a[this.i]?.t ?? \"r\";\n }\n peekLength(): number {\n const x = this.a[this.i];\n return x ? x.len - this.off : Number.POSITIVE_INFINITY;\n }\n hasNext(): boolean {\n return this.peekLength() < Number.POSITIVE_INFINITY;\n }\n /** An insert placed now would land strictly inside a table this delete removes whole. */\n inZone(): boolean {\n const x = this.a[this.i];\n return x?.t === \"d\" && ((x.tz as Zone[]) ?? []).some(([s, e]) => s < this.off && this.off <= e);\n }\n next(length?: number): Act {\n let len = length || Number.POSITIVE_INFINITY;\n const x = this.a[this.i];\n if (!x) return { t: \"r\", len: Number.POSITIVE_INFINITY };\n const offset = this.off;\n if (len >= x.len - offset) {\n len = x.len - offset;\n this.i += 1;\n this.off = 0;\n } else this.off += len;\n if (x.t === \"d\") {\n const piece: Act = { ...clone(x), len };\n delete piece.tz;\n const tz = ((x.tz as Zone[]) ?? [])\n .map(([s, e]): Zone => [Math.max(s, offset) - offset, Math.min(e, offset + len - 1) - offset])\n .filter(([s, e]) => s <= e);\n if (tz.length) piece.tz = tz;\n return piece;\n }\n if (x.t === \"r\" && x.body == null) return { ...clone(x), len };\n return { ...clone(x), len, body: getBodySliceForSplitTextXAction(x.body, offset, offset + len, false) };\n }\n}\n\n// ── body transforms: ported from Univer transform-utils.ts, cases R3/R4 marked ───────────────────────\n\nfunction transformTextRuns(originTextRuns: any[] | undefined, targetTextRuns: any[] | undefined, originCoverType: number, targetCoverType: number, transformType: 0 | 1): any[] | undefined {\n if (originTextRuns == null || targetTextRuns == null) return targetTextRuns;\n if (originTextRuns.length === 0 || targetTextRuns.length === 0) return [];\n targetTextRuns = clone(targetTextRuns);\n originTextRuns = clone(originTextRuns);\n const out: any[] = [];\n const updateLength = targetTextRuns.length;\n const removeLength = originTextRuns.length;\n let updateIndex = 0;\n let removeIndex = 0;\n let pending: any = null;\n const flush = () => {\n if (pending) {\n out.push(pending);\n pending = null;\n return true;\n }\n return false;\n };\n while (updateIndex < updateLength && removeIndex < removeLength) {\n const { st: updateSt, ed: updateEd, ts: targetStyle } = targetTextRuns[updateIndex];\n const { st: removeSt, ed: removeEd, ts: originStyle, sId } = originTextRuns[removeIndex];\n let newTs: Record<string, unknown> = {};\n if (transformType === 0) {\n newTs = { ...targetStyle };\n if (originCoverType === 0 && targetCoverType === 1 && originStyle) newTs = Object.assign({}, originStyle, newTs);\n } else {\n newTs = { ...targetStyle };\n if (originCoverType === 1) {\n if (targetCoverType === 1) newTs = { ...originStyle };\n else if (targetStyle && originStyle) {\n for (const key of Object.keys(targetStyle)) if (originStyle[key] !== undefined) delete newTs[key]; // R4\n }\n } else if (targetCoverType === 1) {\n if (originStyle) for (const key of Object.keys(originStyle)) if (originStyle[key] !== undefined) newTs[key] = originStyle[key];\n } else if (originStyle) {\n for (const key of Object.keys(originStyle)) if (newTs[key] !== undefined) delete newTs[key];\n }\n }\n if (updateEd < removeSt) {\n if (!flush()) out.push(targetTextRuns[updateIndex]);\n updateIndex++;\n } else if (removeEd < updateSt) {\n if (!flush()) out.push(originTextRuns[removeIndex]);\n removeIndex++;\n } else {\n out.push({ st: Math.max(updateSt, removeSt), ed: Math.min(updateEd, removeEd), ts: newTs, sId });\n if (updateEd < removeEd) {\n updateIndex++;\n originTextRuns[removeIndex].st = updateEd;\n if (originTextRuns[removeIndex].st === originTextRuns[removeIndex].ed) removeIndex++;\n } else {\n removeIndex++;\n targetTextRuns[updateIndex].st = removeEd;\n if (targetTextRuns[updateIndex].st === targetTextRuns[updateIndex].ed) updateIndex++;\n }\n const p = {\n st: Math.min(updateEd, removeEd),\n ed: Math.max(updateEd, removeEd),\n ts: updateEd < removeEd ? { ...originStyle } : { ...targetStyle },\n sId: updateEd < removeEd ? sId : undefined,\n };\n pending = p.ed > p.st ? p : null;\n }\n }\n flush();\n const top = out[out.length - 1];\n const updateLast = targetTextRuns[updateLength - 1];\n const removeLast = originTextRuns[removeLength - 1];\n if (top.ed !== Math.max(updateLast.ed, removeLast.ed)) out.push(updateLast.ed > removeLast.ed ? updateLast : removeLast);\n return normalizeTextRuns(out, true);\n}\n\nfunction transformCustomRanges(o: any[] | undefined, t: any[] | undefined, originCoverType: number, _targetCoverType: number, transformType: 0 | 1): any[] | undefined {\n if (o == null || t == null) return t;\n if (o.length === 0 || t.length === 0) return [];\n if (o.length > 1 || t.length > 1) throw new Error(\"CustomRanges is only supported transform for length one now.\");\n if (originCoverType === 1) return transformType === 1 ? [clone(o[0])] : [clone(t[0])];\n const r = clone(t[0]);\n if (transformType === 1) Object.assign(r, clone(o[0]));\n return [r];\n}\n\nfunction transformParagraph(origin: any, target: any, originCoverType: number, targetCoverType: number, transformType: 0 | 1): any {\n const paragraph: any = { startIndex: target.startIndex, paragraphId: target.paragraphId };\n // R3: on a REPLACE paragraph, a missing paragraphStyle means \"no style\", which is a value.\n const oStyle = originCoverType === 1 ? origin.paragraphStyle ?? {} : origin.paragraphStyle;\n const tStyle = targetCoverType === 1 ? target.paragraphStyle ?? {} : target.paragraphStyle;\n if (tStyle) {\n paragraph.paragraphStyle = clone(tStyle);\n if (oStyle) {\n const ps = paragraph.paragraphStyle;\n if (originCoverType === 1) {\n if (targetCoverType === 1) {\n if (transformType === 1) paragraph.paragraphStyle = { ...oStyle };\n } else if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (oStyle[k] !== undefined) ps[k] = oStyle[k];\n } else for (const k of Object.keys(oStyle)) if (ps[k] === undefined) ps[k] = oStyle[k];\n } else if (targetCoverType === 1) {\n if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (oStyle[k] !== undefined) ps[k] = oStyle[k];\n } else for (const k of Object.keys(oStyle)) if (ps[k] === undefined) ps[k] = oStyle[k];\n } else if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (ps[k] !== undefined) delete ps[k]; // R3: presence, not truthiness\n }\n }\n if (targetCoverType !== 1 && Object.keys(paragraph.paragraphStyle).length === 0) delete paragraph.paragraphStyle;\n }\n if (originCoverType === 1 && targetCoverType === 1) paragraph.bullet = transformType === 1 ? clone(origin.bullet) : clone(target.bullet);\n else if (origin.bullet === undefined) paragraph.bullet = clone(target.bullet);\n else if (originCoverType === 1 || targetCoverType === 1) paragraph.bullet = transformType === 0 && target.bullet ? clone(target.bullet) : clone(origin.bullet);\n else if (transformType === 0 && target.bullet !== undefined) paragraph.bullet = clone(target.bullet);\n if (paragraph.bullet === undefined) delete paragraph.bullet;\n if (paragraph.paragraphId === undefined) delete paragraph.paragraphId;\n return paragraph;\n}\n\nfunction transformCustomDecorations(origin: any[] | undefined, target: any[] | undefined): any[] | undefined {\n if (origin == null || target == null) return target;\n if (origin.length === 0 || target.length === 0) return clone(target);\n const out: any[] = [];\n for (const d of target) {\n let pushed = false;\n for (const o of origin) {\n if (o.id === d.id) {\n if (o.type === 9999 || d.type === 9999) {\n pushed = true;\n out.push({ ...d, type: 9999 });\n }\n break;\n }\n }\n if (!pushed) out.push(d);\n }\n return out;\n}\n\nfunction transformBlockRanges(thisBlockRanges: any[], otherBlockRanges: any[], priority: boolean): any[] {\n if (!thisBlockRanges.length) return otherBlockRanges;\n if (!otherBlockRanges.length) return [];\n return otherBlockRanges.map((o) => {\n const t = thisBlockRanges.find((b) => b.blockId === o.blockId);\n return t && priority ? univerMerge(o, t) : o;\n });\n}\n\n/** transformBody(thisAction = the other op's chunk, otherAction = the chunk being transformed, priority = this wins). */\nfunction transformBody(thisAction: Act, otherAction: Act, priority: boolean): { coverType: number; body: Body } {\n const { body: thisBody, coverType: thisCoverType = 0 } = thisAction;\n const { body: otherBody, coverType: otherCoverType = 0 } = otherAction;\n if (thisBody == null || thisBody.dataStream !== \"\" || otherBody == null || otherBody.dataStream !== \"\") {\n throw new Error(\"Data stream is not supported in retain transform.\");\n }\n const ret: Body = { dataStream: \"\" };\n const { textRuns: tr1, paragraphs: p1 = [], blockRanges: b1 = [], customRanges: c1, customDecorations: d1 } = thisBody;\n const { textRuns: tr2, paragraphs: p2 = [], blockRanges: b2 = [], customRanges: c2, customDecorations: d2 } = otherBody;\n const pt: 0 | 1 = priority ? 1 : 0;\n const textRuns = transformTextRuns(tr1, tr2, thisCoverType, otherCoverType, pt);\n if (textRuns) ret.textRuns = textRuns;\n const customRanges = transformCustomRanges(c1, c2, thisCoverType, otherCoverType, pt);\n if (customRanges) ret.customRanges = customRanges;\n const customDecorations = transformCustomDecorations(d1, d2);\n if (customDecorations) ret.customDecorations = customDecorations;\n const paragraphs: any[] = [];\n let i = 0;\n let j = 0;\n while (i < p1.length && j < p2.length) {\n const a = p1[i];\n const b = p2[j];\n if (a.startIndex === b.startIndex) {\n paragraphs.push(transformParagraph(a, b, thisCoverType, otherCoverType, pt));\n i++;\n j++;\n } else if (a.startIndex < b.startIndex) i++;\n else {\n paragraphs.push(clone(b));\n j++;\n }\n }\n if (j < p2.length) paragraphs.push(...p2.slice(j));\n if (paragraphs.length) ret.paragraphs = paragraphs;\n const blockRanges = transformBlockRanges(b1, b2, priority);\n if (blockRanges.length) ret.blockRanges = blockRanges;\n return { coverType: otherCoverType, body: ret };\n}\n\n// ── the text-x transform ──────────────────────────────────────────────────────────────────────────────\n\nconst valueIds = (acts: Act[]) => new Set(acts.flatMap((a) => (a.t !== \"r\" && a.valueRangeId ? [a.valueRangeId as string] : [])));\nfunction withoutValueRangeMetadata(acts: Act[], suppressed: Set<string>): Act[] {\n return acts.map((a) => {\n if (!a.body?.customRanges?.some((r: any) => suppressed.has(r.rangeId))) return a;\n const body = { ...a.body, customRanges: a.body.customRanges.filter((r: any) => !suppressed.has(r.rangeId)) };\n if (!body.customRanges.length) delete body.customRanges;\n return { ...a, body };\n });\n}\n/** Decorations y adds, in the coordinates of the document after y. */\nfunction addedDecorations(y: Act[]): Array<{ id: string; type: number; ds: number; de: number }> {\n const out: Array<{ id: string; type: number; ds: number; de: number }> = [];\n let pos = 0;\n for (const a of y) {\n if (a.t === \"d\") continue;\n if (a.t === \"r\") for (const d of a.body?.customDecorations ?? []) if (d.type !== 9999) out.push({ id: d.id, type: d.type, ds: pos + d.startIndex, de: pos + d.endIndex });\n pos += a.len;\n }\n return out;\n}\nconst hasRangeUpdates = (acts: Act[]) => acts.some((a) => a.t === \"r\" && a.rangeUpdates?.length);\n\n/** x rewritten to apply after y over one text-x body; `side` is x's side. Drops land in `lost` (R1). */\nexport function transformTextX(xIn: Act[], yIn: Act[], side: \"left\" | \"right\", lost: DocsLost[] = []): Act[] {\n if (hasRangeUpdates(xIn) || hasRangeUpdates(yIn)) return TextX.transform(xIn as any, yIn as any, side) as unknown as Act[];\n const x = normText(xIn);\n const y = normText(yIn);\n const xLeft = side === \"left\";\n const yIds = valueIds(y);\n const conflicts = new Set([...valueIds(x)].filter((id) => yIds.has(id)));\n const X = new It(conflicts.size && !xLeft ? withoutValueRangeMetadata(x, conflicts) : x);\n const Y = new It(conflicts.size && xLeft ? withoutValueRangeMetadata(y, conflicts) : y);\n const decos = addedDecorations(y).map((d) => ({ ...d, pieces: [] as Zone[] }));\n const out: Act[] = [];\n let inPos = 0;\n let outPos = 0;\n while (X.hasNext() || Y.hasNext()) {\n if (X.peekType() === \"i\" && (xLeft || Y.peekType() !== \"i\")) {\n const a = X.next();\n if (Y.inZone()) {\n lost.push({ rule: \"R1\", side: \"insert\", len: a.len, ...(a.body?.dataStream !== undefined ? { text: a.body.dataStream } : {}) });\n continue;\n }\n if (a.valueRangeId && conflicts.has(a.valueRangeId) && !xLeft) continue;\n push(out, a);\n outPos += a.len;\n } else if (Y.peekType() === \"i\") {\n const b = Y.next();\n if (X.inZone()) {\n push(out, { t: \"d\", len: b.len, tz: [[0, b.len - 1]] });\n lost.push({ rule: \"R1\", side: \"delete\", len: b.len, ...(b.body?.dataStream !== undefined ? { text: b.body.dataStream } : {}) });\n inPos += b.len;\n continue;\n }\n if (b.valueRangeId && conflicts.has(b.valueRangeId) && xLeft) push(out, { t: \"d\", len: b.len, valueRangeId: b.valueRangeId });\n else {\n push(out, { t: \"r\", len: b.len });\n outPos += b.len;\n }\n inPos += b.len;\n } else {\n const len = Math.min(X.peekLength(), Y.peekLength());\n const a = X.next(len);\n const b = Y.next(len);\n if (b.t === \"d\") continue;\n if (a.t === \"d\") {\n push(out, a);\n inPos += len;\n continue;\n }\n for (const d of decos) {\n const s = Math.max(d.ds, inPos);\n const e = Math.min(d.de, inPos + len - 1);\n if (s <= e) d.pieces.push([outPos + s - inPos, outPos + e - inPos]);\n }\n let r: Act = a;\n if (a.body != null && b.body != null) {\n const { coverType, body } = transformBody(b, a, !xLeft);\n r = { ...a, t: \"r\", coverType, body };\n }\n // R2: a REPLACE retain re-asserts, whole, every decoration y added that it overlaps.\n if (r.coverType === 1 && r.body) {\n const keep: any[] = [];\n for (const d of decos) {\n if (!(d.de >= inPos && d.ds < inPos + len)) continue;\n const ahead: Zone[] = d.de >= inPos + len ? [[outPos + len + Math.max(d.ds, inPos + len) - (inPos + len), outPos + d.de - inPos]] : [];\n for (const [s, e] of [...d.pieces, ...ahead]) keep.push({ id: d.id, type: d.type, startIndex: s - outPos, endIndex: e - outPos });\n }\n if (keep.length) r = { ...r, body: { ...r.body, customDecorations: [...(r.body.customDecorations ?? []), ...keep] } };\n }\n push(out, r);\n inPos += len;\n outPos += len;\n }\n }\n return trimEnd(out);\n}\n\n// ── ot-json1 binding ─────────────────────────────────────────────────────────────────────────────────\n\n/** A Docs operation: an ot-json1 op over the whole Univer snapshot (what `rich-text-editing` carries as `actions`). */\nexport type DocsOp = unknown[] | null;\n\nexport interface DocsTransformResult {\n op: DocsOp;\n lost: DocsLost[];\n}\n\nlet sink: DocsLost[] | null = null;\nconst ours = {\n name: \"text-x\",\n uri: (TextX as unknown as { uri: string }).uri,\n apply: (doc: any, actions: any) => TextX.apply(doc, actions),\n compose: (a: any, b: any) => TextX.compose(a, b),\n isNoop: (a: any) => TextX.isNoop(a),\n invert: (a: any) => TextX.invert(a),\n makeInvertible: (a: any, doc: any) => TextX.makeInvertible(a, doc),\n transform: (x: any, y: any, side: \"left\" | \"right\") => transformTextX(x, y, side, sink ?? []),\n};\n\n/**\n * `T(x, y, side)` for Docs: ot-json1 `transformNoConflict` (never throws on DROP_COLLISION / RM_UNEXPECTED_CONTENT /\n * BLACKHOLE, §3) with our text-x transform registered only for the duration of one call, so Univer's own apply is\n * untouched even when the bundler shares one ot-json1 instance with `@univerjs/core`. R6 runs on the result.\n */\nexport function transformDocsOp(x: DocsOp, y: DocsOp, side: \"left\" | \"right\"): DocsTransformResult {\n if (x == null) return { op: null, lost: [] };\n if (y == null) return { op: x, lost: [] };\n const lost: DocsLost[] = [];\n sink = lost;\n json1.type.registerSubtype(ours as any);\n try {\n const op = json1.type.transformNoConflict(normalizeDocsOp(x) as any, normalizeDocsOp(y) as any, side) as DocsOp;\n return { op: dropEmptyStyleRetains(op), lost };\n } finally {\n json1.type.registerSubtype(TextX as any);\n sink = null;\n }\n}\n\n/** `a` then `b` as one op (TextX is the subtype every reader composes with). */\nexport function composeDocsOps(a: DocsOp, b: DocsOp): DocsOp {\n if (a == null) return b;\n if (b == null) return a;\n json1.type.registerSubtype(TextX as any);\n return json1.type.compose(a as any, b as any) as DocsOp;\n}\n\nexport function isNoopDocsOp(op: DocsOp): boolean {\n return op == null || (Array.isArray(op) && op.length === 0) || json1.type.isNoop(op as any);\n}\n\n/** Apply an op to a plain snapshot (tests, the fold). Univer's own JSONX, so TextX applies as the editor applies. */\nexport function applyDocsOp<T>(doc: T, op: DocsOp): T {\n if (isNoopDocsOp(op)) return doc;\n return JSONX.apply(structuredClone(doc) as any, op as any) as T;\n}\n\n/** The inverse of `op` against the state it applied to. JSONX.invertWithDoc MUTATES its op: invert a copy (C0). */\nexport function invertDocsOp(op: DocsOp, preDoc: unknown): DocsOp {\n if (isNoopDocsOp(op)) return null;\n return JSONX.invertWithDoc(structuredClone(op) as any, preDoc as any) as DocsOp;\n}\n\n/** Part of `proto` (§6.4): Univer 1.0.4 + this transformer, rules R1–R6. */\nexport const DOCS_TRANSFORM_VERSION = \"univer-1.0.4+docs-ot-r6\";\n","/**\n * The canonical Docs state hash (COLLAB-DESIGN §7.2; C0 item 6, `spikes/c0-collab/lib.mjs`).\n *\n * SHA-256 of the canonical snapshot: keys sorted, empty values dropped, the unit id and seat-local fields\n * removed (revision counter, collab stamps, layout state, selections), adjacent equal text runs merged, split\n * pieces of one custom range or decoration folded, and `paragraphId` dropped (Univer's TextX.apply mints a\n * random one per seat, C0 surprise 3). Header, footer and note bodies get the same rules.\n *\n * Two seats with equal content hash equal; one character more hashes differently. Browser and Node: the\n * digest is Web Crypto's.\n */\n/* eslint-disable @typescript-eslint/no-explicit-any -- snapshot JSON */\n\n/** Never content: the collab stamps, revision counters, seat-local view state. */\nexport const DOC_LOCAL_KEYS = [\"rev\", \"__matrxCollabCovered\", \"__collab\", \"disabled\", \"layoutState\", \"textRanges\", \"selections\"];\n\nfunction sortDeep(v: any): any {\n if (Array.isArray(v)) return v.map(sortDeep);\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v).sort()) {\n const x = v[k];\n if (x === undefined || x === null) continue;\n if (Array.isArray(x) && x.length === 0) continue;\n if (x && typeof x === \"object\" && !Array.isArray(x) && Object.keys(x).length === 0) continue;\n out[k] = sortDeep(x);\n }\n return out;\n }\n return v;\n}\n\nconst sameTs = (a: unknown, b: unknown) => JSON.stringify(sortDeep(a ?? {})) === JSON.stringify(sortDeep(b ?? {}));\n\nfunction canonicalRuns(runs: any[] | undefined): any[] {\n const out: any[] = [];\n for (const r of [...(runs ?? [])].sort((x, y) => x.st - y.st)) {\n if (r.ed <= r.st) continue;\n const ts = sortDeep(r.ts ?? {});\n if (Object.keys(ts).length === 0) continue;\n const last = out[out.length - 1];\n if (last && last.ed === r.st && sameTs(last.ts, ts)) last.ed = r.ed;\n else out.push({ st: r.st, ed: r.ed, ts });\n }\n return out;\n}\n\nfunction foldPieces(items: any[] | undefined, keyOf: (it: any) => string): any[] {\n const groups = new Map<string, any[]>();\n for (const it of items ?? []) {\n const k = keyOf(it);\n const g = groups.get(k) ?? [];\n g.push(it);\n groups.set(k, g);\n }\n const out: any[] = [];\n for (const list of groups.values()) {\n list.sort((a, b) => a.startIndex - b.startIndex);\n let cur: any = null;\n for (const it of list) {\n if (cur && cur.endIndex + 1 >= it.startIndex) cur.endIndex = Math.max(cur.endIndex, it.endIndex);\n else {\n if (cur) out.push(cur);\n cur = { ...it };\n }\n }\n if (cur) out.push(cur);\n }\n return out;\n}\nconst rootId = (id: unknown) => String(id).split(\"$\")[0];\n\nfunction canonicalBody(body: any): any {\n if (!body) return body;\n const b = { ...body };\n b.textRuns = canonicalRuns(b.textRuns);\n if (Array.isArray(b.paragraphs)) b.paragraphs = b.paragraphs.map(({ paragraphId: _p, ...p }: any) => p);\n b.customRanges = foldPieces(b.customRanges, (r) => JSON.stringify([rootId(r.rangeId), r.rangeType, sortDeep(r.properties ?? {})])).map((r) => ({\n ...r,\n rangeId: rootId(r.rangeId),\n }));\n b.customDecorations = foldPieces(b.customDecorations, (d) => JSON.stringify([d.id, d.type]));\n for (const k of [\"paragraphs\", \"customRanges\", \"customBlocks\", \"tables\", \"sectionBreaks\", \"customDecorations\"]) {\n if (Array.isArray(b[k])) {\n b[k] = [...b[k]].sort(\n (x: any, y: any) =>\n (x.startIndex ?? 0) - (y.startIndex ?? 0) ||\n String(x.rangeId ?? x.blockId ?? x.tableId ?? \"\").localeCompare(String(y.rangeId ?? y.blockId ?? y.tableId ?? \"\")),\n );\n }\n }\n return b;\n}\n\n/** The canonical Docs snapshot: content only, keys sorted, runs normalized, local fields removed. */\nexport function canonicalDocsSnapshot(snapshot: unknown): unknown {\n const s = structuredClone(snapshot ?? {}) as any;\n delete s.id;\n for (const k of DOC_LOCAL_KEYS) delete s[k];\n s.body = canonicalBody(s.body);\n for (const seg of [\"headers\", \"footers\", \"notes\"]) {\n if (!s[seg]) continue;\n for (const id of Object.keys(s[seg])) s[seg][id] = { ...s[seg][id], body: canonicalBody(s[seg][id].body) };\n }\n return sortDeep(s);\n}\n\n/** The canonical form as the string the hash digests (tests compare these directly). */\nexport const canonicalDocsString = (snapshot: unknown): string => JSON.stringify(canonicalDocsSnapshot(snapshot));\n\n/** SHA-256 hex of the canonical snapshot (§7.2). */\nexport async function docsStateHash(snapshot: unknown): Promise<string> {\n const bytes = new TextEncoder().encode(canonicalDocsString(snapshot));\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/**\n * Ids every seat agrees on for a snapshot that lacks them (C0 surprise 5): a raw snapshot (an import, markdown)\n * loaded on two seats would otherwise get two random `sectionId`s / `paragraphId`s. Missing ids become\n * positional ones; ids already present are kept. Applied to every snapshot a room loads.\n */\nexport function stampDeterministicIds<T>(snapshot: T): T {\n const s = structuredClone(snapshot) as any;\n const stamp = (body: any, scope: string) => {\n if (!body) return;\n for (const p of body.paragraphs ?? []) if (!p.paragraphId) p.paragraphId = `p_${scope}${p.startIndex}`;\n for (const sb of body.sectionBreaks ?? []) if (!sb.sectionId) sb.sectionId = `s_${scope}${sb.startIndex}`;\n };\n stamp(s?.body, \"\");\n for (const seg of [\"headers\", \"footers\", \"notes\"]) for (const id of Object.keys(s?.[seg] ?? {})) stamp(s[seg][id]?.body, `${id}_`);\n return s as T;\n}\n","/**\n * The Docs co-editing room on the ordered log (COLLAB-DESIGN §6, unit C3): the `OpDocumentAdapter` for\n * `openOpSession` over a document's editors, plus saves, restore and the saver choice.\n *\n * - CAPTURE (§6.3). The document model hands over every local `doc.mutation.rich-text-editing` with the applied\n * params (the handler's own rewrite, C0 surprise 6), the pre-state cloned in `beforeCommandExecuted`, and the\n * outermost command id. `onlyLocal` / `fromCollab` never arrive here (the model filters them). Only `segmentId`\n * and `actions` travel; the inverse is computed from the APPLIED actions on a COPY (`invertWithDoc` mutates its\n * op). Each mutation goes to the session as it happens, so a remote apply can never land between a local\n * mutation and its hand-over; the command id rides along as the change's label.\n * - APPLY (§6.7). `syncExecuteCommand(id, { unitId: own, segmentId, actions, textRanges: null,\n * noNeedSetTextRange: true }, { onlyLocal: true, fromCollab: true })` through the model (every view of the\n * document in this tab). A throw, `false`, or actions the handler emptied fail the apply: the session rebuilds,\n * never skips. While an IME composition is open, remote applies QUEUE (acks continue); a local op captured\n * meanwhile is rebased over the queue (`L' = T(L, Q, 'left')`, `Q' = T(Q, L, 'right')`), and the queue drains\n * at `compositionend`.\n * - UNDO (§6.9). Each applied remote op rebases every stored undo and redo item of this seat\n * (`T(item, R1, 'left')`); `textRanges` and `layoutState` are stripped from rebased items; an item whose rebase\n * is a barrier, throws or comes back empty is dropped. Undo therefore only ever reverts this person's changes.\n * - SAVES (§7.3). Only a quiet seat whose hash matches every peer at its rev saves, and only the chosen saver\n * (the lowest client id among seats publishing a quiet hash) saves on its own; a manual save always tries.\n * - RESTORE (§20). A whole-document replace goes through `collab_replace`: the snapshot is loaded into this seat's\n * editor first, so the stored snapshot and its hash are the Univer-normalised form every seat will load.\n */\nimport type {\n OpDocumentAdapter,\n OpPresence,\n OpSession,\n OpSessionIncident,\n OpSessionNotice,\n OpSessionStatus,\n OpTransport,\n} from \"@ai-matrx/data/realtime/collab\";\nimport { isOpBarrier, openOpSession } from \"@ai-matrx/data/realtime/collab\";\n\nimport { canonicalDocsString, docsStateHash, stampDeterministicIds } from \"./state-hash\";\nimport {\n composeDocsOps,\n DOCS_TRANSFORM_VERSION,\n invertDocsOp,\n isNoopDocsOp,\n normalizeDocsOp,\n transformDocsOp,\n type DocsOp,\n} from \"./transform\";\n\nexport const RICH_TEXT_EDITING = \"doc.mutation.rich-text-editing\";\n\n/**\n * The room's protocol (§6.4): Univer 1.0.4 + transformer `DOCS_TRANSFORM_VERSION`. Any Univer or transformer\n * change raises it; a room at another proto opens read-only for this build.\n */\nexport const DOCS_COLLAB_PROTO = 1;\n\n/** One local mutation as the document model hands it over. */\nexport interface DocsLocalMutation {\n id: string;\n params: unknown;\n /** The document before this mutation (cloned in `beforeCommandExecuted`), when the view could supply it. */\n pre: unknown | null;\n /** The outermost command this mutation belongs to (the depth tracker with its try/finally guard). */\n cmd: string | null;\n /** Whether the mutation changes what a snapshot stores. */\n content: boolean;\n}\n\n/** What the document model lends the room (implemented by `DocumentModel`). */\nexport interface DocsOtPort {\n onLocal(listener: (m: DocsLocalMutation) => void): () => void;\n /** Apply one committed mutation to every view of the document; throws when any view could not. */\n applyRemote(id: string, params: Record<string, unknown>): void;\n /** The document as the editor holds it now (`doc.save()`), or null when no view is mounted. */\n snapshot(): unknown | null;\n /** Replace the document in every view (and the kept editor). */\n load(snapshot: unknown): void;\n /** Univer's undo/redo service of each mounted view and the unit it holds. */\n undoTargets(): Array<{ service: unknown; unitId: string }>;\n /** Ask for a save (the record's one coalesced save). */\n markDirty(): void;\n /** This seat's text selection in the first view (body offsets), for presence (C8). Absent when no view can say. */\n selection?(): Array<{ startOffset: number; endOffset: number; segmentId?: string }> | null;\n}\n\nexport type DocsOtNotice =\n | OpSessionNotice<DocsOp>\n | { kind: \"not_shared\"; mutationId: string }\n | { kind: \"not_live\" };\n\nexport interface OpenDocsOtRoomOptions {\n port: DocsOtPort;\n transport: OpTransport;\n clientId: string;\n presence?: OpPresence;\n /** `collab_replace` for this room (restore, whole import). */\n replace: (req: { snapshot: unknown; stateHash: string; clientId: string }) => Promise<{ rev: number; ref: string }>;\n onNotice?: (n: DocsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n /** Watch IME composition here (default: `document`). */\n compositionTarget?: Pick<Document, \"addEventListener\" | \"removeEventListener\"> | null;\n}\n\nexport interface DocsOtRoom {\n session: OpSession<DocsOp>;\n /** The record's save: a checkpoint at a quiet point (§7.3). False when this seat does not write now. */\n write(reason: \"manual\" | string): Promise<boolean>;\n /** Restore / whole import through `collab_replace` (§20). */\n replace(snapshot: unknown): Promise<void>;\n /** This seat is the one that saves on its own. */\n isSaver(): boolean;\n stop(): void;\n}\n\n// ── helpers ───────────────────────────────────────────────────────────────────────────────────────────\n\n/**\n * Keys in one canonical order. The log stores groups as jsonb, which returns object keys in its own order, so an\n * op read back from the door is the same op with its keys moved. The session compares wire forms (its ack check)\n * through `encode`, so `encode` must not depend on key order or every acknowledgement looks like a mismatch.\n */\nexport function canonicalKeys<T>(v: T): T {\n if (Array.isArray(v)) return v.map(canonicalKeys) as T;\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v as Record<string, unknown>).sort()) out[k] = canonicalKeys((v as Record<string, unknown>)[k]);\n return out as T;\n }\n return v;\n}\n\n/** Top-level keys an op descends into (`[\"body\", …]` or `[[\"body\", …], [\"headers\", …]]`). */\nfunction branches(op: DocsOp): unknown[][] {\n if (!Array.isArray(op) || op.length === 0) return [];\n return Array.isArray(op[0]) ? (op as unknown[][]) : [op as unknown[]];\n}\nconst touchesPageSetup = (op: DocsOp) => branches(op).some((b) => b[0] === \"documentStyle\");\n\n/** The segment a branch edits: `[\"headers\", id, \"body\", …]` → id; the body → \"\". */\nfunction segmentOf(branch: unknown[]): string {\n return (branch[0] === \"headers\" || branch[0] === \"footers\") && typeof branch[1] === \"string\" ? branch[1] : \"\";\n}\n\ninterface UndoItem {\n unitID?: string;\n undoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n redoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n}\ninterface UndoServiceInternals {\n _undoStacks?: Map<string, UndoItem[]>;\n _redoStacks?: Map<string, UndoItem[]>;\n}\n\n/** The Univer 1.0.4 fields the undo rebase reads; a forcing test fails if they move (Univer is pinned). */\nexport function undoStacksOf(service: unknown): { undo: Map<string, UndoItem[]>; redo: Map<string, UndoItem[]> } | null {\n const s = service as UndoServiceInternals | null;\n if (!s || !(s._undoStacks instanceof Map) || !(s._redoStacks instanceof Map)) return null;\n return { undo: s._undoStacks, redo: s._redoStacks };\n}\n\n/** §6.9: rebase one stack over a remote op; items that cannot follow are dropped. Returns how many were dropped. */\nexport function rebaseUndoStack(items: UndoItem[], remote: DocsOp): number {\n let dropped = 0;\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i]!;\n let ok = true;\n for (const list of [item.undoMutations, item.redoMutations]) {\n for (const m of list ?? []) {\n if (m.id !== RICH_TEXT_EDITING) continue;\n try {\n if (touchesPageSetup(m.params.actions as DocsOp) && touchesPageSetup(remote)) throw new Error(\"page setup\");\n const r = transformDocsOp(m.params.actions as DocsOp, remote, \"left\");\n if (isNoopDocsOp(r.op)) ok = false;\n else {\n m.params = { ...m.params, actions: r.op };\n delete m.params.textRanges;\n delete m.params.layoutState;\n }\n } catch {\n ok = false;\n }\n }\n }\n if (!ok) {\n items.splice(i, 1);\n dropped++;\n }\n }\n return dropped;\n}\n\n// ── the room ──────────────────────────────────────────────────────────────────────────────────────────\n\nexport function openDocsOtRoom(o: OpenDocsOtRoomOptions): DocsOtRoom {\n const { port } = o;\n let session: OpSession<DocsOp> | null = null;\n let composing = false;\n /** Remote ops held while an IME composition is open, already rebased over local composition ops. */\n let queue: DocsOp[] = [];\n const drainWaiters: Array<() => void> = [];\n\n const notice = (n: DocsOtNotice) => {\n try {\n o.onNotice?.(n);\n } catch (err) {\n console.warn(\"[docs-ot] notice handler failed\", err);\n }\n };\n\n const applyNow = (op: DocsOp) => {\n for (const b of branches(op)) {\n const params: Record<string, unknown> = { segmentId: segmentOf(b), actions: b };\n port.applyRemote(RICH_TEXT_EDITING, params);\n }\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n if (!stacks) continue;\n for (const m of [stacks.undo, stacks.redo]) {\n const items = m.get(t.unitId);\n if (items?.length) rebaseUndoStack(items, op);\n }\n }\n port.markDirty();\n };\n\n const drain = () => {\n const held = queue;\n queue = [];\n try {\n for (const op of held) applyNow(op);\n } catch (err) {\n console.warn(\"[docs-ot] a held remote edit failed after composition; reloading this seat\", err);\n session?.rebuild(\"ime_drain_failed\");\n }\n for (const w of drainWaiters.splice(0)) w();\n };\n\n const adapter: OpDocumentAdapter<DocsOp> = {\n version: DOCS_TRANSFORM_VERSION,\n transform(x, y, side) {\n // §18: page setup replaces section breaks by array index; a barrier against every family, itself included.\n if (x != null && y != null && (touchesPageSetup(x) || touchesPageSetup(y))) return { barrier: true, reason: \"page_setup\" };\n const r = transformDocsOp(x, y, side);\n return { op: isNoopDocsOp(r.op) ? null : r.op, lost: r.lost };\n },\n compose: (a, b) => composeDocsOps(a, b),\n isNoop: (op) => isNoopDocsOp(op),\n encode: (op) => [{ cmd: \"docs.edit\", mutations: [{ id: RICH_TEXT_EDITING, params: { segmentId: \"\", actions: canonicalKeys(op) } }] }],\n decode(groups) {\n let op: DocsOp = null;\n for (const g of groups) {\n for (const m of g.mutations) {\n if (m.id !== RICH_TEXT_EDITING) throw new Error(`a Docs room cannot apply ${m.id}`);\n op = composeDocsOps(op, (m.params as { actions?: DocsOp }).actions ?? null);\n }\n }\n return op;\n },\n apply(op) {\n if (isNoopDocsOp(op)) return true;\n if (composing) {\n queue.push(op);\n return true;\n }\n applyNow(op);\n return true;\n },\n async load(snapshot) {\n const next = stampDeterministicIds(snapshot ?? {});\n queue = [];\n const current = port.snapshot();\n if (current && canonicalDocsString(current) === canonicalDocsString(next)) return;\n port.load(next);\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n stacks?.undo.delete(t.unitId);\n stacks?.redo.delete(t.unitId);\n }\n },\n snapshot: () => port.snapshot(),\n async hash() {\n if (composing || queue.length) {\n await new Promise<void>((resolve) => {\n drainWaiters.push(resolve);\n setTimeout(resolve, 5000);\n });\n }\n return docsStateHash(port.snapshot());\n },\n };\n\n const onLocal = (m: DocsLocalMutation) => {\n if (!session) return;\n if (m.id !== RICH_TEXT_EDITING) {\n if (!m.content) return;\n // §6.3: an id without an allowlist never travels. Say so and put this seat back on the shared document.\n notice({ kind: \"not_shared\", mutationId: m.id });\n session.rebuild(`not_shared:${m.id}`);\n return;\n }\n const p = (m.params ?? {}) as { actions?: DocsOp };\n const applied = p.actions ?? null;\n if (isNoopDocsOp(applied)) return;\n let op: DocsOp = normalizeDocsOp(structuredClone(applied));\n let inverse: DocsOp | undefined;\n try {\n inverse = m.pre != null ? invertDocsOp(applied, m.pre) : undefined;\n } catch {\n inverse = undefined;\n }\n if (queue.length) {\n // the editor does not hold the queued remote ops yet: rebase this edit over them, and them over it\n inverse = undefined;\n const next: DocsOp[] = [];\n for (const q of queue) {\n const l2 = adapter.transform(op, q, \"left\");\n const q2 = adapter.transform(q, op, \"right\");\n if (isOpBarrier(l2) || isOpBarrier(q2)) {\n queue = [];\n session.rebuild(\"ime_barrier\");\n return;\n }\n op = l2.op;\n next.push(q2.op);\n }\n queue = next.filter((q) => !isNoopDocsOp(q));\n if (isNoopDocsOp(op)) return;\n }\n if (!session.local(op, { ...(inverse !== undefined ? { inverse } : {}), label: m.cmd ?? RICH_TEXT_EDITING })) notice({ kind: \"not_live\" });\n };\n\n const unsubLocal = port.onLocal(onLocal);\n const target = o.compositionTarget === undefined ? (typeof document !== \"undefined\" ? document : null) : o.compositionTarget;\n const onStart = () => {\n composing = true;\n };\n const onEnd = () => {\n composing = false;\n // Univer emits the composition's last mutation in the same task as compositionend: drain after it\n setTimeout(() => {\n if (!composing) drain();\n }, 0);\n };\n target?.addEventListener(\"compositionstart\", onStart, true);\n target?.addEventListener(\"compositionend\", onEnd, true);\n\n session = openOpSession<DocsOp>({\n transport: o.transport,\n adapter,\n proto: DOCS_COLLAB_PROTO,\n clientId: o.clientId,\n ...(o.presence ? { presence: o.presence } : {}),\n onNotice: (n) => notice(n),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n\n const isSaver = () => {\n if (!o.presence) return true;\n return o.presence.peers().every((p) => p.clientId === o.clientId || p.clientId > o.clientId);\n };\n\n return {\n session,\n isSaver,\n async write(reason) {\n if (!session) return false;\n if (reason !== \"manual\" && !isSaver()) return false;\n const out = await session.save();\n if (out.saved) return true;\n if (out.reason === \"not_quiet\" || out.reason === \"changed\") setTimeout(() => port.markDirty(), 1500);\n return false;\n },\n async replace(snapshot) {\n port.load(stampDeterministicIds(snapshot));\n const loaded = port.snapshot();\n if (!loaded) throw new Error(\"The document is not open in this tab.\");\n const stateHash = await docsStateHash(loaded);\n await o.replace({ snapshot: loaded, stateHash, clientId: o.clientId });\n },\n stop() {\n unsubLocal();\n target?.removeEventListener(\"compositionstart\", onStart, true);\n target?.removeEventListener(\"compositionend\", onEnd, true);\n session?.close();\n },\n };\n}\n","/**\n * A cloud document's co-editing room on the ordered log (COLLAB-DESIGN §6, §19; unit C3), assembled from the\n * configured docs host: the `udt_document_snapshots` store, the C1 doors over the host's Supabase client, the\n * private `collab:<id>` frames on the app's one realtime manager, and Yjs awareness for presence only (who is\n * here plus `quiet_hash`; no content travels there).\n *\n * The FLIP is per room (§12.2): a document whose room exists always opens on the ordered log; a document with\n * no room opens one only when the host's `collab.ot_rooms` knob says so (`all`, or `new` for a document never\n * saved). Everything else keeps the 0.6 relay. The host reads the knob (host config lives in the app).\n */\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport {\n awarenessOpPresence,\n collabReplace,\n collabRoomExists,\n SupabaseYjsProvider,\n supabaseOpTransport,\n type AwarenessState,\n type CollabRpcClient,\n type OpSessionIncident,\n type OpSessionStatus,\n} from \"@ai-matrx/data/realtime/collab\";\n\nimport { openDocsOtRoom, RICH_TEXT_EDITING, type DocsOtNotice } from \"../univer/collab/docs-ot/room\";\nimport type { DocsOtPort } from \"../univer/collab/docs-ot/room\";\nimport type { DocumentAwareness, DocumentOtFactory } from \"./document-model\";\nimport { CARET_HEARTBEAT_MS, publishedCaretFromSelection, RemoteCaretBook } from \"./remote-carets\";\nimport { getLatestDocumentSnapshot, saveDocumentSnapshot } from \"./document-service\";\nimport { getDocsHost } from \"./ports\";\n\n/** `collab.ot_rooms` (§12.2): which documents without a room open one. */\nexport type OtRoomsKnob = \"off\" | \"new\" | \"all\";\n\nconst db = () => getDocsHost().getSupabase() as unknown as CollabRpcClient;\n\nasync function loadSnapshotRow(documentId: string, ref: string): Promise<unknown> {\n if (ref === \"none\") {\n const res = await getLatestDocumentSnapshot(documentId);\n if (!res.success) throw new Error(res.error);\n return res.data?.snapshot ?? null;\n }\n const { data, error } = await getDocsHost()\n .getSupabase()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"snapshot\")\n .eq(\"id\", ref)\n .maybeSingle();\n if (error) throw new Error(error.message);\n if (!data) throw new Error(`The saved version ${ref} of this document is missing.`);\n return (data as { snapshot?: unknown }).snapshot ?? null;\n}\n\n/** Whether this document opens on the ordered log: its room exists, or the knob opens one. */\nexport async function documentUsesOrderedRoom(documentId: string, knob: OtRoomsKnob, isNewDocument: () => Promise<boolean>): Promise<boolean> {\n try {\n if (await collabRoomExists(db(), documentId)) return true;\n } catch (err) {\n console.warn(\"[document] could not ask whether this document has a co-editing room; opening the relay room\", err);\n return false;\n }\n if (knob === \"all\") return true;\n if (knob === \"new\") return isNewDocument();\n return false;\n}\n\nfunction pickColor(uid: string): string {\n const palette = [\"#ef4444\", \"#f59e0b\", \"#10b981\", \"#3b82f6\", \"#8b5cf6\", \"#ec4899\", \"#14b8a6\", \"#f97316\"];\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return palette[Math.abs(h) % palette.length] ?? \"#ec4899\";\n}\n\nexport interface DocumentOtFactoryOptions {\n documentId: string;\n uid: string;\n /** One per open tab; never reused. */\n clientId: string;\n displayName?: string;\n readAntiEntropyIntervalMs?: () => Promise<number>;\n onNotice?: (n: DocsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n}\n\n/** The `DocumentModel.startOtRoom` factory for one document. */\nexport function documentOtFactory(o: DocumentOtFactoryOptions): DocumentOtFactory {\n return async (basePort, onAwareness) => {\n // §7.4 / C0 surprise 5: a room's first checkpoint must be a real, Univer-normalised snapshot. A document never\n // saved gets this seat's mounted document saved first, so every seat boots from the same ids.\n const latest = await getLatestDocumentSnapshot(o.documentId);\n if (!latest.success) throw new Error(latest.error);\n if (!latest.data) {\n const mounted = basePort.snapshot();\n if (mounted) {\n const saved = await saveDocumentSnapshot({ documentId: o.documentId, snapshot: mounted, origin: \"autosave\" });\n if (!saved.success) throw new Error(saved.error);\n }\n }\n\n const doc = new Y.Doc();\n const awareness = new Awareness(doc);\n awareness.setLocalState({ uid: o.uid, clientId: o.clientId, name: o.displayName ?? o.uid.slice(0, 8), color: pickColor(o.uid), ts: Date.now() });\n\n // C8: other seats' carets, moved through every body edit this seat applies (remote) or makes (local).\n const carets = new RemoteCaretBook(awareness.clientID);\n const emit = () =>\n onAwareness({ states: new Map(awareness.getStates() as Map<number, AwarenessState>), selfUid: o.uid, carets: carets.list() } satisfies DocumentAwareness);\n const publishAwareness = () => {\n carets.ingest(awareness.getStates());\n emit();\n };\n const bodyActions = (params: unknown): unknown => {\n const p = params as { segmentId?: unknown; actions?: unknown } | null;\n return p && !p.segmentId ? p.actions : undefined;\n };\n const port: DocsOtPort = {\n ...basePort,\n applyRemote(id, params) {\n basePort.applyRemote(id, params);\n const a = bodyActions(params);\n if (a !== undefined && carets.shiftThrough(a)) emit();\n },\n onLocal: (listener) =>\n basePort.onLocal((m) => {\n if (m.id === RICH_TEXT_EDITING) {\n const a = bodyActions(m.params);\n if (a !== undefined && carets.shiftThrough(a)) emit();\n }\n listener(m);\n }),\n };\n awareness.on(\"change\", publishAwareness);\n const provider = new SupabaseYjsProvider({\n workbookId: o.documentId,\n channelPrefix: \"document\",\n clientId: o.clientId,\n doc,\n awareness,\n ...(o.readAntiEntropyIntervalMs ? { readAntiEntropyIntervalMs: o.readAntiEntropyIntervalMs } : {}),\n });\n await provider.connect();\n publishAwareness();\n\n const client = db();\n const room = openDocsOtRoom({\n port,\n clientId: o.clientId,\n presence: awarenessOpPresence(awareness),\n transport: supabaseOpTransport({\n client,\n roomId: o.documentId,\n kind: \"univer_doc\",\n store: {\n loadSnapshot: (ref) => loadSnapshotRow(o.documentId, ref),\n async writeSnapshot(snapshot) {\n const res = await saveDocumentSnapshot({ documentId: o.documentId, snapshot, origin: \"autosave\" });\n if (!res.success) throw new Error(res.error);\n return res.data.id;\n },\n },\n }),\n replace: ({ snapshot, stateHash, clientId }) => collabReplace(client, { roomId: o.documentId, snapshot, stateHash, origin: \"restore\", clientId }),\n ...(o.onNotice ? { onNotice: o.onNotice } : {}),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n await room.session.ready;\n\n // C8: publish this seat's caret when it changes, and every heartbeat so a race with an op frame heals.\n let lastKey = \"\";\n let lastAt = 0;\n const publishCaret = () => {\n if (typeof document !== \"undefined\" && document.hidden) return;\n let sel: ReturnType<NonNullable<DocsOtPort[\"selection\"]>> = null;\n try {\n sel = port.selection?.() ?? null;\n } catch {\n sel = null;\n }\n const t = Date.now();\n const c = publishedCaretFromSelection(sel, t);\n const key = c ? JSON.stringify(c.ranges) : \"\";\n if (key === lastKey && (key === \"\" || t - lastAt < CARET_HEARTBEAT_MS)) return;\n lastKey = key;\n lastAt = t;\n awareness.setLocalStateField(\"caret\", c);\n };\n const caretTimer = setInterval(publishCaret, 120);\n\n return {\n isSaver: () => room.isSaver(),\n write: (reason) => room.write(reason),\n replace: (snapshot) => room.replace(snapshot),\n stop: () => {\n clearInterval(caretTimer);\n room.stop();\n awareness.off(\"change\", publishAwareness);\n provider.disconnect();\n awareness.destroy();\n doc.destroy();\n },\n };\n };\n}\n","/**\n * THE DOCUMENT MODEL — the engine of one cloud document per tab.\n *\n * Before this, the document lived only inside each `DocumentEditor`'s Univer\n * instance. A remount (a board tile waking, a tile removed and undone, a route\n * change and back) rebuilt the editor from the SERVER copy, so whatever the\n * last save had not carried yet was gone; two mounts of one document were two\n * editors, each saving full snapshots of its own copy (last write wins), each\n * with its own realtime channel and its own collab room.\n *\n * The document is a record on THE one working-copy primitive\n * (`@ai-matrx/kit/working-copy`, kind `udt_document`,\n * `./documentModels.ts`): its save status, dirty and view count are Redux state\n * (`workingCopies[\"udt_document:<id>\"]`), its one coalesced save is the kind's.\n * What Redux cannot hold — Univer's body — is this engine, registered on the\n * record's session under the same key:\n *\n * - BODY. Every local mutation in one view is replayed into every other view\n * of the document (the same mutation stream collab sends between machines),\n * so two views show one document. A new view boots from the engine's latest\n * state — a live view's snapshot, or the snapshot the last view left behind\n * — never the stale server copy while the record's session is alive.\n * - SIDE EFFECTS, ONCE. The snapshot realtime channel, the collab room, and\n * the pagehide / visibility / beforeunload flush are opened once per\n * document and closed once.\n * - THE EDITOR ITSELF, KEPT. Univer keeps its undo / redo history inside the\n * editor instance, so rebuilding the editor on a remount threw the history\n * away. When the last view leaves, its editor (a Univer instance with its\n * own DOM host) is parked here — off the page, alive — and the next view of\n * the document RE-ATTACHES that same instance to its own container instead\n * of booting a new one (`parkEditor` / `takeParkedEditor`). Undo and redo\n * therefore work across hide / show, a remount and a removed tile undone,\n * for as long as the record's session is warm; `close()` disposes it.\n */\n\nimport type { ICommandInfo, IDocumentData } from \"@univerjs/core\";\nimport { TextX } from \"@univerjs/core\";\nimport type { CommitReason, WorkingCopyHandle } from \"@ai-matrx/kit/working-copy\";\nimport type { AwarenessState } from \"@ai-matrx/data/realtime/collab\";\nimport { isSnapshotMutation } from \"../univer\";\nimport { stampCovered, takeCovered } from \"../univer/collab/covered\";\nimport type {\n CollabMutationInfo,\n CommandServiceLike,\n} from \"../univer/collab\";\nimport type { DocsLocalMutation, DocsOtPort } from \"../univer/collab/docs-ot/room\";\nimport type { RemoteCaret } from \"./remote-carets\";\n\n/** Univer's command service as a view lends it: the collab pair plus the command hooks capture groups by. */\ntype ViewCommandService = CommandServiceLike & {\n beforeCommandExecuted?: (listener: (info: { id: string; type?: number; params?: unknown }) => void) => { dispose: () => void };\n onCommandExecuted?: (listener: (info: { id: string; type?: number; params?: unknown }) => void) => { dispose: () => void };\n executeCommand?: (id: string, params?: unknown, options?: unknown) => Promise<unknown>;\n};\n\nconst RICH_TEXT_EDITING_ID = \"doc.mutation.rich-text-editing\";\n/** Univer's CommandType.COMMAND. */\nconst COMMAND_TYPE = 0;\nconst DEPTH_GUARDED = Symbol.for(\"ai-matrx.office.docs.command-depth-guard\");\n\n/** Debounce from the last edit to the save. */\nexport const DOCUMENT_SAVE_DELAY_MS = 2500;\n\nexport type DocumentSnapshotData = Partial<IDocumentData>;\n\n/** What a view lends the model while it is mounted. */\nexport interface DocumentViewPort {\n /** Univer's command service for this view's instance. */\n commandService: CommandServiceLike;\n /** The live document of this view (`doc.save()`), or null if it has none. */\n snapshot: () => DocumentSnapshotData | null;\n /** Replace the whole document in this view (a collaborator's snapshot). */\n remount: (snapshot: DocumentSnapshotData) => void;\n /** Whether this view may change the document (read at edit time). */\n editable: () => boolean;\n /**\n * This view's text selection (body offsets), so a collaborator's edit moves the caret with the characters\n * (§6.8). Without it a remote apply leaves the caret at its old offset and the next keystrokes land elsewhere.\n */\n selection?: {\n get: () => Array<{ startOffset: number; endOffset: number; segmentId?: string }> | null;\n set: (ranges: Array<{ startOffset: number; endOffset: number }>) => void;\n };\n /** Univer's undo/redo service of this view's instance (the co-editing room rebases its items, §6.9). */\n undoRedo?: () => unknown;\n /**\n * The Univer unit id of this view's mounted document. Every seat mounts its own unit, so a\n * mutation carries the SENDER's id and must be re-addressed to this view's unit before it is\n * applied. Falls back to the id of `snapshot()` when a view does not state it.\n */\n unitId?: () => string | null;\n}\n\n/** Everything the engine reaches outside itself — injected so it is testable. */\nexport interface DocumentModelDeps {\n /** The newest stored snapshot (its row id + body), or null for a document never saved. */\n loadLatest: (documentId: string) => Promise<{ id: string; snapshot: DocumentSnapshotData } | null>;\n save: (input: {\n documentId: string;\n snapshot: DocumentSnapshotData;\n origin: \"autosave\" | \"manual\";\n }) => Promise<{ id: string; createdBy: string | null }>;\n onSaved?: (documentId: string, origin: \"autosave\" | \"manual\") => void;\n /** Window-level listeners (pagehide, visibilitychange, beforeunload). */\n listenToPage?: (handlers: { flush: () => void; hasUnsaved: () => boolean }) => () => void;\n /** A mutation could not be applied to a view: the app says so (a notice); the model re-syncs from the saved version. */\n onApplyFailed?: (documentId: string, mutationId: string, error: unknown) => void;\n}\n\ninterface AttachedView {\n id: number;\n port: DocumentViewPort;\n dispose: () => void;\n /** The outermost commands running in this view (closed in try/finally, C0 surprise 7). */\n commands: string[];\n /** The document before the rich-text mutation about to run (only while a co-editing room listens). */\n pre: unknown | null;\n}\n\n/** The document's room on the ordered log (COLLAB-DESIGN §6, C3), bound through `startOtRoom`. */\nexport interface DocumentOtHandle {\n stop: () => void;\n write: (reason: CommitReason) => Promise<boolean>;\n replace: (snapshot: DocumentSnapshotData) => Promise<void>;\n isSaver: () => boolean;\n}\n\nexport type DocumentOtFactory = (\n port: DocsOtPort,\n onAwareness: (awareness: DocumentAwareness) => void,\n) => Promise<DocumentOtHandle | null>;\n\n/** A collab room (WorkbookCollabSession) bound to the model's command stream. */\nexport interface DocumentCollabHandle {\n stop: () => void;\n isHost: () => boolean;\n /** This tab replaced the whole document and saved it as `snapshotId`: peers reload it. */\n announceReplaced: (snapshotId: string) => void;\n /** The room entries this tab's body holds right now (read with the body that is about to be saved). */\n coveredNow: () => string[];\n /** The saved snapshot `snapshotId` holds `covered`: they leave the room's log (the elected saver only). */\n checkpoint: (snapshotId: string, covered: readonly string[]) => void;\n}\n\n/** The saved snapshot this tab's body started from — what the room must never replay on top of it. */\nexport interface DocumentCollabBase {\n snapshotId: () => string | null;\n covered: () => ReadonlySet<string>;\n /** Show the newest saved snapshot (the room's newest checkpoint is newer than what this tab loaded). */\n reload: () => Promise<void>;\n}\n\n/** Who else is in the document's room (shared by every view of it). */\nexport interface DocumentAwareness {\n states: Map<number, AwarenessState>;\n selfUid: string;\n /** Other seats' carets and selections (ordered-log rooms only, C8), already moved through every edit applied since. */\n carets?: RemoteCaret[];\n}\n\n/**\n * An editor instance kept alive between views of the document: its DOM host\n * (re-parented into the next view's container) and the instance behind it,\n * whose undo history survives because the instance does. Opaque to the model\n * apart from what it calls.\n */\nexport interface ParkedDocumentEditor<T = unknown> {\n /** The element the editor renders into; the next view appends it to its container. */\n element: HTMLElement;\n instance: T;\n /** Replace the whole document (a collaborator's snapshot arrived while parked). */\n remount: (snapshot: DocumentSnapshotData) => void;\n /** Throw the instance away (the record's session closed). */\n dispose: () => void;\n}\n\nexport type DocumentCollabFactory = (\n commandService: CommandServiceLike,\n onAwareness: (awareness: DocumentAwareness) => void,\n /** A peer replaced the whole document (history restore, Google update). */\n onReplaced: () => void,\n /** What this tab's body was loaded from; pass it to the session (`base`). */\n base: DocumentCollabBase,\n) => Promise<DocumentCollabHandle | null>;\n\nlet viewIds = 0;\n\nexport class DocumentModel {\n readonly documentId: string;\n private readonly deps: DocumentModelDeps;\n private readonly handle: WorkingCopyHandle;\n private readonly views = new Map<number, AttachedView>();\n private lastEditedView: number | null = null;\n /** The document as the last view left it, or as last loaded / saved. */\n private stored: DocumentSnapshotData | null = null;\n private loading: Promise<DocumentSnapshotData | null> | null = null;\n private relaying = false;\n /** Snapshot rows this tab already holds (loaded or written) — never re-applied. */\n private readonly knownSnapshots = new Set<string>();\n private readonly collabListeners = new Set<(info: CollabMutationInfo, options?: { onlyLocal?: boolean; fromCollab?: boolean }) => void>();\n private collab: DocumentCollabHandle | null = null;\n /** The ordered-log room (C3); exclusive with `collab` (the 0.6 relay room). */\n private ot: DocumentOtHandle | null = null;\n private otStarting: Promise<void> | null = null;\n private readonly otListeners = new Set<(m: DocsLocalMutation) => void>();\n /** The saved snapshot the body started from, and the room entries it already holds. */\n private baseId: string | null = null;\n private baseCovered: ReadonlySet<string> = new Set();\n private collabStarting: Promise<void> | null = null;\n private awareness: DocumentAwareness | null = null;\n private readonly awarenessListeners = new Set<() => void>();\n private realtimeClose: (() => void) | null = null;\n private pageClose: (() => void) | null = null;\n /** The last view's editor, alive and off the page until a view takes it back. */\n private parked: ParkedDocumentEditor | null = null;\n\n constructor(handle: WorkingCopyHandle, deps: DocumentModelDeps) {\n this.documentId = handle.id;\n this.handle = handle;\n this.deps = deps;\n }\n\n // ── body ────────────────────────────────────────────────────────────────\n\n /** The newest state of the body this tab holds, without a network read. */\n latest(): DocumentSnapshotData | null {\n const preferred = this.lastEditedView !== null ? this.views.get(this.lastEditedView) : undefined;\n for (const view of preferred ? [preferred, ...this.views.values()] : this.views.values()) {\n try {\n const snapshot = view.port.snapshot();\n if (snapshot) return snapshot;\n } catch (error) {\n console.warn(`[document-model] a view of ${this.documentId} could not report its document`, error);\n }\n }\n return this.stored;\n }\n\n /**\n * What a NEW view should boot from: the model's latest state, or (only when\n * this tab holds none) the newest server snapshot. Null = an empty document.\n * Re-read `latest()` synchronously right before mounting — another view may\n * have typed while the server read was in flight.\n */\n async openingSnapshot(createEmpty: () => DocumentSnapshotData): Promise<DocumentSnapshotData> {\n const held = this.latest();\n if (held) return held;\n if (!this.loading) {\n this.loading = this.deps.loadLatest(this.documentId).then(\n (row) => {\n const loaded = row ? this.takeBase(row) : null;\n if (row && loaded) {\n this.knownSnapshots.add(row.id);\n this.savedFingerprint = contentFingerprint(loaded);\n }\n // A document never saved opens as ONE empty document for every view\n // (one unit id), so their edits replay into each other.\n if (!this.stored) this.stored = loaded ?? createEmpty();\n return this.latest() ?? this.stored;\n },\n (error: unknown) => {\n this.loading = null;\n throw error;\n },\n );\n }\n return (await this.loading) ?? createEmpty();\n }\n\n /** A view's Univer instance is ready: it shares the document from now on. */\n attachView(port: DocumentViewPort): () => void {\n const id = ++viewIds;\n const subscription = port.commandService.onMutationExecutedForCollab((info, options) =>\n this.onViewMutation(id, info, options),\n );\n const view: AttachedView = { id, port, dispose: () => {}, commands: [], pre: null };\n const hooks = this.trackCommands(view);\n view.dispose = () => {\n subscription.dispose();\n hooks();\n };\n this.views.set(id, view);\n // Nothing unsaved: what this view mounted IS the saved version (Univer and\n // the snapshot repair may restate it — page geometry, defaults — without\n // anyone changing a word). That is the baseline a save compares against.\n if (!this.handle.hasPending()) {\n try {\n const mounted = port.snapshot();\n if (mounted) this.savedFingerprint = contentFingerprint(mounted);\n } catch (error) {\n console.warn(`[document-model] could not read ${this.documentId}'s mounted document`, error);\n }\n }\n let detached = false;\n return () => {\n if (detached) return;\n detached = true;\n const view = this.views.get(id);\n if (!view) return;\n // Whatever this view shows is the newest body when it is the last one:\n // keep it, so a remount (or the flush on the way out) reads it.\n if (this.views.size === 1) {\n try {\n const snapshot = port.snapshot();\n if (snapshot) this.stored = snapshot;\n } catch (error) {\n console.warn(`[document-model] could not keep ${this.documentId}'s last view's document`, error);\n }\n }\n view.dispose();\n this.views.delete(id);\n if (this.lastEditedView === id) this.lastEditedView = null;\n };\n }\n\n /**\n * The last view of the document is leaving: keep its editor (and Univer's\n * undo history inside it) for the next view. Call AFTER the view's\n * `attachView` detach. Refused — the caller disposes its editor — while\n * another view is still attached (it carries the document) or one is\n * already kept.\n */\n parkEditor(editor: ParkedDocumentEditor): boolean {\n if (this.closed || this.views.size > 0 || this.parked) return false;\n this.parked = editor;\n return true;\n }\n\n /** The kept editor, handed to the view that mounts next (null when none is kept). */\n takeParkedEditor(): ParkedDocumentEditor | null {\n const editor = this.parked;\n this.parked = null;\n return editor;\n }\n\n private onViewMutation(\n viewId: number,\n info: Readonly<CollabMutationInfo>,\n options?: { fromCollab?: boolean; fromChangeset?: boolean; onlyLocal?: boolean },\n ): void {\n // Our own replay into this view, a collab peer's edit, or a load: not a\n // new local edit (each is accounted where it came from).\n if (this.relaying || options?.fromCollab || options?.fromChangeset) return;\n const view = this.views.get(viewId);\n if (!view || !view.port.editable()) return;\n this.lastEditedView = viewId;\n this.relay(info, viewId);\n for (const listener of this.collabListeners) listener(info as CollabMutationInfo, options);\n if (this.otListeners.size && !options?.onlyLocal) {\n const m: DocsLocalMutation = {\n id: info.id,\n params: info.params,\n pre: info.id === RICH_TEXT_EDITING_ID ? view.pre : null,\n cmd: view.commands[0] ?? null,\n content: isContentMutation(info),\n };\n view.pre = null;\n for (const listener of Array.from(this.otListeners)) listener(m);\n }\n if (isContentMutation(info)) this.markDirty();\n }\n\n /**\n * Per view: the outermost command running (a mutation's group label) and, while a room listens, the document\n * before each rich-text mutation (its inverse is computed from the APPLIED actions against this copy). Univer's\n * `executeCommand` has no `finally`: a command that mutates then throws never fires `onCommandExecuted`, so\n * the depth is restored in a try/finally around the instance's `executeCommand` (C0 surprise 7).\n */\n private trackCommands(view: AttachedView): () => void {\n const cs = view.port.commandService as ViewCommandService;\n if (typeof cs.beforeCommandExecuted !== \"function\" || typeof cs.onCommandExecuted !== \"function\") return () => {};\n const before = cs.beforeCommandExecuted((info) => {\n if (info.type === COMMAND_TYPE) view.commands.push(info.id);\n else if (info.id === RICH_TEXT_EDITING_ID && this.otListeners.size && !this.relaying) {\n try {\n const snap = view.port.snapshot();\n view.pre = snap ? structuredClone(snap) : null;\n } catch {\n view.pre = null;\n }\n }\n });\n const after = cs.onCommandExecuted((info) => {\n if (info.type !== COMMAND_TYPE) return;\n const at = view.commands.lastIndexOf(info.id);\n if (at >= 0) view.commands.splice(at, 1);\n });\n const guarded = cs as ViewCommandService & { [DEPTH_GUARDED]?: true };\n if (typeof cs.executeCommand === \"function\" && !guarded[DEPTH_GUARDED]) {\n const original = cs.executeCommand.bind(cs);\n guarded[DEPTH_GUARDED] = true;\n cs.executeCommand = async (id, params, options) => {\n const depth = view.commands.length;\n try {\n return await original(id, params, options);\n } finally {\n if (view.commands.length > depth) view.commands.length = depth;\n }\n };\n }\n return () => {\n before.dispose();\n after.dispose();\n };\n }\n\n /** The unit id a view's document has (what a replayed mutation must be addressed to). */\n private unitIdOf(view: AttachedView): string | null {\n try {\n return view.port.unitId?.() ?? view.port.snapshot()?.id ?? null;\n } catch {\n return null;\n }\n }\n\n /** Replay one mutation into every view except `exceptViewId`, addressed to each view's own unit. */\n private relay(info: Readonly<CollabMutationInfo>, exceptViewId: number | null): void {\n if (this.views.size === 0 || (this.views.size === 1 && exceptViewId !== null)) return;\n this.relaying = true;\n let failure: unknown = null;\n try {\n for (const view of this.views.values()) {\n if (view.id === exceptViewId) continue;\n try {\n const params = info.params as unknown;\n const unitId = this.unitIdOf(view);\n const addressed =\n unitId && params && typeof params === \"object\" && !Array.isArray(params) && typeof (params as { unitId?: unknown }).unitId === \"string\" && (params as { unitId: string }).unitId !== unitId\n ? { ...(params as Record<string, unknown>), unitId }\n : info.params;\n view.port.commandService.syncExecuteCommand(info.id, addressed as never, { onlyLocal: true, fromCollab: true });\n } catch (error) {\n failure ??= error;\n console.error(\n `[document-model] a second view of ${this.documentId} could not apply \"${info.id}\" — it may show an older document until it reopens`,\n error,\n );\n }\n }\n } finally {\n this.relaying = false;\n }\n if (failure !== null) this.applyFailed(info.id, failure);\n }\n\n /** A view could not follow an edit: say so, then show the saved version (unless this tab has unsaved edits of its own). */\n private applyFailed(mutationId: string, error: unknown): void {\n try {\n this.deps.onApplyFailed?.(this.documentId, mutationId, error);\n } catch (notifyError) {\n console.warn(`[document-model] the notice for ${this.documentId}'s failed apply also failed`, notifyError);\n }\n if (this.hasUnsaved()) return;\n void this.deps\n .loadLatest(this.documentId)\n .then((row) => {\n if (row && !this.closed) this.show(row);\n })\n .catch((e) => console.warn(`[document-model] could not re-sync ${this.documentId} after a failed apply`, e));\n }\n\n // ── save (run by the record's one coalesced save — documentModels.ts) ─\n\n private markDirty(): void {\n this.handle.touch();\n }\n\n private saving = false;\n /**\n * The content of the version the server holds (loaded or last written). A\n * save of the same content is no save: attaching, detaching, waking or a\n * flush of an unchanged document never writes a snapshot row.\n */\n private savedFingerprint: string | null = null;\n\n /**\n * Write the body as it is now. Returns false when this tab is a collab peer\n * that does not write (the elected host writes the canonical snapshot; a\n * peer's edits reach it through the room). An explicit Save always writes.\n */\n async write(reason: CommitReason): Promise<boolean> {\n if (this.ot) {\n const wrote = await this.ot.write(reason);\n if (wrote) this.deps.onSaved?.(this.documentId, reason === \"manual\" ? \"manual\" : \"autosave\");\n return wrote;\n }\n const snapshot = this.latest();\n if (!snapshot) throw new Error(\"There is no open document to save.\");\n if (this.collab && !this.collab.isHost() && reason !== \"manual\") return false;\n const fingerprint = contentFingerprint(snapshot);\n if (reason !== \"manual\" && fingerprint === this.savedFingerprint) return false;\n const origin = reason === \"manual\" ? \"manual\" : \"autosave\";\n // The room entries this body holds, read in the same step as the body: the saved row names them,\n // so a tab that reloads from it never replays them on top of it.\n const collab = this.collab;\n const covered = collab ? collab.coveredNow() : null;\n this.saving = true;\n try {\n const { id } = await this.deps.save({\n documentId: this.documentId,\n snapshot: covered ? stampCovered(snapshot, covered) : snapshot,\n origin,\n });\n this.knownSnapshots.add(id);\n this.savedFingerprint = fingerprint;\n if (collab && covered && collab.isHost()) collab.checkpoint(id, covered);\n } finally {\n this.saving = false;\n }\n if (this.views.size === 0) this.stored = snapshot;\n this.deps.onSaved?.(this.documentId, origin);\n return true;\n }\n\n private hasUnsaved(): boolean {\n return this.handle.hasPending();\n }\n\n hasViews(): boolean {\n return this.views.size > 0;\n }\n\n // ── realtime (snapshot inserts) ─────────────────────────────────────────\n\n /** Opened once per document by the first view that asks; idempotent. */\n connectRealtime(open: (onSnapshot: (snapshotId: string) => void) => () => void): void {\n if (this.realtimeClose) return;\n this.realtimeClose = open((snapshotId) => void this.onRemoteSnapshot(snapshotId));\n }\n\n /**\n * A snapshot was committed (here or elsewhere): show a foreign one in every\n * view. Over unsaved edits it is a CONFLICT — the working copy holds it and\n * no save runs (one would overwrite the collaborator's snapshot) until the\n * person chooses; `overUnsaved` is \"Take theirs\" (`./documentModels.ts`).\n */\n async onRemoteSnapshot(snapshotId: string, { overUnsaved = false }: { overUnsaved?: boolean } = {}): Promise<void> {\n if (this.collab || this.ot) return; // the room is the live channel; snapshots are checkpoints\n if (this.knownSnapshots.has(snapshotId)) return; // ours, or already shown\n if (this.saving) return; // our own save's echo, ahead of its response\n if (this.hasUnsaved() && !overUnsaved) {\n this.handle.conflict({ ref: snapshotId });\n return;\n }\n const row = await this.deps.loadLatest(this.documentId);\n if (!row || (this.hasUnsaved() && !overUnsaved) || this.knownSnapshots.has(row.id)) return;\n this.show(row);\n }\n\n /**\n * THE content swap (see @ai-matrx/office/univer openEditorContent): a SAVED snapshot\n * replaces the document in every view and the kept editor. It is the saved\n * version from now on, so the pending save compares equal and writes\n * nothing (it would put the old content back over the new). In a collab\n * room the peers reload it and the shared log is emptied.\n */\n replaceContent(row: { id: string; snapshot: DocumentSnapshotData }): void | Promise<void> {\n // A document with an ordered-log room is replaced through `collab_replace` (one atomic door, §20).\n if (this.ot) return this.ot.replace(row.snapshot);\n this.show(row);\n this.collab?.announceReplaced(row.id);\n }\n\n /** A peer replaced the document: show the newest save (once). */\n private async onPeerReplaced(): Promise<void> {\n const row = await this.deps.loadLatest(this.documentId);\n if (!row || this.knownSnapshots.has(row.id)) return;\n this.show(row);\n }\n\n /** A loaded row becomes the base: its content (what views mount) and the room entries it holds. */\n private takeBase(row: { id: string; snapshot: DocumentSnapshotData }): DocumentSnapshotData {\n const { snapshot, covered } = takeCovered(row.snapshot);\n this.baseId = row.id;\n this.baseCovered = covered;\n return snapshot;\n }\n\n private show(row: { id: string; snapshot: DocumentSnapshotData }): void {\n const snapshot = this.takeBase(row);\n this.knownSnapshots.add(row.id);\n this.savedFingerprint = contentFingerprint(snapshot);\n this.stored = snapshot;\n this.relaying = true;\n try {\n for (const view of this.views.values()) view.port.remount(snapshot);\n this.parked?.remount(snapshot);\n } finally {\n this.relaying = false;\n }\n }\n\n // ── collab (one room per document) ──────────────────────────────────────\n\n /**\n * The model's command stream as ONE command service — what the collab room\n * binds to. Local edits from any view go out once; a peer's edit is applied\n * to every view.\n */\n private readonly virtualCommandService: CommandServiceLike = {\n onMutationExecutedForCollab: (listener) => {\n this.collabListeners.add(listener);\n return { dispose: () => this.collabListeners.delete(listener) };\n },\n syncExecuteCommand: (id, params) => {\n const info = { id, type: 2, params } as CollabMutationInfo;\n this.relay(info, null);\n // The host writes what peers typed.\n if (isContentMutation(info)) this.markDirty();\n return true;\n },\n };\n\n /** Join the document's collab room once (the first view that asks). */\n startCollab(factory: DocumentCollabFactory): Promise<void> {\n if (this.collab) return Promise.resolve();\n if (!this.collabStarting) {\n this.collabStarting = factory(\n this.virtualCommandService,\n (awareness) => {\n this.awareness = awareness;\n for (const listener of Array.from(this.awarenessListeners)) listener();\n },\n () => {\n void this.onPeerReplaced().catch((error: unknown) =>\n console.warn(`[document-model] could not load ${this.documentId}'s replaced version`, error),\n );\n },\n {\n snapshotId: () => this.baseId,\n covered: () => this.baseCovered,\n reload: async () => {\n const row = await this.deps.loadLatest(this.documentId);\n if (row && !this.closed) this.show(row);\n },\n },\n )\n .then((handle) => {\n if (!handle) return;\n if (this.views.size === 0) {\n handle.stop();\n return;\n }\n this.collab = handle;\n })\n .finally(() => {\n this.collabStarting = null;\n });\n }\n return this.collabStarting;\n }\n\n /** The model as the ordered-log room sees it (COLLAB-DESIGN §6.7: the model is the client, not the view). */\n private readonly otPort: DocsOtPort = {\n onLocal: (listener) => {\n this.otListeners.add(listener);\n return () => void this.otListeners.delete(listener);\n },\n applyRemote: (id, params) => {\n if (this.views.size === 0) throw new Error(\"no view of the document is mounted\");\n this.relaying = true;\n try {\n for (const view of this.views.values()) {\n const unitId = this.unitIdOf(view);\n const input = Array.isArray(params.actions) ? params.actions.length : 0;\n let sel: Array<{ startOffset: number; endOffset: number; segmentId?: string }> | null = null;\n try {\n sel = view.port.selection?.get() ?? null;\n } catch {\n sel = null;\n }\n const p: Record<string, unknown> = { ...params, ...(unitId ? { unitId } : {}), textRanges: null, noNeedSetTextRange: true };\n const ok = view.port.commandService.syncExecuteCommand(id, p as never, { onlyLocal: true, fromCollab: true });\n if (ok === false) throw new Error(`\"${id}\" was refused by the editor`);\n // the content-control guard empties `actions` on the params object it was handed (§6.6)\n if (input > 0 && Array.isArray(p.actions) && p.actions.length === 0) throw new Error(`\"${id}\" was emptied by the editor`);\n const moved = sel && sel.length && sel.every((r) => !r.segmentId) ? moveRangesThroughBodyEdit(sel, params.actions) : null;\n if (moved) {\n try {\n view.port.selection?.set(moved);\n } catch (error) {\n console.warn(`[document-model] could not move this view's caret past a collaborator's edit`, error);\n }\n }\n }\n } finally {\n this.relaying = false;\n }\n if (isContentMutation({ id, type: 2, params } as unknown as CollabMutationInfo)) this.markDirty();\n },\n snapshot: () => this.latest(),\n load: (snapshot) => {\n const s = snapshot as DocumentSnapshotData;\n this.stored = s;\n this.savedFingerprint = contentFingerprint(s);\n this.relaying = true;\n try {\n for (const view of this.views.values()) view.port.remount(s);\n this.parked?.remount(s);\n } finally {\n this.relaying = false;\n }\n },\n undoTargets: () => {\n const out: Array<{ service: unknown; unitId: string }> = [];\n for (const view of this.views.values()) {\n const unitId = this.unitIdOf(view);\n const service = view.port.undoRedo?.();\n if (unitId && service) out.push({ service, unitId });\n }\n return out;\n },\n markDirty: () => this.markDirty(),\n selection: () => {\n for (const view of this.views.values()) {\n try {\n const sel = view.port.selection?.get();\n if (sel) return sel;\n } catch {\n /* a view mid-teardown has no selection */\n }\n }\n return null;\n },\n };\n\n /** Join the document's ordered-log room once (C3). Exclusive with `startCollab`. */\n startOtRoom(factory: DocumentOtFactory): Promise<void> {\n if (this.ot || this.collab) return Promise.resolve();\n if (!this.otStarting) {\n this.otStarting = factory(this.otPort, (awareness) => {\n this.awareness = awareness;\n for (const listener of Array.from(this.awarenessListeners)) listener();\n })\n .then((handle) => {\n if (!handle) return;\n if (this.views.size === 0) {\n handle.stop();\n return;\n }\n this.ot = handle;\n })\n .finally(() => {\n this.otStarting = null;\n });\n }\n return this.otStarting;\n }\n\n /** Which co-editing room this document is in right now. */\n collabMode(): \"ordered\" | \"relay\" | null {\n return this.ot ? \"ordered\" : this.collab ? \"relay\" : null;\n }\n\n isCollabHost(): boolean {\n if (this.ot) return this.ot.isSaver();\n return this.collab ? this.collab.isHost() : true;\n }\n\n getAwareness(): DocumentAwareness | null {\n return this.awareness;\n }\n\n subscribeAwareness(listener: () => void): () => void {\n this.awarenessListeners.add(listener);\n return () => this.awarenessListeners.delete(listener);\n }\n\n // ── lifecycle (driven by the record's session) ──────────────────────\n\n /** A view arrived on a document with none. */\n wake(): void {\n if (!this.pageClose && this.deps.listenToPage) {\n this.pageClose = this.deps.listenToPage({\n flush: () => void this.handle.flush(),\n hasUnsaved: () => this.hasUnsaved(),\n });\n }\n }\n\n /**\n * The last view left: leave the collab room (presence must not outlive the\n * person). The snapshot channel stays open while the session is kept alive,\n * so a collaborator's save still reaches the body a returning view boots from.\n */\n rest(): void {\n this.collab?.stop();\n this.collab = null;\n this.ot?.stop();\n this.ot = null;\n this.awareness = null;\n }\n\n private closed = false;\n\n close(): void {\n this.closed = true;\n const parked = this.parked;\n this.parked = null;\n if (parked) {\n try {\n parked.dispose();\n } catch (error) {\n console.warn(`[document-model] could not dispose ${this.documentId}'s kept editor`, error);\n }\n }\n this.realtimeClose?.();\n this.realtimeClose = null;\n this.pageClose?.();\n this.pageClose = null;\n }\n}\n\n/**\n * Body offsets moved through a collaborator's body edit (`[\"body\", {et:\"text-x\", e}]`), §6.4 and §6.8. Text inserted\n * before the caret pushes it right; text inserted after it does not.\n *\n * A tie (text inserted EXACTLY at a collapsed caret) follows the one conflict rule. The caret is where this person's\n * next keystroke goes, and that keystroke commits after the edit being applied, so it takes `'left'` and sits first:\n * the caret stays BEFORE the collaborator's text. That is the side the session already gives this seat's unsent and\n * in-flight inserts (`T(local, remote, 'left')`), so the caret stays at the end of this person's own run and two\n * people typing at one spot each keep their words whole (\"FloodEbb\", never \"FElbobod\"). A selection never grows to\n * take in a collaborator's text: an insert at its start lands before it, at its end after it.\n * Null when the edit is not a body edit.\n */\nexport function moveRangesThroughBodyEdit(\n ranges: Array<{ startOffset: number; endOffset: number }>,\n actions: unknown,\n): Array<{ startOffset: number; endOffset: number }> | null {\n const a = actions as unknown[];\n if (!Array.isArray(a) || a[0] !== \"body\") return null;\n const sub = a[1] as { et?: string; e?: unknown } | undefined;\n if (!sub || sub.et !== \"text-x\" || !Array.isArray(sub.e)) return null;\n const e = sub.e as Parameters<typeof TextX.transformPosition>[0];\n return ranges.map((r) => {\n const collapsed = r.startOffset === r.endOffset;\n // TextX.transformPosition's third argument: true = an insert exactly at this offset lands after it\n const startOffset = TextX.transformPosition(e, r.startOffset, collapsed);\n return { startOffset, endOffset: collapsed ? startOffset : TextX.transformPosition(e, r.endOffset, true) };\n });\n}\n\n/**\n * What a snapshot STORES, as a comparable string: everything but the unit id\n * and Univer's revision counter (both move without the content moving).\n */\nfunction contentFingerprint(snapshot: DocumentSnapshotData): string {\n const { id: _id, rev: _rev, ...content } = snapshot as DocumentSnapshotData & { rev?: unknown };\n return JSON.stringify(content);\n}\n\n/** Mutations that change what a snapshot stores (never scroll / selection) — the editors' one dirty filter. */\nfunction isContentMutation(info: Readonly<CollabMutationInfo>): boolean {\n return isSnapshotMutation({ id: info.id, type: info.type, params: info.params } as ICommandInfo);\n}\n","/**\n * THE ONE way to replace the whole content of an open Univer editor\n * (workbook or document) with a snapshot that is already SAVED: a history\n * restore, \"Update from Google\" / \"Use Google's\", and a collaborator's\n * replacement all arrive here.\n *\n * Callers save first, then call `showSavedSnapshot`. The open editor for that\n * record (registered below) swaps its content in place, drops its pending\n * autosave (it would write the old content back over the new one), and — in\n * a collab room — tells every peer to reload the same snapshot. A caller\n * never touches Univer units itself: disposing the current unit by hand left\n * Univer's selection observers pointing at nothing (`getUnitId` of null).\n *\n * Pure registry (no Univer import), so it is testable without booting Univer.\n */\n\nexport type EditorRecordKind = \"workbook\" | \"document\";\n\n/** A snapshot row as stored: its id and the Univer body. */\nexport type SavedEditorSnapshot = { id: string; snapshot: unknown };\n\nexport type EditorContentReplacer = (row: SavedEditorSnapshot) => void | Promise<void>;\n\nconst replacers = new Map<string, EditorContentReplacer>();\n\nconst keyOf = (kind: EditorRecordKind, recordId: string) => `${kind}:${recordId}`;\n\n/**\n * The open editor of a record lends its replacer while it is mounted. The\n * newest registration wins; the returned release only removes its own.\n */\nexport function registerOpenEditorContent(\n kind: EditorRecordKind,\n recordId: string,\n replace: EditorContentReplacer,\n): () => void {\n const key = keyOf(kind, recordId);\n replacers.set(key, replace);\n return () => {\n if (replacers.get(key) === replace) replacers.delete(key);\n };\n}\n\n/** Whether an editor of this record is open in this tab. */\nexport function hasOpenEditorContent(kind: EditorRecordKind, recordId: string): boolean {\n return replacers.has(keyOf(kind, recordId));\n}\n\n/**\n * Show a saved snapshot in the record's open editor (and its collab peers).\n * Returns false when no editor of the record is open in this tab — the saved\n * row then simply is the content the next open loads.\n */\nexport async function showSavedSnapshot(\n kind: EditorRecordKind,\n recordId: string,\n row: SavedEditorSnapshot,\n): Promise<boolean> {\n const replace = replacers.get(keyOf(kind, recordId));\n if (!replace) return false;\n await replace(row);\n return true;\n}\n\n/**\n * THE CONTENT-SWAP GUARD. A swap is dispose-then-create; if the create throws, the unit is gone and\n * the grid would stay blank. `swap(snapshot)` is the editor's own dispose+create (it disposes\n * whatever unit is open, if any). On a throw this puts the content that was open before straight\n * back (synchronously — never a blank grid) and says so; the editor then reloads the latest SAVED\n * version and still raises the original error, so the person is told.\n */\nexport function swapContentGuarded(args: {\n swap: (snapshot: unknown) => void;\n next: unknown;\n /** What was open before (`workbook.save()` taken before the swap), or null when nothing was. */\n previous: unknown | null;\n}): { ok: true } | { ok: false; error: unknown; previousRestored: boolean } {\n try {\n args.swap(args.next);\n return { ok: true };\n } catch (error) {\n let previousRestored = false;\n if (args.previous) {\n try {\n args.swap(args.previous);\n previousRestored = true;\n } catch {\n /* the latest saved version is tried next, by the caller */\n }\n }\n return { ok: false, error, previousRestored };\n }\n}\n","/**\n * Other people's carets and selections in a Docs co-editing room (COLLAB-DESIGN §6.8, unit C8).\n *\n * Presence travels on Yjs awareness beside `quiet_hash`: each seat publishes `caret = { ranges, at }`, body\n * offsets in ITS OWN editor (header and footer selections are not published). Offsets do not survive edits, so a\n * receiver keeps a book of the last published ranges and moves them through every body edit it applies afterwards,\n * remote or its own, with the same function that moves its own caret (`moveRangesThroughBodyEdit`). A peer\n * republishes on each selection change and every `CARET_HEARTBEAT_MS`, so a race between its awareness and an op\n * frame (a keystroke counted twice) corrects itself within a heartbeat. A caret older than `CARET_STALE_MS` is\n * not shown (judged by when THIS seat received it, never the sender's clock); one whose seat left is dropped with its awareness state.\n */\nimport { moveRangesThroughBodyEdit } from \"./document-model\";\n\nexport const CARET_HEARTBEAT_MS = 2000;\nexport const CARET_STALE_MS = 12000;\n/** Most ranges one seat publishes (a multi-range selection is rare; the rest is dropped, never the first). */\nexport const CARET_MAX_RANGES = 4;\n\nexport interface CaretRange {\n start: number;\n end: number;\n}\n\n/** The `caret` field of a seat's awareness state. */\nexport interface PublishedCaret {\n ranges: CaretRange[];\n at: number;\n}\n\n/** One other seat's caret, ready to draw. */\nexport interface RemoteCaret {\n /** The seat (Yjs client id as a string): two tabs of one person are two carets. */\n key: string;\n uid: string;\n name: string;\n color: string;\n ranges: CaretRange[];\n}\n\ntype SelectionRange = { startOffset: number; endOffset: number; segmentId?: string };\n\n/** What a seat publishes for its selection, or null when there is nothing to show (header/footer, no selection). */\nexport function publishedCaretFromSelection(sel: SelectionRange[] | null | undefined, now: number): PublishedCaret | null {\n if (!sel || sel.length === 0) return null;\n if (sel.some((r) => r.segmentId)) return null;\n const ranges = sel.slice(0, CARET_MAX_RANGES).map((r) => ({ start: Math.min(r.startOffset, r.endOffset), end: Math.max(r.startOffset, r.endOffset) }));\n return { ranges, at: now };\n}\n\nconst sameRanges = (a: CaretRange[], b: CaretRange[]) => a.length === b.length && a.every((r, i) => r.start === b[i]!.start && r.end === b[i]!.end);\n\nfunction readCaret(raw: unknown): PublishedCaret | null {\n const c = (raw as { caret?: { ranges?: unknown; at?: unknown } } | null)?.caret;\n if (!c || !Array.isArray(c.ranges) || typeof c.at !== \"number\") return null;\n const ranges: CaretRange[] = [];\n for (const r of c.ranges.slice(0, CARET_MAX_RANGES)) {\n const s = (r as CaretRange)?.start;\n const e = (r as CaretRange)?.end;\n if (typeof s !== \"number\" || typeof e !== \"number\" || !Number.isFinite(s) || !Number.isFinite(e) || s < 0 || e < 0) return null;\n ranges.push({ start: s, end: e });\n }\n return ranges.length ? { ranges, at: c.at } : null;\n}\n\nexport class RemoteCaretBook {\n private readonly carets = new Map<string, RemoteCaret & { at: number; seenAt: number }>();\n\n constructor(\n private readonly selfClientId: number,\n private readonly now: () => number = Date.now,\n ) {}\n\n /** Take the room's awareness states: new or republished carets replace ours, seats that left are dropped. Returns whether anything changed. */\n ingest(states: Map<number, unknown>): boolean {\n let changed = false;\n const seen = new Set<string>();\n states.forEach((raw, id) => {\n if (id === this.selfClientId) return;\n const s = raw as { uid?: unknown; name?: unknown; color?: unknown } | null;\n const caret = readCaret(raw);\n if (!s || typeof s.uid !== \"string\" || !caret) return;\n const key = String(id);\n seen.add(key);\n const prev = this.carets.get(key);\n const name = typeof s.name === \"string\" && s.name ? s.name : \"Someone\";\n const color = typeof s.color === \"string\" && s.color ? s.color : \"#3b82f6\";\n // The same publication again (awareness re-delivers state): keep the ranges we have already moved.\n if (prev && prev.at === caret.at && prev.name === name && prev.color === color) return;\n this.carets.set(key, { key, uid: s.uid, name, color, ranges: caret.ranges, at: caret.at, seenAt: this.now() });\n changed = true;\n });\n for (const key of [...this.carets.keys()]) {\n if (!seen.has(key)) {\n this.carets.delete(key);\n changed = true;\n }\n }\n return changed;\n }\n\n /** Move every caret through one body edit that was just applied (`actions` of a rich-text mutation). Returns whether any moved. */\n shiftThrough(actions: unknown): boolean {\n let moved = false;\n for (const c of this.carets.values()) {\n const next = moveRangesThroughBodyEdit(c.ranges.map((r) => ({ startOffset: r.start, endOffset: r.end })), actions);\n if (!next) return false; // not a body edit: nothing moves\n const ranges = next.map((r) => ({ start: r.startOffset, end: r.endOffset }));\n if (!sameRanges(ranges, c.ranges)) {\n c.ranges = ranges;\n moved = true;\n }\n }\n return moved;\n }\n\n /** The carets to draw now (stale ones left out). */\n list(): RemoteCaret[] {\n const t = this.now();\n const out: RemoteCaret[] = [];\n for (const c of this.carets.values()) {\n if (t - c.seenAt > CARET_STALE_MS) continue;\n out.push({ key: c.key, uid: c.uid, name: c.name, color: c.color, ranges: c.ranges.map((r) => ({ ...r })) });\n }\n out.sort((a, b) => a.key.localeCompare(b.key));\n return out;\n }\n}\n","/**\n * Document service — typed wrappers for `udt_documents` + `udt_document_snapshots`.\n *\n * Cloud document editor backed by Univer's preset-docs-core. Same shape as\n * `workbook-service.ts` — metadata in `udt_documents`, content state in\n * append-only `udt_document_snapshots`. The editor hydrates from the LATEST\n * snapshot and writes a new snapshot per save (debounced on the client —\n * see DocumentEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - The open document (one model per id per tab: load, one save, realtime,\n * collab): features/documents/document-model/\n * - Component (a view of that model): features/documents/components/DocumentEditor\n *\n * Mirrors `workbook-service.ts`. If you're changing the shape of one, change\n * the other at the same time — see `features/data-tables/FEATURE.md`.\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { readAllRows, tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { DocumentRow, DocumentSnapshot, DocumentSnapshotOrigin } from \"../core\";\nimport { getDocsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getDocsHost().getSupabase();\n// ─── documents ───────────────────────────────────────────────────────────────\n\nexport type CreateDocumentArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the document itself, mirrors `udt_documents.source`. */\n source?: \"created\" | \"imported_docx\" | \"imported_md\" | \"imported_txt\" | \"linked_gdoc\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (DOCX / MD / TXT blob). Set on the\n * import flow so the lossless original is recoverable; FK is ON DELETE SET\n * NULL, so deleting the file just nulls the link — the document survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createDocument(\n args: CreateDocumentArgs,\n): Promise<ServiceResult<DocumentRow>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a document.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .insert({\n document_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; the legacy `is_public` boolean is derived from it by\n // the workbench._bridge_legacy_owner trigger, so writing both here would\n // be two authorities for one fact. A new document defaults to `internal`\n // — it is org work product, not an individual person's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function listAccessibleDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n // RLS handles owner / published-to-the-web / shared access. The library and\n // the pickers treat this list as COMPLETE (\"you have no such document\"), so\n // it pages past PostgREST's silent 1000-row cap (D190).\n try {\n const rows = await readAllRows<DocumentRow>(\n ({ from, to }) =>\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\", { count: \"exact\" })\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false })\n .order(\"id\", { ascending: true })\n .range(from, to)\n .returns<DocumentRow[]>(),\n { label: \"workbench.udt_documents accessible documents\" },\n );\n return { success: true, data: rows };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function getDocument(\n documentId: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .eq(\"id\", documentId)\n .is(\"deleted_at\", null)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n if (!data) {\n // A trashed or unreachable document is a state the person can act on,\n // never PostgREST's \"Cannot coerce the result to a single JSON object\".\n return {\n success: false,\n error:\n \"This document is in the trash or you no longer have access to it. Restore it from Trash, or ask its owner to share it again.\",\n };\n }\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function renameDocument(\n documentId: string,\n name: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ document_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Move the document into a project (or out of one with `null`). Sibling of\n * `renameDocument`: the one named setter for `project_id`.\n */\nexport async function moveDocument(\n documentId: string,\n projectId: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Rewrite the document's description. Sibling of `renameDocument` — the two\n * human-authored fields on `udt_documents` each get a named setter so callers\n * never hand-roll a `.from(\"udt_documents\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Added when the documents surface became agent-writable: the\n * `document_description` write target on `/documents/[id]` is its caller, the\n * same way `updateWorkbookDescription` serves `workbook_description`. Keeping\n * the pair symmetric is this file's standing contract with `workbook-service`\n * (see the module header).\n */\nexport async function updateDocumentDescription(\n documentId: string,\n description: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Soft delete — the document is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreDocument for undo. (aidream migration 0458.)\n */\nexport async function restoreDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: null })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"restore\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a document this very flow just created and\n * failed to populate. Never use for a user-initiated delete: that is\n * deleteDocument, which tombstones and stays recoverable.\n */\nexport async function discardFailedDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"archive\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function deleteDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"delete\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n// ─── snapshots (document content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened document hydrates from. Returns\n * `data: null` (success path) when the document has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestDocumentSnapshot(\n documentId: string,\n): Promise<ServiceResult<DocumentSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"*\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as DocumentSnapshot | null };\n}\n\nexport type SaveDocumentSnapshotArgs = {\n documentId: string;\n snapshot: unknown; // opaque to us — Univer IDocumentData decides the shape\n label?: string | null;\n origin?: DocumentSnapshotOrigin;\n};\n\nexport async function saveDocumentSnapshot(\n args: SaveDocumentSnapshotArgs,\n): Promise<ServiceResult<DocumentSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .insert({\n document_id: args.documentId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent document's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent document; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.documentId);\n\n return { success: true, data: data as DocumentSnapshot };\n}\n\n/**\n * An independent copy of a document: its own row, with the latest snapshot copied over, so editing the copy never\n * touches the original. The copy lives in the original's organization and project. Used by a board-template use.\n */\nexport async function copyDocument(\n documentId: string,\n name?: string,\n): Promise<ServiceResult<DocumentRow>> {\n const original = await getDocument(documentId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return { success: false, error: \"This document has no organization and cannot be copied.\" };\n }\n const created = await createDocument({\n name: name ?? row.document_name,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n isPublic: row.visibility === \"public\",\n });\n if (!created.success) return created;\n const latest = await getLatestDocumentSnapshot(documentId);\n if (!latest.success) return latest;\n if (latest.data) {\n const saved = await saveDocumentSnapshot({\n documentId: created.data.id,\n snapshot: latest.data.snapshot,\n label: latest.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n/** Trash view: the caller's own archived documents (RLS decides what is readable). */\nexport async function listTrashedDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentRow[] };\n}\n\nexport async function listDocumentSnapshots(\n documentId: string,\n limit = 50,\n): Promise<ServiceResult<DocumentSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, document_id, label, origin, created_by, created_at\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentSnapshot[] };\n}\n","/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n","/**\n * Restore a saved version of a document (COLLAB-DESIGN §6.2, §20): THE one path for History, so a document with a\n * co-editing room is never restored behind its room's back.\n *\n * - Open in this tab: save the restored row, then the open editor swaps it in (`showSavedSnapshot`); an ordered-log\n * room sends it through `collab_replace` itself (`DocumentOtHandle.replace`).\n * - Not open in this tab but the document has a room (another tab or person has it open, or its log is ahead of its\n * checkpoint): `collab_replace` writes the snapshot row, the `replace` op, the checkpoint and the frame in one\n * transaction, so every open seat reloads. A snapshot row alone left those seats stale.\n * - No room: a snapshot row; the next open loads it.\n */\nimport { collabReplace, collabRoomExists, type CollabRpcClient } from \"@ai-matrx/data/realtime/collab\";\n\nimport { hasOpenEditorContent, showSavedSnapshot } from \"../univer/openEditorContent\";\nimport { docsStateHash, stampDeterministicIds } from \"../univer/collab/docs-ot/state-hash\";\nimport { saveDocumentSnapshot } from \"./document-service\";\nimport { getDocsHost } from \"./ports\";\n\nexport type DocumentRestoreResult =\n | { via: \"open_editor\"; snapshotId: string }\n | { via: \"room\"; rev: number; snapshotId: string }\n | { via: \"saved\"; snapshotId: string };\n\nexport interface DocumentRestoreDeps {\n client: () => CollabRpcClient;\n roomExists: (client: CollabRpcClient, documentId: string) => Promise<boolean>;\n replace: typeof collabReplace;\n stateHash: (snapshot: unknown) => Promise<string>;\n hasOpenEditor: (documentId: string) => boolean;\n showInOpenEditor: (documentId: string, row: { id: string; snapshot: unknown }) => Promise<boolean>;\n saveRow: (args: { documentId: string; snapshot: unknown; label: string | null }) => Promise<{ id: string }>;\n}\n\nconst defaultDeps: DocumentRestoreDeps = {\n client: () => getDocsHost().getSupabase() as unknown as CollabRpcClient,\n roomExists: collabRoomExists,\n replace: collabReplace,\n stateHash: (snapshot) => docsStateHash(snapshot),\n hasOpenEditor: (documentId) => hasOpenEditorContent(\"document\", documentId),\n showInOpenEditor: (documentId, row) => showSavedSnapshot(\"document\", documentId, row),\n async saveRow(args) {\n const res = await saveDocumentSnapshot({ documentId: args.documentId, snapshot: args.snapshot, origin: \"restored\", label: args.label });\n if (!res.success) throw new Error(res.error);\n return { id: res.data.id };\n },\n};\n\nexport async function restoreDocumentSnapshot(\n args: { documentId: string; snapshot: unknown; label: string | null },\n deps: Partial<DocumentRestoreDeps> = {},\n): Promise<DocumentRestoreResult> {\n const d = { ...defaultDeps, ...deps };\n if (d.hasOpenEditor(args.documentId)) {\n const row = await d.saveRow(args);\n await d.showInOpenEditor(args.documentId, { id: row.id, snapshot: args.snapshot });\n return { via: \"open_editor\", snapshotId: row.id };\n }\n const client = d.client();\n if (await d.roomExists(client, args.documentId)) {\n const next = stampDeterministicIds(structuredClone(args.snapshot ?? {}));\n const out = await d.replace(client, {\n roomId: args.documentId,\n snapshot: next,\n stateHash: await d.stateHash(next),\n origin: \"restore\",\n });\n return { via: \"room\", rev: out.rev, snapshotId: out.ref };\n }\n const row = await d.saveRow(args);\n return { via: \"saved\", snapshotId: row.id };\n}\n"],"mappings":"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","names":["univerMerge","Y","keyOf","import_collab","Y","import_awareness","import_collab","import_core","db","pickColor","import_collab","row"]}
1
+ {"version":3,"sources":["../src/univer/collab/index.ts","../src/univer/collab/WorkbookCollabSession.ts","../src/univer/collab/covered.ts","../src/univer/collab/docs-ot/transform.ts","../src/univer/collab/docs-ot/state-hash.ts","../src/univer/collab/docs-ot/room.ts","../src/docs/document-ot-room.ts","../src/docs/document-model.ts","../src/univer/openEditorContent.ts","../src/docs/remote-carets.ts","../src/docs/document-service.ts","../src/docs/ports.ts","../src/docs/document-restore.ts","../src/univer/collab/sheets-ot/room.ts","../src/collab/sheets/transform/types.ts","../src/collab/sheets/transform/registry.ts","../src/collab/sheets/transform/transform.ts","../src/collab/sheets/transform/axis.ts","../src/collab/sheets/transform/formula.ts","../src/univer/collab/sheets-ot/state-hash.ts","../src/univer/collab/sheets-ot/univer-port.ts","../src/sheets/workbook-ot-room.ts","../src/sheets/ports.ts","../src/sheets/workbook-service.ts"],"sourcesContent":["/**\n * The collab session shared by `/sheets` and `/docs` (was matrx-frontend `features/workbooks/collab`): the\n * Univer <-> Yjs bridge. It owns the Yjs import, so it is loaded on demand (`import()` when a workbook\n * or document goes live). The snapshot-insert subscription hook is its own entry,\n * `@ai-matrx/office/univer/realtime`, so a static import of the hook never carries Yjs into the editor\n * chunk. A transitional subpath, like `./univer`: it goes internal when the editors move.\n */\nexport * from \"./WorkbookCollabSession\";\nexport * from \"./docs-ot\";\nexport * from \"../../docs/document-ot-room\";\nexport * from \"../../docs/document-restore\";\nexport * from \"./sheets-ot\";\nexport * from \"../../sheets/workbook-ot-room\";\n","/**\n * WorkbookCollabSession — the Univer ↔ Yjs bridge.\n *\n * Subscribes to Univer's public `commandService.onMutationExecutedForCollab`\n * hook for local mutations and pushes them onto a `Y.Array<MutationOp>` shared\n * via `SupabaseYjsProvider`. Inbound Yjs updates produce `IMutationInfo` ops\n * that are applied through `commandService.syncExecuteCommand` with the\n * `fromCollab` execution option flagged so the outbound listener short-\n * circuits and we don't echo our own apply.\n *\n * See `FEATURE.md` in this directory for the architecture, the \"do NOT use\n * the Pro preset\" verdict, and the host-election rule. This class is the\n * runtime side of that plan.\n *\n * Lifecycle:\n * - constructor: wire references, no side effects\n * - start(): create Y.Doc + Awareness, instantiate provider, subscribe to\n * command stream, subscribe to Yjs Array observer\n * - stop(): detach all listeners, dispose provider\n *\n * The session is one-shot per workbook open. Reload = stop() + new instance.\n */\n\"use client\";\n\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport { electCollabHost, remoteOriginOf, REMOTE_PARAM_TAG } from \"@ai-matrx/data/realtime/collab\";\n\nexport { COLLAB_COVERED_KEY, stampCovered, takeCovered } from \"./covered\";\n\n/**\n * Structural transport contract. `SupabaseYjsProvider` satisfies it in\n * production; the verification harness injects an in-memory loopback\n * transport through the same seam. Keeping this structural (not the concrete\n * class) is what makes the session testable without network.\n */\nexport type CollabProviderLike = {\n connect(): Promise<void>;\n disconnect(): void;\n ready(): Promise<void>;\n /**\n * True when this is the only holder of its room in this tab allowed to act as\n * host (autosave). Same-tab holders share one client id and one uid, so\n * awareness cannot tell them apart. Absent = a lone holder = leader.\n */\n isTabLeader?(): boolean;\n};\n\n// Univer types are loose at the public hook boundary; we narrow with a\n// structural interface so we don't have to import the full Univer surface.\ntype MutationParams = Record<string, unknown> | unknown[] | null;\n\nexport type CollabMutationInfo = {\n id: string;\n type: number; // CommandType.MUTATION = 2 in Univer's enum\n params: MutationParams;\n /** Who made it (the person's uid), so a peer can tell its own other tab's edit from a stranger's. */\n uid?: string;\n /**\n * The entry's identity in the room (`<clientId>:<seq>`). A saved snapshot names the entries it holds\n * (`stampCovered`), so a seat that boots from that snapshot never replays them a second time.\n */\n eid?: string;\n};\n\n/**\n * What a seat booted from: the saved snapshot's row id and the room entries that snapshot already holds.\n * The session never replays a covered entry, and a seat that booted from an OLDER snapshot than the\n * room's newest checkpoint first reloads (the entries that checkpoint trimmed are only in that snapshot).\n */\nexport type CollabBase = {\n snapshotId: () => string | null;\n covered: () => ReadonlySet<string>;\n /** Show the newest saved snapshot (and make it the base). */\n reload: () => Promise<void>;\n};\n\ntype ExecuteOptions = {\n /** Per-Univer convention: when true, the command runs locally only and is\n * NOT broadcast to other plugins. We set this on inbound-apply so the\n * subsequent onMutationExecutedForCollab does NOT re-fire on our peer. */\n onlyLocal?: boolean;\n fromCollab?: boolean;\n};\n\nexport type CommandServiceLike = {\n onMutationExecutedForCollab(\n listener: (info: CollabMutationInfo, options?: ExecuteOptions) => void,\n ): {\n dispose: () => void;\n };\n syncExecuteCommand(\n id: string,\n params: MutationParams,\n options?: ExecuteOptions,\n ): unknown;\n};\n\nexport type WorkbookCollabSessionOptions = {\n workbookId: string;\n uid: string;\n clientId: string;\n commandService: CommandServiceLike;\n /** Factory so this file does not statically depend on the provider. */\n makeProvider: (args: {\n workbookId: string;\n clientId: string;\n doc: Y.Doc;\n awareness: Awareness;\n /** Wire to the provider so a host handover re-runs the election. */\n onLeaderChange: () => void;\n }) => CollabProviderLike;\n /** Called when the awareness set changes (peers join / leave / move cursor). */\n onAwarenessChange?: (awareness: Awareness) => void;\n /**\n * A peer replaced the whole content (history restore, Google update): the\n * newest saved snapshot is the content now. Reload it in place; never\n * re-announce. See `announceReplaced`.\n */\n onReplaced?: (snapshotId: string) => void;\n /**\n * TRUE when the room is bound to a Univer DOCUMENT unit (the Docs editor): there the `doc.mutation.*`\n * stream IS the content, so it must travel. Leave unset for a workbook, where `doc.mutation.*` is the\n * in-cell editor's scratch document and never travels (see `isCellEditorScratch`).\n */\n forwardDocumentMutations?: boolean;\n /**\n * The Univer unit id this seat mounted. Each seat can mount its own unit, so a peer's mutation\n * (addressed to the SENDER's unit) is re-addressed to this one before it is applied.\n */\n unitId?: () => string | null;\n /** A peer's mutation could not be applied here: the seat says so and re-syncs; never only a console line. */\n onApplyFailed?: (mutationId: string, error: unknown) => void;\n /**\n * The saved snapshot this seat booted from. Without it a reloading seat replays every entry still in\n * the room's log on top of a snapshot that already holds them: the text shows twice, and the next save\n * stores it twice (2026-10-16).\n */\n base?: CollabBase;\n};\n\n/** What `checkpoint` writes into the room's control map: the newest saved snapshot whose entries left the log. */\ntype CheckpointSignal = { snapshotId: string; by: string };\n\n/** What `announceReplaced` writes into the room's control map. */\ntype ReplacedSignal = { snapshotId: string; by: string; nonce: string };\n\nconst MUTATIONS_ARRAY_KEY = \"mutations\";\nconst CONTROL_MAP_KEY = \"control\";\nconst REPLACED_KEY = \"replaced\";\nconst CHECKPOINT_KEY = \"checkpoint\";\n\nexport class WorkbookCollabSession {\n private readonly options: WorkbookCollabSessionOptions;\n private doc: Y.Doc | null = null;\n private awareness: Awareness | null = null;\n private provider: CollabProviderLike | null = null;\n private commandDisposer: { dispose: () => void } | null = null;\n private yArrayObserver:\n ((event: Y.YArrayEvent<CollabMutationInfo>) => void) | null = null;\n private awarenessObserver: (() => void) | null = null;\n private controlObserver: ((event: Y.YMapEvent<unknown>) => void) | null = null;\n /** >0 while this client swaps its own content: its mutations are not edits. */\n private muted = 0;\n private started = false;\n private disposed = false;\n /** Room entries this seat holds in its content: applied from a peer, or made here. */\n private readonly applied = new Set<string>();\n /** Entries without an id (a peer on an older build) are applied once, by identity. */\n private readonly appliedRefs = new WeakSet<object>();\n private seq = 0;\n /** False until this seat has seen the room's content once (the join-time check runs then). */\n private joined = false;\n /** The base is being reloaded: entries wait in the log until it is shown. */\n private reloadingBase = false;\n\n constructor(options: WorkbookCollabSessionOptions) {\n this.options = options;\n }\n\n async start(): Promise<void> {\n if (this.started || this.disposed) return;\n this.started = true;\n\n this.doc = new Y.Doc();\n this.awareness = new Awareness(this.doc);\n\n // Seed local awareness with the user identity. Cursor (sheetId/row/col)\n // is set later via setCursor().\n this.awareness.setLocalState({\n uid: this.options.uid,\n clientId: this.options.clientId,\n name: this.options.uid.slice(0, 8),\n color: pickColor(this.options.uid),\n sheetId: null,\n row: null,\n col: null,\n ts: Date.now(),\n });\n\n this.provider = this.options.makeProvider({\n workbookId: this.options.workbookId,\n clientId: this.options.clientId,\n doc: this.doc,\n awareness: this.awareness,\n onLeaderChange: () => {\n if (this.awareness) this.options.onAwarenessChange?.(this.awareness);\n },\n });\n\n // Subscribe to inbound Yjs array changes BEFORE connecting the provider,\n // so the initial-state replay (if any) hits our observer.\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n this.yArrayObserver = (event) => {\n // Local transactions are OUR OWN pushes from handleLocalMutation —\n // Univer already executed those mutations. Re-applying them here would\n // double-apply every local edit on the originator. Only act on\n // transactions that arrived via Y.applyUpdate (origin 'remote').\n if (event.transaction.local) return;\n if (!event.changes.delta.some((change) => Array.isArray(change.insert) && change.insert.length > 0)) return;\n this.drain();\n };\n yArray.observe(this.yArrayObserver as Parameters<typeof yArray.observe>[0]);\n\n // Awareness change passthrough.\n if (this.options.onAwarenessChange) {\n const cb = this.options.onAwarenessChange;\n this.awarenessObserver = () => {\n if (this.awareness) cb(this.awareness);\n };\n this.awareness.on(\"change\", this.awarenessObserver);\n }\n\n // Subscribe to Univer's collab-grain mutation stream.\n this.commandDisposer =\n this.options.commandService.onMutationExecutedForCollab((info, options) =>\n this.handleLocalMutation(info, options),\n );\n\n await this.provider.connect();\n await this.provider.ready();\n this.drain();\n\n // Whole-content replacement from a peer. Bound AFTER the initial sync: a\n // joiner already loaded the newest snapshot, so the signal it finds in\n // the room's state is history, not news (the editor also skips a\n // snapshot it already shows).\n if (this.disposed || !this.doc) return;\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const seen = (control.get(REPLACED_KEY) as ReplacedSignal | undefined)?.nonce ?? null;\n this.controlObserver = (event) => {\n if (event.transaction.local || !event.keysChanged.has(REPLACED_KEY)) return;\n const signal = control.get(REPLACED_KEY) as ReplacedSignal | undefined;\n if (!signal?.snapshotId || signal.nonce === seen) return;\n this.options.onReplaced?.(signal.snapshotId);\n };\n control.observe(this.controlObserver);\n }\n\n stop(): void {\n if (this.disposed) return;\n this.disposed = true;\n\n this.commandDisposer?.dispose();\n this.commandDisposer = null;\n\n if (this.doc && this.yArrayObserver) {\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n yArray.unobserve(\n this.yArrayObserver as Parameters<typeof yArray.unobserve>[0],\n );\n this.yArrayObserver = null;\n }\n\n if (this.doc && this.controlObserver) {\n this.doc.getMap<unknown>(CONTROL_MAP_KEY).unobserve(this.controlObserver);\n this.controlObserver = null;\n }\n\n if (this.awareness && this.awarenessObserver) {\n this.awareness.off(\"change\", this.awarenessObserver);\n this.awarenessObserver = null;\n }\n\n this.provider?.disconnect();\n this.provider = null;\n\n if (this.awareness) {\n this.awareness.destroy();\n this.awareness = null;\n }\n\n if (this.doc) {\n this.doc.destroy();\n this.doc = null;\n }\n }\n\n /** How many mutations the shared log holds right now. */\n logLength(): number {\n return this.doc?.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY).length ?? 0;\n }\n\n /**\n * The room entries this seat's content holds RIGHT NOW. Read it in the same synchronous step as the\n * content you are about to save, and save it with that content (`stampCovered`); after the save lands,\n * pass it to `checkpoint`.\n */\n coveredNow(): string[] {\n if (!this.doc) return [];\n const covered = this.options.base?.covered();\n const out: string[] = [];\n for (const op of this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY).toArray()) {\n if (op.eid && (this.applied.has(op.eid) || covered?.has(op.eid))) out.push(op.eid);\n }\n return out;\n }\n\n /**\n * The snapshot `snapshotId` was SAVED holding `covered` (from `coveredNow`): those entries leave the\n * shared log, and the room records the snapshot as its newest checkpoint. Removal is by entry id, never\n * by position — an entry that arrived while the save was in flight is not in the snapshot and stays.\n * Only the elected saver calls this; peers receive it as a delete (never replayed).\n */\n checkpoint(snapshotId: string, covered: readonly string[]): void {\n if (!this.doc) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const drop = new Set(covered);\n const signal: CheckpointSignal = { snapshotId, by: this.options.clientId };\n this.doc.transact(() => {\n const entries = yArray.toArray();\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const eid = entries[i]?.eid;\n if (eid && drop.has(eid)) yArray.delete(i, 1);\n }\n control.set(CHECKPOINT_KEY, signal);\n });\n }\n\n /**\n * This client replaced the whole content and SAVED it as `snapshotId`.\n * One transaction empties the shared mutation log (every entry targets the\n * content that is gone — a joiner must never replay them onto the new\n * snapshot) and tells every peer to reload the newest snapshot.\n */\n announceReplaced(snapshotId: string): void {\n if (!this.doc) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const signal: ReplacedSignal = {\n snapshotId,\n by: this.options.clientId,\n nonce: `${this.options.clientId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`,\n };\n this.doc.transact(() => {\n if (yArray.length > 0) yArray.delete(0, yArray.length);\n control.set(REPLACED_KEY, signal);\n control.set(CHECKPOINT_KEY, { snapshotId, by: this.options.clientId } satisfies CheckpointSignal);\n });\n }\n\n /**\n * Run `swap` (this client tearing its content down and mounting the new\n * one) without broadcasting what Univer emits while it does: those are not\n * edits, and peers reload the same snapshot themselves.\n */\n muteWhile<T>(swap: () => T): T {\n this.muted += 1;\n try {\n return swap();\n } finally {\n this.muted -= 1;\n }\n }\n\n /**\n * Update the local awareness cursor. Call this from Univer's selection\n * listener (`worksheet.onSelectionChange(...)`). Throttle at the call site\n * (~50ms is plenty); the provider broadcasts on its own debounced cycle.\n */\n setCursor(input: {\n sheetId: string | null;\n row: number | null;\n col: number | null;\n }): void {\n if (!this.awareness) return;\n const current = this.awareness.getLocalState() ?? {};\n this.awareness.setLocalState({\n ...current,\n sheetId: input.sheetId,\n row: input.row,\n col: input.col,\n ts: Date.now(),\n });\n }\n\n /**\n * Returns the deterministic host: the connected peer with the lowest uid\n * (lexicographic). Host is the only client that writes canonical snapshots.\n * No election protocol; recompute whenever awareness changes.\n */\n electHost(opts: { tabTieBreak?: boolean } = {}): { isHost: boolean; hostUid: string | null } {\n if (!this.awareness) return { isHost: false, hostUid: null };\n const states = Array.from(this.awareness.getStates().values()) as Array<\n Record<string, unknown>\n >;\n // Lowest uid wins ACROSS tabs; inside this tab only the room's tab leader\n // may be host, because every same-tab holder carries the same uid.\n const leader = this.provider?.isTabLeader?.() ?? true;\n return electCollabHost(states, this.options.uid, this.options.clientId, leader, opts.tabTieBreak ?? false);\n }\n\n // ─── internals ────────────────────────────────────────────────────────\n\n private handleLocalMutation(info: CollabMutationInfo, options?: ExecuteOptions): void {\n if (this.muted > 0) return;\n // Univer marks a mutation `onlyLocal` when every seat derives it itself (formula-engine recalculation,\n // layout results): relaying it turns every recalculation into network traffic and a logged op.\n if (options?.onlyLocal) return;\n if (!this.options.forwardDocumentMutations && isCellEditorScratch(info)) return;\n // Inbound-applied mutations re-fire this listener because Univer's\n // syncExecuteCommand legitimately processes them through the full\n // pipeline. Skip by sniffing the sentinel we stamped on apply.\n if (\n info.params &&\n typeof info.params === \"object\" &&\n !Array.isArray(info.params) &&\n remoteOriginOf(info.params) !== null\n ) {\n return;\n }\n if (!this.doc) return;\n\n // Normalize params through a JSON round-trip BEFORE pushing into Yjs.\n // Yjs (and the Broadcast transport) only carry JSON-encodable values;\n // Univer types its mutation params as \"serializable\" but JS objects can\n // smuggle Date / Map / class instances through that promise. The\n // round-trip makes the failure mode deterministic: a non-encodable\n // mutation is skipped with a warning instead of corrupting the shared\n // doc or desyncing peers mid-session. What we push here is byte-for-byte\n // what remote peers will apply, so local-apply == remote-apply.\n let safeParams: MutationParams;\n try {\n safeParams =\n info.params === undefined || info.params === null\n ? null\n : stripSenderView(JSON.parse(JSON.stringify(info.params)) as MutationParams);\n } catch (err) {\n console.warn(\n `[collab] skipping non-serializable mutation \"${info.id}\" — peers will not receive it`,\n err,\n );\n return;\n }\n\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const eid = `${this.options.clientId}:${++this.seq}`;\n this.applied.add(eid);\n // An edit made here is made on what this seat shows: the join-time check is over.\n this.joined = true;\n yArray.push([{ id: info.id, type: info.type, params: safeParams, uid: this.options.uid, eid }]);\n }\n\n /**\n * Apply every log entry this seat's content does not hold yet, in the log's order. The first time the\n * room shows content, the join-time check runs: a seat that booted from a snapshot OLDER than the\n * room's newest checkpoint reloads first (the entries that checkpoint trimmed exist only in it).\n */\n private drain(): void {\n if (!this.doc || this.disposed || this.reloadingBase) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const entries = yArray.toArray();\n const base = this.options.base;\n if (!this.joined) {\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const checkpoint = control.get(CHECKPOINT_KEY) as CheckpointSignal | undefined;\n if (entries.length === 0 && !checkpoint) return;\n this.joined = true;\n if (base && checkpoint?.snapshotId && checkpoint.snapshotId !== base.snapshotId()) {\n this.reloadingBase = true;\n void base\n .reload()\n .catch((error: unknown) => {\n console.warn(\"[collab] could not load the newest saved version on joining\", error);\n this.options.onApplyFailed?.(\"collab.join\", error);\n })\n .finally(() => {\n this.reloadingBase = false;\n this.drain();\n });\n return;\n }\n }\n const covered = base?.covered();\n for (const op of entries) {\n if (op.eid) {\n if (this.applied.has(op.eid) || covered?.has(op.eid)) continue;\n this.applied.add(op.eid);\n } else {\n if (this.appliedRefs.has(op)) continue;\n this.appliedRefs.add(op);\n }\n this.applyRemoteMutation(op);\n }\n }\n\n private applyRemoteMutation(op: CollabMutationInfo): void {\n // Wrap params with the sentinel so handleLocalMutation knows not to\n // echo the apply back into Yjs.\n const ownUnit = this.options.unitId?.() ?? null;\n const taggedParams: MutationParams =\n op.params && typeof op.params === \"object\" && !Array.isArray(op.params)\n ? {\n ...(op.params as Record<string, unknown>),\n ...(ownUnit && typeof (op.params as { unitId?: unknown }).unitId === \"string\" ? { unitId: ownUnit } : {}),\n [REMOTE_PARAM_TAG]: op.uid ?? true,\n }\n : op.params;\n\n try {\n this.options.commandService.syncExecuteCommand(op.id, taggedParams, {\n onlyLocal: true,\n fromCollab: true,\n });\n } catch (err) {\n // One unappliable op (already baked into the loaded snapshot, or a\n // stale target) must not throw into the realtime channel handler and\n // abort the rest of the catch-up. Said, never swallowed.\n console.warn(\n `[collab] could not apply remote mutation \"${op.id}\" — skipped`,\n err,\n );\n this.options.onApplyFailed?.(op.id, err);\n }\n }\n}\n\n// ─── helpers ────────────────────────────────────────────────────────────\n\n/**\n * A workbook holds no Univer DOCUMENT units of its own: the `doc.mutation.*` stream a sheet emits is\n * the in-cell editor's scratch document (typing into a cell). The finished text reaches the sheet as\n * `sheet.mutation.set-range-values`, which does travel. Sending the scratch edits made a joiner replay\n * them against an editor unit it does not have (\"Trying to overwrite value at key\").\n */\nexport const SENDER_VIEW_PARAMS: readonly string[] = [\"layoutState\", \"textRanges\", \"prevTextRanges\"];\n\n/**\n * Remove what describes the SENDER'S view (the editor's layout cache, caret and selection ranges) from a\n * mutation's params before it travels: a receiver would otherwise restore the sender's layout and caret.\n * Everything else (the content-changing `actions`, ids, addresses) is left as is.\n */\nexport function stripSenderView(params: MutationParams): MutationParams {\n if (!params || typeof params !== \"object\" || Array.isArray(params)) return params;\n const out: Record<string, unknown> = { ...params };\n for (const key of SENDER_VIEW_PARAMS) delete out[key];\n return out;\n}\n\nexport function isCellEditorScratch(info: Pick<CollabMutationInfo, \"id\">): boolean {\n return typeof info.id === \"string\" && info.id.startsWith(\"doc.mutation.\");\n}\n\nconst CURSOR_PALETTE = [\n \"#3b82f6\", // blue\n \"#10b981\", // emerald\n \"#f59e0b\", // amber\n \"#ef4444\", // red\n \"#8b5cf6\", // violet\n \"#06b6d4\", // cyan\n \"#ec4899\", // pink\n \"#84cc16\", // lime\n];\n\nfunction pickColor(uid: string): string {\n // Deterministic FNV-1a-ish hash so the same user is always the same color\n // across sessions and across other users' screens.\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return CURSOR_PALETTE[Math.abs(h) % CURSOR_PALETTE.length] ?? \"#ec4899\";\n}\n","/**\n * A saved snapshot names the collab-room entries it already holds, so a seat that boots from it never\n * replays them (2026-10-16: a reload showed the text twice). Pure — no Yjs — so the editors' model can\n * stamp and read it without loading the room.\n */\n\n/** The key a saved snapshot carries its covered room entries under (`stampCovered` / `takeCovered`). */\nexport const COLLAB_COVERED_KEY = \"__matrxCollabCovered\";\n\n/** The snapshot to SAVE: `snapshot` plus the room entries it holds (`WorkbookCollabSession.coveredNow`). */\nexport function stampCovered<T extends object>(snapshot: T, covered: readonly string[]): T {\n return { ...snapshot, [COLLAB_COVERED_KEY]: [...covered] };\n}\n\n/** A LOADED snapshot split into the content to mount and the room entries it already holds. */\nexport function takeCovered<T>(snapshot: T): { snapshot: T; covered: Set<string> } {\n if (!snapshot || typeof snapshot !== \"object\" || !(COLLAB_COVERED_KEY in (snapshot as object))) {\n return { snapshot, covered: new Set() };\n }\n const { [COLLAB_COVERED_KEY]: list, ...rest } = snapshot as Record<string, unknown>;\n return {\n snapshot: rest as T,\n covered: new Set(Array.isArray(list) ? list.filter((e): e is string => typeof e === \"string\") : []),\n };\n}\n","/**\n * The Docs operational transform (COLLAB-DESIGN §6.4, §6.5; C0b rules R1–R5 plus the C2 retain rule R6).\n *\n * Pure and DOM-free. ot-json1 walks the JSON tree; only the `text-x` edit transform is ours. It is a port of\n * Univer 1.0.4's `TextX._transform` / `transformBody` (Apache-2.0, dream-num/univer, core\n * src/docs/data-model/text-x) with these cases changed or added (evidence: C0-REPORT, C0b):\n *\n * R1 a whole-table delete swallows typing inside it; the typist gets a `lost` entry.\n * R2 a REPLACE (coverType 1) retain keeps a concurrent comment decoration whole.\n * R3 a REPLACE paragraph with no paragraphStyle means \"no style\" ({}), on both sides.\n * R4 style keys are tested for presence (`!== undefined`), never truthiness (a winning `bl: 0`).\n * R5 a non-monotonic op (a negative retain) is rewritten as the composition of its forward segments.\n * R6 a merge (not REPLACE) retain whose style lost every key comes back as a PLAIN retain. Without it `textRuns: [{ts:{}}]` and\n * `textRuns: []` apply differently and two-edit chains diverge (C2: 462 of 20,000; with it 0).\n *\n * Ops carrying `rangeUpdates` go to Univer's `TextX.transform` unchanged (no free 1.0.4 command emits them).\n * `T(x, y, side)` returns x rewritten to apply after y; `side` is x's side and the later-committed op takes\n * `'left'` (§6.4). A transform that throws is a barrier for that pair (the session treats a throw as one).\n */\n/* eslint-disable @typescript-eslint/no-explicit-any -- Univer's text-x action shapes are open JSON */\nimport { JSONX, TextX, getBodySliceForSplitTextXAction, normalizeTextRuns, merge as univerMerge } from \"@univerjs/core\";\nimport * as json1 from \"ot-json1\";\n\ntype Act = Record<string, any> & { t: \"i\" | \"r\" | \"d\"; len: number };\ntype Body = Record<string, any>;\ntype Zone = [number, number];\n/** One `lost` entry: what a transform dropped from either side (R1), for the author's notice. */\nexport interface DocsLost {\n rule: string;\n side: \"insert\" | \"delete\";\n len: number;\n text?: string;\n}\n\nconst isTextX = (c: unknown): c is { et: string; e: Act[] } =>\n !!c && typeof c === \"object\" && (c as { et?: unknown }).et === \"text-x\" && Array.isArray((c as { e?: unknown }).e);\nconst clone = <T>(v: T): T => (v == null ? v : structuredClone(v));\n\n// ── normalization: the traveling shape ──────────────────────────────────────────────────────────────\n\nfunction tableZones(a: Act): Zone[] {\n const out: Zone[] = [];\n for (const t of (a.body?.tables ?? []) as Array<{ startIndex: number; endIndex: number }>) {\n if (t.startIndex >= 0 && t.endIndex <= a.len && t.endIndex > t.startIndex) out.push([t.startIndex, t.endIndex - 1]);\n }\n return out;\n}\n\n/** R5: an op whose cursor goes backwards becomes the composition of its forward-only segments. */\nfunction unrewind(actions: Act[]): Act[] {\n if (!actions.some((a) => a.len < 0)) return actions;\n const segs: Act[][] = [];\n let cur: Act[] = [];\n let cursor = 0;\n for (const a of actions) {\n if (a.len < 0) {\n if (a.t !== \"r\") return actions;\n segs.push(cur);\n cursor += a.len;\n cur = cursor > 0 ? [{ t: \"r\", len: cursor }] : [];\n continue;\n }\n cur.push(a);\n if (a.t !== \"d\") cursor += a.len;\n }\n segs.push(cur);\n const out = segs.reduce((acc, s) => TextX.compose(acc as any, s as any) as unknown as Act[]);\n return out.some((a) => a.len < 0) ? actions : out;\n}\n\nfunction normText(actions: Act[]): Act[] {\n const out: Act[] = [];\n for (const a of unrewind(actions)) {\n if (a.t === \"d\") {\n if (!(a.len > 0)) continue;\n const d: Act = { t: \"d\", len: a.len };\n if (a.valueRangeId !== undefined) d.valueRangeId = a.valueRangeId;\n const tz = (a.tz as Zone[] | undefined) ?? tableZones(a);\n if (tz.length) d.tz = tz;\n out.push(d);\n continue;\n }\n if (a.t === \"r\") {\n const { oldBody: _oldBody, ...rest } = a;\n out.push(rest as Act);\n continue;\n }\n out.push(a);\n }\n return out;\n}\n\n/** The traveling shape of a Docs JSON op: text-x edits normalized (R1 zones, R5, no oldBody). */\nexport function normalizeDocsOp<T>(op: T): T {\n if (op == null) return op;\n const walk = (v: unknown): unknown => {\n if (Array.isArray(v)) return v.map(walk);\n if (isTextX(v)) return { ...v, e: normText(v.e) };\n return v;\n };\n return walk(op) as T;\n}\n\n/** R6: a retain whose style lost every key to the other side is a plain retain. */\nexport function dropEmptyStyleRetains<T>(op: T): T {\n if (op == null) return op;\n const walk = (v: unknown): unknown => {\n if (Array.isArray(v)) return v.map(walk);\n if (isTextX(v)) {\n return {\n ...v,\n e: v.e.map((a) => {\n const b = a.body as Body | undefined;\n if (a.t !== \"r\" || !b || a.coverType === 1) return a;\n const runs = ((b.textRuns as Array<{ ts?: Record<string, unknown> }>) ?? []).filter((r) => r.ts && Object.keys(r.ts).length);\n const other = Object.keys(b).filter(\n (k) => k !== \"textRuns\" && k !== \"dataStream\" && !(Array.isArray(b[k]) && (b[k] as unknown[]).length === 0),\n );\n if (!runs.length && !other.length && !b.dataStream && !a.rangeUpdates?.length) return { t: \"r\", len: a.len };\n if (b.textRuns === undefined || runs.length === (b.textRuns as unknown[]).length) return a;\n return { ...a, body: { ...b, textRuns: runs } };\n }),\n };\n }\n return v;\n };\n return walk(op) as T;\n}\n\n// ── action list helpers (Univer's TextX.push / trimEndUselessRetainAction, plus zone merging) ────────\n\nconst onlyDataStream = (body: Body) => Object.keys(body).length === 1;\nconst shiftZones = (tz: Zone[], by: number): Zone[] => tz.map(([s, e]) => [s + by, e + by]);\nfunction mergeZones(tz: Zone[]): Zone[] {\n const s = [...tz].sort((x, y) => x[0] - y[0]);\n const out: Zone[] = [];\n for (const z of s) {\n const l = out[out.length - 1];\n if (l && l[1] + 1 >= z[0]) l[1] = Math.max(l[1], z[1]);\n else out.push([z[0], z[1]]);\n }\n return out;\n}\nfunction push(list: Act[], action: Act): void {\n let index = list.length;\n let last = list[index - 1];\n const a = clone(action);\n if (a.t === \"r\" && a.len === 0 && a.body == null && !a.rangeUpdates) return;\n if (last) {\n if (last.t === \"d\" && a.t === \"d\" && last.valueRangeId === a.valueRangeId) {\n const tz = [...((last.tz as Zone[]) ?? []), ...shiftZones((a.tz as Zone[]) ?? [], last.len)];\n last.len += a.len;\n if (tz.length) last.tz = mergeZones(tz);\n return;\n }\n if (last.t === \"d\" && a.t === \"i\") {\n index -= 1;\n last = list[index - 1];\n if (last == null) {\n list.unshift(a);\n return;\n }\n }\n if (last.t === \"r\" && a.t === \"r\" && last.body == null && a.body == null && !last.rangeUpdates && !a.rangeUpdates) {\n last.len += a.len;\n return;\n }\n if (last.t === \"i\" && onlyDataStream(last.body) && a.t === \"i\" && onlyDataStream(a.body) && last.valueRangeId === a.valueRangeId) {\n last.len += a.len;\n last.body.dataStream += a.body.dataStream;\n return;\n }\n }\n if (index === list.length) list.push(a);\n else list.splice(index, 0, a);\n}\nconst BODY_FIELDS = [\n \"textRuns\", \"paragraphs\", \"customRanges\", \"customBlocks\", \"docxRawCustomBlocks\", \"docxRawBlocks\",\n \"docxExportExcludedRanges\", \"customDecorations\", \"tables\", \"columnGroups\", \"blockRanges\",\n];\nconst uselessRetain = (a: Act) => !a.rangeUpdates?.length && (a.body == null || BODY_FIELDS.every((k) => a.body[k] == null));\nfunction trimEnd(list: Act[]): Act[] {\n while (list.length && list[list.length - 1]!.t === \"r\" && uselessRetain(list[list.length - 1]!)) list.pop();\n return list;\n}\n\n/** Univer's ActionIterator, plus the offset inside the current action and table zones sliced on split. */\nclass It {\n private i = 0;\n private off = 0;\n constructor(private readonly a: Act[]) {}\n peekType(): Act[\"t\"] {\n return this.a[this.i]?.t ?? \"r\";\n }\n peekLength(): number {\n const x = this.a[this.i];\n return x ? x.len - this.off : Number.POSITIVE_INFINITY;\n }\n hasNext(): boolean {\n return this.peekLength() < Number.POSITIVE_INFINITY;\n }\n /** An insert placed now would land strictly inside a table this delete removes whole. */\n inZone(): boolean {\n const x = this.a[this.i];\n return x?.t === \"d\" && ((x.tz as Zone[]) ?? []).some(([s, e]) => s < this.off && this.off <= e);\n }\n next(length?: number): Act {\n let len = length || Number.POSITIVE_INFINITY;\n const x = this.a[this.i];\n if (!x) return { t: \"r\", len: Number.POSITIVE_INFINITY };\n const offset = this.off;\n if (len >= x.len - offset) {\n len = x.len - offset;\n this.i += 1;\n this.off = 0;\n } else this.off += len;\n if (x.t === \"d\") {\n const piece: Act = { ...clone(x), len };\n delete piece.tz;\n const tz = ((x.tz as Zone[]) ?? [])\n .map(([s, e]): Zone => [Math.max(s, offset) - offset, Math.min(e, offset + len - 1) - offset])\n .filter(([s, e]) => s <= e);\n if (tz.length) piece.tz = tz;\n return piece;\n }\n if (x.t === \"r\" && x.body == null) return { ...clone(x), len };\n return { ...clone(x), len, body: getBodySliceForSplitTextXAction(x.body, offset, offset + len, false) };\n }\n}\n\n// ── body transforms: ported from Univer transform-utils.ts, cases R3/R4 marked ───────────────────────\n\nfunction transformTextRuns(originTextRuns: any[] | undefined, targetTextRuns: any[] | undefined, originCoverType: number, targetCoverType: number, transformType: 0 | 1): any[] | undefined {\n if (originTextRuns == null || targetTextRuns == null) return targetTextRuns;\n if (originTextRuns.length === 0 || targetTextRuns.length === 0) return [];\n targetTextRuns = clone(targetTextRuns);\n originTextRuns = clone(originTextRuns);\n const out: any[] = [];\n const updateLength = targetTextRuns.length;\n const removeLength = originTextRuns.length;\n let updateIndex = 0;\n let removeIndex = 0;\n let pending: any = null;\n const flush = () => {\n if (pending) {\n out.push(pending);\n pending = null;\n return true;\n }\n return false;\n };\n while (updateIndex < updateLength && removeIndex < removeLength) {\n const { st: updateSt, ed: updateEd, ts: targetStyle } = targetTextRuns[updateIndex];\n const { st: removeSt, ed: removeEd, ts: originStyle, sId } = originTextRuns[removeIndex];\n let newTs: Record<string, unknown> = {};\n if (transformType === 0) {\n newTs = { ...targetStyle };\n if (originCoverType === 0 && targetCoverType === 1 && originStyle) newTs = Object.assign({}, originStyle, newTs);\n } else {\n newTs = { ...targetStyle };\n if (originCoverType === 1) {\n if (targetCoverType === 1) newTs = { ...originStyle };\n else if (targetStyle && originStyle) {\n for (const key of Object.keys(targetStyle)) if (originStyle[key] !== undefined) delete newTs[key]; // R4\n }\n } else if (targetCoverType === 1) {\n if (originStyle) for (const key of Object.keys(originStyle)) if (originStyle[key] !== undefined) newTs[key] = originStyle[key];\n } else if (originStyle) {\n for (const key of Object.keys(originStyle)) if (newTs[key] !== undefined) delete newTs[key];\n }\n }\n if (updateEd < removeSt) {\n if (!flush()) out.push(targetTextRuns[updateIndex]);\n updateIndex++;\n } else if (removeEd < updateSt) {\n if (!flush()) out.push(originTextRuns[removeIndex]);\n removeIndex++;\n } else {\n out.push({ st: Math.max(updateSt, removeSt), ed: Math.min(updateEd, removeEd), ts: newTs, sId });\n if (updateEd < removeEd) {\n updateIndex++;\n originTextRuns[removeIndex].st = updateEd;\n if (originTextRuns[removeIndex].st === originTextRuns[removeIndex].ed) removeIndex++;\n } else {\n removeIndex++;\n targetTextRuns[updateIndex].st = removeEd;\n if (targetTextRuns[updateIndex].st === targetTextRuns[updateIndex].ed) updateIndex++;\n }\n const p = {\n st: Math.min(updateEd, removeEd),\n ed: Math.max(updateEd, removeEd),\n ts: updateEd < removeEd ? { ...originStyle } : { ...targetStyle },\n sId: updateEd < removeEd ? sId : undefined,\n };\n pending = p.ed > p.st ? p : null;\n }\n }\n flush();\n const top = out[out.length - 1];\n const updateLast = targetTextRuns[updateLength - 1];\n const removeLast = originTextRuns[removeLength - 1];\n if (top.ed !== Math.max(updateLast.ed, removeLast.ed)) out.push(updateLast.ed > removeLast.ed ? updateLast : removeLast);\n return normalizeTextRuns(out, true);\n}\n\nfunction transformCustomRanges(o: any[] | undefined, t: any[] | undefined, originCoverType: number, _targetCoverType: number, transformType: 0 | 1): any[] | undefined {\n if (o == null || t == null) return t;\n if (o.length === 0 || t.length === 0) return [];\n if (o.length > 1 || t.length > 1) throw new Error(\"CustomRanges is only supported transform for length one now.\");\n if (originCoverType === 1) return transformType === 1 ? [clone(o[0])] : [clone(t[0])];\n const r = clone(t[0]);\n if (transformType === 1) Object.assign(r, clone(o[0]));\n return [r];\n}\n\nfunction transformParagraph(origin: any, target: any, originCoverType: number, targetCoverType: number, transformType: 0 | 1): any {\n const paragraph: any = { startIndex: target.startIndex, paragraphId: target.paragraphId };\n // R3: on a REPLACE paragraph, a missing paragraphStyle means \"no style\", which is a value.\n const oStyle = originCoverType === 1 ? origin.paragraphStyle ?? {} : origin.paragraphStyle;\n const tStyle = targetCoverType === 1 ? target.paragraphStyle ?? {} : target.paragraphStyle;\n if (tStyle) {\n paragraph.paragraphStyle = clone(tStyle);\n if (oStyle) {\n const ps = paragraph.paragraphStyle;\n if (originCoverType === 1) {\n if (targetCoverType === 1) {\n if (transformType === 1) paragraph.paragraphStyle = { ...oStyle };\n } else if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (oStyle[k] !== undefined) ps[k] = oStyle[k];\n } else for (const k of Object.keys(oStyle)) if (ps[k] === undefined) ps[k] = oStyle[k];\n } else if (targetCoverType === 1) {\n if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (oStyle[k] !== undefined) ps[k] = oStyle[k];\n } else for (const k of Object.keys(oStyle)) if (ps[k] === undefined) ps[k] = oStyle[k];\n } else if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (ps[k] !== undefined) delete ps[k]; // R3: presence, not truthiness\n }\n }\n if (targetCoverType !== 1 && Object.keys(paragraph.paragraphStyle).length === 0) delete paragraph.paragraphStyle;\n }\n if (originCoverType === 1 && targetCoverType === 1) paragraph.bullet = transformType === 1 ? clone(origin.bullet) : clone(target.bullet);\n else if (origin.bullet === undefined) paragraph.bullet = clone(target.bullet);\n else if (originCoverType === 1 || targetCoverType === 1) paragraph.bullet = transformType === 0 && target.bullet ? clone(target.bullet) : clone(origin.bullet);\n else if (transformType === 0 && target.bullet !== undefined) paragraph.bullet = clone(target.bullet);\n if (paragraph.bullet === undefined) delete paragraph.bullet;\n if (paragraph.paragraphId === undefined) delete paragraph.paragraphId;\n return paragraph;\n}\n\nfunction transformCustomDecorations(origin: any[] | undefined, target: any[] | undefined): any[] | undefined {\n if (origin == null || target == null) return target;\n if (origin.length === 0 || target.length === 0) return clone(target);\n const out: any[] = [];\n for (const d of target) {\n let pushed = false;\n for (const o of origin) {\n if (o.id === d.id) {\n if (o.type === 9999 || d.type === 9999) {\n pushed = true;\n out.push({ ...d, type: 9999 });\n }\n break;\n }\n }\n if (!pushed) out.push(d);\n }\n return out;\n}\n\nfunction transformBlockRanges(thisBlockRanges: any[], otherBlockRanges: any[], priority: boolean): any[] {\n if (!thisBlockRanges.length) return otherBlockRanges;\n if (!otherBlockRanges.length) return [];\n return otherBlockRanges.map((o) => {\n const t = thisBlockRanges.find((b) => b.blockId === o.blockId);\n return t && priority ? univerMerge(o, t) : o;\n });\n}\n\n/** transformBody(thisAction = the other op's chunk, otherAction = the chunk being transformed, priority = this wins). */\nfunction transformBody(thisAction: Act, otherAction: Act, priority: boolean): { coverType: number; body: Body } {\n const { body: thisBody, coverType: thisCoverType = 0 } = thisAction;\n const { body: otherBody, coverType: otherCoverType = 0 } = otherAction;\n if (thisBody == null || thisBody.dataStream !== \"\" || otherBody == null || otherBody.dataStream !== \"\") {\n throw new Error(\"Data stream is not supported in retain transform.\");\n }\n const ret: Body = { dataStream: \"\" };\n const { textRuns: tr1, paragraphs: p1 = [], blockRanges: b1 = [], customRanges: c1, customDecorations: d1 } = thisBody;\n const { textRuns: tr2, paragraphs: p2 = [], blockRanges: b2 = [], customRanges: c2, customDecorations: d2 } = otherBody;\n const pt: 0 | 1 = priority ? 1 : 0;\n const textRuns = transformTextRuns(tr1, tr2, thisCoverType, otherCoverType, pt);\n if (textRuns) ret.textRuns = textRuns;\n const customRanges = transformCustomRanges(c1, c2, thisCoverType, otherCoverType, pt);\n if (customRanges) ret.customRanges = customRanges;\n const customDecorations = transformCustomDecorations(d1, d2);\n if (customDecorations) ret.customDecorations = customDecorations;\n const paragraphs: any[] = [];\n let i = 0;\n let j = 0;\n while (i < p1.length && j < p2.length) {\n const a = p1[i];\n const b = p2[j];\n if (a.startIndex === b.startIndex) {\n paragraphs.push(transformParagraph(a, b, thisCoverType, otherCoverType, pt));\n i++;\n j++;\n } else if (a.startIndex < b.startIndex) i++;\n else {\n paragraphs.push(clone(b));\n j++;\n }\n }\n if (j < p2.length) paragraphs.push(...p2.slice(j));\n if (paragraphs.length) ret.paragraphs = paragraphs;\n const blockRanges = transformBlockRanges(b1, b2, priority);\n if (blockRanges.length) ret.blockRanges = blockRanges;\n return { coverType: otherCoverType, body: ret };\n}\n\n// ── the text-x transform ──────────────────────────────────────────────────────────────────────────────\n\nconst valueIds = (acts: Act[]) => new Set(acts.flatMap((a) => (a.t !== \"r\" && a.valueRangeId ? [a.valueRangeId as string] : [])));\nfunction withoutValueRangeMetadata(acts: Act[], suppressed: Set<string>): Act[] {\n return acts.map((a) => {\n if (!a.body?.customRanges?.some((r: any) => suppressed.has(r.rangeId))) return a;\n const body = { ...a.body, customRanges: a.body.customRanges.filter((r: any) => !suppressed.has(r.rangeId)) };\n if (!body.customRanges.length) delete body.customRanges;\n return { ...a, body };\n });\n}\n/** Decorations y adds, in the coordinates of the document after y. */\nfunction addedDecorations(y: Act[]): Array<{ id: string; type: number; ds: number; de: number }> {\n const out: Array<{ id: string; type: number; ds: number; de: number }> = [];\n let pos = 0;\n for (const a of y) {\n if (a.t === \"d\") continue;\n if (a.t === \"r\") for (const d of a.body?.customDecorations ?? []) if (d.type !== 9999) out.push({ id: d.id, type: d.type, ds: pos + d.startIndex, de: pos + d.endIndex });\n pos += a.len;\n }\n return out;\n}\nconst hasRangeUpdates = (acts: Act[]) => acts.some((a) => a.t === \"r\" && a.rangeUpdates?.length);\n\n/** x rewritten to apply after y over one text-x body; `side` is x's side. Drops land in `lost` (R1). */\nexport function transformTextX(xIn: Act[], yIn: Act[], side: \"left\" | \"right\", lost: DocsLost[] = []): Act[] {\n if (hasRangeUpdates(xIn) || hasRangeUpdates(yIn)) return TextX.transform(xIn as any, yIn as any, side) as unknown as Act[];\n const x = normText(xIn);\n const y = normText(yIn);\n const xLeft = side === \"left\";\n const yIds = valueIds(y);\n const conflicts = new Set([...valueIds(x)].filter((id) => yIds.has(id)));\n const X = new It(conflicts.size && !xLeft ? withoutValueRangeMetadata(x, conflicts) : x);\n const Y = new It(conflicts.size && xLeft ? withoutValueRangeMetadata(y, conflicts) : y);\n const decos = addedDecorations(y).map((d) => ({ ...d, pieces: [] as Zone[] }));\n const out: Act[] = [];\n let inPos = 0;\n let outPos = 0;\n while (X.hasNext() || Y.hasNext()) {\n if (X.peekType() === \"i\" && (xLeft || Y.peekType() !== \"i\")) {\n const a = X.next();\n if (Y.inZone()) {\n lost.push({ rule: \"R1\", side: \"insert\", len: a.len, ...(a.body?.dataStream !== undefined ? { text: a.body.dataStream } : {}) });\n continue;\n }\n if (a.valueRangeId && conflicts.has(a.valueRangeId) && !xLeft) continue;\n push(out, a);\n outPos += a.len;\n } else if (Y.peekType() === \"i\") {\n const b = Y.next();\n if (X.inZone()) {\n push(out, { t: \"d\", len: b.len, tz: [[0, b.len - 1]] });\n lost.push({ rule: \"R1\", side: \"delete\", len: b.len, ...(b.body?.dataStream !== undefined ? { text: b.body.dataStream } : {}) });\n inPos += b.len;\n continue;\n }\n if (b.valueRangeId && conflicts.has(b.valueRangeId) && xLeft) push(out, { t: \"d\", len: b.len, valueRangeId: b.valueRangeId });\n else {\n push(out, { t: \"r\", len: b.len });\n outPos += b.len;\n }\n inPos += b.len;\n } else {\n const len = Math.min(X.peekLength(), Y.peekLength());\n const a = X.next(len);\n const b = Y.next(len);\n if (b.t === \"d\") continue;\n if (a.t === \"d\") {\n push(out, a);\n inPos += len;\n continue;\n }\n for (const d of decos) {\n const s = Math.max(d.ds, inPos);\n const e = Math.min(d.de, inPos + len - 1);\n if (s <= e) d.pieces.push([outPos + s - inPos, outPos + e - inPos]);\n }\n let r: Act = a;\n if (a.body != null && b.body != null) {\n const { coverType, body } = transformBody(b, a, !xLeft);\n r = { ...a, t: \"r\", coverType, body };\n }\n // R2: a REPLACE retain re-asserts, whole, every decoration y added that it overlaps.\n if (r.coverType === 1 && r.body) {\n const keep: any[] = [];\n for (const d of decos) {\n if (!(d.de >= inPos && d.ds < inPos + len)) continue;\n const ahead: Zone[] = d.de >= inPos + len ? [[outPos + len + Math.max(d.ds, inPos + len) - (inPos + len), outPos + d.de - inPos]] : [];\n for (const [s, e] of [...d.pieces, ...ahead]) keep.push({ id: d.id, type: d.type, startIndex: s - outPos, endIndex: e - outPos });\n }\n if (keep.length) r = { ...r, body: { ...r.body, customDecorations: [...(r.body.customDecorations ?? []), ...keep] } };\n }\n push(out, r);\n inPos += len;\n outPos += len;\n }\n }\n return trimEnd(out);\n}\n\n// ── ot-json1 binding ─────────────────────────────────────────────────────────────────────────────────\n\n/** A Docs operation: an ot-json1 op over the whole Univer snapshot (what `rich-text-editing` carries as `actions`). */\nexport type DocsOp = unknown[] | null;\n\nexport interface DocsTransformResult {\n op: DocsOp;\n lost: DocsLost[];\n}\n\nlet sink: DocsLost[] | null = null;\nconst ours = {\n name: \"text-x\",\n uri: (TextX as unknown as { uri: string }).uri,\n apply: (doc: any, actions: any) => TextX.apply(doc, actions),\n compose: (a: any, b: any) => TextX.compose(a, b),\n isNoop: (a: any) => TextX.isNoop(a),\n invert: (a: any) => TextX.invert(a),\n makeInvertible: (a: any, doc: any) => TextX.makeInvertible(a, doc),\n transform: (x: any, y: any, side: \"left\" | \"right\") => transformTextX(x, y, side, sink ?? []),\n};\n\n/**\n * `T(x, y, side)` for Docs: ot-json1 `transformNoConflict` (never throws on DROP_COLLISION / RM_UNEXPECTED_CONTENT /\n * BLACKHOLE, §3) with our text-x transform registered only for the duration of one call, so Univer's own apply is\n * untouched even when the bundler shares one ot-json1 instance with `@univerjs/core`. R6 runs on the result.\n */\nexport function transformDocsOp(x: DocsOp, y: DocsOp, side: \"left\" | \"right\"): DocsTransformResult {\n if (x == null) return { op: null, lost: [] };\n if (y == null) return { op: x, lost: [] };\n const lost: DocsLost[] = [];\n sink = lost;\n json1.type.registerSubtype(ours as any);\n try {\n const op = json1.type.transformNoConflict(normalizeDocsOp(x) as any, normalizeDocsOp(y) as any, side) as DocsOp;\n return { op: dropEmptyStyleRetains(op), lost };\n } finally {\n json1.type.registerSubtype(TextX as any);\n sink = null;\n }\n}\n\n/** `a` then `b` as one op (TextX is the subtype every reader composes with). */\nexport function composeDocsOps(a: DocsOp, b: DocsOp): DocsOp {\n if (a == null) return b;\n if (b == null) return a;\n json1.type.registerSubtype(TextX as any);\n return json1.type.compose(a as any, b as any) as DocsOp;\n}\n\nexport function isNoopDocsOp(op: DocsOp): boolean {\n return op == null || (Array.isArray(op) && op.length === 0) || json1.type.isNoop(op as any);\n}\n\n/** Apply an op to a plain snapshot (tests, the fold). Univer's own JSONX, so TextX applies as the editor applies. */\nexport function applyDocsOp<T>(doc: T, op: DocsOp): T {\n if (isNoopDocsOp(op)) return doc;\n return JSONX.apply(structuredClone(doc) as any, op as any) as T;\n}\n\n/** The inverse of `op` against the state it applied to. JSONX.invertWithDoc MUTATES its op: invert a copy (C0). */\nexport function invertDocsOp(op: DocsOp, preDoc: unknown): DocsOp {\n if (isNoopDocsOp(op)) return null;\n return JSONX.invertWithDoc(structuredClone(op) as any, preDoc as any) as DocsOp;\n}\n\n/** Part of `proto` (§6.4): Univer 1.0.4 + this transformer, rules R1–R6. */\nexport const DOCS_TRANSFORM_VERSION = \"univer-1.0.4+docs-ot-r6\";\n","/**\n * The canonical Docs state hash (COLLAB-DESIGN §7.2; C0 item 6, `spikes/c0-collab/lib.mjs`).\n *\n * SHA-256 of the canonical snapshot: keys sorted, empty values dropped, the unit id and seat-local fields\n * removed (revision counter, collab stamps, layout state, selections), adjacent equal text runs merged, split\n * pieces of one custom range or decoration folded, and `paragraphId` dropped (Univer's TextX.apply mints a\n * random one per seat, C0 surprise 3). Header, footer and note bodies get the same rules.\n *\n * Two seats with equal content hash equal; one character more hashes differently. Browser and Node: the\n * digest is Web Crypto's.\n */\n/* eslint-disable @typescript-eslint/no-explicit-any -- snapshot JSON */\n\n/** Never content: the collab stamps, revision counters, seat-local view state. */\nexport const DOC_LOCAL_KEYS = [\"rev\", \"__matrxCollabCovered\", \"__collab\", \"disabled\", \"layoutState\", \"textRanges\", \"selections\"];\n\nfunction sortDeep(v: any): any {\n if (Array.isArray(v)) return v.map(sortDeep);\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v).sort()) {\n const x = v[k];\n if (x === undefined || x === null) continue;\n if (Array.isArray(x) && x.length === 0) continue;\n if (x && typeof x === \"object\" && !Array.isArray(x) && Object.keys(x).length === 0) continue;\n out[k] = sortDeep(x);\n }\n return out;\n }\n return v;\n}\n\nconst sameTs = (a: unknown, b: unknown) => JSON.stringify(sortDeep(a ?? {})) === JSON.stringify(sortDeep(b ?? {}));\n\nfunction canonicalRuns(runs: any[] | undefined): any[] {\n const out: any[] = [];\n for (const r of [...(runs ?? [])].sort((x, y) => x.st - y.st)) {\n if (r.ed <= r.st) continue;\n const ts = sortDeep(r.ts ?? {});\n if (Object.keys(ts).length === 0) continue;\n const last = out[out.length - 1];\n if (last && last.ed === r.st && sameTs(last.ts, ts)) last.ed = r.ed;\n else out.push({ st: r.st, ed: r.ed, ts });\n }\n return out;\n}\n\nfunction foldPieces(items: any[] | undefined, keyOf: (it: any) => string): any[] {\n const groups = new Map<string, any[]>();\n for (const it of items ?? []) {\n const k = keyOf(it);\n const g = groups.get(k) ?? [];\n g.push(it);\n groups.set(k, g);\n }\n const out: any[] = [];\n for (const list of groups.values()) {\n list.sort((a, b) => a.startIndex - b.startIndex);\n let cur: any = null;\n for (const it of list) {\n if (cur && cur.endIndex + 1 >= it.startIndex) cur.endIndex = Math.max(cur.endIndex, it.endIndex);\n else {\n if (cur) out.push(cur);\n cur = { ...it };\n }\n }\n if (cur) out.push(cur);\n }\n return out;\n}\nconst rootId = (id: unknown) => String(id).split(\"$\")[0];\n\nfunction canonicalBody(body: any): any {\n if (!body) return body;\n const b = { ...body };\n b.textRuns = canonicalRuns(b.textRuns);\n if (Array.isArray(b.paragraphs)) b.paragraphs = b.paragraphs.map(({ paragraphId: _p, ...p }: any) => p);\n b.customRanges = foldPieces(b.customRanges, (r) => JSON.stringify([rootId(r.rangeId), r.rangeType, sortDeep(r.properties ?? {})])).map((r) => ({\n ...r,\n rangeId: rootId(r.rangeId),\n }));\n b.customDecorations = foldPieces(b.customDecorations, (d) => JSON.stringify([d.id, d.type]));\n for (const k of [\"paragraphs\", \"customRanges\", \"customBlocks\", \"tables\", \"sectionBreaks\", \"customDecorations\"]) {\n if (Array.isArray(b[k])) {\n b[k] = [...b[k]].sort(\n (x: any, y: any) =>\n (x.startIndex ?? 0) - (y.startIndex ?? 0) ||\n String(x.rangeId ?? x.blockId ?? x.tableId ?? \"\").localeCompare(String(y.rangeId ?? y.blockId ?? y.tableId ?? \"\")),\n );\n }\n }\n return b;\n}\n\n/** The canonical Docs snapshot: content only, keys sorted, runs normalized, local fields removed. */\nexport function canonicalDocsSnapshot(snapshot: unknown): unknown {\n const s = structuredClone(snapshot ?? {}) as any;\n delete s.id;\n for (const k of DOC_LOCAL_KEYS) delete s[k];\n s.body = canonicalBody(s.body);\n for (const seg of [\"headers\", \"footers\", \"notes\"]) {\n if (!s[seg]) continue;\n for (const id of Object.keys(s[seg])) s[seg][id] = { ...s[seg][id], body: canonicalBody(s[seg][id].body) };\n }\n return sortDeep(s);\n}\n\n/** The canonical form as the string the hash digests (tests compare these directly). */\nexport const canonicalDocsString = (snapshot: unknown): string => JSON.stringify(canonicalDocsSnapshot(snapshot));\n\n/** SHA-256 hex of the canonical snapshot (§7.2). */\nexport async function docsStateHash(snapshot: unknown): Promise<string> {\n const bytes = new TextEncoder().encode(canonicalDocsString(snapshot));\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/**\n * Ids every seat agrees on for a snapshot that lacks them (C0 surprise 5): a raw snapshot (an import, markdown)\n * loaded on two seats would otherwise get two random `sectionId`s / `paragraphId`s. Missing ids become\n * positional ones; ids already present are kept. Applied to every snapshot a room loads.\n */\nexport function stampDeterministicIds<T>(snapshot: T): T {\n const s = structuredClone(snapshot) as any;\n const stamp = (body: any, scope: string) => {\n if (!body) return;\n for (const p of body.paragraphs ?? []) if (!p.paragraphId) p.paragraphId = `p_${scope}${p.startIndex}`;\n for (const sb of body.sectionBreaks ?? []) if (!sb.sectionId) sb.sectionId = `s_${scope}${sb.startIndex}`;\n };\n stamp(s?.body, \"\");\n for (const seg of [\"headers\", \"footers\", \"notes\"]) for (const id of Object.keys(s?.[seg] ?? {})) stamp(s[seg][id]?.body, `${id}_`);\n return s as T;\n}\n","/**\n * The Docs co-editing room on the ordered log (COLLAB-DESIGN §6, unit C3): the `OpDocumentAdapter` for\n * `openOpSession` over a document's editors, plus saves, restore and the saver choice.\n *\n * - CAPTURE (§6.3). The document model hands over every local `doc.mutation.rich-text-editing` with the applied\n * params (the handler's own rewrite, C0 surprise 6), the pre-state cloned in `beforeCommandExecuted`, and the\n * outermost command id. `onlyLocal` / `fromCollab` never arrive here (the model filters them). Only `segmentId`\n * and `actions` travel; the inverse is computed from the APPLIED actions on a COPY (`invertWithDoc` mutates its\n * op). Each mutation goes to the session as it happens, so a remote apply can never land between a local\n * mutation and its hand-over; the command id rides along as the change's label.\n * - APPLY (§6.7). `syncExecuteCommand(id, { unitId: own, segmentId, actions, textRanges: null,\n * noNeedSetTextRange: true }, { onlyLocal: true, fromCollab: true })` through the model (every view of the\n * document in this tab). A throw, `false`, or actions the handler emptied fail the apply: the session rebuilds,\n * never skips. While an IME composition is open, remote applies QUEUE (acks continue); a local op captured\n * meanwhile is rebased over the queue (`L' = T(L, Q, 'left')`, `Q' = T(Q, L, 'right')`), and the queue drains\n * at `compositionend`.\n * - UNDO (§6.9). Each applied remote op rebases every stored undo and redo item of this seat\n * (`T(item, R1, 'left')`); `textRanges` and `layoutState` are stripped from rebased items; an item whose rebase\n * is a barrier, throws or comes back empty is dropped. Undo therefore only ever reverts this person's changes.\n * - SAVES (§7.3). Only a quiet seat whose hash matches every peer at its rev saves, and only the chosen saver\n * (the lowest client id among seats publishing a quiet hash) saves on its own; a manual save always tries.\n * - RESTORE (§20). A whole-document replace goes through `collab_replace`: the snapshot is loaded into this seat's\n * editor first, so the stored snapshot and its hash are the Univer-normalised form every seat will load.\n */\nimport type {\n OpDocumentAdapter,\n OpPresence,\n OpSession,\n OpSessionIncident,\n OpSessionNotice,\n OpSessionStatus,\n OpTransport,\n} from \"@ai-matrx/data/realtime/collab\";\nimport { isOpBarrier, openOpSession } from \"@ai-matrx/data/realtime/collab\";\n\nimport { canonicalDocsString, docsStateHash, stampDeterministicIds } from \"./state-hash\";\nimport {\n composeDocsOps,\n DOCS_TRANSFORM_VERSION,\n invertDocsOp,\n isNoopDocsOp,\n normalizeDocsOp,\n transformDocsOp,\n type DocsOp,\n} from \"./transform\";\n\nexport const RICH_TEXT_EDITING = \"doc.mutation.rich-text-editing\";\n\n/**\n * The room's protocol (§6.4): Univer 1.0.4 + transformer `DOCS_TRANSFORM_VERSION`. Any Univer or transformer\n * change raises it; a room at another proto opens read-only for this build.\n */\nexport const DOCS_COLLAB_PROTO = 1;\n\n/** One local mutation as the document model hands it over. */\nexport interface DocsLocalMutation {\n id: string;\n params: unknown;\n /** The document before this mutation (cloned in `beforeCommandExecuted`), when the view could supply it. */\n pre: unknown | null;\n /** The outermost command this mutation belongs to (the depth tracker with its try/finally guard). */\n cmd: string | null;\n /** Whether the mutation changes what a snapshot stores. */\n content: boolean;\n}\n\n/** What the document model lends the room (implemented by `DocumentModel`). */\nexport interface DocsOtPort {\n onLocal(listener: (m: DocsLocalMutation) => void): () => void;\n /** Apply one committed mutation to every view of the document; throws when any view could not. */\n applyRemote(id: string, params: Record<string, unknown>): void;\n /** The document as the editor holds it now (`doc.save()`), or null when no view is mounted. */\n snapshot(): unknown | null;\n /** Replace the document in every view (and the kept editor). */\n load(snapshot: unknown): void;\n /** Univer's undo/redo service of each mounted view and the unit it holds. */\n undoTargets(): Array<{ service: unknown; unitId: string }>;\n /** Ask for a save (the record's one coalesced save). */\n markDirty(): void;\n /** This seat's text selection in the first view (body offsets), for presence (C8). Absent when no view can say. */\n selection?(): Array<{ startOffset: number; endOffset: number; segmentId?: string }> | null;\n}\n\nexport type DocsOtNotice =\n | OpSessionNotice<DocsOp>\n | { kind: \"not_shared\"; mutationId: string }\n | { kind: \"not_live\" };\n\nexport interface OpenDocsOtRoomOptions {\n port: DocsOtPort;\n transport: OpTransport;\n clientId: string;\n presence?: OpPresence;\n /** `collab_replace` for this room (restore, whole import). */\n replace: (req: { snapshot: unknown; stateHash: string; clientId: string }) => Promise<{ rev: number; ref: string }>;\n onNotice?: (n: DocsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n /** Watch IME composition here (default: `document`). */\n compositionTarget?: Pick<Document, \"addEventListener\" | \"removeEventListener\"> | null;\n}\n\nexport interface DocsOtRoom {\n session: OpSession<DocsOp>;\n /** The record's save: a checkpoint at a quiet point (§7.3). False when this seat does not write now. */\n write(reason: \"manual\" | string): Promise<boolean>;\n /** Restore / whole import through `collab_replace` (§20). */\n replace(snapshot: unknown): Promise<void>;\n /** This seat is the one that saves on its own. */\n isSaver(): boolean;\n stop(): void;\n}\n\n// ── helpers ───────────────────────────────────────────────────────────────────────────────────────────\n\n/**\n * Keys in one canonical order. The log stores groups as jsonb, which returns object keys in its own order, so an\n * op read back from the door is the same op with its keys moved. The session compares wire forms (its ack check)\n * through `encode`, so `encode` must not depend on key order or every acknowledgement looks like a mismatch.\n */\nexport function canonicalKeys<T>(v: T): T {\n if (Array.isArray(v)) return v.map(canonicalKeys) as T;\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v as Record<string, unknown>).sort()) out[k] = canonicalKeys((v as Record<string, unknown>)[k]);\n return out as T;\n }\n return v;\n}\n\n/** Top-level keys an op descends into (`[\"body\", …]` or `[[\"body\", …], [\"headers\", …]]`). */\nfunction branches(op: DocsOp): unknown[][] {\n if (!Array.isArray(op) || op.length === 0) return [];\n return Array.isArray(op[0]) ? (op as unknown[][]) : [op as unknown[]];\n}\nconst touchesPageSetup = (op: DocsOp) => branches(op).some((b) => b[0] === \"documentStyle\");\n\n/** The segment a branch edits: `[\"headers\", id, \"body\", …]` → id; the body → \"\". */\nfunction segmentOf(branch: unknown[]): string {\n return (branch[0] === \"headers\" || branch[0] === \"footers\") && typeof branch[1] === \"string\" ? branch[1] : \"\";\n}\n\ninterface UndoItem {\n unitID?: string;\n undoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n redoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n}\ninterface UndoServiceInternals {\n _undoStacks?: Map<string, UndoItem[]>;\n _redoStacks?: Map<string, UndoItem[]>;\n}\n\n/** The Univer 1.0.4 fields the undo rebase reads; a forcing test fails if they move (Univer is pinned). */\nexport function undoStacksOf(service: unknown): { undo: Map<string, UndoItem[]>; redo: Map<string, UndoItem[]> } | null {\n const s = service as UndoServiceInternals | null;\n if (!s || !(s._undoStacks instanceof Map) || !(s._redoStacks instanceof Map)) return null;\n return { undo: s._undoStacks, redo: s._redoStacks };\n}\n\n/** §6.9: rebase one stack over a remote op; items that cannot follow are dropped. Returns how many were dropped. */\nexport function rebaseUndoStack(items: UndoItem[], remote: DocsOp): number {\n let dropped = 0;\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i]!;\n let ok = true;\n for (const list of [item.undoMutations, item.redoMutations]) {\n for (const m of list ?? []) {\n if (m.id !== RICH_TEXT_EDITING) continue;\n try {\n if (touchesPageSetup(m.params.actions as DocsOp) && touchesPageSetup(remote)) throw new Error(\"page setup\");\n const r = transformDocsOp(m.params.actions as DocsOp, remote, \"left\");\n if (isNoopDocsOp(r.op)) ok = false;\n else {\n m.params = { ...m.params, actions: r.op };\n delete m.params.textRanges;\n delete m.params.layoutState;\n }\n } catch {\n ok = false;\n }\n }\n }\n if (!ok) {\n items.splice(i, 1);\n dropped++;\n }\n }\n return dropped;\n}\n\n// ── the room ──────────────────────────────────────────────────────────────────────────────────────────\n\nexport function openDocsOtRoom(o: OpenDocsOtRoomOptions): DocsOtRoom {\n const { port } = o;\n let session: OpSession<DocsOp> | null = null;\n let composing = false;\n /** Remote ops held while an IME composition is open, already rebased over local composition ops. */\n let queue: DocsOp[] = [];\n const drainWaiters: Array<() => void> = [];\n\n const notice = (n: DocsOtNotice) => {\n try {\n o.onNotice?.(n);\n } catch (err) {\n console.warn(\"[docs-ot] notice handler failed\", err);\n }\n };\n\n const applyNow = (op: DocsOp) => {\n for (const b of branches(op)) {\n const params: Record<string, unknown> = { segmentId: segmentOf(b), actions: b };\n port.applyRemote(RICH_TEXT_EDITING, params);\n }\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n if (!stacks) continue;\n for (const m of [stacks.undo, stacks.redo]) {\n const items = m.get(t.unitId);\n if (items?.length) rebaseUndoStack(items, op);\n }\n }\n port.markDirty();\n };\n\n const drain = () => {\n const held = queue;\n queue = [];\n try {\n for (const op of held) applyNow(op);\n } catch (err) {\n console.warn(\"[docs-ot] a held remote edit failed after composition; reloading this seat\", err);\n session?.rebuild(\"ime_drain_failed\");\n }\n for (const w of drainWaiters.splice(0)) w();\n };\n\n const adapter: OpDocumentAdapter<DocsOp> = {\n version: DOCS_TRANSFORM_VERSION,\n transform(x, y, side) {\n // §18: page setup replaces section breaks by array index; a barrier against every family, itself included.\n if (x != null && y != null && (touchesPageSetup(x) || touchesPageSetup(y))) return { barrier: true, reason: \"page_setup\" };\n const r = transformDocsOp(x, y, side);\n return { op: isNoopDocsOp(r.op) ? null : r.op, lost: r.lost };\n },\n compose: (a, b) => composeDocsOps(a, b),\n isNoop: (op) => isNoopDocsOp(op),\n encode: (op) => [{ cmd: \"docs.edit\", mutations: [{ id: RICH_TEXT_EDITING, params: { segmentId: \"\", actions: canonicalKeys(op) } }] }],\n decode(groups) {\n let op: DocsOp = null;\n for (const g of groups) {\n for (const m of g.mutations) {\n if (m.id !== RICH_TEXT_EDITING) throw new Error(`a Docs room cannot apply ${m.id}`);\n op = composeDocsOps(op, (m.params as { actions?: DocsOp }).actions ?? null);\n }\n }\n return op;\n },\n apply(op) {\n if (isNoopDocsOp(op)) return true;\n if (composing) {\n queue.push(op);\n return true;\n }\n applyNow(op);\n return true;\n },\n async load(snapshot) {\n const next = stampDeterministicIds(snapshot ?? {});\n queue = [];\n const current = port.snapshot();\n if (current && canonicalDocsString(current) === canonicalDocsString(next)) return;\n port.load(next);\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n stacks?.undo.delete(t.unitId);\n stacks?.redo.delete(t.unitId);\n }\n },\n snapshot: () => port.snapshot(),\n async hash() {\n if (composing || queue.length) {\n await new Promise<void>((resolve) => {\n drainWaiters.push(resolve);\n setTimeout(resolve, 5000);\n });\n }\n return docsStateHash(port.snapshot());\n },\n };\n\n const onLocal = (m: DocsLocalMutation) => {\n if (!session) return;\n if (m.id !== RICH_TEXT_EDITING) {\n if (!m.content) return;\n // §6.3: an id without an allowlist never travels. Say so and put this seat back on the shared document.\n notice({ kind: \"not_shared\", mutationId: m.id });\n session.rebuild(`not_shared:${m.id}`);\n return;\n }\n const p = (m.params ?? {}) as { actions?: DocsOp };\n const applied = p.actions ?? null;\n if (isNoopDocsOp(applied)) return;\n let op: DocsOp = normalizeDocsOp(structuredClone(applied));\n let inverse: DocsOp | undefined;\n try {\n inverse = m.pre != null ? invertDocsOp(applied, m.pre) : undefined;\n } catch {\n inverse = undefined;\n }\n if (queue.length) {\n // the editor does not hold the queued remote ops yet: rebase this edit over them, and them over it\n inverse = undefined;\n const next: DocsOp[] = [];\n for (const q of queue) {\n const l2 = adapter.transform(op, q, \"left\");\n const q2 = adapter.transform(q, op, \"right\");\n if (isOpBarrier(l2) || isOpBarrier(q2)) {\n queue = [];\n session.rebuild(\"ime_barrier\");\n return;\n }\n op = l2.op;\n next.push(q2.op);\n }\n queue = next.filter((q) => !isNoopDocsOp(q));\n if (isNoopDocsOp(op)) return;\n }\n if (!session.local(op, { ...(inverse !== undefined ? { inverse } : {}), label: m.cmd ?? RICH_TEXT_EDITING })) notice({ kind: \"not_live\" });\n };\n\n const unsubLocal = port.onLocal(onLocal);\n const target = o.compositionTarget === undefined ? (typeof document !== \"undefined\" ? document : null) : o.compositionTarget;\n const onStart = () => {\n composing = true;\n };\n const onEnd = () => {\n composing = false;\n // Univer emits the composition's last mutation in the same task as compositionend: drain after it\n setTimeout(() => {\n if (!composing) drain();\n }, 0);\n };\n target?.addEventListener(\"compositionstart\", onStart, true);\n target?.addEventListener(\"compositionend\", onEnd, true);\n\n session = openOpSession<DocsOp>({\n transport: o.transport,\n adapter,\n proto: DOCS_COLLAB_PROTO,\n clientId: o.clientId,\n ...(o.presence ? { presence: o.presence } : {}),\n onNotice: (n) => notice(n),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n\n const isSaver = () => {\n if (!o.presence) return true;\n return o.presence.peers().every((p) => p.clientId === o.clientId || p.clientId > o.clientId);\n };\n\n return {\n session,\n isSaver,\n async write(reason) {\n if (!session) return false;\n if (reason !== \"manual\" && !isSaver()) return false;\n const out = await session.save();\n if (out.saved) return true;\n if (out.reason === \"not_quiet\" || out.reason === \"changed\") setTimeout(() => port.markDirty(), 1500);\n return false;\n },\n async replace(snapshot) {\n port.load(stampDeterministicIds(snapshot));\n const loaded = port.snapshot();\n if (!loaded) throw new Error(\"The document is not open in this tab.\");\n const stateHash = await docsStateHash(loaded);\n await o.replace({ snapshot: loaded, stateHash, clientId: o.clientId });\n },\n stop() {\n unsubLocal();\n target?.removeEventListener(\"compositionstart\", onStart, true);\n target?.removeEventListener(\"compositionend\", onEnd, true);\n session?.close();\n },\n };\n}\n","/**\n * A cloud document's co-editing room on the ordered log (COLLAB-DESIGN §6, §19; unit C3), assembled from the\n * configured docs host: the `udt_document_snapshots` store, the C1 doors over the host's Supabase client, the\n * private `collab:<id>` frames on the app's one realtime manager, and Yjs awareness for presence only (who is\n * here plus `quiet_hash`; no content travels there).\n *\n * The FLIP is per room (§12.2): a document whose room exists always opens on the ordered log; a document with\n * no room opens one only when the host's `collab.ot_rooms` knob says so (`all`, or `new` for a document never\n * saved). Everything else keeps the 0.6 relay. The host reads the knob (host config lives in the app).\n */\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport {\n awarenessOpPresence,\n collabReplace,\n collabRoomExists,\n SupabaseYjsProvider,\n supabaseOpTransport,\n type AwarenessState,\n type CollabRpcClient,\n type OpSessionIncident,\n type OpSessionStatus,\n} from \"@ai-matrx/data/realtime/collab\";\n\nimport { openDocsOtRoom, RICH_TEXT_EDITING, type DocsOtNotice } from \"../univer/collab/docs-ot/room\";\nimport type { DocsOtPort } from \"../univer/collab/docs-ot/room\";\nimport type { DocumentAwareness, DocumentOtFactory } from \"./document-model\";\nimport { CARET_HEARTBEAT_MS, publishedCaretFromSelection, RemoteCaretBook } from \"./remote-carets\";\nimport { getLatestDocumentSnapshot, saveDocumentSnapshot } from \"./document-service\";\nimport { getDocsHost } from \"./ports\";\n\n/** `collab.ot_rooms` (§12.2): which documents without a room open one. */\nexport type OtRoomsKnob = \"off\" | \"new\" | \"all\";\n\nconst db = () => getDocsHost().getSupabase() as unknown as CollabRpcClient;\n\nasync function loadSnapshotRow(documentId: string, ref: string): Promise<unknown> {\n if (ref === \"none\") {\n const res = await getLatestDocumentSnapshot(documentId);\n if (!res.success) throw new Error(res.error);\n return res.data?.snapshot ?? null;\n }\n const { data, error } = await getDocsHost()\n .getSupabase()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"snapshot\")\n .eq(\"id\", ref)\n .maybeSingle();\n if (error) throw new Error(error.message);\n if (!data) throw new Error(`The saved version ${ref} of this document is missing.`);\n return (data as { snapshot?: unknown }).snapshot ?? null;\n}\n\n/** Whether this document opens on the ordered log: its room exists, or the knob opens one. */\nexport async function documentUsesOrderedRoom(documentId: string, knob: OtRoomsKnob, isNewDocument: () => Promise<boolean>): Promise<boolean> {\n try {\n if (await collabRoomExists(db(), documentId)) return true;\n } catch (err) {\n console.warn(\"[document] could not ask whether this document has a co-editing room; opening the relay room\", err);\n return false;\n }\n if (knob === \"all\") return true;\n if (knob === \"new\") return isNewDocument();\n return false;\n}\n\nfunction pickColor(uid: string): string {\n const palette = [\"#ef4444\", \"#f59e0b\", \"#10b981\", \"#3b82f6\", \"#8b5cf6\", \"#ec4899\", \"#14b8a6\", \"#f97316\"];\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return palette[Math.abs(h) % palette.length] ?? \"#ec4899\";\n}\n\nexport interface DocumentOtFactoryOptions {\n documentId: string;\n uid: string;\n /** One per open tab; never reused. */\n clientId: string;\n displayName?: string;\n readAntiEntropyIntervalMs?: () => Promise<number>;\n onNotice?: (n: DocsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n}\n\n/** The `DocumentModel.startOtRoom` factory for one document. */\nexport function documentOtFactory(o: DocumentOtFactoryOptions): DocumentOtFactory {\n return async (basePort, onAwareness) => {\n // §7.4 / C0 surprise 5: a room's first checkpoint must be a real, Univer-normalised snapshot. A document never\n // saved gets this seat's mounted document saved first, so every seat boots from the same ids.\n const latest = await getLatestDocumentSnapshot(o.documentId);\n if (!latest.success) throw new Error(latest.error);\n if (!latest.data) {\n const mounted = basePort.snapshot();\n if (mounted) {\n const saved = await saveDocumentSnapshot({ documentId: o.documentId, snapshot: mounted, origin: \"autosave\" });\n if (!saved.success) throw new Error(saved.error);\n }\n }\n\n const doc = new Y.Doc();\n const awareness = new Awareness(doc);\n awareness.setLocalState({ uid: o.uid, clientId: o.clientId, name: o.displayName ?? o.uid.slice(0, 8), color: pickColor(o.uid), ts: Date.now() });\n\n // C8: other seats' carets, moved through every body edit this seat applies (remote) or makes (local).\n const carets = new RemoteCaretBook(awareness.clientID);\n const emit = () =>\n onAwareness({ states: new Map(awareness.getStates() as Map<number, AwarenessState>), selfUid: o.uid, carets: carets.list() } satisfies DocumentAwareness);\n const publishAwareness = () => {\n carets.ingest(awareness.getStates());\n emit();\n };\n const bodyActions = (params: unknown): unknown => {\n const p = params as { segmentId?: unknown; actions?: unknown } | null;\n return p && !p.segmentId ? p.actions : undefined;\n };\n const port: DocsOtPort = {\n ...basePort,\n applyRemote(id, params) {\n basePort.applyRemote(id, params);\n const a = bodyActions(params);\n if (a !== undefined && carets.shiftThrough(a)) emit();\n },\n onLocal: (listener) =>\n basePort.onLocal((m) => {\n if (m.id === RICH_TEXT_EDITING) {\n const a = bodyActions(m.params);\n if (a !== undefined && carets.shiftThrough(a)) emit();\n }\n listener(m);\n }),\n };\n awareness.on(\"change\", publishAwareness);\n const provider = new SupabaseYjsProvider({\n workbookId: o.documentId,\n channelPrefix: \"document\",\n clientId: o.clientId,\n doc,\n awareness,\n ...(o.readAntiEntropyIntervalMs ? { readAntiEntropyIntervalMs: o.readAntiEntropyIntervalMs } : {}),\n });\n await provider.connect();\n publishAwareness();\n\n const client = db();\n const room = openDocsOtRoom({\n port,\n clientId: o.clientId,\n presence: awarenessOpPresence(awareness),\n transport: supabaseOpTransport({\n client,\n roomId: o.documentId,\n kind: \"univer_doc\",\n store: {\n loadSnapshot: (ref) => loadSnapshotRow(o.documentId, ref),\n async writeSnapshot(snapshot) {\n const res = await saveDocumentSnapshot({ documentId: o.documentId, snapshot, origin: \"autosave\" });\n if (!res.success) throw new Error(res.error);\n return res.data.id;\n },\n },\n }),\n replace: ({ snapshot, stateHash, clientId }) => collabReplace(client, { roomId: o.documentId, snapshot, stateHash, origin: \"restore\", clientId }),\n ...(o.onNotice ? { onNotice: o.onNotice } : {}),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n await room.session.ready;\n\n // C8: publish this seat's caret when it changes, and every heartbeat so a race with an op frame heals.\n let lastKey = \"\";\n let lastAt = 0;\n const publishCaret = () => {\n if (typeof document !== \"undefined\" && document.hidden) return;\n let sel: ReturnType<NonNullable<DocsOtPort[\"selection\"]>> = null;\n try {\n sel = port.selection?.() ?? null;\n } catch {\n sel = null;\n }\n const t = Date.now();\n const c = publishedCaretFromSelection(sel, t);\n const key = c ? JSON.stringify(c.ranges) : \"\";\n if (key === lastKey && (key === \"\" || t - lastAt < CARET_HEARTBEAT_MS)) return;\n lastKey = key;\n lastAt = t;\n awareness.setLocalStateField(\"caret\", c);\n };\n const caretTimer = setInterval(publishCaret, 120);\n\n return {\n isSaver: () => room.isSaver(),\n write: (reason) => room.write(reason),\n replace: (snapshot) => room.replace(snapshot),\n stop: () => {\n clearInterval(caretTimer);\n room.stop();\n awareness.off(\"change\", publishAwareness);\n provider.disconnect();\n awareness.destroy();\n doc.destroy();\n },\n };\n };\n}\n","/**\n * THE DOCUMENT MODEL — the engine of one cloud document per tab.\n *\n * Before this, the document lived only inside each `DocumentEditor`'s Univer\n * instance. A remount (a board tile waking, a tile removed and undone, a route\n * change and back) rebuilt the editor from the SERVER copy, so whatever the\n * last save had not carried yet was gone; two mounts of one document were two\n * editors, each saving full snapshots of its own copy (last write wins), each\n * with its own realtime channel and its own collab room.\n *\n * The document is a record on THE one working-copy primitive\n * (`@ai-matrx/kit/working-copy`, kind `udt_document`,\n * `./documentModels.ts`): its save status, dirty and view count are Redux state\n * (`workingCopies[\"udt_document:<id>\"]`), its one coalesced save is the kind's.\n * What Redux cannot hold — Univer's body — is this engine, registered on the\n * record's session under the same key:\n *\n * - BODY. Every local mutation in one view is replayed into every other view\n * of the document (the same mutation stream collab sends between machines),\n * so two views show one document. A new view boots from the engine's latest\n * state — a live view's snapshot, or the snapshot the last view left behind\n * — never the stale server copy while the record's session is alive.\n * - SIDE EFFECTS, ONCE. The snapshot realtime channel, the collab room, and\n * the pagehide / visibility / beforeunload flush are opened once per\n * document and closed once.\n * - THE EDITOR ITSELF, KEPT. Univer keeps its undo / redo history inside the\n * editor instance, so rebuilding the editor on a remount threw the history\n * away. When the last view leaves, its editor (a Univer instance with its\n * own DOM host) is parked here — off the page, alive — and the next view of\n * the document RE-ATTACHES that same instance to its own container instead\n * of booting a new one (`parkEditor` / `takeParkedEditor`). Undo and redo\n * therefore work across hide / show, a remount and a removed tile undone,\n * for as long as the record's session is warm; `close()` disposes it.\n */\n\nimport type { ICommandInfo, IDocumentData } from \"@univerjs/core\";\nimport { TextX } from \"@univerjs/core\";\nimport type { CommitReason, WorkingCopyHandle } from \"@ai-matrx/kit/working-copy\";\nimport type { AwarenessState } from \"@ai-matrx/data/realtime/collab\";\nimport { isSnapshotMutation } from \"../univer\";\nimport { stampCovered, takeCovered } from \"../univer/collab/covered\";\nimport type {\n CollabMutationInfo,\n CommandServiceLike,\n} from \"../univer/collab\";\nimport type { DocsLocalMutation, DocsOtPort } from \"../univer/collab/docs-ot/room\";\nimport type { RemoteCaret } from \"./remote-carets\";\n\n/** Univer's command service as a view lends it: the collab pair plus the command hooks capture groups by. */\ntype ViewCommandService = CommandServiceLike & {\n beforeCommandExecuted?: (listener: (info: { id: string; type?: number; params?: unknown }) => void) => { dispose: () => void };\n onCommandExecuted?: (listener: (info: { id: string; type?: number; params?: unknown }) => void) => { dispose: () => void };\n executeCommand?: (id: string, params?: unknown, options?: unknown) => Promise<unknown>;\n};\n\nconst RICH_TEXT_EDITING_ID = \"doc.mutation.rich-text-editing\";\n/** Univer's CommandType.COMMAND. */\nconst COMMAND_TYPE = 0;\nconst DEPTH_GUARDED = Symbol.for(\"ai-matrx.office.docs.command-depth-guard\");\n\n/** Debounce from the last edit to the save. */\nexport const DOCUMENT_SAVE_DELAY_MS = 2500;\n\nexport type DocumentSnapshotData = Partial<IDocumentData>;\n\n/** What a view lends the model while it is mounted. */\nexport interface DocumentViewPort {\n /** Univer's command service for this view's instance. */\n commandService: CommandServiceLike;\n /** The live document of this view (`doc.save()`), or null if it has none. */\n snapshot: () => DocumentSnapshotData | null;\n /** Replace the whole document in this view (a collaborator's snapshot). */\n remount: (snapshot: DocumentSnapshotData) => void;\n /** Whether this view may change the document (read at edit time). */\n editable: () => boolean;\n /**\n * This view's text selection (body offsets), so a collaborator's edit moves the caret with the characters\n * (§6.8). Without it a remote apply leaves the caret at its old offset and the next keystrokes land elsewhere.\n */\n selection?: {\n get: () => Array<{ startOffset: number; endOffset: number; segmentId?: string }> | null;\n set: (ranges: Array<{ startOffset: number; endOffset: number }>) => void;\n };\n /** Univer's undo/redo service of this view's instance (the co-editing room rebases its items, §6.9). */\n undoRedo?: () => unknown;\n /**\n * The Univer unit id of this view's mounted document. Every seat mounts its own unit, so a\n * mutation carries the SENDER's id and must be re-addressed to this view's unit before it is\n * applied. Falls back to the id of `snapshot()` when a view does not state it.\n */\n unitId?: () => string | null;\n}\n\n/** Everything the engine reaches outside itself — injected so it is testable. */\nexport interface DocumentModelDeps {\n /** The newest stored snapshot (its row id + body), or null for a document never saved. */\n loadLatest: (documentId: string) => Promise<{ id: string; snapshot: DocumentSnapshotData } | null>;\n save: (input: {\n documentId: string;\n snapshot: DocumentSnapshotData;\n origin: \"autosave\" | \"manual\";\n }) => Promise<{ id: string; createdBy: string | null }>;\n onSaved?: (documentId: string, origin: \"autosave\" | \"manual\") => void;\n /** Window-level listeners (pagehide, visibilitychange, beforeunload). */\n listenToPage?: (handlers: { flush: () => void; hasUnsaved: () => boolean }) => () => void;\n /** A mutation could not be applied to a view: the app says so (a notice); the model re-syncs from the saved version. */\n onApplyFailed?: (documentId: string, mutationId: string, error: unknown) => void;\n}\n\ninterface AttachedView {\n id: number;\n port: DocumentViewPort;\n dispose: () => void;\n /** The outermost commands running in this view (closed in try/finally, C0 surprise 7). */\n commands: string[];\n /** The document before the rich-text mutation about to run (only while a co-editing room listens). */\n pre: unknown | null;\n}\n\n/** The document's room on the ordered log (COLLAB-DESIGN §6, C3), bound through `startOtRoom`. */\nexport interface DocumentOtHandle {\n stop: () => void;\n write: (reason: CommitReason) => Promise<boolean>;\n replace: (snapshot: DocumentSnapshotData) => Promise<void>;\n isSaver: () => boolean;\n}\n\nexport type DocumentOtFactory = (\n port: DocsOtPort,\n onAwareness: (awareness: DocumentAwareness) => void,\n) => Promise<DocumentOtHandle | null>;\n\n/** A collab room (WorkbookCollabSession) bound to the model's command stream. */\nexport interface DocumentCollabHandle {\n stop: () => void;\n isHost: () => boolean;\n /** This tab replaced the whole document and saved it as `snapshotId`: peers reload it. */\n announceReplaced: (snapshotId: string) => void;\n /** The room entries this tab's body holds right now (read with the body that is about to be saved). */\n coveredNow: () => string[];\n /** The saved snapshot `snapshotId` holds `covered`: they leave the room's log (the elected saver only). */\n checkpoint: (snapshotId: string, covered: readonly string[]) => void;\n}\n\n/** The saved snapshot this tab's body started from — what the room must never replay on top of it. */\nexport interface DocumentCollabBase {\n snapshotId: () => string | null;\n covered: () => ReadonlySet<string>;\n /** Show the newest saved snapshot (the room's newest checkpoint is newer than what this tab loaded). */\n reload: () => Promise<void>;\n}\n\n/** Who else is in the document's room (shared by every view of it). */\nexport interface DocumentAwareness {\n states: Map<number, AwarenessState>;\n selfUid: string;\n /** Other seats' carets and selections (ordered-log rooms only, C8), already moved through every edit applied since. */\n carets?: RemoteCaret[];\n}\n\n/**\n * An editor instance kept alive between views of the document: its DOM host\n * (re-parented into the next view's container) and the instance behind it,\n * whose undo history survives because the instance does. Opaque to the model\n * apart from what it calls.\n */\nexport interface ParkedDocumentEditor<T = unknown> {\n /** The element the editor renders into; the next view appends it to its container. */\n element: HTMLElement;\n instance: T;\n /** Replace the whole document (a collaborator's snapshot arrived while parked). */\n remount: (snapshot: DocumentSnapshotData) => void;\n /** Throw the instance away (the record's session closed). */\n dispose: () => void;\n}\n\nexport type DocumentCollabFactory = (\n commandService: CommandServiceLike,\n onAwareness: (awareness: DocumentAwareness) => void,\n /** A peer replaced the whole document (history restore, Google update). */\n onReplaced: () => void,\n /** What this tab's body was loaded from; pass it to the session (`base`). */\n base: DocumentCollabBase,\n) => Promise<DocumentCollabHandle | null>;\n\nlet viewIds = 0;\n\nexport class DocumentModel {\n readonly documentId: string;\n private readonly deps: DocumentModelDeps;\n private readonly handle: WorkingCopyHandle;\n private readonly views = new Map<number, AttachedView>();\n private lastEditedView: number | null = null;\n /** The document as the last view left it, or as last loaded / saved. */\n private stored: DocumentSnapshotData | null = null;\n private loading: Promise<DocumentSnapshotData | null> | null = null;\n private relaying = false;\n /** Snapshot rows this tab already holds (loaded or written) — never re-applied. */\n private readonly knownSnapshots = new Set<string>();\n private readonly collabListeners = new Set<(info: CollabMutationInfo, options?: { onlyLocal?: boolean; fromCollab?: boolean }) => void>();\n private collab: DocumentCollabHandle | null = null;\n /** The ordered-log room (C3); exclusive with `collab` (the 0.6 relay room). */\n private ot: DocumentOtHandle | null = null;\n private otStarting: Promise<void> | null = null;\n private readonly otListeners = new Set<(m: DocsLocalMutation) => void>();\n /** The saved snapshot the body started from, and the room entries it already holds. */\n private baseId: string | null = null;\n private baseCovered: ReadonlySet<string> = new Set();\n private collabStarting: Promise<void> | null = null;\n private awareness: DocumentAwareness | null = null;\n private readonly awarenessListeners = new Set<() => void>();\n private realtimeClose: (() => void) | null = null;\n private pageClose: (() => void) | null = null;\n /** The last view's editor, alive and off the page until a view takes it back. */\n private parked: ParkedDocumentEditor | null = null;\n\n constructor(handle: WorkingCopyHandle, deps: DocumentModelDeps) {\n this.documentId = handle.id;\n this.handle = handle;\n this.deps = deps;\n }\n\n // ── body ────────────────────────────────────────────────────────────────\n\n /** The newest state of the body this tab holds, without a network read. */\n latest(): DocumentSnapshotData | null {\n const preferred = this.lastEditedView !== null ? this.views.get(this.lastEditedView) : undefined;\n for (const view of preferred ? [preferred, ...this.views.values()] : this.views.values()) {\n try {\n const snapshot = view.port.snapshot();\n if (snapshot) return snapshot;\n } catch (error) {\n console.warn(`[document-model] a view of ${this.documentId} could not report its document`, error);\n }\n }\n return this.stored;\n }\n\n /**\n * What a NEW view should boot from: the model's latest state, or (only when\n * this tab holds none) the newest server snapshot. Null = an empty document.\n * Re-read `latest()` synchronously right before mounting — another view may\n * have typed while the server read was in flight.\n */\n async openingSnapshot(createEmpty: () => DocumentSnapshotData): Promise<DocumentSnapshotData> {\n const held = this.latest();\n if (held) return held;\n if (!this.loading) {\n this.loading = this.deps.loadLatest(this.documentId).then(\n (row) => {\n const loaded = row ? this.takeBase(row) : null;\n if (row && loaded) {\n this.knownSnapshots.add(row.id);\n this.savedFingerprint = contentFingerprint(loaded);\n }\n // A document never saved opens as ONE empty document for every view\n // (one unit id), so their edits replay into each other.\n if (!this.stored) this.stored = loaded ?? createEmpty();\n return this.latest() ?? this.stored;\n },\n (error: unknown) => {\n this.loading = null;\n throw error;\n },\n );\n }\n return (await this.loading) ?? createEmpty();\n }\n\n /** A view's Univer instance is ready: it shares the document from now on. */\n attachView(port: DocumentViewPort): () => void {\n const id = ++viewIds;\n const subscription = port.commandService.onMutationExecutedForCollab((info, options) =>\n this.onViewMutation(id, info, options),\n );\n const view: AttachedView = { id, port, dispose: () => {}, commands: [], pre: null };\n const hooks = this.trackCommands(view);\n view.dispose = () => {\n subscription.dispose();\n hooks();\n };\n this.views.set(id, view);\n // Nothing unsaved: what this view mounted IS the saved version (Univer and\n // the snapshot repair may restate it — page geometry, defaults — without\n // anyone changing a word). That is the baseline a save compares against.\n if (!this.handle.hasPending()) {\n try {\n const mounted = port.snapshot();\n if (mounted) this.savedFingerprint = contentFingerprint(mounted);\n } catch (error) {\n console.warn(`[document-model] could not read ${this.documentId}'s mounted document`, error);\n }\n }\n let detached = false;\n return () => {\n if (detached) return;\n detached = true;\n const view = this.views.get(id);\n if (!view) return;\n // Whatever this view shows is the newest body when it is the last one:\n // keep it, so a remount (or the flush on the way out) reads it.\n if (this.views.size === 1) {\n try {\n const snapshot = port.snapshot();\n if (snapshot) this.stored = snapshot;\n } catch (error) {\n console.warn(`[document-model] could not keep ${this.documentId}'s last view's document`, error);\n }\n }\n view.dispose();\n this.views.delete(id);\n if (this.lastEditedView === id) this.lastEditedView = null;\n };\n }\n\n /**\n * The last view of the document is leaving: keep its editor (and Univer's\n * undo history inside it) for the next view. Call AFTER the view's\n * `attachView` detach. Refused — the caller disposes its editor — while\n * another view is still attached (it carries the document) or one is\n * already kept.\n */\n parkEditor(editor: ParkedDocumentEditor): boolean {\n if (this.closed || this.views.size > 0 || this.parked) return false;\n this.parked = editor;\n return true;\n }\n\n /** The kept editor, handed to the view that mounts next (null when none is kept). */\n takeParkedEditor(): ParkedDocumentEditor | null {\n const editor = this.parked;\n this.parked = null;\n return editor;\n }\n\n private onViewMutation(\n viewId: number,\n info: Readonly<CollabMutationInfo>,\n options?: { fromCollab?: boolean; fromChangeset?: boolean; onlyLocal?: boolean },\n ): void {\n // Our own replay into this view, a collab peer's edit, or a load: not a\n // new local edit (each is accounted where it came from).\n if (this.relaying || options?.fromCollab || options?.fromChangeset) return;\n const view = this.views.get(viewId);\n if (!view || !view.port.editable()) return;\n this.lastEditedView = viewId;\n this.relay(info, viewId);\n for (const listener of this.collabListeners) listener(info as CollabMutationInfo, options);\n if (this.otListeners.size && !options?.onlyLocal) {\n const m: DocsLocalMutation = {\n id: info.id,\n params: info.params,\n pre: info.id === RICH_TEXT_EDITING_ID ? view.pre : null,\n cmd: view.commands[0] ?? null,\n content: isContentMutation(info),\n };\n view.pre = null;\n for (const listener of Array.from(this.otListeners)) listener(m);\n }\n if (isContentMutation(info)) this.markDirty();\n }\n\n /**\n * Per view: the outermost command running (a mutation's group label) and, while a room listens, the document\n * before each rich-text mutation (its inverse is computed from the APPLIED actions against this copy). Univer's\n * `executeCommand` has no `finally`: a command that mutates then throws never fires `onCommandExecuted`, so\n * the depth is restored in a try/finally around the instance's `executeCommand` (C0 surprise 7).\n */\n private trackCommands(view: AttachedView): () => void {\n const cs = view.port.commandService as ViewCommandService;\n if (typeof cs.beforeCommandExecuted !== \"function\" || typeof cs.onCommandExecuted !== \"function\") return () => {};\n const before = cs.beforeCommandExecuted((info) => {\n if (info.type === COMMAND_TYPE) view.commands.push(info.id);\n else if (info.id === RICH_TEXT_EDITING_ID && this.otListeners.size && !this.relaying) {\n try {\n const snap = view.port.snapshot();\n view.pre = snap ? structuredClone(snap) : null;\n } catch {\n view.pre = null;\n }\n }\n });\n const after = cs.onCommandExecuted((info) => {\n if (info.type !== COMMAND_TYPE) return;\n const at = view.commands.lastIndexOf(info.id);\n if (at >= 0) view.commands.splice(at, 1);\n });\n const guarded = cs as ViewCommandService & { [DEPTH_GUARDED]?: true };\n if (typeof cs.executeCommand === \"function\" && !guarded[DEPTH_GUARDED]) {\n const original = cs.executeCommand.bind(cs);\n guarded[DEPTH_GUARDED] = true;\n cs.executeCommand = async (id, params, options) => {\n const depth = view.commands.length;\n try {\n return await original(id, params, options);\n } finally {\n if (view.commands.length > depth) view.commands.length = depth;\n }\n };\n }\n return () => {\n before.dispose();\n after.dispose();\n };\n }\n\n /** The unit id a view's document has (what a replayed mutation must be addressed to). */\n private unitIdOf(view: AttachedView): string | null {\n try {\n return view.port.unitId?.() ?? view.port.snapshot()?.id ?? null;\n } catch {\n return null;\n }\n }\n\n /** Replay one mutation into every view except `exceptViewId`, addressed to each view's own unit. */\n private relay(info: Readonly<CollabMutationInfo>, exceptViewId: number | null): void {\n if (this.views.size === 0 || (this.views.size === 1 && exceptViewId !== null)) return;\n this.relaying = true;\n let failure: unknown = null;\n try {\n for (const view of this.views.values()) {\n if (view.id === exceptViewId) continue;\n try {\n const params = info.params as unknown;\n const unitId = this.unitIdOf(view);\n const addressed =\n unitId && params && typeof params === \"object\" && !Array.isArray(params) && typeof (params as { unitId?: unknown }).unitId === \"string\" && (params as { unitId: string }).unitId !== unitId\n ? { ...(params as Record<string, unknown>), unitId }\n : info.params;\n view.port.commandService.syncExecuteCommand(info.id, addressed as never, { onlyLocal: true, fromCollab: true });\n } catch (error) {\n failure ??= error;\n console.error(\n `[document-model] a second view of ${this.documentId} could not apply \"${info.id}\" — it may show an older document until it reopens`,\n error,\n );\n }\n }\n } finally {\n this.relaying = false;\n }\n if (failure !== null) this.applyFailed(info.id, failure);\n }\n\n /** A view could not follow an edit: say so, then show the saved version (unless this tab has unsaved edits of its own). */\n private applyFailed(mutationId: string, error: unknown): void {\n try {\n this.deps.onApplyFailed?.(this.documentId, mutationId, error);\n } catch (notifyError) {\n console.warn(`[document-model] the notice for ${this.documentId}'s failed apply also failed`, notifyError);\n }\n if (this.hasUnsaved()) return;\n void this.deps\n .loadLatest(this.documentId)\n .then((row) => {\n if (row && !this.closed) this.show(row);\n })\n .catch((e) => console.warn(`[document-model] could not re-sync ${this.documentId} after a failed apply`, e));\n }\n\n // ── save (run by the record's one coalesced save — documentModels.ts) ─\n\n private markDirty(): void {\n this.handle.touch();\n }\n\n private saving = false;\n /**\n * The content of the version the server holds (loaded or last written). A\n * save of the same content is no save: attaching, detaching, waking or a\n * flush of an unchanged document never writes a snapshot row.\n */\n private savedFingerprint: string | null = null;\n\n /**\n * Write the body as it is now. Returns false when this tab is a collab peer\n * that does not write (the elected host writes the canonical snapshot; a\n * peer's edits reach it through the room). An explicit Save always writes.\n */\n async write(reason: CommitReason): Promise<boolean> {\n if (this.ot) {\n const wrote = await this.ot.write(reason);\n if (wrote) this.deps.onSaved?.(this.documentId, reason === \"manual\" ? \"manual\" : \"autosave\");\n return wrote;\n }\n const snapshot = this.latest();\n if (!snapshot) throw new Error(\"There is no open document to save.\");\n if (this.collab && !this.collab.isHost() && reason !== \"manual\") return false;\n const fingerprint = contentFingerprint(snapshot);\n if (reason !== \"manual\" && fingerprint === this.savedFingerprint) return false;\n const origin = reason === \"manual\" ? \"manual\" : \"autosave\";\n // The room entries this body holds, read in the same step as the body: the saved row names them,\n // so a tab that reloads from it never replays them on top of it.\n const collab = this.collab;\n const covered = collab ? collab.coveredNow() : null;\n this.saving = true;\n try {\n const { id } = await this.deps.save({\n documentId: this.documentId,\n snapshot: covered ? stampCovered(snapshot, covered) : snapshot,\n origin,\n });\n this.knownSnapshots.add(id);\n this.savedFingerprint = fingerprint;\n if (collab && covered && collab.isHost()) collab.checkpoint(id, covered);\n } finally {\n this.saving = false;\n }\n if (this.views.size === 0) this.stored = snapshot;\n this.deps.onSaved?.(this.documentId, origin);\n return true;\n }\n\n private hasUnsaved(): boolean {\n return this.handle.hasPending();\n }\n\n hasViews(): boolean {\n return this.views.size > 0;\n }\n\n // ── realtime (snapshot inserts) ─────────────────────────────────────────\n\n /** Opened once per document by the first view that asks; idempotent. */\n connectRealtime(open: (onSnapshot: (snapshotId: string) => void) => () => void): void {\n if (this.realtimeClose) return;\n this.realtimeClose = open((snapshotId) => void this.onRemoteSnapshot(snapshotId));\n }\n\n /**\n * A snapshot was committed (here or elsewhere): show a foreign one in every\n * view. Over unsaved edits it is a CONFLICT — the working copy holds it and\n * no save runs (one would overwrite the collaborator's snapshot) until the\n * person chooses; `overUnsaved` is \"Take theirs\" (`./documentModels.ts`).\n */\n async onRemoteSnapshot(snapshotId: string, { overUnsaved = false }: { overUnsaved?: boolean } = {}): Promise<void> {\n if (this.collab || this.ot) return; // the room is the live channel; snapshots are checkpoints\n if (this.knownSnapshots.has(snapshotId)) return; // ours, or already shown\n if (this.saving) return; // our own save's echo, ahead of its response\n if (this.hasUnsaved() && !overUnsaved) {\n this.handle.conflict({ ref: snapshotId });\n return;\n }\n const row = await this.deps.loadLatest(this.documentId);\n if (!row || (this.hasUnsaved() && !overUnsaved) || this.knownSnapshots.has(row.id)) return;\n this.show(row);\n }\n\n /**\n * THE content swap (see @ai-matrx/office/univer openEditorContent): a SAVED snapshot\n * replaces the document in every view and the kept editor. It is the saved\n * version from now on, so the pending save compares equal and writes\n * nothing (it would put the old content back over the new). In a collab\n * room the peers reload it and the shared log is emptied.\n */\n replaceContent(row: { id: string; snapshot: DocumentSnapshotData }): void | Promise<void> {\n // A document with an ordered-log room is replaced through `collab_replace` (one atomic door, §20).\n if (this.ot) return this.ot.replace(row.snapshot);\n this.show(row);\n this.collab?.announceReplaced(row.id);\n }\n\n /** A peer replaced the document: show the newest save (once). */\n private async onPeerReplaced(): Promise<void> {\n const row = await this.deps.loadLatest(this.documentId);\n if (!row || this.knownSnapshots.has(row.id)) return;\n this.show(row);\n }\n\n /** A loaded row becomes the base: its content (what views mount) and the room entries it holds. */\n private takeBase(row: { id: string; snapshot: DocumentSnapshotData }): DocumentSnapshotData {\n const { snapshot, covered } = takeCovered(row.snapshot);\n this.baseId = row.id;\n this.baseCovered = covered;\n return snapshot;\n }\n\n private show(row: { id: string; snapshot: DocumentSnapshotData }): void {\n const snapshot = this.takeBase(row);\n this.knownSnapshots.add(row.id);\n this.savedFingerprint = contentFingerprint(snapshot);\n this.stored = snapshot;\n this.relaying = true;\n try {\n for (const view of this.views.values()) view.port.remount(snapshot);\n this.parked?.remount(snapshot);\n } finally {\n this.relaying = false;\n }\n }\n\n // ── collab (one room per document) ──────────────────────────────────────\n\n /**\n * The model's command stream as ONE command service — what the collab room\n * binds to. Local edits from any view go out once; a peer's edit is applied\n * to every view.\n */\n private readonly virtualCommandService: CommandServiceLike = {\n onMutationExecutedForCollab: (listener) => {\n this.collabListeners.add(listener);\n return { dispose: () => this.collabListeners.delete(listener) };\n },\n syncExecuteCommand: (id, params) => {\n const info = { id, type: 2, params } as CollabMutationInfo;\n this.relay(info, null);\n // The host writes what peers typed.\n if (isContentMutation(info)) this.markDirty();\n return true;\n },\n };\n\n /** Join the document's collab room once (the first view that asks). */\n startCollab(factory: DocumentCollabFactory): Promise<void> {\n if (this.collab) return Promise.resolve();\n if (!this.collabStarting) {\n this.collabStarting = factory(\n this.virtualCommandService,\n (awareness) => {\n this.awareness = awareness;\n for (const listener of Array.from(this.awarenessListeners)) listener();\n },\n () => {\n void this.onPeerReplaced().catch((error: unknown) =>\n console.warn(`[document-model] could not load ${this.documentId}'s replaced version`, error),\n );\n },\n {\n snapshotId: () => this.baseId,\n covered: () => this.baseCovered,\n reload: async () => {\n const row = await this.deps.loadLatest(this.documentId);\n if (row && !this.closed) this.show(row);\n },\n },\n )\n .then((handle) => {\n if (!handle) return;\n if (this.views.size === 0) {\n handle.stop();\n return;\n }\n this.collab = handle;\n })\n .finally(() => {\n this.collabStarting = null;\n });\n }\n return this.collabStarting;\n }\n\n /** The model as the ordered-log room sees it (COLLAB-DESIGN §6.7: the model is the client, not the view). */\n private readonly otPort: DocsOtPort = {\n onLocal: (listener) => {\n this.otListeners.add(listener);\n return () => void this.otListeners.delete(listener);\n },\n applyRemote: (id, params) => {\n if (this.views.size === 0) throw new Error(\"no view of the document is mounted\");\n this.relaying = true;\n try {\n for (const view of this.views.values()) {\n const unitId = this.unitIdOf(view);\n const input = Array.isArray(params.actions) ? params.actions.length : 0;\n let sel: Array<{ startOffset: number; endOffset: number; segmentId?: string }> | null = null;\n try {\n sel = view.port.selection?.get() ?? null;\n } catch {\n sel = null;\n }\n const p: Record<string, unknown> = { ...params, ...(unitId ? { unitId } : {}), textRanges: null, noNeedSetTextRange: true };\n const ok = view.port.commandService.syncExecuteCommand(id, p as never, { onlyLocal: true, fromCollab: true });\n if (ok === false) throw new Error(`\"${id}\" was refused by the editor`);\n // the content-control guard empties `actions` on the params object it was handed (§6.6)\n if (input > 0 && Array.isArray(p.actions) && p.actions.length === 0) throw new Error(`\"${id}\" was emptied by the editor`);\n const moved = sel && sel.length && sel.every((r) => !r.segmentId) ? moveRangesThroughBodyEdit(sel, params.actions) : null;\n if (moved) {\n try {\n view.port.selection?.set(moved);\n } catch (error) {\n console.warn(`[document-model] could not move this view's caret past a collaborator's edit`, error);\n }\n }\n }\n } finally {\n this.relaying = false;\n }\n if (isContentMutation({ id, type: 2, params } as unknown as CollabMutationInfo)) this.markDirty();\n },\n snapshot: () => this.latest(),\n load: (snapshot) => {\n const s = snapshot as DocumentSnapshotData;\n this.stored = s;\n this.savedFingerprint = contentFingerprint(s);\n this.relaying = true;\n try {\n for (const view of this.views.values()) view.port.remount(s);\n this.parked?.remount(s);\n } finally {\n this.relaying = false;\n }\n },\n undoTargets: () => {\n const out: Array<{ service: unknown; unitId: string }> = [];\n for (const view of this.views.values()) {\n const unitId = this.unitIdOf(view);\n const service = view.port.undoRedo?.();\n if (unitId && service) out.push({ service, unitId });\n }\n return out;\n },\n markDirty: () => this.markDirty(),\n selection: () => {\n for (const view of this.views.values()) {\n try {\n const sel = view.port.selection?.get();\n if (sel) return sel;\n } catch {\n /* a view mid-teardown has no selection */\n }\n }\n return null;\n },\n };\n\n /** Join the document's ordered-log room once (C3). Exclusive with `startCollab`. */\n startOtRoom(factory: DocumentOtFactory): Promise<void> {\n if (this.ot || this.collab) return Promise.resolve();\n if (!this.otStarting) {\n this.otStarting = factory(this.otPort, (awareness) => {\n this.awareness = awareness;\n for (const listener of Array.from(this.awarenessListeners)) listener();\n })\n .then((handle) => {\n if (!handle) return;\n if (this.views.size === 0) {\n handle.stop();\n return;\n }\n this.ot = handle;\n })\n .finally(() => {\n this.otStarting = null;\n });\n }\n return this.otStarting;\n }\n\n /** Which co-editing room this document is in right now. */\n collabMode(): \"ordered\" | \"relay\" | null {\n return this.ot ? \"ordered\" : this.collab ? \"relay\" : null;\n }\n\n isCollabHost(): boolean {\n if (this.ot) return this.ot.isSaver();\n return this.collab ? this.collab.isHost() : true;\n }\n\n getAwareness(): DocumentAwareness | null {\n return this.awareness;\n }\n\n subscribeAwareness(listener: () => void): () => void {\n this.awarenessListeners.add(listener);\n return () => this.awarenessListeners.delete(listener);\n }\n\n // ── lifecycle (driven by the record's session) ──────────────────────\n\n /** A view arrived on a document with none. */\n wake(): void {\n if (!this.pageClose && this.deps.listenToPage) {\n this.pageClose = this.deps.listenToPage({\n flush: () => void this.handle.flush(),\n hasUnsaved: () => this.hasUnsaved(),\n });\n }\n }\n\n /**\n * The last view left: leave the collab room (presence must not outlive the\n * person). The snapshot channel stays open while the session is kept alive,\n * so a collaborator's save still reaches the body a returning view boots from.\n */\n rest(): void {\n this.collab?.stop();\n this.collab = null;\n this.ot?.stop();\n this.ot = null;\n this.awareness = null;\n }\n\n private closed = false;\n\n close(): void {\n this.closed = true;\n const parked = this.parked;\n this.parked = null;\n if (parked) {\n try {\n parked.dispose();\n } catch (error) {\n console.warn(`[document-model] could not dispose ${this.documentId}'s kept editor`, error);\n }\n }\n this.realtimeClose?.();\n this.realtimeClose = null;\n this.pageClose?.();\n this.pageClose = null;\n }\n}\n\n/**\n * Body offsets moved through a collaborator's body edit (`[\"body\", {et:\"text-x\", e}]`), §6.4 and §6.8. Text inserted\n * before the caret pushes it right; text inserted after it does not.\n *\n * A tie (text inserted EXACTLY at a collapsed caret) follows the one conflict rule. The caret is where this person's\n * next keystroke goes, and that keystroke commits after the edit being applied, so it takes `'left'` and sits first:\n * the caret stays BEFORE the collaborator's text. That is the side the session already gives this seat's unsent and\n * in-flight inserts (`T(local, remote, 'left')`), so the caret stays at the end of this person's own run and two\n * people typing at one spot each keep their words whole (\"FloodEbb\", never \"FElbobod\"). A selection never grows to\n * take in a collaborator's text: an insert at its start lands before it, at its end after it.\n * Null when the edit is not a body edit.\n */\nexport function moveRangesThroughBodyEdit(\n ranges: Array<{ startOffset: number; endOffset: number }>,\n actions: unknown,\n): Array<{ startOffset: number; endOffset: number }> | null {\n const a = actions as unknown[];\n if (!Array.isArray(a) || a[0] !== \"body\") return null;\n const sub = a[1] as { et?: string; e?: unknown } | undefined;\n if (!sub || sub.et !== \"text-x\" || !Array.isArray(sub.e)) return null;\n const e = sub.e as Parameters<typeof TextX.transformPosition>[0];\n return ranges.map((r) => {\n const collapsed = r.startOffset === r.endOffset;\n // TextX.transformPosition's third argument: true = an insert exactly at this offset lands after it\n const startOffset = TextX.transformPosition(e, r.startOffset, collapsed);\n return { startOffset, endOffset: collapsed ? startOffset : TextX.transformPosition(e, r.endOffset, true) };\n });\n}\n\n/**\n * What a snapshot STORES, as a comparable string: everything but the unit id\n * and Univer's revision counter (both move without the content moving).\n */\nfunction contentFingerprint(snapshot: DocumentSnapshotData): string {\n const { id: _id, rev: _rev, ...content } = snapshot as DocumentSnapshotData & { rev?: unknown };\n return JSON.stringify(content);\n}\n\n/** Mutations that change what a snapshot stores (never scroll / selection) — the editors' one dirty filter. */\nfunction isContentMutation(info: Readonly<CollabMutationInfo>): boolean {\n return isSnapshotMutation({ id: info.id, type: info.type, params: info.params } as ICommandInfo);\n}\n","/**\n * THE ONE way to replace the whole content of an open Univer editor\n * (workbook or document) with a snapshot that is already SAVED: a history\n * restore, \"Update from Google\" / \"Use Google's\", and a collaborator's\n * replacement all arrive here.\n *\n * Callers save first, then call `showSavedSnapshot`. The open editor for that\n * record (registered below) swaps its content in place, drops its pending\n * autosave (it would write the old content back over the new one), and — in\n * a collab room — tells every peer to reload the same snapshot. A caller\n * never touches Univer units itself: disposing the current unit by hand left\n * Univer's selection observers pointing at nothing (`getUnitId` of null).\n *\n * Pure registry (no Univer import), so it is testable without booting Univer.\n */\n\nexport type EditorRecordKind = \"workbook\" | \"document\";\n\n/** A snapshot row as stored: its id and the Univer body. */\nexport type SavedEditorSnapshot = { id: string; snapshot: unknown };\n\nexport type EditorContentReplacer = (row: SavedEditorSnapshot) => void | Promise<void>;\n\nconst replacers = new Map<string, EditorContentReplacer>();\n\nconst keyOf = (kind: EditorRecordKind, recordId: string) => `${kind}:${recordId}`;\n\n/**\n * The open editor of a record lends its replacer while it is mounted. The\n * newest registration wins; the returned release only removes its own.\n */\nexport function registerOpenEditorContent(\n kind: EditorRecordKind,\n recordId: string,\n replace: EditorContentReplacer,\n): () => void {\n const key = keyOf(kind, recordId);\n replacers.set(key, replace);\n return () => {\n if (replacers.get(key) === replace) replacers.delete(key);\n };\n}\n\n/** Whether an editor of this record is open in this tab. */\nexport function hasOpenEditorContent(kind: EditorRecordKind, recordId: string): boolean {\n return replacers.has(keyOf(kind, recordId));\n}\n\n/**\n * Show a saved snapshot in the record's open editor (and its collab peers).\n * Returns false when no editor of the record is open in this tab — the saved\n * row then simply is the content the next open loads.\n */\nexport async function showSavedSnapshot(\n kind: EditorRecordKind,\n recordId: string,\n row: SavedEditorSnapshot,\n): Promise<boolean> {\n const replace = replacers.get(keyOf(kind, recordId));\n if (!replace) return false;\n await replace(row);\n return true;\n}\n\n/**\n * THE CONTENT-SWAP GUARD. A swap is dispose-then-create; if the create throws, the unit is gone and\n * the grid would stay blank. `swap(snapshot)` is the editor's own dispose+create (it disposes\n * whatever unit is open, if any). On a throw this puts the content that was open before straight\n * back (synchronously — never a blank grid) and says so; the editor then reloads the latest SAVED\n * version and still raises the original error, so the person is told.\n */\nexport function swapContentGuarded(args: {\n swap: (snapshot: unknown) => void;\n next: unknown;\n /** What was open before (`workbook.save()` taken before the swap), or null when nothing was. */\n previous: unknown | null;\n}): { ok: true } | { ok: false; error: unknown; previousRestored: boolean } {\n try {\n args.swap(args.next);\n return { ok: true };\n } catch (error) {\n let previousRestored = false;\n if (args.previous) {\n try {\n args.swap(args.previous);\n previousRestored = true;\n } catch {\n /* the latest saved version is tried next, by the caller */\n }\n }\n return { ok: false, error, previousRestored };\n }\n}\n","/**\n * Other people's carets and selections in a Docs co-editing room (COLLAB-DESIGN §6.8, unit C8).\n *\n * Presence travels on Yjs awareness beside `quiet_hash`: each seat publishes `caret = { ranges, at }`, body\n * offsets in ITS OWN editor (header and footer selections are not published). Offsets do not survive edits, so a\n * receiver keeps a book of the last published ranges and moves them through every body edit it applies afterwards,\n * remote or its own, with the same function that moves its own caret (`moveRangesThroughBodyEdit`). A peer\n * republishes on each selection change and every `CARET_HEARTBEAT_MS`, so a race between its awareness and an op\n * frame (a keystroke counted twice) corrects itself within a heartbeat. A caret older than `CARET_STALE_MS` is\n * not shown (judged by when THIS seat received it, never the sender's clock); one whose seat left is dropped with its awareness state.\n */\nimport { moveRangesThroughBodyEdit } from \"./document-model\";\n\nexport const CARET_HEARTBEAT_MS = 2000;\nexport const CARET_STALE_MS = 12000;\n/** Most ranges one seat publishes (a multi-range selection is rare; the rest is dropped, never the first). */\nexport const CARET_MAX_RANGES = 4;\n\nexport interface CaretRange {\n start: number;\n end: number;\n}\n\n/** The `caret` field of a seat's awareness state. */\nexport interface PublishedCaret {\n ranges: CaretRange[];\n at: number;\n}\n\n/** One other seat's caret, ready to draw. */\nexport interface RemoteCaret {\n /** The seat (Yjs client id as a string): two tabs of one person are two carets. */\n key: string;\n uid: string;\n name: string;\n color: string;\n ranges: CaretRange[];\n}\n\ntype SelectionRange = { startOffset: number; endOffset: number; segmentId?: string };\n\n/** What a seat publishes for its selection, or null when there is nothing to show (header/footer, no selection). */\nexport function publishedCaretFromSelection(sel: SelectionRange[] | null | undefined, now: number): PublishedCaret | null {\n if (!sel || sel.length === 0) return null;\n if (sel.some((r) => r.segmentId)) return null;\n const ranges = sel.slice(0, CARET_MAX_RANGES).map((r) => ({ start: Math.min(r.startOffset, r.endOffset), end: Math.max(r.startOffset, r.endOffset) }));\n return { ranges, at: now };\n}\n\nconst sameRanges = (a: CaretRange[], b: CaretRange[]) => a.length === b.length && a.every((r, i) => r.start === b[i]!.start && r.end === b[i]!.end);\n\nfunction readCaret(raw: unknown): PublishedCaret | null {\n const c = (raw as { caret?: { ranges?: unknown; at?: unknown } } | null)?.caret;\n if (!c || !Array.isArray(c.ranges) || typeof c.at !== \"number\") return null;\n const ranges: CaretRange[] = [];\n for (const r of c.ranges.slice(0, CARET_MAX_RANGES)) {\n const s = (r as CaretRange)?.start;\n const e = (r as CaretRange)?.end;\n if (typeof s !== \"number\" || typeof e !== \"number\" || !Number.isFinite(s) || !Number.isFinite(e) || s < 0 || e < 0) return null;\n ranges.push({ start: s, end: e });\n }\n return ranges.length ? { ranges, at: c.at } : null;\n}\n\nexport class RemoteCaretBook {\n private readonly carets = new Map<string, RemoteCaret & { at: number; seenAt: number }>();\n\n constructor(\n private readonly selfClientId: number,\n private readonly now: () => number = Date.now,\n ) {}\n\n /** Take the room's awareness states: new or republished carets replace ours, seats that left are dropped. Returns whether anything changed. */\n ingest(states: Map<number, unknown>): boolean {\n let changed = false;\n const seen = new Set<string>();\n states.forEach((raw, id) => {\n if (id === this.selfClientId) return;\n const s = raw as { uid?: unknown; name?: unknown; color?: unknown } | null;\n const caret = readCaret(raw);\n if (!s || typeof s.uid !== \"string\" || !caret) return;\n const key = String(id);\n seen.add(key);\n const prev = this.carets.get(key);\n const name = typeof s.name === \"string\" && s.name ? s.name : \"Someone\";\n const color = typeof s.color === \"string\" && s.color ? s.color : \"#3b82f6\";\n // The same publication again (awareness re-delivers state): keep the ranges we have already moved.\n if (prev && prev.at === caret.at && prev.name === name && prev.color === color) return;\n this.carets.set(key, { key, uid: s.uid, name, color, ranges: caret.ranges, at: caret.at, seenAt: this.now() });\n changed = true;\n });\n for (const key of [...this.carets.keys()]) {\n if (!seen.has(key)) {\n this.carets.delete(key);\n changed = true;\n }\n }\n return changed;\n }\n\n /** Move every caret through one body edit that was just applied (`actions` of a rich-text mutation). Returns whether any moved. */\n shiftThrough(actions: unknown): boolean {\n let moved = false;\n for (const c of this.carets.values()) {\n const next = moveRangesThroughBodyEdit(c.ranges.map((r) => ({ startOffset: r.start, endOffset: r.end })), actions);\n if (!next) return false; // not a body edit: nothing moves\n const ranges = next.map((r) => ({ start: r.startOffset, end: r.endOffset }));\n if (!sameRanges(ranges, c.ranges)) {\n c.ranges = ranges;\n moved = true;\n }\n }\n return moved;\n }\n\n /** The carets to draw now (stale ones left out). */\n list(): RemoteCaret[] {\n const t = this.now();\n const out: RemoteCaret[] = [];\n for (const c of this.carets.values()) {\n if (t - c.seenAt > CARET_STALE_MS) continue;\n out.push({ key: c.key, uid: c.uid, name: c.name, color: c.color, ranges: c.ranges.map((r) => ({ ...r })) });\n }\n out.sort((a, b) => a.key.localeCompare(b.key));\n return out;\n }\n}\n","/**\n * Document service — typed wrappers for `udt_documents` + `udt_document_snapshots`.\n *\n * Cloud document editor backed by Univer's preset-docs-core. Same shape as\n * `workbook-service.ts` — metadata in `udt_documents`, content state in\n * append-only `udt_document_snapshots`. The editor hydrates from the LATEST\n * snapshot and writes a new snapshot per save (debounced on the client —\n * see DocumentEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - The open document (one model per id per tab: load, one save, realtime,\n * collab): features/documents/document-model/\n * - Component (a view of that model): features/documents/components/DocumentEditor\n *\n * Mirrors `workbook-service.ts`. If you're changing the shape of one, change\n * the other at the same time — see `features/data-tables/FEATURE.md`.\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { readAllRows, tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { DocumentRow, DocumentSnapshot, DocumentSnapshotOrigin } from \"../core\";\nimport { getDocsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getDocsHost().getSupabase();\n// ─── documents ───────────────────────────────────────────────────────────────\n\nexport type CreateDocumentArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the document itself, mirrors `udt_documents.source`. */\n source?: \"created\" | \"imported_docx\" | \"imported_md\" | \"imported_txt\" | \"linked_gdoc\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (DOCX / MD / TXT blob). Set on the\n * import flow so the lossless original is recoverable; FK is ON DELETE SET\n * NULL, so deleting the file just nulls the link — the document survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createDocument(\n args: CreateDocumentArgs,\n): Promise<ServiceResult<DocumentRow>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a document.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .insert({\n document_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; the legacy `is_public` boolean is derived from it by\n // the workbench._bridge_legacy_owner trigger, so writing both here would\n // be two authorities for one fact. A new document defaults to `internal`\n // — it is org work product, not an individual person's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function listAccessibleDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n // RLS handles owner / published-to-the-web / shared access. The library and\n // the pickers treat this list as COMPLETE (\"you have no such document\"), so\n // it pages past PostgREST's silent 1000-row cap (D190).\n try {\n const rows = await readAllRows<DocumentRow>(\n ({ from, to }) =>\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\", { count: \"exact\" })\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false })\n .order(\"id\", { ascending: true })\n .range(from, to)\n .returns<DocumentRow[]>(),\n { label: \"workbench.udt_documents accessible documents\" },\n );\n return { success: true, data: rows };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function getDocument(\n documentId: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .eq(\"id\", documentId)\n .is(\"deleted_at\", null)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n if (!data) {\n // A trashed or unreachable document is a state the person can act on,\n // never PostgREST's \"Cannot coerce the result to a single JSON object\".\n return {\n success: false,\n error:\n \"This document is in the trash or you no longer have access to it. Restore it from Trash, or ask its owner to share it again.\",\n };\n }\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function renameDocument(\n documentId: string,\n name: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ document_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Move the document into a project (or out of one with `null`). Sibling of\n * `renameDocument`: the one named setter for `project_id`.\n */\nexport async function moveDocument(\n documentId: string,\n projectId: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Rewrite the document's description. Sibling of `renameDocument` — the two\n * human-authored fields on `udt_documents` each get a named setter so callers\n * never hand-roll a `.from(\"udt_documents\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Added when the documents surface became agent-writable: the\n * `document_description` write target on `/documents/[id]` is its caller, the\n * same way `updateWorkbookDescription` serves `workbook_description`. Keeping\n * the pair symmetric is this file's standing contract with `workbook-service`\n * (see the module header).\n */\nexport async function updateDocumentDescription(\n documentId: string,\n description: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Soft delete — the document is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreDocument for undo. (aidream migration 0458.)\n */\nexport async function restoreDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: null })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"restore\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a document this very flow just created and\n * failed to populate. Never use for a user-initiated delete: that is\n * deleteDocument, which tombstones and stays recoverable.\n */\nexport async function discardFailedDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"archive\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function deleteDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"delete\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n// ─── snapshots (document content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened document hydrates from. Returns\n * `data: null` (success path) when the document has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestDocumentSnapshot(\n documentId: string,\n): Promise<ServiceResult<DocumentSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"*\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as DocumentSnapshot | null };\n}\n\nexport type SaveDocumentSnapshotArgs = {\n documentId: string;\n snapshot: unknown; // opaque to us — Univer IDocumentData decides the shape\n label?: string | null;\n origin?: DocumentSnapshotOrigin;\n};\n\nexport async function saveDocumentSnapshot(\n args: SaveDocumentSnapshotArgs,\n): Promise<ServiceResult<DocumentSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .insert({\n document_id: args.documentId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent document's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent document; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.documentId);\n\n return { success: true, data: data as DocumentSnapshot };\n}\n\n/**\n * An independent copy of a document: its own row, with the latest snapshot copied over, so editing the copy never\n * touches the original. The copy lives in the original's organization and project. Used by a board-template use.\n */\nexport async function copyDocument(\n documentId: string,\n name?: string,\n): Promise<ServiceResult<DocumentRow>> {\n const original = await getDocument(documentId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return { success: false, error: \"This document has no organization and cannot be copied.\" };\n }\n const created = await createDocument({\n name: name ?? row.document_name,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n isPublic: row.visibility === \"public\",\n });\n if (!created.success) return created;\n const latest = await getLatestDocumentSnapshot(documentId);\n if (!latest.success) return latest;\n if (latest.data) {\n const saved = await saveDocumentSnapshot({\n documentId: created.data.id,\n snapshot: latest.data.snapshot,\n label: latest.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n/** Trash view: the caller's own archived documents (RLS decides what is readable). */\nexport async function listTrashedDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentRow[] };\n}\n\nexport async function listDocumentSnapshots(\n documentId: string,\n limit = 50,\n): Promise<ServiceResult<DocumentSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, document_id, label, origin, created_by, created_at\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentSnapshot[] };\n}\n","/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n","/**\n * Restore a saved version of a document (COLLAB-DESIGN §6.2, §20): THE one path for History, so a document with a\n * co-editing room is never restored behind its room's back.\n *\n * - Open in this tab: save the restored row, then the open editor swaps it in (`showSavedSnapshot`); an ordered-log\n * room sends it through `collab_replace` itself (`DocumentOtHandle.replace`).\n * - Not open in this tab but the document has a room (another tab or person has it open, or its log is ahead of its\n * checkpoint): `collab_replace` writes the snapshot row, the `replace` op, the checkpoint and the frame in one\n * transaction, so every open seat reloads. A snapshot row alone left those seats stale.\n * - No room: a snapshot row; the next open loads it.\n */\nimport { collabReplace, collabRoomExists, type CollabRpcClient } from \"@ai-matrx/data/realtime/collab\";\n\nimport { hasOpenEditorContent, showSavedSnapshot } from \"../univer/openEditorContent\";\nimport { docsStateHash, stampDeterministicIds } from \"../univer/collab/docs-ot/state-hash\";\nimport { saveDocumentSnapshot } from \"./document-service\";\nimport { getDocsHost } from \"./ports\";\n\nexport type DocumentRestoreResult =\n | { via: \"open_editor\"; snapshotId: string }\n | { via: \"room\"; rev: number; snapshotId: string }\n | { via: \"saved\"; snapshotId: string };\n\nexport interface DocumentRestoreDeps {\n client: () => CollabRpcClient;\n roomExists: (client: CollabRpcClient, documentId: string) => Promise<boolean>;\n replace: typeof collabReplace;\n stateHash: (snapshot: unknown) => Promise<string>;\n hasOpenEditor: (documentId: string) => boolean;\n showInOpenEditor: (documentId: string, row: { id: string; snapshot: unknown }) => Promise<boolean>;\n saveRow: (args: { documentId: string; snapshot: unknown; label: string | null }) => Promise<{ id: string }>;\n}\n\nconst defaultDeps: DocumentRestoreDeps = {\n client: () => getDocsHost().getSupabase() as unknown as CollabRpcClient,\n roomExists: collabRoomExists,\n replace: collabReplace,\n stateHash: (snapshot) => docsStateHash(snapshot),\n hasOpenEditor: (documentId) => hasOpenEditorContent(\"document\", documentId),\n showInOpenEditor: (documentId, row) => showSavedSnapshot(\"document\", documentId, row),\n async saveRow(args) {\n const res = await saveDocumentSnapshot({ documentId: args.documentId, snapshot: args.snapshot, origin: \"restored\", label: args.label });\n if (!res.success) throw new Error(res.error);\n return { id: res.data.id };\n },\n};\n\nexport async function restoreDocumentSnapshot(\n args: { documentId: string; snapshot: unknown; label: string | null },\n deps: Partial<DocumentRestoreDeps> = {},\n): Promise<DocumentRestoreResult> {\n const d = { ...defaultDeps, ...deps };\n if (d.hasOpenEditor(args.documentId)) {\n const row = await d.saveRow(args);\n await d.showInOpenEditor(args.documentId, { id: row.id, snapshot: args.snapshot });\n return { via: \"open_editor\", snapshotId: row.id };\n }\n const client = d.client();\n if (await d.roomExists(client, args.documentId)) {\n const next = stampDeterministicIds(structuredClone(args.snapshot ?? {}));\n const out = await d.replace(client, {\n roomId: args.documentId,\n snapshot: next,\n stateHash: await d.stateHash(next),\n origin: \"restore\",\n });\n return { via: \"room\", rev: out.rev, snapshotId: out.ref };\n }\n const row = await d.saveRow(args);\n return { via: \"saved\", snapshotId: row.id };\n}\n","/**\n * The Sheets co-editing room on the ordered log (COLLAB-DESIGN §6, §10, unit C6): the `OpDocumentAdapter` for\n * `openOpSession` over a workbook, plus saves, restore and the saver choice. The Sheets twin of the Docs room\n * (`../docs-ot/room.ts`): same session, transport, key-order rule, saver rule and restore door.\n *\n * - THE OP. A changeset is a list of allowlisted sheet mutations in order (`SheetMutation[]`); compose is\n * concatenation and the transform is the C5a/C5b group transform (`sheetTransformer`). A group with any\n * barrier pair is a barrier: the later side rolls back with a notice.\n * - CAPTURE happens in the port (`univer-port.ts`): one hand-over per outermost command, already filtered,\n * allowlisted, content-completed, exact-merge, style-object and formula-annotated, with its inverse. A\n * mutation that cannot travel (a barrier id: sort, number formats, conditional formats …) is reported as\n * `not_shared`: this seat is put back on the shared workbook and the person is told in plain words.\n * - APPLY (§6.7). Each mutation through the port (`forApply` strips the transformer-only params, the unit is\n * re-addressed, `{ onlyLocal: true, fromCollab: true }`). A refusal throws: the session rebuilds, never skips.\n * A remote op that arrives while a local command is still running is held and the local group is rebased\n * over it when the command finishes (the Docs IME rule, for sheet commands).\n * - LOSING IS NEVER SILENT. `lost` carries what x overrode of y, including what y can no longer apply because\n * of x (an edit in a column x removed), so the earlier author hears of it; `dropped` reaches this seat's own\n * author through the session's `dropped` notice.\n * - UNDO (§6.9). Each applied remote op rebases every stored undo and redo item of this seat\n * (`T(item, R1, 'left')`); an item that cannot follow (barrier, throw, emptied) is dropped. Undo therefore\n * only ever reverts this person's own changes.\n * - SAVES (§7.3). Only a quiet seat whose hash matches every peer at its rev saves, and only the chosen saver\n * saves on its own; a manual save always tries. RESTORE goes through `collab_replace`.\n */\nimport type {\n OpDocumentAdapter,\n OpPresence,\n OpSession,\n OpSessionIncident,\n OpSessionNotice,\n OpSessionStatus,\n OpTransport,\n} from \"@ai-matrx/data/realtime/collab\";\nimport { openOpSession } from \"@ai-matrx/data/realtime/collab\";\n\nimport { CONTENT_KEYS, SHEET_MUTATIONS, SHEET_TRANSFORMER_VERSION, allowParams, forApply, isBarrier, transformGroup } from \"../../../collab/sheets/transform\";\nimport type { SheetMutation } from \"../../../collab/sheets/transform\";\nimport { canonicalKeys } from \"../docs-ot/room\";\nimport { canonicalSheetString, sheetsStateHash } from \"./state-hash\";\n\n/** A changeset: allowlisted sheet mutations in order. `null` / `[]` is the no-op. */\nexport type SheetOp = SheetMutation[] | null;\n\n/**\n * The room's protocol (§6.4): Univer 1.0.4 + transformer `SHEET_TRANSFORMER_VERSION`. Any Univer or transformer\n * change raises it; a room at another proto opens read-only for this build.\n */\nexport const SHEETS_COLLAB_PROTO = 1;\nexport const SHEETS_EDIT_GROUP = \"sheets.edit\";\n\n/** One outermost command's traveling mutations, as the port hands them over. */\nexport interface SheetsLocalGroup {\n kind: \"group\";\n mutations: SheetMutation[];\n /** The group's inverse against the pre-state (§6.3), or undefined when one of its mutations has none. */\n inverse?: SheetMutation[];\n /** The outermost command id (the change's label in a rollback notice). */\n label: string | null;\n}\n/** A local change that cannot travel (no allowlist: a barrier id, an unknown id, a whole-style override …). */\nexport interface SheetsNotShared {\n kind: \"not_shared\";\n mutationId: string;\n label: string | null;\n}\nexport type SheetsLocalEvent = SheetsLocalGroup | SheetsNotShared;\n\n/** What the workbook editor lends the room (implemented by `univerSheetsOtPort`). */\nexport interface SheetsOtPort {\n onLocal(listener: (e: SheetsLocalEvent) => void): () => void;\n /** True while a local command is still running (its group is not handed over yet). */\n busy(): boolean;\n /** Run `fn` once no local command is running (immediately when none is). */\n whenIdle(fn: () => void): void;\n /** Apply one committed mutation to this seat's workbook; throws when the editor refused it. */\n applyRemote(m: SheetMutation): void;\n /** The workbook as the editor holds it now (with resources), or null when none is mounted. */\n snapshot(): unknown | null;\n /** Replace the workbook's whole content (same unit id). */\n load(snapshot: unknown): void;\n /** Univer's undo/redo service and this seat's unit. */\n undoTargets(): Array<{ service: unknown; unitId: string }>;\n /** Ask for a save (the record's one coalesced save). */\n markDirty(): void;\n}\n\nexport type SheetsOtNotice = OpSessionNotice<SheetOp> | { kind: \"not_shared\"; mutationId: string } | { kind: \"not_live\" };\n\n// ── helpers ───────────────────────────────────────────────────────────────────────────────────────────\n\nconst flip = (side: \"left\" | \"right\") => (side === \"left\" ? \"right\" : \"left\");\nconst isNoopSheetOp = (op: SheetOp): boolean => op == null || op.length === 0;\n\n/**\n * The adapter's transform: the C5a/C5b group transform, with `lost` widened by what y can no longer apply\n * after x (y's `dropped` over x). The session tells an earlier author through `lost`; without this, an edit\n * in a column a later op removed would vanish without a word.\n */\nexport function transformSheetOp(x: SheetOp, y: SheetOp, side: \"left\" | \"right\") {\n if (isNoopSheetOp(x) || isNoopSheetOp(y)) return { op: isNoopSheetOp(x) ? null : x, lost: [] as string[], dropped: [] as string[] };\n const r = transformGroup(x!, y!, side);\n if (isBarrier(r)) return r;\n const back = transformGroup(y!, x!, flip(side));\n const lost = [...new Set([...r.lost, ...(isBarrier(back) ? [] : back.dropped)])];\n return { op: r.op.length ? r.op : null, lost, dropped: r.dropped };\n}\n\n/**\n * The wire form. Keys in one canonical order: the log stores groups as jsonb, which hands object keys back in\n * its own order, and the session compares wire forms (its ack check) through `encode` (C3's rule).\n */\nexport function encodeSheetOp(op: SheetOp) {\n return canonicalKeys([{ cmd: SHEETS_EDIT_GROUP, mutations: (op ?? []).map((m) => ({ id: m.id, params: m.params })) }]);\n}\nexport function decodeSheetOp(groups: Array<{ mutations: Array<{ id: string; params: unknown }> }>): SheetOp {\n const out: SheetMutation[] = [];\n for (const g of groups) for (const m of g.mutations) out.push({ id: m.id, params: (m.params ?? {}) as Record<string, unknown> });\n return out.length ? out : null;\n}\n\ninterface UndoItem {\n unitID?: string;\n undoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n redoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n}\ninterface UndoServiceInternals {\n _undoStacks?: Map<string, UndoItem[]>;\n _redoStacks?: Map<string, UndoItem[]>;\n}\n\n/** The Univer 1.0.4 fields the undo rebase reads (pinned with the Docs room's forcing test). */\nfunction undoStacksOf(service: unknown): { undo: Map<string, UndoItem[]>; redo: Map<string, UndoItem[]> } | null {\n const s = service as UndoServiceInternals | null;\n if (!s || !(s._undoStacks instanceof Map) || !(s._redoStacks instanceof Map)) return null;\n return { undo: s._undoStacks, redo: s._redoStacks };\n}\n\nconst CONTENT_TOUCH = CONTENT_KEYS.filter((k) => k !== \"t\");\n\n/**\n * An undo item's mutation in the traveling shape the transform needs: allowlisted, a content write completed\n * (Univer's undo factory leaves absent keys out; absent there means \"was empty\"). Null = cannot be rebased.\n */\nfunction travelingShape(m: { id: string; params: Record<string, unknown> }): SheetMutation | null {\n const params = allowParams(m.id, m.params);\n if (!params) return null;\n if (m.params.isOverrideStyle) return null;\n if (m.id === \"sheet.mutation.set-range-values\") {\n const cells = structuredClone((params.cellValue ?? {}) as Record<string, Record<string, Record<string, unknown> | null>>);\n for (const row of Object.values(cells))\n for (const [c, v] of Object.entries(row)) {\n if (!v) continue;\n if (typeof v.s === \"string\") return null;\n if (!CONTENT_TOUCH.some((k) => k in v)) continue;\n const full: Record<string, unknown> = {};\n for (const k of CONTENT_KEYS) full[k] = v[k] !== undefined ? v[k] : null;\n if (full.v === null) delete full.t;\n if (\"s\" in v) full.s = v.s;\n row[c] = full;\n }\n return { id: m.id, params: { ...params, cellValue: cells } };\n }\n return { id: m.id, params };\n}\n\n/** §6.9: rebase one stack over a remote op; items that cannot follow are dropped. Returns how many were dropped. */\nexport function rebaseSheetUndoStack(items: UndoItem[], remote: SheetOp, unitId: string): number {\n if (isNoopSheetOp(remote)) return 0;\n let dropped = 0;\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i]!;\n let ok = true;\n for (const key of [\"undoMutations\", \"redoMutations\"] as const) {\n const list = item[key];\n if (!ok || !list?.length) continue;\n // operations (the selection a redo restores) are not content: they ride along untouched, after the edits\n const isOperation = (id: string) => !SHEET_MUTATIONS[id] && id.includes(\".operation.\");\n const operations = list.filter((m) => isOperation(m.id));\n const shaped = list.filter((m) => !isOperation(m.id)).map(travelingShape);\n if (shaped.some((m) => m === null)) {\n ok = false;\n continue;\n }\n if (!shaped.length) continue;\n try {\n const r = transformGroup(shaped as SheetMutation[], remote!, \"left\");\n if (isBarrier(r) || r.op.length === 0) {\n ok = false;\n continue;\n }\n if (JSON.stringify(r.op) === JSON.stringify(shaped)) continue; // untouched: keep Univer's own item\n item[key] = [...r.op.map((m) => ({ id: m.id, params: { ...forApply(m).params, unitId } })), ...operations];\n } catch {\n ok = false;\n }\n }\n if (!ok) {\n items.splice(i, 1);\n dropped++;\n }\n }\n return dropped;\n}\n\n// ── the adapter (shared by the room and the session fuzz) ─────────────────────────────────────────────\n\nexport interface SheetsOtAdapterHooks {\n /** Called once per applied remote op that rebased this seat's undo stacks (for tests and logs). */\n onUndoRebased?: (dropped: number) => void;\n}\n\n/** The `OpDocumentAdapter` over a sheets port, plus the held-remote queue the room drives. */\nexport interface SheetsOtAdapter extends OpDocumentAdapter<SheetOp> {\n /** Remote ops held while a local command runs. */\n held(): number;\n /** A local group finished while remote ops were held: rebase it over them and them over it (Docs IME rule). */\n rebaseLocalOverHeld(local: SheetMutation[]): SheetMutation[] | \"barrier\";\n clearHeld(): void;\n}\n\nexport function createSheetsOtAdapter(port: SheetsOtPort, hooks: SheetsOtAdapterHooks = {}): SheetsOtAdapter {\n /** Remote ops held while a local command runs, already rebased over the local groups captured meanwhile. */\n let queue: SheetMutation[][] = [];\n let draining = false;\n\n const applyNow = (op: SheetMutation[]) => {\n for (const m of op) port.applyRemote(m);\n let dropped = 0;\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n if (!stacks) continue;\n for (const map of [stacks.undo, stacks.redo]) {\n const items = map.get(t.unitId);\n if (items?.length) dropped += rebaseSheetUndoStack(items, op, t.unitId);\n }\n }\n hooks.onUndoRebased?.(dropped);\n port.markDirty();\n };\n\n const adapter: SheetsOtAdapter = {\n version: SHEET_TRANSFORMER_VERSION,\n transform: (x: SheetOp, y: SheetOp, side: \"left\" | \"right\") => transformSheetOp(x, y, side),\n compose: (a: SheetOp, b: SheetOp): SheetOp => [...(a ?? []), ...(b ?? [])],\n isNoop: isNoopSheetOp,\n encode: encodeSheetOp,\n decode: decodeSheetOp,\n apply(op: SheetOp) {\n if (isNoopSheetOp(op)) return true;\n if (port.busy() || queue.length) {\n queue.push(op!);\n if (!draining) {\n draining = true;\n port.whenIdle(() => {\n draining = false;\n const held = queue;\n queue = [];\n for (const q of held) applyNow(q);\n });\n }\n return true;\n }\n applyNow(op!);\n return true;\n },\n async load(snapshot: unknown) {\n queue = [];\n const current = port.snapshot();\n if (!(current && snapshot && canonicalSheetString(current) === canonicalSheetString(snapshot))) port.load(snapshot);\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n stacks?.undo.delete(t.unitId);\n stacks?.redo.delete(t.unitId);\n }\n },\n snapshot: () => port.snapshot(),\n async hash() {\n if (port.busy() || queue.length) {\n await new Promise<void>((resolve) => {\n const done = setTimeout(resolve, 5000);\n port.whenIdle(() => {\n clearTimeout(done);\n setTimeout(resolve, 0);\n });\n });\n }\n return sheetsStateHash(port.snapshot());\n },\n held: () => queue.length,\n rebaseLocalOverHeld(local) {\n let op: SheetMutation[] = local;\n const next: SheetMutation[][] = [];\n for (const q of queue) {\n const l2 = transformSheetOp(op, q, \"left\");\n const q2 = transformSheetOp(q, op, \"right\");\n if (\"barrier\" in l2 || \"barrier\" in q2) return \"barrier\";\n op = l2.op ?? [];\n if (q2.op?.length) next.push(q2.op);\n }\n queue = next;\n return op;\n },\n clearHeld() {\n queue = [];\n },\n };\n return adapter;\n}\n\n// ── the room ──────────────────────────────────────────────────────────────────────────────────────────\n\nexport interface OpenSheetsOtRoomOptions {\n port: SheetsOtPort;\n transport: OpTransport;\n clientId: string;\n presence?: OpPresence;\n /** `collab_replace` for this room (restore, whole import). */\n replace: (req: { snapshot: unknown; stateHash: string; clientId: string }) => Promise<{ rev: number; ref: string }>;\n onNotice?: (n: SheetsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n}\n\nexport interface SheetsOtRoom {\n session: OpSession<SheetOp>;\n /** The record's save: a checkpoint at a quiet point (§7.3). False when this seat does not write now. */\n write(reason: \"manual\" | string): Promise<boolean>;\n /** Restore / whole import through `collab_replace`. */\n replace(snapshot: unknown): Promise<void>;\n /** This seat is the one that saves on its own. */\n isSaver(): boolean;\n stop(): void;\n}\n\nexport function openSheetsOtRoom(o: OpenSheetsOtRoomOptions): SheetsOtRoom {\n const { port } = o;\n let session: OpSession<SheetOp> | null = null;\n const adapter = createSheetsOtAdapter(port);\n\n const notice = (n: SheetsOtNotice) => {\n try {\n o.onNotice?.(n);\n } catch (err) {\n console.warn(\"[sheets-ot] notice handler failed\", err);\n }\n };\n\n const onLocal = (e: SheetsLocalEvent) => {\n if (!session) return;\n if (e.kind === \"not_shared\") {\n // §6.3: an id without an allowlist never travels. Say so and put this seat back on the shared workbook.\n notice({ kind: \"not_shared\", mutationId: e.mutationId });\n adapter.clearHeld();\n session.rebuild(`not_shared:${e.mutationId}`);\n return;\n }\n if (!e.mutations.length) return;\n for (const m of e.mutations) {\n if (SHEET_MUTATIONS[m.id]?.kind !== \"covered\") {\n notice({ kind: \"not_shared\", mutationId: m.id });\n adapter.clearHeld();\n session.rebuild(`not_shared:${m.id}`);\n return;\n }\n }\n let op: SheetMutation[] = e.mutations;\n let inverse = e.inverse;\n if (adapter.held()) {\n // the editor does not hold the held remote ops yet: rebase this group over them, and them over it\n inverse = undefined;\n const r = adapter.rebaseLocalOverHeld(op);\n if (r === \"barrier\") {\n adapter.clearHeld();\n session.rebuild(\"held_barrier\");\n return;\n }\n op = r;\n if (!op.length) return;\n }\n if (!session.local(op, { ...(inverse !== undefined ? { inverse } : {}), label: e.label ?? SHEETS_EDIT_GROUP })) notice({ kind: \"not_live\" });\n };\n\n const unsubLocal = port.onLocal(onLocal);\n\n session = openOpSession<SheetOp>({\n transport: o.transport,\n adapter,\n proto: SHEETS_COLLAB_PROTO,\n clientId: o.clientId,\n ...(o.presence ? { presence: o.presence } : {}),\n onNotice: (n) => notice(n),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n\n const isSaver = () => {\n if (!o.presence) return true;\n return o.presence.peers().every((p) => p.clientId === o.clientId || p.clientId > o.clientId);\n };\n\n return {\n session,\n isSaver,\n async write(reason) {\n if (!session) return false;\n if (reason !== \"manual\" && !isSaver()) return false;\n const out = await session.save();\n if (out.saved) return true;\n if (out.reason === \"not_quiet\" || out.reason === \"changed\") setTimeout(() => port.markDirty(), 1500);\n return false;\n },\n async replace(snapshot) {\n port.load(snapshot);\n const loaded = port.snapshot();\n if (!loaded) throw new Error(\"The workbook is not open in this tab.\");\n const stateHash = await sheetsStateHash(loaded);\n await o.replace({ snapshot: loaded, stateHash, clientId: o.clientId });\n },\n stop() {\n unsubLocal();\n session?.close();\n },\n };\n}\n","/**\n * Sheet co-editing transforms (C5a): the shapes. Pure data; no Univer import.\n *\n * Convention (COLLAB-DESIGN §6.4): `transform(x, y, side)` returns `x` rewritten to apply AFTER `y`, where\n * `side` is x's side. The later-committed op always takes \"left\": it wins overwrites and sits first on\n * position ties.\n */\n\n/** One allowlisted Univer mutation as it travels: no `unitId` (the receiver re-addresses to its own unit). */\nexport interface SheetMutation {\n readonly id: string;\n readonly params: Readonly<Record<string, unknown>>;\n}\n\n/** A top-level command's mutations, applied in order. The unit the transformer works on. */\nexport type SheetGroup = readonly SheetMutation[];\n\nexport type Side = \"left\" | \"right\";\n\nexport interface Barrier {\n readonly barrier: true;\n readonly reason: string;\n}\n\nexport interface Transformed {\n /** x rewritten to apply after y; `[]` when nothing of x survives. */\n readonly op: SheetMutation[];\n /** Parts of the OTHER op (y) that x overrode: y's author is told (\"Sam changed B4 at the same time\"). */\n readonly lost: string[];\n /** Parts of x itself that cannot apply after y (an edit inside rows y removed): x's author is told. */\n readonly dropped: string[];\n}\n\nexport type TransformResult = Transformed | Barrier;\n\nexport const isBarrier = (r: TransformResult): r is Barrier => (r as Barrier).barrier === true;\n\nexport interface SheetRange {\n startRow: number;\n endRow: number;\n startColumn: number;\n endColumn: number;\n rangeType?: number;\n [k: string]: unknown;\n}\n","/**\n * The sheet mutation registry (COLLAB-DESIGN §10): every mutation id Univer 1.0.4 can emit into a workbook\n * is declared here exactly once, as covered (with its params allowlist), never-travels, or a barrier.\n * `census.test.ts` fails when an emitted id is missing or a declared id is stale.\n *\n * Covered in C5a: cell values and styles, row/column insert, remove and move, merge/unmerge, row height,\n * column width, worksheet name. C5b: formula text in cells (`f`, array `ref`) and defined names. Shared\n * formulas (`si`) stay barriers (see transform.ts cellBarrier); ranged resources are C5c.\n */\n\nexport type SheetFamily = \"cell\" | \"structure\" | \"merge\" | \"size\" | \"name\" | \"defname\";\n\nexport interface CoveredEntry {\n readonly kind: \"covered\";\n readonly family: SheetFamily;\n /** The params that travel. `unitId` never travels. */\n readonly allow: readonly string[];\n}\nexport interface NeverEntry {\n readonly kind: \"never-travels\";\n readonly reason: string;\n}\nexport interface BarrierEntry {\n readonly kind: \"barrier\";\n /** The unit that owns its transform (C5c resources) or \"X\" (no unit yet). */\n readonly until: \"C5c\" | \"X\";\n readonly reason: string;\n}\nexport type RegistryEntry = CoveredEntry | NeverEntry | BarrierEntry;\n\nconst covered = (family: SheetFamily, ...allow: string[]): CoveredEntry => ({ kind: \"covered\", family, allow: [\"subUnitId\", ...allow] });\nconst never = (reason: string): NeverEntry => ({ kind: \"never-travels\", reason });\nconst barrier = (until: BarrierEntry[\"until\"], reason: string): BarrierEntry => ({ kind: \"barrier\", until, reason });\n\nconst FORMULA_RESULT = \"formula engine output; every seat computes it (dropped at capture)\";\nconst RESOURCE = \"ranged resource keyed by id; C5c\";\nconst UNIVER_COMMENTS = \"Univer's own thread-comment store; our comments anchor elsewhere (design §8)\";\n\nexport const SHEET_MUTATIONS: Readonly<Record<string, RegistryEntry>> = {\n // ── covered (C5a) ────────────────────────────────────────────────────────────────────────────────\n \"sheet.mutation.set-range-values\": covered(\"cell\", \"cellValue\", \"refSheets\", \"derived\"),\n \"sheet.mutation.insert-row\": covered(\"structure\", \"range\", \"rowInfo\"),\n \"sheet.mutation.remove-rows\": covered(\"structure\", \"range\"),\n \"sheet.mutation.insert-col\": covered(\"structure\", \"range\", \"colInfo\"),\n \"sheet.mutation.remove-col\": covered(\"structure\", \"range\"),\n \"sheet.mutation.move-rows\": covered(\"structure\", \"sourceRange\", \"targetRange\"),\n \"sheet.mutation.move-columns\": covered(\"structure\", \"sourceRange\", \"targetRange\"),\n \"sheet.mutation.add-worksheet-merge\": covered(\"merge\", \"ranges\"),\n \"sheet.mutation.remove-worksheet-merge\": covered(\"merge\", \"ranges\"),\n \"sheet.mutation.set-worksheet-row-height\": covered(\"size\", \"ranges\", \"rowHeight\"),\n \"sheet.mutation.set-worksheet-row-is-auto-height\": covered(\"size\", \"ranges\", \"autoHeightInfo\"),\n \"sheet.mutation.set-worksheet-row-auto-height\": covered(\"size\", \"rowsAutoHeightInfo\"),\n \"sheet.mutation.set-worksheet-col-width\": covered(\"size\", \"ranges\", \"colWidth\"),\n \"sheet.mutation.set-worksheet-name\": covered(\"name\", \"name\"),\n\n // ── never travels ────────────────────────────────────────────────────────────────────────────────\n \"formula.mutation.set-formula-calculation-start\": never(FORMULA_RESULT),\n \"formula.mutation.set-trigger-formula-calculation-start\": never(FORMULA_RESULT),\n \"formula.mutation.set-formula-calculation-stop\": never(FORMULA_RESULT),\n \"formula.mutation.set-formula-calculation-notification\": never(FORMULA_RESULT),\n \"formula.mutation.set-formula-calculation-result\": never(FORMULA_RESULT),\n \"formula.mutation.set-array-formula-data\": never(FORMULA_RESULT),\n \"formula.mutation.set-formula-data\": never(FORMULA_RESULT),\n \"formula.mutation.set-image-formula-data\": never(FORMULA_RESULT),\n \"formula.mutation.set-formula-string-batch-calculation\": never(FORMULA_RESULT),\n \"formula.mutation.set-formula-string-batch-calculation-result\": never(FORMULA_RESULT),\n \"formula.mutation.set-formula-dependency-calculation\": never(FORMULA_RESULT),\n \"formula.mutation.set-formula-dependency-calculation-result\": never(FORMULA_RESULT),\n \"formula.mutation.set-cell-formula-dependency-calculation\": never(FORMULA_RESULT),\n \"formula.mutation.set-cell-formula-dependency-calculation-result\": never(FORMULA_RESULT),\n \"formula.mutation.set-query-formula-dependency\": never(FORMULA_RESULT),\n \"formula.mutation.set-query-formula-dependency-result\": never(FORMULA_RESULT),\n \"formula.mutation.set-query-formula-dependency-all\": never(FORMULA_RESULT),\n \"formula.mutation.set-query-formula-dependency-all-result\": never(FORMULA_RESULT),\n \"formula.mutation.register-function\": never(\"registers a function body on this seat's engine\"),\n \"sheet.mutation.data-validation-formula-mark-dirty\": never(\"dirty mark\"),\n \"sheet.mutation.mark-dirty-filter-change\": never(\"dirty mark\"),\n \"sheet.mutation.re-calc-filter\": never(\"filter recalculation result\"),\n \"sheet.mutation.toggle-note-popup\": never(\"popup state\"),\n \"sheet.operation.clear-drawing-transformer\": never(\"drawing selection handles (declared as a mutation)\"),\n \"sheet.mutation.copy-worksheet-end\": never(\"end marker of a copy; the copy travels as insert-sheet\"),\n \"sheet.mutation.empty\": never(\"no content\"),\n \"thread-comment.mutation.add-comment\": never(UNIVER_COMMENTS),\n \"thread-comment.mutation.update-comment\": never(UNIVER_COMMENTS),\n \"thread-comment.mutation.update-comment-ref\": never(UNIVER_COMMENTS),\n \"thread-comment.mutation.resolve-comment\": never(UNIVER_COMMENTS),\n \"thread-comment.mutation.delete-comment\": never(UNIVER_COMMENTS),\n\n // ── barriers: X (no transform yet, design §10) ───────────────────────────────────────────────────\n \"sheet.mutation.reorder-range\": barrier(\"X\", \"sort: a permutation, not transformed yet\"),\n \"sheet.mutation.set-worksheet-row-count\": barrier(\"X\", \"absolute row count; needs delta semantics\"),\n \"sheet.mutation.set-worksheet-column-count\": barrier(\"X\", \"absolute column count; needs delta semantics\"),\n \"sheet.mutation.set-worksheet-order\": barrier(\"X\", \"absolute sheet order; needs move semantics\"),\n \"sheet.mutation.move-range\": barrier(\"X\", \"cut-paste carries the sender's cell matrices\"),\n \"sheet.mutation.insert-sheet\": barrier(\"X\", \"sheet add: not in C5a\"),\n \"sheet.mutation.remove-sheet\": barrier(\"X\", \"sheet remove: not in C5a\"),\n \"sheet.mutation.set-worksheet-hidden\": barrier(\"X\", \"sheet-level setting: not in C5a\"),\n \"sheet.mutation.set-tab-color\": barrier(\"X\", \"sheet-level setting: not in C5a\"),\n \"sheet.mutation.set-workbook-name\": barrier(\"X\", \"workbook-level setting: not in C5a\"),\n \"sheet.mutation.set-worksheet-right-to-left\": barrier(\"X\", \"sheet-level setting: not in C5a\"),\n \"sheet.mutation.toggle-gridlines\": barrier(\"X\", \"sheet-level setting: not in C5a\"),\n \"sheet.mutation.set-gridlines-color\": barrier(\"X\", \"sheet-level setting: not in C5a\"),\n \"sheet.mutation.set-worksheet-default-style\": barrier(\"X\", \"sheet-level setting: not in C5a\"),\n \"sheet.mutation.set-frozen\": barrier(\"X\", \"absolute frozen indices: not in C5a\"),\n \"sheet.mutation.set-row-data\": barrier(\"X\", \"row properties by index: not in C5a\"),\n \"sheet.mutation.set-col-data\": barrier(\"X\", \"column properties by index: not in C5a\"),\n \"sheet.mutation.set-row-hidden\": barrier(\"X\", \"row visibility: not in C5a\"),\n \"sheet.mutation.set-row-visible\": barrier(\"X\", \"row visibility: not in C5a\"),\n \"sheet.mutation.set-col-hidden\": barrier(\"X\", \"column visibility: not in C5a\"),\n \"sheet.mutation.set-col-visible\": barrier(\"X\", \"column visibility: not in C5a\"),\n \"sheet.mutation.set.numfmt\": barrier(\"X\", \"number formats by range: not in C5a\"),\n \"sheet.mutation.remove.numfmt\": barrier(\"X\", \"number formats by range: not in C5a\"),\n \"sheet.mutation.add-range-protection\": barrier(\"X\", \"permissions: not in C5a\"),\n \"sheet.mutation.set-range-protection\": barrier(\"X\", \"permissions: not in C5a\"),\n \"sheet.mutation.delete-range-protection\": barrier(\"X\", \"permissions: not in C5a\"),\n \"sheet.mutation.add-worksheet-protection\": barrier(\"X\", \"permissions: not in C5a\"),\n \"sheet.mutation.set-worksheet-protection\": barrier(\"X\", \"permissions: not in C5a\"),\n \"sheet.mutation.delete-worksheet-protection\": barrier(\"X\", \"permissions: not in C5a\"),\n \"sheet.mutation.set-worksheet-permission-points\": barrier(\"X\", \"permissions: not in C5a\"),\n\n // ── formulas (C5b) ───────────────────────────────────────────────────────────────────────────────\n \"formula.mutation.set-defined-name\": covered(\"defname\", \"id\", \"name\", \"formulaOrRefString\", \"formulaOrRefStringWithPrefix\", \"comment\", \"localSheetId\", \"hidden\", \"refSheets\", \"previousName\", \"derived\"),\n \"formula.mutation.remove-defined-name\": covered(\"defname\", \"id\", \"name\"),\n \"formula.mutation.set-feature-calculation\": barrier(\"X\", \"a plugin's registered calculation (feature id + dependency ranges); no transform yet\"),\n \"formula.mutation.remove-feature-calculation\": barrier(\"X\", \"a plugin's registered calculation; no transform yet\"),\n \"formula.mutation.set-other-formula\": barrier(\"C5c\", \"formulas owned by conditional formats and data validation travel with their rule\"),\n \"formula.mutation.remove-other-formula\": barrier(\"C5c\", \"formulas owned by conditional formats and data validation travel with their rule\"),\n \"formula.mutation.set-super-table\": barrier(\"C5c\", \"table names in structured references belong to tables (C5c)\"),\n \"formula.mutation.remove-super-table\": barrier(\"C5c\", \"table names in structured references belong to tables (C5c)\"),\n \"formula.mutation.set-super-table-option\": barrier(\"C5c\", \"table names in structured references belong to tables (C5c)\"),\n\n // ── barriers until C5c (ranged resources) ────────────────────────────────────────────────────────\n \"sheet.mutation.add-conditional-rule\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-conditional-rule\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.delete-conditional-rule\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.move-conditional-rule\": barrier(\"C5c\", \"conditional-format priority (ordered list)\"),\n \"data-validation.mutation.addRule\": barrier(\"C5c\", RESOURCE),\n \"data-validation.mutation.updateRule\": barrier(\"C5c\", RESOURCE),\n \"data-validation.mutation.removeRule\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-filter-range\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-filter-criteria\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.remove-filter\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.add-table\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.delete-table\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-sheet-table\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-table-filter\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.move-table\": barrier(\"C5c\", RESOURCE),\n \"sheets.mutation.add-hyper-link\": barrier(\"C5c\", RESOURCE),\n \"sheets.mutation.remove-hyper-link\": barrier(\"C5c\", RESOURCE),\n \"sheets.mutation.update-hyper-link\": barrier(\"C5c\", RESOURCE),\n \"sheets.mutation.update-hyper-link-ref\": barrier(\"C5c\", RESOURCE),\n \"sheets.mutation.update-rich-hyper-link\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.update-note\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.remove-note\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.update-note-position\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-drawing-apply\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-worksheet-background-image\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.add-range-theme\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-range-theme\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.remove-range-theme\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.set-worksheet-range-theme-style\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.remove-worksheet-range-theme-style\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.register-worksheet-range-theme-style\": barrier(\"C5c\", RESOURCE),\n \"sheet.mutation.unregister-worksheet-range-theme-style\": barrier(\"C5c\", RESOURCE),\n};\n\n/** Keep only the allowlisted params of a covered id; anything else returns null (it does not travel). */\nexport function allowParams(id: string, params: Readonly<Record<string, unknown>>): Record<string, unknown> | null {\n const entry = SHEET_MUTATIONS[id];\n if (!entry || entry.kind !== \"covered\") return null;\n const out: Record<string, unknown> = {};\n for (const f of entry.allow) if (params[f] !== undefined) out[f] = params[f];\n return out;\n}\n","/**\n * The C5a sheet transformer: `transformGroup(x, y, side)` rewrites command group x to apply after group y.\n * Pure: no Univer runtime, no DOM. One rule (COLLAB-DESIGN §6.4): the later-committed op takes \"left\"; it\n * wins overwrites and sits first on position ties. Anything without a proven transform is a Barrier.\n *\n * Covered families: cell values and styles (set-range-values), row/column insert, remove and move,\n * merge/unmerge, row height / column width, worksheet name. See `registry.ts` for every other id.\n *\n * Merges: Univer moves merges two ways when rows or columns change. A listener in MergeCellController shifts\n * merges that sit wholly after the change on EVERY seat (no mutation travels); the command adds explicit\n * remove-merge / add-merge fixups for merges the change cuts through. `mergeThrough` reproduces both, so a\n * merge added concurrently is moved exactly as the command would have moved it.\n */\nimport { adjustRangeOnMutation } from \"@univerjs/sheets\";\nimport { type Axis, type AxisOp, mapIndex, runs, transformAxis } from \"./axis\";\nimport { type FormulaCtx, type RefChange, type RefSheets, REF_ERROR, formulaBarrier, isFormulaText, refSheetsAfter, refSheetsFor, rewriteFormula } from \"./formula\";\nimport { SHEET_MUTATIONS } from \"./registry\";\nimport { type Barrier, type SheetGroup, type SheetMutation, type SheetRange, type Side, type TransformResult, type Transformed, isBarrier } from \"./types\";\n\nexport const SHEET_TRANSFORMER_VERSION = \"c5b-1\";\n\nconst ID = {\n values: \"sheet.mutation.set-range-values\",\n insertRow: \"sheet.mutation.insert-row\",\n removeRows: \"sheet.mutation.remove-rows\",\n insertCol: \"sheet.mutation.insert-col\",\n removeCol: \"sheet.mutation.remove-col\",\n moveRows: \"sheet.mutation.move-rows\",\n moveCols: \"sheet.mutation.move-columns\",\n addMerge: \"sheet.mutation.add-worksheet-merge\",\n removeMerge: \"sheet.mutation.remove-worksheet-merge\",\n rowHeight: \"sheet.mutation.set-worksheet-row-height\",\n rowIsAuto: \"sheet.mutation.set-worksheet-row-is-auto-height\",\n rowAutoHeight: \"sheet.mutation.set-worksheet-row-auto-height\",\n colWidth: \"sheet.mutation.set-worksheet-col-width\",\n name: \"sheet.mutation.set-worksheet-name\",\n setName: \"formula.mutation.set-defined-name\",\n removeName: \"formula.mutation.remove-defined-name\",\n} as const;\n\n/**\n * Pairs the fuzz proved divergent (or that have no transform yet), as unordered mutation-id pairs, with the\n * failing seed. Each returns a Barrier until it has its own correct transform under a new proto.\n */\nexport const PAIR_BARRIERS: Readonly<Record<string, { seed: number | null; reason: string }>> = {};\n\nconst pairKey = (a: string, b: string) => (a < b ? `${a}|${b}` : `${b}|${a}`);\nconst barrier = (reason: string): Barrier => ({ barrier: true, reason });\nconst ok = (op: SheetMutation[], lost: string[] = [], dropped: string[] = []): Transformed => ({ op, lost, dropped });\nconst flip = (side: Side): Side => (side === \"left\" ? \"right\" : \"left\");\n\n// ── addressing ──────────────────────────────────────────────────────────────────────────────────────\nconst sheetOf = (m: SheetMutation) => String(m.params.subUnitId ?? \"\");\nfunction colName(c: number): string {\n let s = \"\";\n for (let n = c + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + ((n - 1) % 26)) + s;\n return s;\n}\nexport const cellRef = (sheet: string, row: number, col: number) => `${sheet}!${colName(col)}${row + 1}`;\nconst rangeRef = (sheet: string, r: SheetRange) =>\n `${sheet}!${colName(r.startColumn)}${r.startRow + 1}:${colName(r.endColumn)}${r.endRow + 1}`;\n\n// ── structural ops ──────────────────────────────────────────────────────────────────────────────────\ninterface Structural {\n axis: Axis;\n op: AxisOp;\n}\nfunction structuralOf(m: SheetMutation): Structural | null {\n const p = m.params as Record<string, SheetRange | undefined>;\n switch (m.id) {\n case ID.insertRow:\n return { axis: \"row\", op: { kind: \"insert\", at: p.range!.startRow, count: p.range!.endRow - p.range!.startRow + 1 } };\n case ID.removeRows:\n return { axis: \"row\", op: { kind: \"remove\", start: p.range!.startRow, count: p.range!.endRow - p.range!.startRow + 1 } };\n case ID.insertCol:\n return { axis: \"col\", op: { kind: \"insert\", at: p.range!.startColumn, count: p.range!.endColumn - p.range!.startColumn + 1 } };\n case ID.removeCol:\n return { axis: \"col\", op: { kind: \"remove\", start: p.range!.startColumn, count: p.range!.endColumn - p.range!.startColumn + 1 } };\n case ID.moveRows:\n return {\n axis: \"row\",\n op: { kind: \"move\", from: p.sourceRange!.startRow, count: p.sourceRange!.endRow - p.sourceRange!.startRow + 1, to: p.targetRange!.startRow },\n };\n case ID.moveCols:\n return {\n axis: \"col\",\n op: {\n kind: \"move\",\n from: p.sourceRange!.startColumn,\n count: p.sourceRange!.endColumn - p.sourceRange!.startColumn + 1,\n to: p.targetRange!.startColumn,\n },\n };\n default:\n return null;\n }\n}\n\nconst S = (axis: Axis) => (axis === \"row\" ? ([\"startRow\", \"endRow\"] as const) : ([\"startColumn\", \"endColumn\"] as const));\n\nfunction buildStructural(template: SheetMutation, axis: Axis, op: AxisOp): SheetMutation {\n const [a0, a1] = S(axis);\n const p = template.params as Record<string, unknown>;\n if (op.kind === \"move\") {\n const src = p.sourceRange as SheetRange;\n const tgt = p.targetRange as SheetRange;\n return {\n id: template.id,\n params: {\n ...p,\n sourceRange: { ...src, [a0]: op.from, [a1]: op.from + op.count - 1 },\n targetRange: { ...tgt, [a0]: op.to, [a1]: op.to + op.count - 1 },\n },\n };\n }\n const start = op.kind === \"insert\" ? op.at : op.start;\n return { id: template.id, params: { ...p, range: { ...(p.range as SheetRange), [a0]: start, [a1]: start + op.count - 1 } } };\n}\n\n/** The same structural op as a Univer mutation info, normalized to span the whole other axis, for Univer's helper. */\nfunction univerMutationInfo(axis: Axis, op: Exclude<AxisOp, { kind: \"move\" }>) {\n const FULL = { startRow: 0, endRow: Number.MAX_SAFE_INTEGER, startColumn: 0, endColumn: Number.MAX_SAFE_INTEGER };\n const start = op.kind === \"insert\" ? op.at : op.start;\n const range = axis === \"row\" ? { ...FULL, startRow: start, endRow: start + op.count - 1 } : { ...FULL, startColumn: start, endColumn: start + op.count - 1 };\n const id = op.kind === \"insert\" ? (axis === \"row\" ? ID.insertRow : ID.insertCol) : axis === \"row\" ? ID.removeRows : ID.removeCol;\n return { id, params: { unitId: \"\", subUnitId: \"\", range } };\n}\n\n// ── merges ──────────────────────────────────────────────────────────────────────────────────────────\nconst intersects = (a: SheetRange, b: SheetRange) =>\n a.startRow <= b.endRow && b.startRow <= a.endRow && a.startColumn <= b.endColumn && b.startColumn <= a.endColumn;\nconst isSingleCell = (r: SheetRange) => r.startRow === r.endRow && r.startColumn === r.endColumn;\n\n/**\n * Where Univer puts merge `m` when structural op `s` runs, and whether that move is a command fixup (a\n * traveling remove/add pair) rather than the seat-local listener shift. `null` = the merge is gone.\n */\nexport function mergeThrough(s: Structural, m: SheetRange): { range: SheetRange | null; fixup: boolean } {\n const [a0, a1] = S(s.axis);\n const lo = m[a0] as number;\n const hi = m[a1] as number;\n const op = s.op;\n if (op.kind === \"insert\") {\n // Univer's own helper is exact here once the insert spans the whole other axis.\n const fixup = lo < op.at && op.at <= hi;\n return { range: adjustRangeOnMutation(m, univerMutationInfo(s.axis, op)) as SheetRange, fixup };\n }\n if (op.kind === \"remove\") {\n const e = op.start + op.count - 1;\n if (e < lo || op.start > hi) return { range: adjustRangeOnMutation(m, univerMutationInfo(s.axis, op)) as SheetRange, fixup: false };\n // The command's own shrink rule (MergeCellController._handleRemove*Command), then a single cell is no merge.\n if (op.start <= lo && e >= hi) return { range: null, fixup: true };\n const r = { ...m };\n if (op.start >= lo && e <= hi) r[a1] = hi - op.count;\n else if (op.start < lo) {\n r[a0] = op.start;\n r[a1] = hi - op.count;\n } else r[a1] = op.start - 1;\n return { range: isSingleCell(r) ? null : r, fixup: true };\n }\n // move: the listener shifts merges clear of the source; the command moves merges wholly inside it; a merge\n // the source cuts through stays where it is (Univer refuses such moves on the sender's own seat).\n const fe = op.from + op.count - 1;\n if (hi < op.from || lo > fe) {\n const r = { ...m };\n if (op.from < lo && op.to > hi) {\n r[a0] = lo - op.count;\n r[a1] = hi - op.count;\n } else if (op.from > hi && op.to <= lo) {\n r[a0] = lo + op.count;\n r[a1] = hi + op.count;\n }\n return { range: r, fixup: false };\n }\n if (lo >= op.from && hi <= fe) {\n const r = { ...m, [a0]: mapIndex(op, lo)!, [a1]: mapIndex(op, hi)! };\n return { range: r, fixup: true };\n }\n return { range: m, fixup: false };\n}\n\n/**\n * Rewrites every remove-merge in a group to name the exact merges it removes. Univer removes every merge a\n * range intersects, and the unmerge command sends the SELECTION; a selection does not move the way the\n * merges under it move, so only exact merges transform correctly. `merges` is each sheet's mergeData right\n * before the group (C6 reads it in beforeCommandExecuted). Pure: the group is simulated, not applied.\n */\nexport function exactMergeRemovals(group: SheetGroup, merges: Readonly<Record<string, readonly SheetRange[]>>): SheetMutation[] {\n const sim = new Map<string, SheetRange[]>(Object.entries(merges).map(([k, v]) => [k, v.map((r) => ({ ...r }))]));\n const out: SheetMutation[] = [];\n for (const m of group) {\n const sheet = sheetOf(m);\n const cur = sim.get(sheet) ?? [];\n if (m.id === ID.removeMerge) {\n const hit = cur.filter((q) => mergeRanges(m).some((r) => intersects(r, q)));\n sim.set(sheet, cur.filter((q) => !hit.includes(q)));\n if (hit.length) out.push(withRanges(m, hit.map((r) => ({ ...r }))));\n continue;\n }\n if (m.id === ID.addMerge) sim.set(sheet, [...cur, ...mergeRanges(m).map((r) => ({ ...r }))]);\n const st = structuralOf(m);\n if (st) sim.set(sheet, cur.map((q) => mergeThrough(st, q).range).filter((q): q is SheetRange => q !== null));\n out.push(m);\n }\n return out;\n}\n\nconst mergeRanges = (m: SheetMutation) => (m.params.ranges as SheetRange[] | undefined) ?? [];\nconst withRanges = (m: SheetMutation, ranges: SheetRange[]): SheetMutation => ({ id: m.id, params: { ...m.params, ranges } });\nconst mergeMutation = (id: string, sheet: string, ranges: SheetRange[]): SheetMutation => ({ id, params: { subUnitId: sheet, ranges } });\n\n// ── cells ───────────────────────────────────────────────────────────────────────────────────────────\ntype Cell = Record<string, unknown> | null;\ntype CellMatrix = Record<string, Record<string, Cell>>;\n/** The content slot of a cell. A traveling entry that touches content must carry all of them (see completeCellContent). */\nexport const CONTENT_KEYS = [\"v\", \"t\", \"p\", \"f\", \"si\", \"custom\", \"ref\", \"xf\", \"ft\", \"fd\"] as const;\nconst CONTENT_TOUCH = [\"v\", \"p\", \"f\", \"si\", \"custom\", \"ref\", \"xf\", \"ft\", \"fd\"];\nconst KNOWN_CELL_KEYS = new Set<string>([...CONTENT_KEYS, \"s\"]);\n\n/**\n * Completes a captured cell entry's content slot from the sender's post-state, so content writes are full\n * replacements (an entry that sets `v` alone would otherwise keep a stale `p` on some seats). C6's capture\n * calls this per touched cell with the cell as it stands right after the command.\n */\nexport function completeCellContent(entry: Cell, post: Record<string, unknown> | null | undefined): Cell {\n if (entry === null) return null;\n if (!CONTENT_TOUCH.some((k) => k in entry)) return entry;\n const out: Record<string, unknown> = {};\n for (const k of CONTENT_KEYS) out[k] = post && post[k] !== undefined ? post[k] : null;\n if (out.v === null) delete out.t; // Univer stores no type without a value; t:null is not a content write\n if (\"s\" in entry) out.s = entry.s;\n return out;\n}\n\nfunction cellsOf(m: SheetMutation): CellMatrix {\n return (m.params.cellValue as CellMatrix | undefined) ?? {};\n}\nfunction forEachCell(cells: CellMatrix, fn: (r: number, c: number, v: Cell) => void) {\n for (const r of Object.keys(cells)) for (const c of Object.keys(cells[r] ?? {})) fn(Number(r), Number(c), cells[r]![c] ?? null);\n}\nfunction cellsMutation(template: SheetMutation, cells: CellMatrix): SheetMutation {\n return { id: template.id, params: { ...template.params, cellValue: cells } };\n}\nfunction putCell(cells: CellMatrix, r: number, c: number, v: Cell) {\n (cells[r] ??= {})[c] = v;\n}\nconst isEmptyMatrix = (cells: CellMatrix) => Object.values(cells).every((row) => Object.keys(row).length === 0);\n\n/** Why a set-range-values cannot be transformed by C5a, or null. */\nfunction cellBarrier(m: SheetMutation): string | null {\n if (m.params.isOverrideStyle) return \"set-range-values with isOverrideStyle (whole-style replace) is not covered\";\n let why: string | null = null;\n forEachCell(cellsOf(m), (_r, _c, v) => {\n if (why || v === null) return;\n for (const k of Object.keys(v)) {\n if (why) break;\n if (!KNOWN_CELL_KEYS.has(k)) why = `cell key \"${k}\" is not covered`;\n else if (k === \"si\" && v.si != null) why = \"shared formula (si): its text lives in a master cell this op does not carry\";\n else if ((k === \"f\" && isFormulaText(v.f)) || (k === \"ref\" && typeof v.ref === \"string\")) why = formulaBarrier(v[k] as string, formulaCtx(m));\n }\n if (typeof v.s === \"string\") why = \"a style id travels (style ids are seat-local; capture must send the style object)\";\n if (!why && CONTENT_TOUCH.some((k) => k in v) && !CONTENT_KEYS.every((k) => k in v || (k === \"t\" && v.v == null)))\n why = \"cell content is not completed (capture must call completeCellContent)\";\n });\n return why;\n}\n\nconst hasContent = (v: Record<string, unknown>) => CONTENT_TOUCH.some((k) => k in v);\nconst contentOf = (v: Record<string, unknown>) => {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v)) if (k !== \"s\") out[k] = v[k];\n return out;\n};\nconst richText = (v: Record<string, unknown>) => v.p != null;\n\n/** Style keys of a style object; borders count per side (\"bd.t\", \"bd.b\" …). */\nfunction styleKeys(s: Record<string, unknown>): string[] {\n const out: string[] = [];\n for (const k of Object.keys(s)) {\n if (k === \"bd\" && s.bd && typeof s.bd === \"object\") for (const side of Object.keys(s.bd)) out.push(`bd.${side}`);\n else out.push(k);\n }\n return out;\n}\nfunction withoutStyleKeys(s: Record<string, unknown>, drop: Set<string>): Record<string, unknown> | null {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(s)) {\n if (k === \"bd\" && s.bd && typeof s.bd === \"object\") {\n const bd: Record<string, unknown> = {};\n for (const side of Object.keys(s.bd)) if (!drop.has(`bd.${side}`)) bd[side] = (s.bd as Record<string, unknown>)[side];\n if (Object.keys(bd).length) out.bd = bd;\n } else if (!drop.has(k)) out[k] = s[k];\n }\n return Object.keys(out).length ? out : null;\n}\n\n/**\n * One cell touched by both x and y (same sheet). Returns x's entry after y as a list of entries applied in\n * order (a later entry re-applies what the other side keeps), plus what each side lost.\n */\nfunction transformCell(X: Cell, Y: Cell, side: Side): { entries: Cell[]; xLost: boolean; yLost: boolean } | string {\n // A null entry deletes the whole cell.\n if (X === null || Y === null) {\n if (side === \"left\") return { entries: [X], xLost: false, yLost: true };\n // x loses: a delete of x becomes delete-then-y; x's write on a cell y deleted is dropped.\n return X === null ? { entries: [null, Y], xLost: true, yLost: false } : { entries: [], xLost: true, yLost: false };\n }\n if ((hasContent(X) && richText(X) && \"s\" in Y) || (hasContent(Y) && richText(Y) && \"s\" in X))\n return \"rich-text content concurrent with a style change on the same cell is not covered\";\n const out: Record<string, unknown> = {};\n let xLost = false;\n let yLost = false;\n // content slot: later wins\n if (hasContent(X)) {\n if (!hasContent(Y) || side === \"left\") Object.assign(out, contentOf(X));\n else xLost = true;\n if (hasContent(Y) && side === \"left\") yLost = true;\n }\n // style slot: per key, later wins; a null style clears every key\n const tail: Cell[] = [];\n if (\"s\" in X) {\n const xs = X.s as Record<string, unknown> | null;\n const ys = \"s\" in Y ? (Y.s as Record<string, unknown> | null) : undefined;\n if (ys === undefined || side === \"left\") {\n if (xs !== undefined) out.s = xs;\n if (ys !== undefined) yLost = true;\n } else if (ys === null) {\n xLost = true; // y cleared every style key after x\n } else if (xs === null) {\n // x cleared styles, y (later) set some: clear, then put y's keys back\n out.s = null;\n tail.push({ s: ys });\n xLost = true;\n } else {\n const kept = withoutStyleKeys(xs, new Set(styleKeys(ys)));\n if (kept) out.s = kept;\n if (styleKeys(xs).length !== styleKeys(kept ?? {}).length) xLost = true;\n }\n }\n return { entries: Object.keys(out).length ? [out, ...tail] : tail, xLost, yLost };\n}\n\nfunction transformCellsOverCells(x: SheetMutation, y: SheetMutation, side: Side): TransformResult {\n if (sheetOf(x) !== sheetOf(y)) return ok([x]);\n const ycells = cellsOf(y);\n const xd = isDerived(x);\n const yd = isDerived(y);\n const eff = derivedSide(x, y, side);\n const passes: CellMatrix[] = [{}];\n const lost: string[] = [];\n const dropped: string[] = [];\n let why: string | null = null;\n forEachCell(cellsOf(x), (r, c, X) => {\n if (why) return;\n const yRow = ycells[r];\n if (!yRow || !(String(c) in yRow)) {\n putCell(passes[0]!, r, c, X);\n return;\n }\n const res = transformCell(X, yRow[c] ?? null, eff);\n if (typeof res === \"string\") {\n why = res;\n return;\n }\n res.entries.forEach((e, i) => putCell((passes[i] ??= {}), r, c, e));\n // a derived rewrite losing is nobody's loss: no notice\n if (res.xLost && !xd) dropped.push(cellRef(sheetOf(x), r, c));\n if (res.yLost && !yd) lost.push(cellRef(sheetOf(x), r, c));\n });\n if (why) return barrier(why);\n const op = passes.filter((p) => !isEmptyMatrix(p)).map((p) => cellsMutation(x, p));\n return ok(op, lost, dropped);\n}\n\n\n// ── formulas (C5b) ──────────────────────────────────────────────────────────────────────────────────\n/** Params that travel for the transformer only; `forApply` strips them before Univer sees the mutation. */\nexport const SIDE_CAR_PARAMS = [\"refSheets\", \"previousName\", \"derived\"] as const;\n\n/**\n * A derived mutation is a formula rewrite a structural op, a rename or a defined-name change carries for\n * formulas that already existed (Univer's interceptors). It never outranks a person's concurrent write to the\n * same cell or name, whichever committed first: the person's write is rewritten by the same change instead.\n */\nconst isDerived = (m: SheetMutation) => m.params.derived === true;\nfunction derivedSide(x: SheetMutation, y: SheetMutation, side: Side): Side {\n const xd = isDerived(x);\n const yd = isDerived(y);\n return xd === yd ? side : xd ? \"right\" : \"left\";\n}\nexport function forApply(m: SheetMutation): SheetMutation {\n if (!SIDE_CAR_PARAMS.some((k) => k in m.params)) return m;\n const params = { ...m.params };\n for (const k of SIDE_CAR_PARAMS) delete params[k];\n return { id: m.id, params };\n}\n\nconst refSheetsOf = (m: SheetMutation) => m.params.refSheets as RefSheets | undefined;\nconst formulaCtx = (m: SheetMutation): FormulaCtx => ({ ownSheet: sheetOf(m), refSheets: refSheetsOf(m) });\nfunction withRefSheets(params: Readonly<Record<string, unknown>>, rs: RefSheets | undefined): Record<string, unknown> {\n const out: Record<string, unknown> = { ...params };\n if (rs) out.refSheets = rs;\n else delete out.refSheets;\n return out;\n}\nconst hasFormulaText = (v: Cell) => !!v && (isFormulaText(v.f) || typeof v.ref === \"string\");\nfunction hasFormula(m: SheetMutation): boolean {\n let any = false;\n forEachCell(cellsOf(m), (_r, _c, v) => {\n any ||= hasFormulaText(v);\n });\n return any;\n}\nconst setNameWithoutPrevious = (m: SheetMutation) => m.id === ID.setName && !(\"previousName\" in m.params);\n\n/** The change a mutation makes to formula text elsewhere, or null. */\nfunction refChangeOf(m: SheetMutation): RefChange | null {\n const st = structuralOf(m);\n if (st) return { kind: \"axis\", sheet: sheetOf(m), axis: st.axis, op: st.op };\n if (m.id === ID.name) return { kind: \"rename\", sheet: sheetOf(m), name: String(m.params.name) };\n if (m.id === ID.removeName) return { kind: \"defined-name\", from: String(m.params.name), to: null };\n if (m.id === ID.setName && typeof m.params.previousName === \"string\" && m.params.previousName !== m.params.name)\n return { kind: \"defined-name\", from: m.params.previousName, to: String(m.params.name) };\n return null;\n}\n\n/** A cell entry's formula text (`f`) and array range (`ref`) after `change`. */\nfunction rewriteEntry(v: Record<string, unknown>, ctx: FormulaCtx, change: RefChange): { entry: Record<string, unknown>; changed: boolean } | string {\n let entry = v;\n let changed = false;\n for (const k of [\"f\", \"ref\"] as const) {\n const t = v[k];\n if (k === \"f\" ? !isFormulaText(t) : typeof t !== \"string\") continue;\n const r = rewriteFormula(t as string, ctx, change);\n if (typeof r === \"string\") return r;\n if (!r.changed) continue;\n if (k === \"ref\" && r.text.includes(REF_ERROR)) return \"an array formula's range was removed under it\";\n entry = { ...entry, [k]: r.text };\n changed = true;\n }\n return { entry, changed };\n}\n\n/** Where cell (r, c) of a mutation on `sheet` lands after `change`; null = removed. */\nfunction cellThrough(sheet: string, change: RefChange, r: number, c: number): [number, number] | null {\n if (change.kind !== \"axis\" || change.sheet !== sheet) return [r, c];\n const nr = change.axis === \"row\" ? mapIndex(change.op, r) : r;\n const nc = change.axis === \"col\" ? mapIndex(change.op, c) : c;\n return nr === null || nc === null ? null : [nr, nc];\n}\n\n/** Cell op x after a structural op, a rename or a defined-name change: cells move, formula text is rewritten. */\nfunction cellsOverChange(x: SheetMutation, change: RefChange): TransformResult {\n const ctx = formulaCtx(x);\n const out: CellMatrix = {};\n const dropped: string[] = [];\n let why: string | null = null;\n forEachCell(cellsOf(x), (r, c, v) => {\n if (why) return;\n const at = cellThrough(sheetOf(x), change, r, c);\n if (!at) {\n dropped.push(cellRef(sheetOf(x), r, c));\n return;\n }\n let e = v;\n if (hasFormulaText(v)) {\n const res = rewriteEntry(v!, ctx, change);\n if (typeof res === \"string\") {\n why = res;\n return;\n }\n e = res.entry;\n }\n putCell(out, at[0], at[1], e);\n });\n if (why) return barrier(why);\n const params = { ...withRefSheets(x.params, refSheetsAfter(ctx.refSheets, change)), cellValue: out };\n return ok(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);\n}\n\n/**\n * The formula rewrites a change owes to cell op y's formulas: what Univer's interceptor would have written had\n * y's formulas been there when the change was made. Placed after the change, at the cells' new positions.\n */\nfunction rewritesOf(y: SheetMutation, change: RefChange): SheetMutation | null | string {\n const ctx = formulaCtx(y);\n const out: CellMatrix = {};\n let why: string | null = null;\n forEachCell(cellsOf(y), (r, c, v) => {\n if (why || !hasFormulaText(v)) return;\n const at = cellThrough(sheetOf(y), change, r, c);\n if (!at) return;\n const res = rewriteEntry(v!, ctx, change);\n if (typeof res === \"string\") {\n why = res;\n return;\n }\n if (res.changed) putCell(out, at[0], at[1], contentOf(res.entry));\n });\n if (why) return why;\n if (isEmptyMatrix(out)) return null;\n return { id: ID.values, params: withRefSheets({ subUnitId: sheetOf(y), cellValue: out, derived: true }, refSheetsAfter(ctx.refSheets, change)) };\n}\n\nconst NAME_TEXT_KEYS = [\"formulaOrRefString\", \"formulaOrRefStringWithPrefix\"] as const;\n/** A set-defined-name after a structural op or a rename (sheets-formula UpdateDefinedNameController rules). */\nfunction definedNameThrough(m: SheetMutation, change: RefChange): { op: SheetMutation; changed: boolean } | string {\n if (change.kind === \"defined-name\" || m.id !== ID.setName) return { op: m, changed: false };\n // Univer resolves a defined name's unqualified references against the changed sheet and keeps qualifiers.\n const ctx: FormulaCtx = { ownSheet: change.sheet, refSheets: refSheetsOf(m), keepQualifier: true };\n const params: Record<string, unknown> = { ...m.params };\n let changed = false;\n for (const k of NAME_TEXT_KEYS) {\n if (typeof params[k] !== \"string\" || !params[k]) continue;\n const r = rewriteFormula(params[k] as string, ctx, change);\n if (typeof r === \"string\") return r;\n if (r.changed) {\n params[k] = r.text;\n changed = true;\n }\n }\n return { op: { id: m.id, params: withRefSheets(params, refSheetsAfter(ctx.refSheets, change)) }, changed };\n}\nfunction asDerived(m: SheetMutation): SheetMutation {\n return { id: m.id, params: { ...m.params, derived: true } };\n}\n\n/** Formula-aware pairs (C5b). null = not a formula pair; the C5a rules apply. */\nfunction formulaPair(x: SheetMutation, y: SheetMutation, side: Side): TransformResult | null {\n const fx = familyOf(x.id);\n const fy = familyOf(y.id);\n const SET_NAME_BARRIER = \"set-defined-name without previousName (capture must record the name it replaces) against formula text\";\n if (fx === \"defname\" && fy === \"defname\") {\n if (String(x.params.id) !== String(y.params.id)) return ok([x]);\n const eff = derivedSide(x, y, side);\n if (eff === \"left\") return ok([x], isDerived(y) ? [] : [`defined name \"${String(y.params.name)}\"`]);\n return ok([], [], isDerived(x) ? [] : [`defined name \"${String(x.params.name)}\"`]);\n }\n if (fx === \"defname\") {\n if (fy === \"cell\") {\n if (setNameWithoutPrevious(x) && hasFormula(y)) return barrier(SET_NAME_BARRIER);\n const ch = refChangeOf(x);\n if (!ch) return ok([x]);\n const add = rewritesOf(y, ch);\n if (typeof add === \"string\") return barrier(add);\n return ok(add ? [x, add] : [x]);\n }\n const ch = refChangeOf(y);\n if (!ch) return ok([x]);\n const r = definedNameThrough(x, ch);\n return typeof r === \"string\" ? barrier(r) : ok([r.op]);\n }\n if (fy === \"defname\") {\n if (fx === \"cell\") {\n if (setNameWithoutPrevious(y) && hasFormula(x)) return barrier(SET_NAME_BARRIER);\n const ch = refChangeOf(y);\n return ch ? cellsOverChange(x, ch) : ok([x]);\n }\n const ch = refChangeOf(x);\n if (!ch) return ok([x]);\n const r = definedNameThrough(y, ch);\n if (typeof r === \"string\") return barrier(r);\n return ok(r.changed ? [x, asDerived(r.op)] : [x]);\n }\n if (fx === \"cell\") {\n const ch = refChangeOf(y);\n return ch ? cellsOverChange(x, ch) : null;\n }\n if (fy === \"cell\") {\n const ch = refChangeOf(x);\n if (!ch) return null;\n // x removes rows/columns holding y's cells: y's author is told (S3).\n const lost: string[] = [];\n forEachCell(cellsOf(y), (r, c) => {\n if (!cellThrough(sheetOf(y), ch, r, c)) lost.push(cellRef(sheetOf(y), r, c));\n });\n const add = rewritesOf(y, ch);\n if (typeof add === \"string\") return barrier(add);\n return ok(add ? [x, add] : [x], lost);\n }\n return null;\n}\n\nconst withPrevious = (m: SheetMutation, definedNames: Readonly<Record<string, string>>): SheetMutation =>\n m.id === ID.setName && !(\"previousName\" in m.params) ? { id: m.id, params: { ...m.params, previousName: definedNames[String(m.params.id)] ?? null } } : m;\n\n/**\n * Capture-time annotation (C6 calls it per group, like completeCellContent): every op whose formula text\n * qualifies a reference with a sheet name gets `refSheets`, and every set-defined-name gets `previousName`\n * (the name its id had before the command; null for a new name). Rewrites that follow a structural op, a\n * rename or a defined-name change in the same group are marked `derived`. `sheets` is sheet id → name and\n * `definedNames` defined-name id → name, both read right before the command ran.\n */\nexport function annotateFormulas(group: SheetGroup, sheets: Readonly<Record<string, string>>, definedNames: Readonly<Record<string, string>>): SheetMutation[] {\n let changed = false;\n return group.map((m0) => {\n // Everything a structural op, rename or defined-name change brings after it is its interceptors' rewrites.\n const m = changed && (m0.id === ID.values || m0.id === ID.setName) ? asDerived(m0) : m0;\n if (!changed && refChangeOf(withPrevious(m0, definedNames))) changed = true;\n if (m.id === ID.values) {\n const texts: string[] = [];\n forEachCell(cellsOf(m), (_r, _c, v) => {\n if (v && isFormulaText(v.f)) texts.push(v.f);\n if (v && typeof v.ref === \"string\") texts.push(v.ref);\n });\n return { id: m.id, params: withRefSheets(m.params, refSheetsFor(texts, sheets)) };\n }\n if (m.id === ID.setName) {\n const texts = NAME_TEXT_KEYS.map((k) => m.params[k]).filter((t): t is string => typeof t === \"string\");\n return { id: m.id, params: { ...withRefSheets(m.params, refSheetsFor(texts, sheets)), previousName: withPrevious(m, definedNames).params.previousName } };\n }\n return m;\n });\n}\n\n// ── sizes (row height, auto-height flag, auto height, column width) ────────────────────────────────\ninterface SizeOp {\n axis: Axis;\n attr: string;\n values: Map<number, unknown>;\n}\nfunction sizeOf(m: SheetMutation): SizeOp {\n const p = m.params as Record<string, unknown>;\n const values = new Map<number, unknown>();\n if (m.id === ID.rowAutoHeight) {\n for (const { row, autoHeight } of (p.rowsAutoHeightInfo as Array<{ row: number; autoHeight: unknown }>) ?? []) values.set(row, autoHeight);\n return { axis: \"row\", attr: \"ah\", values };\n }\n const axis: Axis = m.id === ID.colWidth ? \"col\" : \"row\";\n const field = m.id === ID.colWidth ? \"colWidth\" : m.id === ID.rowHeight ? \"rowHeight\" : \"autoHeightInfo\";\n const value = p[field];\n const [a0, a1] = S(axis);\n for (const r of (p.ranges as SheetRange[]) ?? [])\n for (let i = r[a0] as number; i <= (r[a1] as number); i++) {\n if (typeof value === \"number\") values.set(i, value);\n else if (m.id === ID.rowIsAuto) values.set(i, (value as Record<number, unknown> | undefined)?.[i]);\n else if ((value as Record<number, unknown> | undefined)?.[i] != null) values.set(i, (value as Record<number, unknown>)[i]);\n }\n return { axis, attr: m.id === ID.colWidth ? \"w\" : m.id === ID.rowHeight ? \"h\" : \"ia\", values };\n}\nfunction buildSize(template: SheetMutation, values: Map<number, unknown>): SheetMutation | null {\n if (values.size === 0) return null;\n const p = template.params as Record<string, unknown>;\n if (template.id === ID.rowAutoHeight)\n return { id: template.id, params: { ...p, rowsAutoHeightInfo: [...values].sort((a, b) => a[0] - b[0]).map(([row, autoHeight]) => ({ row, autoHeight })) } };\n const axis: Axis = template.id === ID.colWidth ? \"col\" : \"row\";\n const field = template.id === ID.colWidth ? \"colWidth\" : template.id === ID.rowHeight ? \"rowHeight\" : \"autoHeightInfo\";\n const [a0, a1] = S(axis);\n const first = ((p.ranges as SheetRange[]) ?? [])[0] ?? ({ startRow: 0, endRow: 0, startColumn: 0, endColumn: 0 } as SheetRange);\n const ranges = runs(values.keys()).map((r) => ({ ...first, [a0]: r.start, [a1]: r.start + r.count - 1 }));\n const uniform = typeof p[field] === \"number\" ? p[field] : undefined;\n const value = uniform !== undefined && [...values.values()].every((v) => v === uniform) ? uniform : Object.fromEntries(values);\n return { id: template.id, params: { ...p, ranges, [field]: value } };\n}\n\n// ── the pair transform ──────────────────────────────────────────────────────────────────────────────\nfunction familyOf(id: string): string {\n const e = SHEET_MUTATIONS[id];\n return e && e.kind === \"covered\" ? e.family : \"\";\n}\n\n/** x over y for single mutations. */\nexport function transformMutation(x: SheetMutation, y: SheetMutation, side: Side): TransformResult {\n for (const m of [x, y]) {\n const e = SHEET_MUTATIONS[m.id];\n if (!e) return barrier(`${m.id} is not in the registry`);\n if (e.kind !== \"covered\") return barrier(`${m.id}: ${e.kind === \"barrier\" ? `barrier until ${e.until} (${e.reason})` : \"never travels\"}`);\n if (m.id === ID.values) {\n const why = cellBarrier(m);\n if (why) return barrier(why);\n }\n }\n const pb = PAIR_BARRIERS[pairKey(x.id, y.id)];\n if (pb) return barrier(`${x.id} × ${y.id}: ${pb.reason}${pb.seed === null ? \"\" : ` (fuzz seed ${pb.seed})`}`);\n const fp = formulaPair(x, y, side);\n if (fp) return fp;\n if (sheetOf(x) !== sheetOf(y)) return ok([x]);\n\n const fx = familyOf(x.id);\n const fy = familyOf(y.id);\n const sy = structuralOf(y);\n const sx = structuralOf(x);\n\n // structural over structural\n if (sx && sy) {\n if (sx.axis !== sy.axis) return ok([x]);\n const out = transformAxis(sx.op, sy.op, side);\n if (!out) return barrier(`${x.id} over ${y.id}: moved blocks overlap in part, or the block would split`);\n const dropped = out.length === 0 && sx.op.kind === \"move\" ? [`${sheetOf(x)}: moved ${sx.axis}s`] : [];\n return ok(out.map((o) => buildStructural(x, sx.axis, o)), [], dropped);\n }\n\n // anything over structural: coordinates move\n if (sy) {\n if (fx === \"merge\") {\n const kept: SheetRange[] = [];\n const dropped: string[] = [];\n for (const r of mergeRanges(x)) {\n const t = mergeThrough(sy, r).range;\n if (t) kept.push(t);\n else dropped.push(rangeRef(sheetOf(x), r));\n }\n return ok(kept.length ? [withRanges(x, kept)] : [], [], x.id === ID.addMerge ? dropped : []);\n }\n if (fx === \"size\") {\n const size = sizeOf(x);\n if (size.axis !== sy.axis) return ok([x]);\n const next = new Map<number, unknown>();\n for (const [i, v] of size.values) {\n const m = mapIndex(sy.op, i);\n if (m !== null) next.set(m, v);\n }\n const built = buildSize(x, next);\n return ok(built ? [built] : []);\n }\n return ok([x]); // name\n }\n\n // structural over others\n if (sx) {\n if (fy !== \"merge\" || y.id !== ID.addMerge) return ok([x]);\n // y added merges this seat already holds; the raw structural mutation leaves the ones it cuts through\n // where they were, so the fixups the command would have made travel with x.\n const remove: SheetRange[] = [];\n const add: SheetRange[] = [];\n for (const r of mergeRanges(y)) {\n const t = mergeThrough(sx, r);\n if (!t.fixup) continue;\n remove.push(r);\n if (t.range) add.push(t.range);\n }\n const lostMerges = mergeRanges(y).filter((r) => mergeThrough(sx, r).range === null).map((r) => rangeRef(sheetOf(y), r));\n if (!remove.length) return ok([x], lostMerges);\n const sheet = sheetOf(x);\n const pre = sx.op.kind === \"insert\" ? [] : [mergeMutation(ID.removeMerge, sheet, remove)];\n const mid = sx.op.kind === \"insert\" ? [mergeMutation(ID.removeMerge, sheet, remove)] : [];\n return ok([...pre, x, ...mid, ...(add.length ? [mergeMutation(ID.addMerge, sheet, add)] : [])], lostMerges);\n }\n\n if (fx === \"cell\" && fy === \"cell\") return transformCellsOverCells(x, y, side);\n\n if (fx === \"merge\" && fy === \"merge\") {\n const xr = mergeRanges(x);\n const yr = mergeRanges(y);\n const hit = (r: SheetRange) => yr.some((q) => intersects(r, q));\n const sheet = sheetOf(x);\n if (x.id === ID.addMerge && y.id === ID.addMerge) {\n if (!xr.some(hit)) return ok([x]);\n if (side === \"left\") {\n // the later merge stands: clear what it overlaps, then add it\n const lost = yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q));\n return ok([mergeMutation(ID.removeMerge, sheet, xr.filter(hit)), x], lost);\n }\n const kept = xr.filter((r) => !hit(r));\n return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));\n }\n if (x.id === ID.addMerge && y.id === ID.removeMerge) {\n if (side === \"left\" || !xr.some(hit)) return ok([x], side === \"left\" && xr.some(hit) ? yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q)) : []);\n const kept = xr.filter((r) => !hit(r));\n return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));\n }\n if (x.id === ID.removeMerge && y.id === ID.addMerge) {\n // Univer removes every merge a range intersects, so x would also take y's merge with it.\n const touched = yr.filter((q) => xr.some((r) => intersects(r, q)));\n if (!touched.length) return ok([x]);\n if (side === \"left\") return ok([x], touched.map((q) => rangeRef(sheet, q)));\n return ok([x, mergeMutation(ID.addMerge, sheet, touched)], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));\n }\n return ok([x]); // remove over remove: idempotent\n }\n\n if (fx === \"size\" && fy === \"size\") {\n const a = sizeOf(x);\n const b = sizeOf(y);\n if (a.axis !== b.axis || a.attr !== b.attr) return ok([x]);\n if (side === \"left\") {\n const lost = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);\n return ok([x], lost);\n }\n const next = new Map([...a.values].filter(([i]) => !b.values.has(i)));\n const built = buildSize(x, next);\n const dropped = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);\n return ok(built ? [built] : [], [], dropped);\n }\n\n if (fx === \"name\" && fy === \"name\") {\n if (side === \"left\") return ok([x], [`${sheetOf(x)}: name \"${String(y.params.name)}\"`]);\n return ok([], [], [`${sheetOf(x)}: name \"${String(x.params.name)}\"`]);\n }\n\n // different families of different kinds commute (cells × merges, cells × sizes, merges × sizes, name × any)\n return ok([x]);\n}\n\n// ── groups ──────────────────────────────────────────────────────────────────────────────────────────\ninterface Acc {\n lost: string[];\n dropped: string[];\n}\ntype Pair = [SheetMutation[], SheetMutation[]] | Barrier;\nconst blocked = (p: Pair): p is Barrier => !Array.isArray(p);\n\n/** Transforms two sequences against each other: [xs after ys, ys after xs]. */\nfunction tSeq(xs: SheetMutation[], ys: SheetMutation[], side: Side, acc: Acc): Pair {\n if (xs.length === 0 || ys.length === 0) return [xs, ys];\n if (xs.length === 1 && ys.length === 1) {\n const a = transformMutation(xs[0]!, ys[0]!, side);\n if (isBarrier(a)) return a;\n const b = transformMutation(ys[0]!, xs[0]!, flip(side));\n if (isBarrier(b)) return b;\n acc.lost.push(...a.lost);\n acc.dropped.push(...a.dropped);\n return [a.op, b.op];\n }\n if (xs.length > 1) {\n const first = tSeq([xs[0]!], ys, side, acc);\n if (blocked(first)) return first;\n const rest = tSeq(xs.slice(1), first[1], side, acc);\n if (blocked(rest)) return rest;\n return [[...first[0], ...rest[0]], rest[1]];\n }\n const first = tSeq(xs, [ys[0]!], side, acc);\n if (blocked(first)) return first;\n const rest = tSeq(first[0], ys.slice(1), side, acc);\n if (blocked(rest)) return rest;\n return [rest[0], [...first[1], ...rest[1]]];\n}\n\n/** Command group x rewritten to apply after command group y. One Barrier makes the whole group a barrier. */\nexport function transformGroup(x: SheetGroup, y: SheetGroup, side: Side): TransformResult {\n const acc: Acc = { lost: [], dropped: [] };\n const r = tSeq([...x], [...y], side, acc);\n if (blocked(r)) return r;\n return { op: r[0], lost: [...new Set(acc.lost)], dropped: [...new Set(acc.dropped)] };\n}\n\n/** The OpTransformer the C2 session takes (`@ai-matrx/data/realtime/collab`), for sheet command groups. */\nexport const sheetTransformer = {\n version: SHEET_TRANSFORMER_VERSION,\n transform(x: SheetGroup, y: SheetGroup, side: Side): { op: SheetMutation[] | null; lost: string[]; dropped: string[] } | Barrier {\n const r = transformGroup(x, y, side);\n if (isBarrier(r)) return r;\n return { op: r.op.length ? r.op : null, lost: r.lost, dropped: r.dropped };\n },\n compose(a: SheetGroup, b: SheetGroup): SheetMutation[] {\n return [...a, ...b];\n },\n isNoop(op: SheetGroup): boolean {\n return op.length === 0;\n },\n};\n","/**\n * One-dimensional structural algebra for rows and columns: insert, remove and move, the index map each\n * induces, and S-over-S transforms. Index arithmetic is ours (not Univer's ref-range helpers) because ties\n * need the side rule and overlapping removes must subtract, which no free helper does.\n *\n * Semantics pinned to Univer 1.0.4:\n * - insert(at, n): new rows occupy [at, at+n); old row i >= at moves to i+n (the row AT `at` moves down).\n * - remove(start, n): rows [start, start+n) go; i >= start+n moves to i-n.\n * - move(from, n, to): `moveMatrixArray` — rows [from, from+n) are placed before old row `to`. Forward\n * (to >= from+n): block lands at [to-n, to). Backward (to < from): block lands at [to, to+n). A `to` in\n * [from, from+n] moves nothing (Univer throws for [from, from+n)); we treat it as a no-op.\n */\nimport type { Side } from \"./types\";\n\nexport type Axis = \"row\" | \"col\";\n\nexport type AxisOp =\n | { kind: \"insert\"; at: number; count: number }\n | { kind: \"remove\"; start: number; count: number }\n | { kind: \"move\"; from: number; count: number; to: number };\n\nexport function isNoopMove(op: { from: number; count: number; to: number }): boolean {\n return op.count <= 0 || (op.to >= op.from && op.to <= op.from + op.count);\n}\n\n/** Where the moved block starts after the move. */\nexport function movedBlockStart(op: { from: number; count: number; to: number }): number {\n return op.to > op.from ? op.to - op.count : op.to;\n}\n\n/** Old index → new index, or null when the index is removed. */\nexport function mapIndex(op: AxisOp, i: number): number | null {\n switch (op.kind) {\n case \"insert\":\n return i >= op.at ? i + op.count : i;\n case \"remove\":\n if (i < op.start) return i;\n if (i < op.start + op.count) return null;\n return i - op.count;\n case \"move\": {\n if (isNoopMove(op)) return i;\n const { from, count, to } = op;\n if (i >= from && i < from + count) return movedBlockStart(op) + (i - from);\n if (to > from) return i >= from + count && i < to ? i - count : i;\n return i >= to && i < from ? i + count : i;\n }\n }\n}\n\n/** Contiguous runs of a sorted, de-duplicated index list. */\nexport function runs(indices: Iterable<number>): Array<{ start: number; count: number }> {\n const sorted = [...new Set(indices)].sort((a, b) => a - b);\n const out: Array<{ start: number; count: number }> = [];\n for (const i of sorted) {\n const last = out[out.length - 1];\n if (last && last.start + last.count === i) last.count++;\n else out.push({ start: i, count: 1 });\n }\n return out;\n}\n\n/**\n * A gap (insert position: \"before old row p\") through a move. Gaps strictly inside the block ride with\n * it; any other gap is a gap of the non-block rows. At the move's own target gap an insert lands BEFORE\n * the block (side-independent; `transformAxis(move, insert)` keeps the same order).\n */\nfunction mapGapThroughMove(p: number, mv: { from: number; count: number; to: number }): number {\n const { from, count, to } = mv;\n if (p > from && p < from + count) return movedBlockStart(mv) + (p - from);\n const g = p <= from ? p : p - count; // gap index among the non-block rows\n const tg = to <= from ? to : to - count;\n return g <= tg ? g : g + count;\n}\n\n/**\n * x over y on ONE axis. Returns the list of axis ops that apply after y (empty = x vanished), or null when\n * the pair has no transform (the caller turns that into a barrier).\n */\nexport function transformAxis(x: AxisOp, y: AxisOp, side: Side): AxisOp[] | null {\n if (y.kind === \"move\" && isNoopMove(y)) return [x];\n if (x.kind === \"move\" && isNoopMove(x)) return [];\n switch (x.kind) {\n case \"insert\": {\n if (y.kind === \"insert\") {\n if (x.at < y.at || (x.at === y.at && side === \"left\")) return [x];\n return [{ ...x, at: x.at + y.count }];\n }\n if (y.kind === \"remove\") {\n if (x.at <= y.start) return [x];\n if (x.at >= y.start + y.count) return [{ ...x, at: x.at - y.count }];\n return [{ ...x, at: y.start }]; // an insert inside a removed span survives at its start\n }\n return [{ ...x, at: mapGapThroughMove(x.at, y) }];\n }\n case \"remove\": {\n const kept: number[] = [];\n for (let i = x.start; i < x.start + x.count; i++) {\n const m = mapIndex(y, i);\n if (m !== null) kept.push(m);\n }\n if (y.kind === \"insert\" || y.kind === \"remove\" || y.kind === \"move\") {\n // Removes are emitted highest first so each index is still valid when it applies.\n return runs(kept)\n .reverse()\n .map((r) => ({ kind: \"remove\" as const, start: r.start, count: r.count }));\n }\n return null;\n }\n case \"move\": {\n if (y.kind === \"insert\") {\n const inside = y.at > x.from && y.at < x.from + x.count;\n const from = inside || y.at > x.from ? x.from : x.from + y.count;\n const count = inside ? x.count + y.count : x.count;\n const to = x.to >= y.at ? x.to + y.count : x.to;\n const out = { kind: \"move\" as const, from, count, to };\n return isNoopMove(out) ? [] : [out];\n }\n if (y.kind === \"remove\") {\n const kept: number[] = [];\n for (let i = x.from; i < x.from + x.count; i++) {\n const m = mapIndex(y, i);\n if (m !== null) kept.push(m);\n }\n if (kept.length === 0) return [];\n const r = runs(kept);\n if (r.length !== 1) return null;\n const to = x.to <= y.start ? x.to : x.to >= y.start + y.count ? x.to - y.count : y.start;\n const out = { kind: \"move\" as const, from: r[0]!.start, count: r[0]!.count, to };\n return isNoopMove(out) ? [] : [out];\n }\n // move over move. The same rows moved twice: the later move wins, the earlier one is dropped.\n // Blocks that only partly overlap have no transform yet.\n const overlap = Math.min(x.from + x.count, y.from + y.count) - Math.max(x.from, y.from);\n if (overlap > 0) {\n if (x.from !== y.from || x.count !== y.count) return null;\n if (side === \"right\") return [];\n const out = { kind: \"move\" as const, from: movedBlockStart(y), count: x.count, to: mapGapThroughMove(x.to, y) };\n return isNoopMove(out) ? [] : [out];\n }\n // Disjoint blocks: x's rows through y must stay contiguous; the target gap goes through y.\n const mapped: number[] = [];\n for (let i = x.from; i < x.from + x.count; i++) mapped.push(mapIndex(y, i)!);\n const r = runs(mapped);\n if (r.length !== 1) return null;\n let to: number;\n if (x.to > y.from && x.to < y.from + y.count) to = movedBlockStart(y) + (x.to - y.from);\n else to = mapGapThroughMove(x.to, y) + (x.to === y.to && side === \"right\" ? y.count : 0); // same target: later block first\n const out = { kind: \"move\" as const, from: r[0]!.start, count: r[0]!.count, to };\n if (to > out.from && to < out.from + out.count) return null;\n return isNoopMove(out) ? [] : [out];\n }\n }\n}\n","/**\n * C5b: formula references under concurrent structural edits and sheet renames. Pure: Univer's free formula\n * lexer (`LexerTreeBuilder.sequenceNodesBuilder`) reads the text, Univer's free ref-range helpers from\n * `@univerjs/sheets` move each reference, and the rewrite mirrors `@univerjs/sheets-formula` 1.0.4\n * (`getNewRangeByMoveParam`, `getMoveNewRange`, `checkMoveEdge`, `updateRefOffset`; Apache-2.0, ported because\n * sheets-formula exports none of them). A concurrent formula therefore ends up exactly as Univer's own\n * interceptor would have rewritten it had the two edits been made one after the other.\n *\n * Sheet names: formula text names sheets, ops name sheet ids. Every traveling op whose formula text carries a\n * sheet-qualified reference holds `refSheets` (name → sheet id, null for a name no sheet has), written at\n * capture by `annotateRefSheets`. An unqualified reference means the formula's own sheet.\n */\nimport { Direction, RANGE_TYPE, Rectangle, getIntersectRange, type IRange } from \"@univerjs/core\";\nimport { type ISequenceNode, LexerTreeBuilder, deserializeRangeWithSheet, generateStringWithSequence, sequenceNodeType, serializeRangeToRefString } from \"@univerjs/engine-formula\";\nimport {\n EffectRefRangId,\n handleIRemoveCol,\n handleIRemoveRow,\n handleInsertCol,\n handleInsertRow,\n handleMoveCols,\n handleMoveRows,\n runRefRangeMutations,\n} from \"@univerjs/sheets\";\nimport type { Axis, AxisOp } from \"./axis\";\n\n/** Sheet name → sheet id (null: the name is no sheet of this workbook). */\nexport type RefSheets = Readonly<Record<string, string | null>>;\n\n/** What changed under a formula: rows/columns of one sheet, or one sheet's name. */\nexport type RefChange =\n | { readonly kind: \"axis\"; readonly sheet: string; readonly axis: Axis; readonly op: AxisOp }\n | { readonly kind: \"rename\"; readonly sheet: string; readonly name: string }\n | { readonly kind: \"defined-name\"; readonly from: string; readonly to: string | null };\n\nexport interface FormulaCtx {\n /** The sheet the formula lives in (its unqualified references point here). */\n readonly ownSheet: string;\n readonly refSheets: RefSheets | undefined;\n /** Defined names keep the sheet qualifier of a moved reference (sheets-formula `preserveSheetQualifier`). */\n readonly keepQualifier?: boolean;\n}\n\nexport const REF_ERROR = \"#REF!\";\n/** Larger than any sheet; stands in for \"the whole other axis\" in the ref-range helpers. */\nconst FULL = 16383 * 64;\n\nlet lexer: LexerTreeBuilder | null = null;\nconst lex = (body: string) => (lexer ??= new LexerTreeBuilder()).sequenceNodesBuilder(body);\n\nexport const isFormulaText = (f: unknown): f is string => typeof f === \"string\" && f.length > 1 && f.startsWith(\"=\");\n\nconst IDENT = /^[A-Za-z_\\\\][A-Za-z0-9_.\\\\]*$/;\nconst ERROR_TOKEN = /^(?:[^!]+!)?#(?:REF!|NAME\\?|VALUE!|DIV\\/0!|N\\/A|NUM!|NULL!|SPILL!|CALC!)$/i;\n\ntype Node = string | ISequenceNode;\n\nfunction parse(text: string): { prefix: string; nodes: Node[] } | string {\n const prefix = text.startsWith(\"=\") ? \"=\" : \"\";\n const nodes = lex(text.slice(prefix.length));\n if (!nodes) return \"the formula lexer could not read the text\";\n for (const n of nodes) {\n if (typeof n === \"string\") continue;\n if (n.nodeType === sequenceNodeType.TABLE || (n.nodeType === sequenceNodeType.FUNCTION && n.token.includes(\"[\"))) return \"a structured table reference (tables are C5c)\";\n if (n.nodeType === sequenceNodeType.FUNCTION && !IDENT.test(n.token) && !ERROR_TOKEN.test(n.token))\n return `the lexer read \"${n.token}\" as one name (an intersection or a reference it cannot split)`;\n if (n.nodeType === sequenceNodeType.REFERENCE) {\n const d = deserializeRangeWithSheet(n.token);\n if (d.unitId) return \"a reference into another workbook\";\n }\n }\n return { prefix, nodes };\n}\n\n/** The sheet id a reference points at, \"\" when it names no sheet, or undefined when capture did not say. */\nfunction targetSheet(sheetName: string, ctx: FormulaCtx): string | undefined {\n if (!sheetName) return ctx.ownSheet;\n const id = ctx.refSheets?.[sheetName];\n if (id === undefined) return undefined;\n return id ?? \"\";\n}\n\n/** Why a formula cannot be transformed (null = it can). */\nexport function formulaBarrier(text: string, ctx: FormulaCtx): string | null {\n const p = parse(text);\n if (typeof p === \"string\") return p;\n for (const n of p.nodes) {\n if (typeof n === \"string\" || n.nodeType !== sequenceNodeType.REFERENCE) continue;\n const { sheetName } = deserializeRangeWithSheet(n.token);\n if (targetSheet(sheetName, ctx) === undefined) return `sheet \"${sheetName}\" is not in refSheets (capture must call annotateRefSheets)`;\n }\n return null;\n}\n\n/** Sheet names the text qualifies references with. */\nexport function referencedSheetNames(text: string): string[] {\n const p = parse(text);\n if (typeof p === \"string\") return [];\n const out = new Set<string>();\n for (const n of p.nodes) if (typeof n !== \"string\" && n.nodeType === sequenceNodeType.REFERENCE) {\n const { sheetName } = deserializeRangeWithSheet(n.token);\n if (sheetName) out.add(sheetName);\n }\n return [...out];\n}\n\n// ── one reference through one change (sheets-formula getNewRangeByMoveParam, types 1–6) ──────────────\nconst fullRowsRange = (start: number, count: number): IRange => ({ startRow: start, endRow: start + count - 1, startColumn: 0, endColumn: FULL, rangeType: RANGE_TYPE.ROW });\nconst fullColsRange = (start: number, count: number): IRange => ({ startRow: 0, endRow: FULL, startColumn: start, endColumn: start + count - 1, rangeType: RANGE_TYPE.COLUMN });\n\nconst startV = (v: number) => (Number.isNaN(v) || v == null ? -Infinity : v);\nconst endV = (v: number) => (Number.isNaN(v) || v == null ? Infinity : v);\nfunction startEnd(r: IRange) {\n return { ...r, startRow: startV(r.startRow), endRow: endV(r.endRow), startColumn: startV(r.startColumn), endColumn: endV(r.endColumn) };\n}\n\nfunction checkMoveEdge(origin: IRange, from: IRange): number | null {\n const startRow = startV(origin.startRow), endRow = endV(origin.endRow), startColumn = startV(origin.startColumn), endColumn = endV(origin.endColumn);\n const fromStartRow = startV(from.startRow), fromEndRow = endV(from.endRow), fromStartColumn = startV(from.startColumn), fromEndColumn = endV(from.endColumn);\n const rowsCover = () => (origin.rangeType === RANGE_TYPE.COLUMN && from.rangeType === RANGE_TYPE.COLUMN) || (startRow >= fromStartRow && endRow <= fromEndRow);\n const columnsCover = () => (origin.rangeType === RANGE_TYPE.ROW && from.rangeType === RANGE_TYPE.ROW) || (startColumn >= fromStartColumn && endColumn <= fromEndColumn);\n const allCover = () => origin.rangeType === RANGE_TYPE.ALL && from.rangeType === RANGE_TYPE.ALL;\n if ((rowsCover() && columnsCover()) || allCover()) return 4;\n if (columnsCover() && startRow >= fromStartRow && startRow <= fromEndRow && endRow > fromEndRow) return 0;\n if (columnsCover() && endRow >= fromStartRow && endRow <= fromEndRow && startRow < fromStartRow) return 1;\n if (rowsCover() && startColumn >= fromStartColumn && startColumn <= fromEndColumn && endColumn > fromEndColumn) return 2;\n if (rowsCover() && endColumn >= fromStartColumn && endColumn <= fromEndColumn && startColumn < fromStartColumn) return 3;\n return null;\n}\n\nfunction getMoveNewRange(moveEdge: number | null, result: IRange, from: IRange, to: IRange, origin: IRange, remain: IRange): IRange | undefined {\n const { startRow, endRow, startColumn, endColumn, rangeType } = startEnd(result);\n const f = startEnd(from);\n const fromRangeType = from.rangeType ?? RANGE_TYPE.NORMAL;\n const t = startEnd(to);\n const rm = startEnd(remain);\n const o = startEnd(origin);\n const originRangeType = origin.rangeType ?? RANGE_TYPE.NORMAL;\n const newRange: IRange = { ...origin };\n const rowsCover = () => (rangeType === RANGE_TYPE.COLUMN && originRangeType === RANGE_TYPE.COLUMN) || (startColumn >= o.startColumn && endColumn <= o.endColumn);\n const columnsCover = () => (rangeType === RANGE_TYPE.ROW && originRangeType === RANGE_TYPE.ROW) || (startRow >= o.startRow && endRow <= o.endRow);\n if (moveEdge === 0) {\n if (!rowsCover()) return undefined;\n if (startRow < o.startRow) newRange.startRow = startRow;\n else if (startRow >= o.endRow) newRange.endRow -= f.endRow + 1 - o.startRow;\n else return undefined;\n } else if (moveEdge === 1) {\n if (!rowsCover()) return undefined;\n if (endRow > o.endRow) newRange.endRow = endRow;\n else if (endRow <= o.startRow) newRange.startRow += o.endRow - f.startRow + 1;\n else return undefined;\n } else if (moveEdge === 2) {\n if (!columnsCover()) return undefined;\n if (startColumn < o.startColumn) newRange.startColumn = startColumn;\n else if (startColumn >= o.endColumn) newRange.endColumn -= f.endColumn + 1 - o.startColumn;\n else return undefined;\n } else if (moveEdge === 3) {\n if (!columnsCover()) return undefined;\n if (endColumn > o.endColumn) newRange.endColumn = endColumn;\n else if (endColumn <= o.startColumn) newRange.startColumn += o.endColumn - f.startColumn + 1;\n else return undefined;\n } else if (moveEdge === 4) {\n Object.assign(newRange, { startRow, startColumn, endRow, endColumn });\n } else if ((f.startColumn <= o.startColumn && f.endColumn >= o.endColumn) || (fromRangeType === RANGE_TYPE.ROW && originRangeType === RANGE_TYPE.ROW)) {\n const n = f.endRow - f.startRow + 1;\n if (from.endRow < o.startRow) {\n if (t.startRow >= o.startRow) newRange.startRow -= n;\n if (t.startRow >= o.endRow) newRange.endRow -= n;\n } else if (from.startRow > o.endRow) {\n if (t.endRow <= o.endRow) newRange.endRow += n;\n if (t.endRow <= o.startRow) newRange.startRow += n;\n } else if (from.startRow >= o.startRow && from.endRow <= o.endRow) {\n if (t.startRow <= o.startRow) newRange.startRow += n;\n else if (t.startRow >= o.endRow) newRange.endRow -= n;\n }\n } else if ((f.startRow <= o.startRow && f.endRow >= o.endRow) || (fromRangeType === RANGE_TYPE.COLUMN && originRangeType === RANGE_TYPE.COLUMN)) {\n const n = f.endColumn - f.startColumn + 1;\n if (from.endColumn < o.startColumn) {\n if (t.startColumn >= o.startColumn) newRange.startColumn -= n;\n if (t.startColumn >= o.endColumn) newRange.endColumn -= n;\n } else if (from.startColumn > o.endColumn) {\n if (t.endColumn <= o.endColumn) newRange.endColumn += n;\n if (t.endColumn <= o.startColumn) newRange.startColumn += n;\n } else if (from.startColumn >= o.startColumn && from.endColumn <= o.endColumn) {\n if (t.startColumn <= o.startColumn) newRange.startColumn += n;\n else if (t.startColumn >= o.endColumn) newRange.endColumn -= n;\n }\n } else {\n // the three remaining branches of the original all take the result as is\n Object.assign(newRange, { startRow, startColumn, endRow, endColumn });\n void rm;\n }\n return newRange;\n}\n\n/** The new range of one reference, REF_ERROR when it is gone, or undefined when the change leaves it alone. */\nfunction moveRange(range: IRange, axis: Axis, op: AxisOp): IRange | typeof REF_ERROR | undefined {\n const isRow = axis === \"row\";\n if (op.kind === \"insert\") {\n const r = isRow ? fullRowsRange(op.at, op.count) : fullColsRange(op.at, op.count);\n const ops = isRow\n ? handleInsertRow({ id: EffectRefRangId.InsertRowCommandId, params: { range: r, unitId: \"\", subUnitId: \"\", direction: Direction.DOWN } }, range)\n : handleInsertCol({ id: EffectRefRangId.InsertColCommandId, params: { range: r, unitId: \"\", subUnitId: \"\", direction: Direction.RIGHT } }, range);\n const res = runRefRangeMutations(ops, range);\n return res == null ? undefined : { ...range, ...res };\n }\n if (op.kind === \"remove\") {\n const r = isRow ? fullRowsRange(op.start, op.count) : fullColsRange(op.start, op.count);\n const ops = isRow\n ? handleIRemoveRow({ id: EffectRefRangId.RemoveRowCommandId, params: { range: r } }, range, [])\n : handleIRemoveCol({ id: EffectRefRangId.RemoveColCommandId, params: { range: r } }, range);\n const res = runRefRangeMutations(ops, range);\n return res == null ? REF_ERROR : { ...range, ...res };\n }\n const from = isRow ? fullRowsRange(op.from, op.count) : fullColsRange(op.from, op.count);\n const to = isRow ? fullRowsRange(op.to, op.count) : fullColsRange(op.to, op.count);\n const moveEdge = checkMoveEdge(range, from);\n let remain = getIntersectRange(range, from);\n if (isRow) {\n if (remain == null && ((from.endRow < range.startRow && to.endRow <= range.startRow) || (from.startRow > range.endRow && to.startRow > range.endRow))) return undefined;\n } else if (remain == null && ((from.endColumn < range.startColumn && to.endColumn <= range.startColumn) || (from.startColumn > range.endColumn && to.startColumn > range.endColumn))) return undefined;\n remain ??= { startRow: range.startRow, endRow: range.endRow, startColumn: range.startColumn, endColumn: range.endColumn, rangeType: RANGE_TYPE.NORMAL };\n const ops = isRow\n ? handleMoveRows({ id: EffectRefRangId.MoveRowsCommandId, params: { toRange: to, fromRange: from } }, remain)\n : handleMoveCols({ id: EffectRefRangId.MoveColsCommandId, params: { toRange: to, fromRange: from } }, remain);\n const res = runRefRangeMutations(ops, remain);\n if (res == null) return REF_ERROR;\n return getMoveNewRange(moveEdge, res, from, to, range, remain);\n}\n\nexport interface Rewritten {\n readonly text: string;\n readonly changed: boolean;\n}\n\n/**\n * The formula (or defined-name ref string) after `change`, exactly as Univer rewrites it: every reference into\n * the changed sheet moves (or becomes #REF!), and once anything changed every other reference is re-serialized\n * (`updateRefOffset`). Returns a reason string when the text cannot be transformed.\n */\nexport function rewriteFormula(text: string, ctx: FormulaCtx, change: RefChange): Rewritten | string {\n const p = parse(text);\n if (typeof p === \"string\") return p;\n const nodes = p.nodes.slice();\n const changedIds: number[] = [];\n for (let i = 0; i < nodes.length; i++) {\n const n = nodes[i]!;\n if (typeof n === \"string\") continue;\n if (change.kind === \"defined-name\") {\n if ((n.nodeType === sequenceNodeType.DEFINED_NAME || n.nodeType === sequenceNodeType.FUNCTION) && n.token === change.from) {\n nodes[i] = { ...n, token: change.to ?? REF_ERROR };\n changedIds.push(i);\n }\n continue;\n }\n if (n.nodeType !== sequenceNodeType.REFERENCE) continue;\n const { range, sheetName, unitId } = deserializeRangeWithSheet(n.token);\n const target = targetSheet(sheetName, ctx);\n if (target === undefined) return `sheet \"${sheetName}\" is not in refSheets (capture must call annotateRefSheets)`;\n if (target !== change.sheet) continue;\n let token: string | undefined;\n if (change.kind === \"rename\") {\n if (!sheetName) continue; // an unqualified reference names no sheet\n token = serializeRangeToRefString({ range, sheetName: change.name, unitId });\n } else {\n // sheets-formula moves `Rectangle.moveOffset(range, 0, 0)`, not the parsed range (it differs for whole rows/columns)\n const moved = moveRange(Rectangle.moveOffset(range, 0, 0), change.axis, change.op);\n if (moved === undefined) continue;\n token = moved === REF_ERROR ? REF_ERROR : serializeRangeToRefString({ range: moved, sheetName: target === ctx.ownSheet && !ctx.keepQualifier ? \"\" : sheetName, unitId });\n }\n nodes[i] = { ...n, token };\n changedIds.push(i);\n }\n if (!changedIds.length) return { text, changed: false };\n // updateRefOffset: every other reference is re-serialized too, as Univer does\n for (let i = 0; i < nodes.length; i++) {\n const n = nodes[i]!;\n if (typeof n === \"string\" || n.nodeType !== sequenceNodeType.REFERENCE || changedIds.includes(i)) continue;\n nodes[i] = { ...n, token: serializeRangeToRefString(deserializeRangeWithSheet(n.token)) };\n }\n const out = p.prefix + generateStringWithSequence(nodes);\n return { text: out, changed: out !== text };\n}\n\n/**\n * An op's `refSheets` after a rename: the renamed sheet answers to its new name only, and a name that was\n * no sheet before now names it. Unchanged (same object) when the rename touches nothing it lists.\n */\nexport function refSheetsAfter(refSheets: RefSheets | undefined, change: RefChange): RefSheets | undefined {\n if (change.kind !== \"rename\" || !refSheets) return refSheets;\n const entries = Object.entries(refSheets);\n if (!entries.some(([name, id]) => id === change.sheet || name === change.name)) return refSheets;\n const next: Record<string, string | null> = {};\n for (const [name, id] of entries) if (id !== change.sheet && name !== change.name) next[name] = id;\n next[change.name] = change.sheet;\n return next;\n}\n\n/** `refSheets` for the given formula texts: every sheet name they qualify a reference with, resolved now. */\nexport function refSheetsFor(texts: Iterable<string>, sheets: Readonly<Record<string, string>>): RefSheets | undefined {\n const byName = new Map(Object.entries(sheets).map(([id, name]) => [name, id] as const));\n const out: Record<string, string | null> = {};\n for (const t of texts) for (const name of referencedSheetNames(t)) out[name] = byName.get(name) ?? null;\n return Object.keys(out).length ? out : undefined;\n}\n","/**\n * The canonical Sheets state hash (COLLAB-DESIGN §7.2, C0 item 6, §21.3): two seats holding the same workbook\n * hash equal, whatever their seat-local differences.\n *\n * - Dropped: the unit `id`, `rev`, the collab stamps, and per sheet `zoomRatio`, `scrollTop`, `scrollLeft`,\n * `selections`.\n * - Style ids are seat-local (C0 surprise 4): every `s` id is replaced by its style object; `styles` is dropped.\n * - A cell holding a formula (`f` or `si`) drops its computed `v` and `t`: recalculation timing differs per seat.\n * - Empty values, cells and rows are dropped; keys are sorted.\n * - `mergeData` is a set (Univer never reads its order); concurrent merges leave one set in two orders.\n * - Resources are parsed and key-sorted, so the defined names (`SHEET_DEFINED_NAME_PLUGIN`, a map keyed by id)\n * are compared sorted by id; a `definedNames` list (the transform tests' seats) is sorted by id too.\n */\n\nconst SHEET_LOCAL_SHEET_KEYS = [\"zoomRatio\", \"scrollTop\", \"scrollLeft\", \"selections\", \"__collab\"];\nconst SHEET_LOCAL_KEYS = [\"id\", \"rev\", \"__matrxCollabCovered\", \"__collab\"];\n\ntype Obj = Record<string, any>;\n\nfunction sortDeep(v: unknown): unknown {\n if (Array.isArray(v)) return v.map(sortDeep);\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v).sort()) {\n const x = (v as Record<string, unknown>)[k];\n if (x === undefined || x === null) continue;\n if (Array.isArray(x) && x.length === 0) continue;\n if (x && typeof x === \"object\" && !Array.isArray(x) && Object.keys(x).length === 0) continue;\n out[k] = sortDeep(x);\n }\n return out;\n }\n return v;\n}\n\nfunction parsedResource(data: unknown): unknown {\n if (typeof data !== \"string\") return data;\n try {\n return JSON.parse(data);\n } catch {\n return data;\n }\n}\n\n/** The canonical form of a workbook snapshot (`IWorkbookData`, optionally with a `definedNames` list). */\nexport function canonicalSheet(snapshot: unknown): unknown {\n const s: Obj = structuredClone((snapshot ?? {}) as Obj);\n for (const k of SHEET_LOCAL_KEYS) delete s[k];\n const styles: Obj = s.styles ?? {};\n const deref = (v: unknown) => (typeof v === \"string\" && styles[v] ? sortDeep(styles[v]) : v);\n delete s.styles;\n for (const sheet of Object.values<Obj>(s.sheets ?? {})) {\n for (const k of SHEET_LOCAL_SHEET_KEYS) delete sheet[k];\n if (sheet.defaultStyle) sheet.defaultStyle = deref(sheet.defaultStyle);\n for (const key of [\"rowData\", \"columnData\"]) for (const v of Object.values<Obj>(sheet[key] ?? {})) if (v?.s) v.s = deref(v.s);\n const cd: Obj = sheet.cellData ?? {};\n for (const row of Object.keys(cd)) {\n for (const col of Object.keys(cd[row] ?? {})) {\n const c = cd[row][col];\n if (c?.s) c.s = deref(c.s);\n if (c && (c.f || c.si)) {\n delete c.v;\n delete c.t;\n }\n if (!c || Object.keys(sortDeep(c) as Obj).length === 0) delete cd[row][col];\n }\n if (Object.keys(cd[row] ?? {}).length === 0) delete cd[row];\n }\n if (Array.isArray(sheet.mergeData))\n sheet.mergeData = sheet.mergeData\n .map((m: Obj) => JSON.stringify(sortDeep(m)))\n .sort()\n .map((j: string) => JSON.parse(j));\n }\n if (Array.isArray(s.resources))\n s.resources = s.resources\n .map((r: Obj) => ({ name: r.name, data: sortDeep(parsedResource(r.data)) }))\n .filter((r: Obj) => r.data != null && r.data !== \"\" && !(typeof r.data === \"object\" && Object.keys(r.data).length === 0))\n .sort((a: Obj, b: Obj) => String(a.name).localeCompare(String(b.name)));\n if (Array.isArray(s.definedNames)) s.definedNames = [...s.definedNames].sort((x: Obj, y: Obj) => String(x.id).localeCompare(String(y.id)));\n return sortDeep(s);\n}\n\nexport const canonicalSheetString = (snapshot: unknown): string => JSON.stringify(canonicalSheet(snapshot));\n\n/** SHA-256 (hex) of the canonical form. Web Crypto, so the browser and Node compute the same hash. */\nexport async function sheetsStateHash(snapshot: unknown): Promise<string> {\n const bytes = new TextEncoder().encode(canonicalSheetString(snapshot));\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n","/**\n * The `SheetsOtPort` over a live Univer workbook (COLLAB-DESIGN §6.3, §6.7, C0 items 4, 6, 7, C5a/C5b capture\n * rules). The host lends Univer's services (it resolves them with its own tokens, so this module never pulls a\n * second copy of Univer's DI into the app); this module does every capture rule:\n *\n * - FILTER. Only mutations of THIS seat's unit, never `onlyLocal` or `fromCollab` ones (formula results, our own\n * remote applies), never the never-travels class.\n * - GROUP. By the outermost COMMAND (`beforeCommandExecuted` / `onCommandExecuted` depth), with a try/finally\n * around `executeCommand` so a command that mutates and then throws still closes its group (C0 surprise 7).\n * One hand-over per group: the formula annotation needs the whole group (a rewrite after a structural op is\n * `derived`, §21.2).\n * - ALLOWLIST. `allowParams`; an id without one (a barrier id, an unknown id) makes the group `not_shared`.\n * - THE THREE C5a RULES. Cell content is completed from the cell right after the mutation\n * (`completeCellContent`); a remove-merge names the exact merges it removed (`exactMergeRemovals`, merges read\n * right before the mutation); a style travels as its object, never a seat-local id. A whole-style override\n * (paste) is restated as a merge with explicit nulls, which every seat applies identically.\n * - FORMULAS. `annotateFormulas` with the sheet names and defined names as they were before the command.\n * - INVERSE from the APPLIED params against a COPY of the pre-state taken in `beforeCommandExecuted`\n * (C0 surprise 6). Families without a safe inverse leave it unknown.\n */\nimport type { SheetMutation, SheetRange } from \"../../../collab/sheets/transform\";\nimport { CONTENT_KEYS, SHEET_MUTATIONS, allowParams, annotateFormulas, completeCellContent, exactMergeRemovals, forApply } from \"../../../collab/sheets/transform\";\nimport type { SheetsLocalEvent, SheetsOtPort } from \"./room\";\n\ntype Obj = Record<string, unknown>;\ntype CommandInfo = { id: string; type?: number; params?: unknown };\ntype Disposable = { dispose: () => void };\n\n/** Univer's command service as the workbook editor lends it. */\nexport interface SheetsCommandService {\n onMutationExecutedForCollab(listener: (info: CommandInfo, options?: unknown) => void): Disposable;\n beforeCommandExecuted(listener: (info: CommandInfo, options?: unknown) => void): Disposable;\n onCommandExecuted(listener: (info: CommandInfo, options?: unknown) => void): Disposable;\n syncExecuteCommand(id: string, params?: unknown, options?: unknown): unknown;\n executeCommand?: (id: string, params?: unknown, options?: unknown) => Promise<unknown>;\n}\nexport interface SheetsWorksheetLike {\n getSheetId(): string;\n getName(): string;\n getCellRaw(row: number, col: number): Obj | null | undefined;\n getMergeData(): SheetRange[];\n}\nexport interface SheetsWorkbookLike {\n getUnitId(): string;\n getSheets(): SheetsWorksheetLike[];\n getSheetBySheetId(id: string): SheetsWorksheetLike | null | undefined;\n getStyles(): { get(id: string): unknown };\n getSnapshot(): unknown;\n}\n\nexport interface UniverSheetsOtPortOptions {\n commandService: SheetsCommandService;\n /** This seat's workbook unit right now (a content swap keeps the unit id). */\n workbook(): SheetsWorkbookLike | null;\n /** `IDefinedNamesService.getDefinedNameMap(unitId)`: defined-name id → entry. */\n definedNames?(unitId: string): Record<string, { name?: string }> | null | undefined;\n /** `IResourceLoaderService.saveUnit(unitId)`: the snapshot with its resources (what a save stores). */\n saveUnit?(unitId: string): unknown | null;\n /** Univer's undo/redo service. */\n undoRedo?(): unknown | null;\n /** Replace the workbook's whole content, keeping its unit id. */\n load(snapshot: unknown): void;\n markDirty(): void;\n}\n\nconst COMMAND = 0;\nconst MUTATION = 2;\nconst VALUES = \"sheet.mutation.set-range-values\";\nconst ADD_MERGE = \"sheet.mutation.add-worksheet-merge\";\nconst REMOVE_MERGE = \"sheet.mutation.remove-worksheet-merge\";\nconst SHEET_NAME = \"sheet.mutation.set-worksheet-name\";\nconst DEPTH_GUARD = Symbol.for(\"ai-matrx.office.sheets.command-depth-guard\");\n\nconst json = <T>(v: T): T => (v === undefined ? v : (JSON.parse(JSON.stringify(v)) as T));\nconst flagged = (options: unknown) => {\n const o = options as { onlyLocal?: boolean; fromCollab?: boolean } | undefined;\n return !!(o?.onlyLocal || o?.fromCollab);\n};\n\ninterface Pre {\n cells?: Map<string, Obj | null>;\n merges?: SheetRange[];\n name?: string;\n}\ninterface Group {\n label: string | null;\n sheets: Record<string, string>;\n names: Record<string, string>;\n mutations: SheetMutation[];\n inverses: Array<SheetMutation[] | undefined>;\n notShared: string | null;\n}\n\n/** The trackers of every port on one command service: the try/finally guard restores each one's depth. */\ntype Tracker = { stack: string[]; settle: () => void };\n\nexport function univerSheetsOtPort(o: UniverSheetsOtPortOptions): SheetsOtPort & { dispose(): void } {\n const cs = o.commandService;\n const listeners = new Set<(e: SheetsLocalEvent) => void>();\n const idle: Array<() => void> = [];\n const pre = new WeakMap<object, Pre>();\n const tracker: Tracker = { stack: [], settle: () => settle() };\n let group: Group | null = null;\n let applying = false;\n\n const unitId = () => o.workbook()?.getUnitId() ?? null;\n const mine = (params: unknown) => {\n const u = unitId();\n return !!u && !!params && typeof params === \"object\" && (params as Obj).unitId === u;\n };\n const styleObject = (s: unknown): unknown => {\n if (typeof s !== \"string\") return s;\n const found = o.workbook()?.getStyles().get(s);\n return found ? json(found) : s;\n };\n const sheetNames = (): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const ws of o.workbook()?.getSheets() ?? []) out[ws.getSheetId()] = ws.getName();\n return out;\n };\n const definedNames = (): Record<string, string> => {\n const u = unitId();\n const map = (u && o.definedNames?.(u)) || {};\n const out: Record<string, string> = {};\n for (const [id, d] of Object.entries(map)) out[id] = String(d?.name ?? \"\");\n return out;\n };\n const openGroup = (label: string | null): Group => ({ label, sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });\n\n const emit = (e: SheetsLocalEvent) => {\n for (const l of [...listeners]) {\n try {\n l(e);\n } catch (err) {\n console.warn(\"[sheets-ot] local change handler failed\", err);\n }\n }\n };\n\n const flush = () => {\n const g = group;\n group = null;\n if (!g) return;\n if (g.notShared) emit({ kind: \"not_shared\", mutationId: g.notShared, label: g.label });\n else if (g.mutations.length) {\n const mutations = annotateFormulas(g.mutations, g.sheets, g.names);\n const known = g.inverses.every((i) => i !== undefined);\n const inverse = known ? annotateFormulas(g.inverses.slice().reverse().flat() as SheetMutation[], g.sheets, g.names) : undefined;\n emit({ kind: \"group\", mutations, ...(inverse !== undefined ? { inverse } : {}), label: g.label });\n }\n };\n function settle() {\n if (tracker.stack.length === 0) flush();\n if (tracker.stack.length === 0 && !group) for (const fn of idle.splice(0)) fn();\n }\n\n // ── pre-state, before each local mutation ──\n const before = cs.beforeCommandExecuted((info, options) => {\n if (info.type === COMMAND) {\n if (tracker.stack.length === 0 && !group) group = openGroup(info.id);\n tracker.stack.push(info.id);\n return;\n }\n if (info.type !== MUTATION || applying || flagged(options) || !mine(info.params)) return;\n const p = info.params as Obj;\n const ws = o.workbook()?.getSheetBySheetId(String(p.subUnitId ?? \"\"));\n if (!ws) return;\n const record: Pre = { merges: json(ws.getMergeData() ?? []) };\n if (info.id === VALUES) {\n record.cells = new Map();\n const cells = (p.cellValue ?? {}) as Record<string, Record<string, unknown>>;\n for (const r of Object.keys(cells))\n for (const c of Object.keys(cells[r] ?? {})) {\n const raw = ws.getCellRaw(Number(r), Number(c));\n const copy = raw ? (json(raw) as Obj) : null;\n if (copy && \"s\" in copy) copy.s = styleObject(copy.s);\n record.cells.set(`${r}:${c}`, copy);\n }\n }\n if (info.id === SHEET_NAME) record.name = ws.getName();\n pre.set(p, record);\n });\n\n const after = cs.onCommandExecuted((info) => {\n if (info.type !== COMMAND) return;\n const at = tracker.stack.lastIndexOf(info.id);\n if (at >= 0) tracker.stack.splice(at, 1);\n settle();\n });\n\n // the try/finally guard: one per command service, restoring every port's depth\n const guarded = cs as SheetsCommandService & { [DEPTH_GUARD]?: Set<Tracker> };\n if (!guarded[DEPTH_GUARD] && typeof cs.executeCommand === \"function\") {\n const trackers = new Set<Tracker>();\n guarded[DEPTH_GUARD] = trackers;\n const original = cs.executeCommand.bind(cs);\n cs.executeCommand = async (id, params, options) => {\n const depths = new Map([...trackers].map((t) => [t, t.stack.length] as const));\n try {\n return await original(id, params, options);\n } finally {\n for (const [t, d] of depths) {\n if (t.stack.length > d) {\n t.stack.length = d;\n t.settle();\n }\n }\n }\n };\n }\n guarded[DEPTH_GUARD]?.add(tracker);\n\n // ── the traveling form of one applied local mutation ──\n const capture = (info: CommandInfo): { m: SheetMutation | null; inverse: SheetMutation[] | undefined; notShared?: string } => {\n const entry = SHEET_MUTATIONS[info.id];\n if (!entry) {\n console.warn(`[sheets-ot] ${info.id} is not in the sheet mutation registry; it cannot be shared`);\n return { m: null, inverse: undefined, notShared: info.id };\n }\n if (entry.kind === \"never-travels\") return { m: null, inverse: undefined };\n if (entry.kind === \"barrier\") return { m: null, inverse: undefined, notShared: info.id };\n const raw = json(info.params as Obj);\n const before = pre.get(info.params as object) ?? {};\n const params = allowParams(info.id, raw);\n if (!params) return { m: null, inverse: undefined, notShared: info.id };\n const sheet = String(params.subUnitId ?? \"\");\n const ws = o.workbook()?.getSheetBySheetId(sheet);\n\n if (info.id === VALUES) {\n const cells = (params.cellValue ?? {}) as Record<string, Record<string, Obj | null>>;\n const invCells: Record<string, Record<string, Obj | null>> = {};\n let invKnown = !!before.cells;\n for (const r of Object.keys(cells))\n for (const c of Object.keys(cells[r] ?? {})) {\n let e = cells[r]![c] ?? null;\n const p = before.cells?.get(`${r}:${c}`) ?? null;\n if (e && \"s\" in e) {\n e = { ...e, s: styleObject(e.s) };\n if (raw.isOverrideStyle) {\n // a whole-style replace, restated as a merge every seat applies the same way\n const next = (e.s && typeof e.s === \"object\" ? e.s : {}) as Obj;\n const prev = (p?.s && typeof p.s === \"object\" ? p.s : {}) as Obj;\n const merged: Obj = { ...next };\n for (const k of Object.keys(prev)) if (!(k in next)) merged[k] = null;\n e.s = Object.keys(merged).length ? merged : null;\n }\n }\n const post = ws?.getCellRaw(Number(r), Number(c)) ?? null;\n const done = completeCellContent(e, post ? (json(post) as Obj) : null);\n cells[r]![c] = done;\n if (!invKnown) continue;\n let inv: Obj | null;\n if (done === null) inv = p ? { ...fullContent(p), ...(p.s !== undefined ? { s: p.s } : {}) } : null;\n else {\n inv = {};\n if (CONTENT_KEYS.some((k) => k !== \"t\" && k in done)) Object.assign(inv, fullContent(p));\n if (\"s\" in done) inv.s = p?.s ?? null;\n }\n (invCells[r] ??= {})[c] = inv;\n }\n return {\n m: { id: info.id, params: { ...params, cellValue: cells } },\n inverse: invKnown ? [{ id: VALUES, params: { subUnitId: sheet, cellValue: invCells } }] : undefined,\n };\n }\n if (info.id === REMOVE_MERGE) {\n const exact = exactMergeRemovals([{ id: info.id, params }], { [sheet]: before.merges ?? ws?.getMergeData() ?? [] });\n const m = exact[0] ?? null;\n if (!m) return { m: null, inverse: undefined };\n return { m, inverse: [{ id: ADD_MERGE, params: { subUnitId: sheet, ranges: json(m.params.ranges) } }] };\n }\n const m: SheetMutation = { id: info.id, params };\n switch (info.id) {\n case \"sheet.mutation.insert-row\":\n return { m, inverse: [{ id: \"sheet.mutation.remove-rows\", params: { subUnitId: sheet, range: json(params.range) } }] };\n case \"sheet.mutation.insert-col\":\n return { m, inverse: [{ id: \"sheet.mutation.remove-col\", params: { subUnitId: sheet, range: json(params.range) } }] };\n case ADD_MERGE:\n return { m, inverse: [{ id: REMOVE_MERGE, params: { subUnitId: sheet, ranges: json(params.ranges) } }] };\n case SHEET_NAME:\n return { m, inverse: before.name !== undefined ? [{ id: SHEET_NAME, params: { subUnitId: sheet, name: before.name } }] : undefined };\n default:\n return { m, inverse: undefined };\n }\n };\n\n const collab = cs.onMutationExecutedForCollab((info, options) => {\n if (applying || flagged(options) || !mine(info.params)) return;\n const lone = !group;\n if (lone) group = openGroup(null);\n const g = group!;\n if (!g.notShared) {\n const r = capture(info);\n if (r.notShared) g.notShared = r.notShared;\n else if (r.m) {\n g.mutations.push(r.m);\n g.inverses.push(r.inverse);\n }\n }\n if (lone && tracker.stack.length === 0) settle();\n });\n\n return {\n onLocal(listener) {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n busy: () => tracker.stack.length > 0 || group !== null,\n whenIdle(fn) {\n if (tracker.stack.length === 0 && !group) fn();\n else idle.push(fn);\n },\n applyRemote(m) {\n const u = unitId();\n if (!u) throw new Error(\"no workbook is mounted\");\n const a = forApply(m);\n applying = true;\n try {\n const ok = cs.syncExecuteCommand(a.id, { ...json(a.params), unitId: u }, { onlyLocal: true, fromCollab: true });\n if (ok === false) throw new Error(`\"${m.id}\" was refused by the editor`);\n } finally {\n applying = false;\n }\n },\n snapshot() {\n const wb = o.workbook();\n if (!wb) return null;\n const saved = o.saveUnit?.(wb.getUnitId()) ?? wb.getSnapshot();\n return saved ? json(saved) : null;\n },\n load(snapshot) {\n group = null;\n applying = true;\n try {\n o.load(snapshot);\n } finally {\n applying = false;\n }\n },\n undoTargets() {\n const u = unitId();\n const service = o.undoRedo?.();\n return u && service ? [{ service, unitId: u }] : [];\n },\n markDirty: () => o.markDirty(),\n dispose() {\n before.dispose();\n after.dispose();\n collab.dispose();\n guarded[DEPTH_GUARD]?.delete(tracker);\n listeners.clear();\n },\n };\n}\n\n/** Every content key of a cell, `null` where it has none (a content write is a full replacement, C5a). */\nfunction fullContent(cell: Obj | null): Obj {\n const out: Obj = {};\n for (const k of CONTENT_KEYS) out[k] = cell && cell[k] !== undefined ? cell[k] : null;\n if (out.v === null) delete out.t;\n return out;\n}\n","/**\n * A cloud workbook's co-editing room on the ordered log (COLLAB-DESIGN §6, §12.6; unit C6), assembled from the\n * configured sheets host: the `udt_workbook_snapshots` store, the C1 doors over the host's Supabase client, the\n * private `collab:<id>` frames on the app's one realtime manager, and Yjs awareness for presence only (who is\n * here, their cell, and `quiet_hash`; no content travels there). The Sheets twin of `docs/document-ot-room.ts`.\n *\n * The FLIP is per room (§12.2): a workbook whose room exists always opens on the ordered log; a workbook with\n * no room opens one only when the host's `collab.ot_rooms` knob says so (`all`, or `new` for a workbook never\n * saved). Everything else keeps the 0.6 relay. The host reads the knob (host config lives in the app).\n */\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport {\n awarenessOpPresence,\n collabReplace,\n collabRoomExists,\n SupabaseYjsProvider,\n supabaseOpTransport,\n type AwarenessState,\n type CollabRpcClient,\n type OpSession,\n type OpSessionIncident,\n type OpSessionStatus,\n} from \"@ai-matrx/data/realtime/collab\";\n\nimport { openSheetsOtRoom, type SheetOp, type SheetsOtNotice, type SheetsOtPort } from \"../univer/collab/sheets-ot/room\";\nimport { getSheetsHost } from \"./ports\";\nimport { getLatestSnapshot, saveSnapshot } from \"./workbook-service\";\n\n/** `collab.ot_rooms` (§12.2): which workbooks without a room open one. */\nexport type WorkbookOtRoomsKnob = \"off\" | \"new\" | \"all\";\n\nconst db = () => getSheetsHost().getSupabase() as unknown as CollabRpcClient;\n\nasync function loadSnapshotRow(workbookId: string, ref: string): Promise<unknown> {\n if (ref === \"none\") {\n const res = await getLatestSnapshot(workbookId);\n if (!res.success) throw new Error(res.error);\n return res.data?.snapshot ?? null;\n }\n const { data, error } = await getSheetsHost()\n .getSupabase()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n .select(\"snapshot\")\n .eq(\"id\", ref)\n .maybeSingle();\n if (error) throw new Error(error.message);\n if (!data) throw new Error(`The saved version ${ref} of this workbook is missing.`);\n return (data as { snapshot?: unknown }).snapshot ?? null;\n}\n\n/** Whether this workbook opens on the ordered log: its room exists, or the knob opens one. */\nexport async function workbookUsesOrderedRoom(workbookId: string, knob: WorkbookOtRoomsKnob, isNewWorkbook: () => Promise<boolean>): Promise<boolean> {\n try {\n if (await collabRoomExists(db(), workbookId)) return true;\n } catch (err) {\n console.warn(\"[workbook] could not ask whether this workbook has a co-editing room; opening the relay room\", err);\n return false;\n }\n if (knob === \"all\") return true;\n if (knob === \"new\") return isNewWorkbook();\n return false;\n}\n\nfunction pickColor(uid: string): string {\n const palette = [\"#ef4444\", \"#f59e0b\", \"#10b981\", \"#3b82f6\", \"#8b5cf6\", \"#ec4899\", \"#14b8a6\", \"#f97316\"];\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return palette[Math.abs(h) % palette.length] ?? \"#ec4899\";\n}\n\nexport interface WorkbookOtRoomOptions {\n workbookId: string;\n uid: string;\n /** One per open tab; never reused. */\n clientId: string;\n displayName?: string;\n readAntiEntropyIntervalMs?: () => Promise<number>;\n onAwareness?: (states: Map<number, AwarenessState>) => void;\n onNotice?: (n: SheetsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n}\n\nexport interface WorkbookOtRoomHandle {\n session: OpSession<SheetOp>;\n isSaver(): boolean;\n /** The record's save: a checkpoint at a quiet point. False when this seat does not write now. */\n write(reason: \"manual\" | string): Promise<boolean>;\n /** Restore / whole import through `collab_replace`. */\n replace(snapshot: unknown): Promise<void>;\n /** This seat's cell, for the other seats' cursor rings. */\n setCursor(c: { sheetId: string | null; row: number | null; col: number | null }): void;\n stop(): void;\n}\n\n/** Join the workbook's ordered-log room with the editor's port (`univerSheetsOtPort`). */\nexport async function startWorkbookOtRoom(port: SheetsOtPort & { dispose?: () => void }, o: WorkbookOtRoomOptions): Promise<WorkbookOtRoomHandle> {\n // §7.4 / C0 surprise 5: a room's first checkpoint must be a real, Univer-normalised snapshot. A workbook never\n // saved gets this seat's mounted workbook saved first, so every seat boots from the same sheet ids.\n const latest = await getLatestSnapshot(o.workbookId);\n if (!latest.success) throw new Error(latest.error);\n if (!latest.data) {\n const mounted = port.snapshot();\n if (mounted) {\n const saved = await saveSnapshot({ workbookId: o.workbookId, snapshot: mounted, origin: \"autosave\" });\n if (!saved.success) throw new Error(saved.error);\n }\n }\n\n const doc = new Y.Doc();\n const awareness = new Awareness(doc);\n awareness.setLocalState({\n uid: o.uid,\n clientId: o.clientId,\n name: o.displayName ?? o.uid.slice(0, 8),\n color: pickColor(o.uid),\n sheetId: null,\n row: null,\n col: null,\n ts: Date.now(),\n });\n const publishAwareness = () => o.onAwareness?.(new Map(awareness.getStates() as Map<number, AwarenessState>));\n awareness.on(\"change\", publishAwareness);\n const provider = new SupabaseYjsProvider({\n workbookId: o.workbookId,\n clientId: o.clientId,\n doc,\n awareness,\n ...(o.readAntiEntropyIntervalMs ? { readAntiEntropyIntervalMs: o.readAntiEntropyIntervalMs } : {}),\n });\n await provider.connect();\n publishAwareness();\n\n const client = db();\n const room = openSheetsOtRoom({\n port,\n clientId: o.clientId,\n presence: awarenessOpPresence(awareness),\n transport: supabaseOpTransport({\n client,\n roomId: o.workbookId,\n kind: \"univer_sheet\",\n store: {\n loadSnapshot: (ref) => loadSnapshotRow(o.workbookId, ref),\n async writeSnapshot(snapshot) {\n const res = await saveSnapshot({ workbookId: o.workbookId, snapshot, origin: \"autosave\" });\n if (!res.success) throw new Error(res.error);\n return res.data.id;\n },\n },\n }),\n replace: ({ snapshot, stateHash, clientId }) => collabReplace(client, { roomId: o.workbookId, snapshot, stateHash, origin: \"restore\", clientId }),\n ...(o.onNotice ? { onNotice: o.onNotice } : {}),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n await room.session.ready;\n\n return {\n session: room.session,\n isSaver: () => room.isSaver(),\n write: (reason) => room.write(reason),\n replace: (snapshot) => room.replace(snapshot),\n setCursor(c) {\n const current = awareness.getLocalState() ?? {};\n awareness.setLocalState({ ...current, sheetId: c.sheetId, row: c.row, col: c.col, ts: Date.now() });\n },\n stop() {\n room.stop();\n port.dispose?.();\n awareness.off(\"change\", publishAwareness);\n provider.disconnect();\n awareness.destroy();\n doc.destroy();\n },\n };\n}\n","/**\n * The host ports of the Sheets model and io.\n *\n * The package owns the workbook service, the page-setup store and the import flow, but three things\n * belong to the app that mounts them: the database client (a package owns no client), the\n * organization a write acts in (the active-organization ladder is app state) and the file store that\n * keeps a lossless copy of an imported file. The host states them once at start-up with\n * `configureSheetsHost`. State sits on a `globalThis` slot so a dual-bundled copy of the package\n * still sees one host. An unconfigured port THROWS naming itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type SheetsSupabase = SupabaseClient<any, any, any>;\n\nexport interface SheetsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): SheetsSupabase;\n /** The organization a write acts in: the record's own when given, otherwise the active one. */\n ensureOrgId(organizationId: string | null): Promise<string>;\n /** Keep the original of an imported spreadsheet in the file store, in `folderPath`. */\n uploadOriginalFile(file: File, options: { folderPath: string }): Promise<{ fileId: string }>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.sheets-host\");\ntype Slot = { ports?: SheetsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureSheetsHost(ports: SheetsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getSheetsHost(): SheetsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/sheets: configureSheetsHost(ports) was not called before the workbook service ran.\");\n return ports;\n}\n","/**\n * Workbook service — typed wrappers for `udt_workbooks` + `udt_workbook_snapshots`.\n *\n * Workbooks are the lossless-spreadsheet surface (P4): metadata in\n * `udt_workbooks`, content state in append-only `udt_workbook_snapshots`. The\n * editor (Univer or equivalent) hydrates from the LATEST snapshot and writes\n * a new snapshot per save (debounced on the client — see WorkbookEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - Realtime: @ai-matrx/office/univer/collab useWorkbookRealtime\n * - Component: the Sheets editor\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { Workbook, WorkbookSnapshot, WorkbookSnapshotOrigin } from \"../core/types\";\nimport { getSheetsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getSheetsHost().getSupabase();\n\n// ─── workbooks ────────────────────────────────────────────────────────────────\n\nconst WORKBOOK_SOURCE_LABELS: Record<string, string> = {\n created: \"Created\",\n imported_xlsx: \"Imported Excel\",\n imported_gsheet: \"Imported from Google Sheets\",\n imported_csv: \"Imported CSV\",\n linked_gsheet: \"Imported from Google Sheets\",\n};\n\n/** Honest, human label for `udt_workbooks.source`. */\nexport function workbookSourceLabel(source: string): string {\n return WORKBOOK_SOURCE_LABELS[source] ?? source.replace(/_/g, \" \");\n}\n\nexport type CreateWorkbookArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the workbook itself, mirrors `udt_workbooks.source`. */\n source?:\n | \"created\"\n | \"imported_xlsx\"\n | \"imported_gsheet\"\n | \"imported_csv\"\n | \"linked_gsheet\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (XLSX / CSV blob). Set on the import\n * flow so the lossless original is recoverable; FK is ON DELETE SET NULL,\n * so deleting the file just nulls the link — the workbook survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createWorkbook(\n args: CreateWorkbookArgs,\n): Promise<ServiceResult<Workbook>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a workbook.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .insert({\n workbook_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; legacy `is_public` is derived from it by the\n // workbench._bridge_legacy_owner trigger. A new workbook defaults to\n // `internal` — org work product, not an individual's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\nexport async function listAccessibleWorkbooks(): Promise<\n ServiceResult<Workbook[]>\n> {\n // RLS handles owner / published-to-the-web / shared access.\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as Workbook[] };\n}\n\nexport async function getWorkbook(\n workbookId: string,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .eq(\"id\", workbookId)\n .is(\"deleted_at\", null)\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\nexport async function renameWorkbook(\n workbookId: string,\n name: string,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ workbook_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Move the workbook into a project (or out of one with `null`). Sibling of\n * `renameWorkbook`: the one named setter for `project_id`.\n */\nexport async function moveWorkbook(\n workbookId: string,\n projectId: string | null,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Rewrite the workbook's description. Sibling of `renameWorkbook` — the two\n * human-authored fields on `udt_workbooks` each get a named setter so callers\n * never hand-roll a `.from(\"udt_workbooks\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Written by the import flow at creation (\"Imported from <file>\") and, since\n * the workbooks surface became agent-writable, by the `workbook_description`\n * write target on `/workbooks/[id]`.\n */\nexport async function updateWorkbookDescription(\n workbookId: string,\n description: string | null,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Soft delete — the workbook is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreWorkbook for undo.\n */\nexport async function deleteWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"delete\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a workbook this very flow just created and\n * failed to populate (see the import path in app/(core)/workbooks/page.tsx).\n * Never use this for a user-initiated delete: that is deleteWorkbook, which\n * tombstones and stays recoverable.\n */\nexport async function discardFailedWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"archive\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function restoreWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: null })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"restore\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/** Trash view: the caller's own archived workbooks (RLS decides what is readable). */\nexport async function listTrashedWorkbooks(): Promise<\n ServiceResult<Workbook[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as Workbook[] };\n}\n\n/**\n * An independent copy of a workbook: its own row in the original's organization\n * and project, with the latest snapshot copied over. Editing the copy never\n * touches the original.\n */\nexport async function copyWorkbook(\n workbookId: string,\n name?: string,\n): Promise<ServiceResult<Workbook>> {\n const original = await getWorkbook(workbookId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return {\n success: false,\n error: \"This workbook has no organization and cannot be copied.\",\n };\n }\n const created = await createWorkbook({\n name: name ?? `Copy of ${row.workbook_name}`,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n });\n if (!created.success) return created;\n const latest = await getLatestSnapshot(workbookId);\n if (!latest.success) return latest;\n if (latest.data) {\n const saved = await saveSnapshot({\n workbookId: created.data.id,\n snapshot: latest.data.snapshot,\n label: latest.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n// ─── snapshots (workbook content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened workbook hydrates from. Returns\n * `data: null` (success path) when the workbook has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestSnapshot(\n workbookId: string,\n): Promise<ServiceResult<WorkbookSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n .select(\"*\")\n .eq(\"workbook_id\", workbookId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as WorkbookSnapshot | null };\n}\n\nexport type SaveSnapshotArgs = {\n workbookId: string;\n snapshot: unknown; // opaque to us — editor library decides the shape\n label?: string | null;\n origin?: WorkbookSnapshotOrigin;\n};\n\nexport async function saveSnapshot(\n args: SaveSnapshotArgs,\n): Promise<ServiceResult<WorkbookSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n // A snapshot is a component of its workbook and carries the workbook's organization.\n const { data: workbook, error: workbookError } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"organization_id\")\n .eq(\"id\", args.workbookId)\n .single();\n if (workbookError) return { success: false, error: workbookError.message };\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n .insert({\n organization_id: workbook.organization_id,\n workbook_id: args.workbookId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent workbook's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent workbook; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.workbookId);\n\n return { success: true, data: data as WorkbookSnapshot };\n}\n\nexport async function listSnapshots(\n workbookId: string,\n limit = 50,\n): Promise<ServiceResult<WorkbookSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, workbook_id, label, origin, created_by, created_at\")\n .eq(\"workbook_id\", workbookId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as WorkbookSnapshot[] };\n}\n"],"mappings":"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","names":["covered","covered","runs","univerMerge","Y","runs","keyOf","import_collab","ok","Y","import_awareness","import_collab","import_core","db","pickColor","import_collab","row","import_collab","import_sheets","to","out","r","import_core","ops","res","barrier","FULL","Y","ch","first","rest","sortDeep","flip","undoStacksOf","CONTENT_TOUCH","ok","before","m","ok","Y","import_awareness","import_collab","SLOT","slot","slot","import_api","import_auth","import_db","db","db","db","loadSnapshotRow","pickColor"]}