Mostly Done.
Contents

11 Preserve what the user wrote

An editor’s most dangerous defects leave the screen looking right. The rendered document appears fine even though the source changed, a delimiter vanished, or the caret moved to a different logical position. The same exposure exists in any system that holds user data behind a friendlier projection of it, and appearance alone cannot verify any of them. The product needs a clear answer to one question: what is the document?

11.1 Keep one source of truth

The strongest design treats the source string and its syntax tree as the document. Everything on screen is a projection. A projection may hide syntax, replace a source range with a rendered block, or add visual decoration. It does not own an independent version of the content.

This asymmetry removes an entire reconciliation problem. The view can be discarded and rebuilt. The source cannot depend on reconstructing itself from the view.

A rich-text editor that treats both the view model and the source as authoritative must synchronize two truths after every edit. That design creates hard questions:

The one-truth design refuses the premise. The source wins.

11.2 Prove byte preservation

Semantic equivalence is not enough for a source editor. Two documents may render identically while differing in line endings, spacing, delimiters, or user formatting. Those differences belong to the author.

The preservation suite should cover:

A useful fixture begins with an exact byte sequence, performs a projection or edit cycle, and compares the resulting bytes. The regression for an ordinary edit can state the smallest permitted mutation and prove everything outside it stayed unchanged: replace one word in the middle of a line, then assert that every byte outside that span is identical, that undo restores the exact original, and that redo reapplies the exact edit. A separate test should pin UTF-8 slicing against a fixture that mixes one-, two-, and four-byte characters, say an ASCII letter, an accented vowel, and an emoji, because the interesting offsets are not where ASCII intuition puts them. Normalizing a fixture before comparison would erase the contract the test is supposed to protect.

Details at this level are not trivia. \r\n is one grapheme cluster in two bytes, and that fact marks a place where text, bytes, and cursor behavior intersect.

11.3 Treat the caret as state

Projection changes can preserve text and still betray the user by moving the caret. A user who reveals source syntax expects to remain on the same conceptual line, not jump because the visible range changed.

Name this as a viewport invariant and test it as a number. Suppose your editor reveals a table’s source when the user activates it. Record the screen position of the row, activate it, relocate the caret, and assert the row moved less than 2 points. The failure symptom is the one the user would report: the row you clicked jumps when it becomes editable. The test operates on a user-visible property while allowing implementation details to change.

The best bug reports in this domain are exact and perceptual:

The cursor lands between the n and g of formatting.

That sentence gives the agent a concrete anchor. The investigation can trace source offsets, rendered ranges, grapheme clusters, and line layout until the model explains the position.

11.4 Compare incremental and full projection

Editors optimize by patching only the affected projection. That creates two implementations of the same contract: incremental update and full recomputation.

Equivalence tests should require both paths to produce the same relevant state. The hard part is defining relevant. Whatever fields you enumerate first, expect the list to be incomplete. If your editor carries suggestion marks, an equivalence check that omits their metadata lets the fast path leave a mark’s byte range stale while the suite stays green.

Attack the checker field by field. Change one field in a known fixture and confirm that the test fails. A comparison that has never noticed a selection or decoration mismatch should not be assumed to cover them.

11.5 Pay the invariant’s cost openly

A constraint that costs nothing may not be constraining much. The one-source rule forbids the most attractive editor shortcut: replacing revealed source with rendered content inline. Byte mapping depends on every character staying where the file says it is. Under that rule, hidden delimiters become one-point clear glyphs instead of being removed. Live preview moves to a side panel. A held-preview state carries the last good render while mid-edit source is invalid. Suggestion marks with absolute byte ranges force a full parse, because the incremental fast path cannot shift them safely.

None of this is free. The design accepts a slower path and a more complex product to keep the mapping exact. The visible costs are also the evidence that the invariant is real. Ask yourself where your strongest architectural rule made a feature harder rather than easier. A specific answer means the rule has been tested against real work. No answer usually means the rule constrains nothing.

11.6 Preserve unsupported source visibly

A source editor will encounter syntax it cannot render or edit structurally. The safe fallback is visible source, not a partial projection.

The rule holds beyond prose. If your editor typesets math or lays out diagrams, a broken diagram should become a labeled source card, pathological math should degrade to an unsupported marker instead of crashing, and raw embedded markup should display as styled literal source. When the projection cannot represent the input faithfully, show the source and the diagnostic rather than guessing or deleting.

The fallback must remain locatable. A generic error card that loses the original span prevents the user from repairing the text. Preserve the range, the literal source, and the reason the projection declined it.

11.7 Use the model to diagnose the pixels

A user sees the screen. The agent should inspect the layout model behind it. Exact offsets and geometry are more reliable than a second round of squinting at a screenshot.

This does not eliminate visual tests. It puts them at the right boundary:

The editor remains pleasant because the human supplies perception. It remains trustworthy because the source model supplies proof.

use ← and → to turn pages