Split PreviewEdit edits into lineEdits + textEdits#206
Conversation
The old flat `edits` array forced Claude to mentally simulate line-number offsets when mixing insert/delete ops with text-search ops in a single call. The implementation applied text-search patches against the original file positions, then merged them with structural edits — but never adjusted for insert/delete offsets. Result: text replacements landed N lines too early silently. New schema: - `lineEdits` (insert | replace | delete): all line numbers reference the file before the call. Tool sorts bottom-to-top internally, so no offset arithmetic needed from the caller. - `textEdits` (replace_text | regex_text): applied in order after all lineEdits complete, searching post-lineEdit content. This eliminates the entire class of offset bugs and the workaround rules that documented them. The Ref default limit description was also updated (limit was raised from 1000 to 10000 in a previous commit but the description string and tests still said 1000).
…factor The current-state section still described the architecture refactor as active work with a step-by-step table. That series finished at PR #199. Replace it with the three open PRs (#206, #207, #211) and a pointer to the backlog plans. Recent decisions gains entries for the PreviewEdit lineEdits/textEdits redesign and the CacheTtl enum move. Remove the stale cancelFn note — that work landed in #199.
bananabot9000
left a comment
There was a problem hiding this comment.
Clean fix for the multi-edit line-shift bug 🍌 The lineEdits/textEdits split is the right call -- two independent position streams that were never reconciled, now properly sequenced (line ops first against original, text ops second against post-edit content).
Code quality: Good. sortBottomToTop is pure (copies array), overlap detection is O(n²) but edit arrays are small, error messages improved with quoted strings vs escaped regex.
One question: Two inserts at the same after_line will trigger the overlap check (a.start <= b.end && b.start <= a.end where both start=end=after_line). Is this intentional? Multiple inserts at the same position have ambiguous ordering, so blocking them is arguably correct, but worth confirming.
Ref limit bump (1k/2k → 10k/20k): Separate concern bundled in, but not worth blocking over. Consistent across description + schema + tests.
No sensitive data. Session log is design notes only.
Reviewed by BananaBot9000 🍌
* Add sdk-tools and cli-features backlogs, link all GitHub issues * Update CLAUDE.md: current state reflects active PRs, not completed refactor The current-state section still described the architecture refactor as active work with a step-by-step table. That series finished at PR #199. Replace it with the three open PRs (#206, #207, #211) and a pointer to the backlog plans. Recent decisions gains entries for the PreviewEdit lineEdits/textEdits redesign and the CacheTtl enum move. Remove the stale cancelFn note — that work landed in #199.
* Add changes.jsonl for claude-sdk-tools, .gitattributes merge=union Retroactive change log for claude-sdk-tools covering PRs #176 and #206. No release marker yet — package hasn't shipped. .gitattributes sets merge=union on changes.jsonl so concurrent entries on different branches append rather than conflict. * Bump claude-sdk-tools to 1.0.0-alpha.1, add release marker * Add trailing newline to changes.jsonl Without it, echo >> changes.jsonl appends on the same line as the last entry, producing invalid JSONL.
Summary
lineEditssorts bottom-to-top internally so all line numbers reference the file before the calltextEditsrun after alllineEdits, searching the post-edit contenteditsarray removed; Ref tool description updated to match actual limit of 10000