F3 SLICE-3 host fixes: disk-compare sync detection + self-minimized seam edits (INV-9) (#6)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-06-10 10:50:07 -07:00
parent fe23ffa100
commit 2604ab4925
3 changed files with 89 additions and 9 deletions
+29
View File
@@ -7,6 +7,27 @@
*/
import type { Provenance } from "./model";
/**
* Greedily trim the common prefix then common suffix between the replaced
* text and its replacement (non-overlapping), mirroring the host's own
* WorkspaceEdit diff-minimization so a registered seam edit matches the
* change event VS Code actually delivers (INV-9).
*/
export function minimizeReplace(
oldText: string,
newText: string,
): { prefix: number; suffix: number } {
const max = Math.min(oldText.length, newText.length);
let prefix = 0;
while (prefix < max && oldText[prefix] === newText[prefix]) prefix++;
let suffix = 0;
while (
suffix < max - prefix &&
oldText[oldText.length - 1 - suffix] === newText[newText.length - 1 - suffix]
) suffix++;
return { prefix, suffix };
}
export interface PendingEdit {
docPath: string;
/** half-open [start, end) offsets of the replaced range. */
@@ -15,6 +36,14 @@ export interface PendingEdit {
newText: string;
provenance: Provenance;
turnId?: string;
/**
* The agent's full intended replacement before self-minimization (pre-edit
* half-open range + replacement length). The minimized start/end/newText are
* transport-only (so the registration matches the host-delivered change);
* attribution uses this extent — the agent owns every char it asserted,
* including chars the minimized diff left unchanged.
*/
full?: { start: number; end: number; newLength: number };
}
export class PendingEditRegistry {