import type { HashMismatch } from "./types.ts"; /** * Search ±N lines from the target position for a line whose computed hash * matches the expected hash. Used for fuzzy re-anchoring when a line has shifted. * * The search is truly symmetric: at each distance d the line above * (targetLine - d) is checked before the line below (targetLine + d), so an * ambiguous duplicate resolves to the nearest line, with above winning ties — * the caller's anchor was captured against an older revision, and a line * pushed down by an insertion above it is more likely to be the intended * target than a look-alike duplicate below. * * @returns The matching line number, or null if no match found within window. */ export declare function findNearbyMatch(lines: string[], targetLine: number, expectedHash: string, hashWidth: number, maxDistance?: number): number | null; /** * Suggest the correct anchor for a mismatched line reference. * Returns a human-readable suggestion string, or null if no suggestion found. * * Example output: 'Line 42#aB not found. Did you mean line 43#cD? (content matches, line shifted by +1)' */ export declare function suggestCorrectAnchor(mismatch: HashMismatch, fileLines: string[], hashWidth: number): string | null; /** * Thrown when a hash collision makes the corrected anchor ambiguous: two or * more qualifying uniform offsets map the SAME mismatch to candidate lines * whose CONTENT differs. Silently preferring the smallest |offset| would edit * the wrong line (D5 — silent wrong-line edit via a narrow-width hash * collision), so instead of guessing we refuse and ask the caller to re-read. * * Identical-content candidates (true duplicate lines) are NOT ambiguous — they * are a legitimate tie that {@link detectUniformOffset} still resolves to the * smallest |offset|/above-preferred pick. */ export declare class AmbiguousAnchorError extends Error { /** The mismatched anchor that is ambiguous, as "line#hash". */ readonly anchor: string; /** The candidate line numbers the qualifying offsets map this anchor to. */ readonly candidateLines: number[]; /** The hash width at which the collision occurred. */ readonly hashWidth: number; constructor(anchor: string, candidateLines: number[], hashWidth: number); } /** * Attempt to auto-correct all mismatches by detecting a uniform offset. * If all mismatches are off by the same number of lines (e.g., an insertion * happened above the edit region), return the corrected anchors. * * For each mismatch the FULL candidate set (offset → line) within the search * window is collected; an offset qualifies only if it appears in EVERY * mismatch's candidate set (a uniform shift). When the qualifying offsets tie * (or there is a single mismatch), the smallest |offset| wins, with the above * (negative) side preferred. * * D5 guard: when MORE THAN ONE offset qualifies uniformly, a narrow-width hash * collision can make two qualifying offsets map the same mismatch to lines with * DIFFERENT content, in which case the tie-break would silently edit the wrong * line. Before picking, every mismatch is checked: if any mismatch has two * qualifying candidates with non-identical content, an {@link AmbiguousAnchorError} * is thrown instead of guessing. Identical-content candidates (duplicate lines) * are still resolved by the normal tie-break. * * @returns Map of old_ref -> new_ref, or null if offsets are not uniform. * @throws {AmbiguousAnchorError} when a hash collision makes the uniform * correction ambiguous (non-identical candidate content across offsets). */ export declare function detectUniformOffset(mismatches: HashMismatch[], fileLines: string[], hashWidth: number): Map | null; //# sourceMappingURL=fuzzy.d.ts.map