Since Milestone 1 the code editor’s JavaScript reported the whole text after every keystroke (P-037): a JSON hop of the entire file per key, O(n) per keystroke — the thing that made big files sluggish and blocked the plain-text tier of the Case Selector.
Done 2026-09-21. The CodeMirror bundle now reports splices: for each transaction, iterChanges yields (from, to, insert) in UTF-16 offsets of the text before the change, in document order, plus the new length as a consistency check. Rust keeps a mirror of the view’s text (view_text) and applies the splices to it in place (backend::apply_splices, applied back to front so old offsets stay valid, UTF-16 → byte offsets via utf16_to_byte), then the document takes the mirror (a memcpy, not a serialisation). A mismatch (out-of-range offset, length disagreement) is logged and the view is resynced from the document. Text pushed into the view (agent edits, reload, rename rewrites) is no longer mirrored eagerly: the view echoes the splice it applied, which keeps the mirror honest. The LSP still gets didChange with the full text (incremental sync is a separate step). Unit test for apply_splices (order, unicode, out of range); the editor suites pass unchanged; highlight.mjs gained a 3 MB file step — a keystroke is dirty in Rust after 87 ms (was seconds).