Skip to content

v4.100.67

Choose a tag to compare

@mann1x mann1x released this 05 Sep 12:57
· 1418 commits to main since this release

A range and an old_text that disagree is not an edit

editor dispatched on start_line and never passed old_text to the range
path. A call carrying both replaced the lines it named and never checked the
anchor it also sent
.

Measured live, in a transaction that then failed:

{ start_line: 100, end_line: 102, old_text: "\n", new_text: "\n" }

One blank line named as the anchor, three lines replaced. It deleted a class's
closing brace and a function update(){ declaration, reported Replaced lines 100-102 as success, and left the model to work out what had eaten its code.
It concluded that blank lines "anchor incorrectly" and that the file was
"un-editable through micro-edits". They were not anchoring at all.

Across six sessions: 134 editor calls, 26 carried both, and 13 of those 26
had an old_text whose line count could not fit the span it named.
Ten of
the thirteen were on 4.100.65 — before restore_file existed — so this is not
a regression in the new tools. It is the failure they made visible: until a
model could undo one file, a destructive edit stayed in the transaction and
poisoned everything after it, silently.

The two halves must agree, or nothing happens. A mismatch is refused, with
the file's current lines quoted back, and the file untouched. A leading or
trailing newline around the anchor is tolerated — a model brackets its anchor
with line breaks about as often as not, and refusing over punctuation is its
own failure — and a pasted read gutter is stripped before comparing.

Refused, not re-anchored. Preferring old_text and re-finding it would act
on whichever half happened to be right by luck. A call whose two halves
describe different code is a call whose author is wrong about the file, and the
repair that works is to read it again. A refusal costs one turn; the silent
version cost a transaction.

The large-range guard now skips an anchored range, which is what its own
message and the test named for it always claimed. That test passes old_text
with no range, so it took the other path entirely and the both-supplied case
had no coverage at all. Its carries no old_text to check it against is now
only printed when that is true.

Four tests, two of which go red with the check disabled.