Reject on an optimistically-applied proposal now restores the retained original even after interior tweaks: appliedSpans tracked-range fallback (pure shiftTracked, boundary-straddle distrust, close-clears, rebuild-only resync), honest hard failure with a Discard action, INV-16 read-only guards, rejectAll {reverted,skipped} reporting on all batch surfaces, CodeLens reachability at the tracked span. 312 unit + 94/5 host E2E.
Closes #70.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit was merged in pull request #73.
This commit is contained in:
@@ -101,6 +101,30 @@ export function resolve(docText: string, fp: Fingerprint): OffsetRange | "orphan
|
||||
return "orphaned";
|
||||
}
|
||||
|
||||
/**
|
||||
* #70 (INV-5/INV-11): maintain a TRACKED applied span across an in-session edit.
|
||||
* Unlike `shift`, which clamps every point into a best-effort range, a tracked
|
||||
* span must stay *provably* meaningful — it is a revert target. So:
|
||||
* - an edit fully OUTSIDE or fully INSIDE the span shifts it (the span is
|
||||
* still "the applied block, as tweaked");
|
||||
* - an insertion exactly AT the span start lands BEFORE the span (both ends
|
||||
* shift right) — matching exact-resolve semantics, where text typed just
|
||||
* before the applied block is never part of it;
|
||||
* - any edit STRADDLING a span boundary returns "distrusted": the shifted
|
||||
* result would be a clamped guess, and stale text is never reverted by
|
||||
* guess (INV-11).
|
||||
*/
|
||||
export function shiftTracked(range: OffsetRange, edit: TextEdit): OffsetRange | "distrusted" {
|
||||
const delta = edit.newLength - (edit.end - edit.start);
|
||||
if (edit.start === edit.end && edit.start === range.start) {
|
||||
return { start: range.start + delta, end: range.end + delta };
|
||||
}
|
||||
const outside = edit.end <= range.start || edit.start >= range.end;
|
||||
const inside = edit.start >= range.start && edit.end <= range.end;
|
||||
if (!outside && !inside) return "distrusted";
|
||||
return shift(range, edit);
|
||||
}
|
||||
|
||||
/** Maintain a live range across an in-session edit (spec §6.4 `shift`). */
|
||||
export function shift(range: OffsetRange, edit: TextEdit): OffsetRange {
|
||||
const delta = edit.newLength - (edit.end - edit.start);
|
||||
|
||||
Reference in New Issue
Block a user