From 2a9c198859210a39335104baff14221efa253708 Mon Sep 17 00:00:00 2001 From: Ben Stull Date: Wed, 10 Jun 2026 06:53:50 -0700 Subject: [PATCH] F2 SLICE-4: lock reload/re-anchor/orphan decision logic with unit tests (#4) Co-Authored-By: Claude Opus 4.8 (1M context) --- test/reanchor.test.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/reanchor.test.ts diff --git a/test/reanchor.test.ts b/test/reanchor.test.ts new file mode 100644 index 0000000..5aabb31 --- /dev/null +++ b/test/reanchor.test.ts @@ -0,0 +1,28 @@ +import { describe, it, expect } from "vitest"; +import { buildFingerprint, resolve } from "../src/anchorer"; + +const ORIGINAL = "intro\nThe quick brown fox\noutro\n"; + +describe("re-anchor scenarios (SLICE-4 decision logic)", () => { + it("reload, document unchanged: resolves to the same range", () => { + const start = ORIGINAL.indexOf("quick brown"); + const fp = buildFingerprint(ORIGINAL, { start, end: start + "quick brown".length }); + expect(resolve(ORIGINAL, fp)).toEqual({ start, end: start + "quick brown".length }); + }); + + it("external edit that moves the anchored text down: re-resolves to the new range", () => { + const start = ORIGINAL.indexOf("quick brown"); + const fp = buildFingerprint(ORIGINAL, { start, end: start + "quick brown".length }); + const edited = "a new first line\nanother line\n" + ORIGINAL; + const newStart = edited.indexOf("quick brown"); + expect(newStart).not.toBe(start); + expect(resolve(edited, fp)).toEqual({ start: newStart, end: newStart + "quick brown".length }); + }); + + it("external edit that deletes the anchored text: orphaned, never moved (INV-1)", () => { + const start = ORIGINAL.indexOf("quick brown"); + const fp = buildFingerprint(ORIGINAL, { start, end: start + "quick brown".length }); + const edited = "intro\nThe lazy dog\noutro\n"; + expect(resolve(edited, fp)).toBe("orphaned"); + }); +});