@mrsf/cli 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +12 -9
  2. package/dist/browser.cjs +1101 -24
  3. package/dist/browser.cjs.map +4 -4
  4. package/dist/browser.d.ts +11 -0
  5. package/dist/browser.js +8 -0
  6. package/dist/commands/add.js +12 -4
  7. package/dist/evaluation/generate-reanchor-cases.d.ts +10 -0
  8. package/dist/evaluation/generate-reanchor-cases.js +301 -0
  9. package/dist/evaluation/reanchor-eval.d.ts +111 -0
  10. package/dist/evaluation/reanchor-eval.js +266 -0
  11. package/dist/evaluation/reanchor-gates.d.ts +29 -0
  12. package/dist/evaluation/reanchor-gates.js +47 -0
  13. package/dist/evaluation/run-reanchor-eval.d.ts +3 -0
  14. package/dist/evaluation/run-reanchor-eval.js +103 -0
  15. package/dist/evaluation/run-reanchor-generator.d.ts +3 -0
  16. package/dist/evaluation/run-reanchor-generator.js +63 -0
  17. package/dist/evaluation/run-reanchor-profile.d.ts +3 -0
  18. package/dist/evaluation/run-reanchor-profile.js +129 -0
  19. package/dist/index.cjs +1226 -34
  20. package/dist/index.cjs.map +4 -4
  21. package/dist/index.d.ts +13 -0
  22. package/dist/index.js +10 -0
  23. package/dist/lib/anchor-context.d.ts +46 -0
  24. package/dist/lib/anchor-context.js +474 -0
  25. package/dist/lib/confidence-calibration.d.ts +16 -0
  26. package/dist/lib/confidence-calibration.js +120 -0
  27. package/dist/lib/fuzzy.d.ts +14 -1
  28. package/dist/lib/fuzzy.js +140 -19
  29. package/dist/lib/git.d.ts +9 -0
  30. package/dist/lib/git.js +30 -0
  31. package/dist/lib/global-reconciliation.d.ts +11 -0
  32. package/dist/lib/global-reconciliation.js +145 -0
  33. package/dist/lib/reanchor-core.d.ts +7 -0
  34. package/dist/lib/reanchor-core.js +46 -4
  35. package/dist/lib/reanchor.js +82 -11
  36. package/dist/lib/revision-projection.d.ts +21 -0
  37. package/dist/lib/revision-projection.js +203 -0
  38. package/package.json +5 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/browser.ts", "../src/lib/fuzzy.ts", "../src/lib/identity.ts", "../src/lib/reanchor-core.ts", "../src/lib/validate-core.ts", "../mrsf.schema.json", "../src/lib/schema.ts", "../src/lib/serialize.ts"],
4
- "sourcesContent": ["import * as fuzzy from \"./lib/fuzzy.js\";\nimport * as identity from \"./lib/identity.js\";\nimport * as reanchorCore from \"./lib/reanchor-core.js\";\nimport * as validateCore from \"./lib/validate-core.js\";\nimport * as serialize from \"./lib/serialize.js\";\nimport { mrsfSchema } from \"./lib/schema.js\";\n\nexport type {\n AnchorPosition,\n Comment,\n DiffHunk,\n FuzzyCandidate,\n MrsfDocument,\n ReanchorResult,\n ReanchorStatus,\n ValidationDiagnostic,\n ValidationResult,\n DiagnosticSeverity,\n} from \"./lib/types.js\";\nexport type { ParsedAuthor } from \"./lib/identity.js\";\nexport type { LenientParseResult } from \"./lib/serialize.js\";\n\n// Parse / serialize (pure string \u21C4 document; no filesystem or argv deps).\nexport const parseSidecarContent = serialize.parseSidecarContent;\nexport const parseSidecarContentLenient = serialize.parseSidecarContentLenient;\nexport const toYaml = serialize.toYaml;\nexport const toJson = serialize.toJson;\n\nexport const combinedScore = fuzzy.combinedScore;\nexport const exactMatch = fuzzy.exactMatch;\nexport const fuzzySearch = fuzzy.fuzzySearch;\nexport const levenshteinScore = fuzzy.levenshteinScore;\nexport const normalizedMatch = fuzzy.normalizedMatch;\nexport const tokenLcsScore = fuzzy.tokenLcsScore;\n\nexport const applyReanchorResults = reanchorCore.applyReanchorResults;\nexport const DEFAULT_THRESHOLD = reanchorCore.DEFAULT_THRESHOLD;\nexport const HIGH_THRESHOLD = reanchorCore.HIGH_THRESHOLD;\nexport const reanchorComment = reanchorCore.reanchorComment;\nexport const reanchorDocumentLines = reanchorCore.reanchorDocumentLines;\nexport const reanchorDocumentText = reanchorCore.reanchorDocumentText;\nexport const resolveAnchor = reanchorCore.resolveAnchor;\nexport const toReanchorLines = reanchorCore.toReanchorLines;\n\nexport const validateDocument = validateCore.validateDocument;\nexport { mrsfSchema };\n\nexport const formatAuthor = identity.formatAuthor;\nexport const parseAuthor = identity.parseAuthor;\nexport const newCommentId = identity.newCommentId;\n", "/**\n * MRSF Fuzzy Matching Engine\n *\n * Provides exact, normalized, token-level LCS, and character-level\n * Levenshtein matching for re-anchoring selected_text.\n */\n\nimport { distance as levenshtein } from \"fastest-levenshtein\";\nimport type { FuzzyCandidate } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Exact matching\n// ---------------------------------------------------------------------------\n\n/**\n * Find all exact occurrences of `needle` in lines (1-based array).\n */\nexport function exactMatch(\n lines: string[],\n needle: string,\n): FuzzyCandidate[] {\n if (!needle) return [];\n\n const results: FuzzyCandidate[] = [];\n const needleLines = needle.split(\"\\n\");\n const needleLineCount = needleLines.length;\n\n // Slide a window across the document\n for (let startLine = 1; startLine <= lines.length - needleLineCount; startLine++) {\n // Build the text for this window\n const windowLines = lines.slice(startLine, startLine + needleLineCount);\n const windowText = windowLines.join(\"\\n\");\n\n // Check if the needle appears anywhere within this window (for single-line)\n if (needleLineCount === 1) {\n let col = 0;\n const line = windowLines[0];\n while (col < line.length) {\n const idx = line.indexOf(needle, col);\n if (idx === -1) break;\n results.push({\n text: needle,\n line: startLine,\n endLine: startLine,\n startColumn: idx,\n endColumn: idx + needle.length,\n score: 1.0,\n });\n col = idx + 1;\n }\n } else {\n // Multi-line: check if the window contains the exact needle\n const idx = windowText.indexOf(needle);\n if (idx !== -1) {\n // Calculate start column\n const beforeMatch = windowText.slice(0, idx);\n const linesBeforeEnd = beforeMatch.split(\"\\n\");\n const startCol = linesBeforeEnd[linesBeforeEnd.length - 1].length;\n\n // Calculate end column\n const afterMatch = needle.split(\"\\n\");\n const endCol = afterMatch[afterMatch.length - 1].length;\n if (startCol === 0 || linesBeforeEnd.length === 1) {\n results.push({\n text: needle,\n line: startLine + linesBeforeEnd.length - 1,\n endLine: startLine + linesBeforeEnd.length - 1 + afterMatch.length - 1,\n startColumn: startCol,\n endColumn: endCol,\n score: 1.0,\n });\n }\n }\n }\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Normalized matching (collapse whitespace)\n// ---------------------------------------------------------------------------\n\nfunction normalize(text: string): string {\n return text.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Find matches after normalizing whitespace.\n */\nexport function normalizedMatch(\n lines: string[],\n needle: string,\n): FuzzyCandidate[] {\n const normNeedle = normalize(needle);\n if (!normNeedle) return [];\n\n const results: FuzzyCandidate[] = [];\n\n // Try expanding windows of varying sizes\n const needleLineEstimate = needle.split(\"\\n\").length;\n const minWindow = Math.max(1, needleLineEstimate - 1);\n const maxWindow = Math.min(lines.length - 1, needleLineEstimate + 2);\n\n for (let winSize = minWindow; winSize <= maxWindow; winSize++) {\n for (let startLine = 1; startLine + winSize - 1 < lines.length; startLine++) {\n const windowLines = lines.slice(startLine, startLine + winSize);\n const windowText = windowLines.join(\"\\n\");\n const normWindow = normalize(windowText);\n\n if (normWindow.includes(normNeedle)) {\n results.push({\n text: windowText,\n line: startLine,\n endLine: startLine + winSize - 1,\n startColumn: 0,\n endColumn: windowLines[windowLines.length - 1].length,\n score: 0.95,\n });\n }\n }\n }\n\n return deduplicateCandidates(results);\n}\n\n// ---------------------------------------------------------------------------\n// Token-level LCS\n// ---------------------------------------------------------------------------\n\nfunction tokenize(text: string): string[] {\n return text.split(/\\s+/).filter((t) => t.length > 0);\n}\n\n/**\n * Longest Common Subsequence length of two token arrays.\n */\nfunction lcsLength(a: string[], b: string[]): number {\n const m = a.length;\n const n = b.length;\n // Optimize: use two rows instead of full matrix\n let prev = new Array<number>(n + 1).fill(0);\n let curr = new Array<number>(n + 1).fill(0);\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (a[i - 1] === b[j - 1]) {\n curr[j] = prev[j - 1] + 1;\n } else {\n curr[j] = Math.max(prev[j], curr[j - 1]);\n }\n }\n [prev, curr] = [curr, prev];\n curr.fill(0);\n }\n\n return prev[n];\n}\n\n/**\n * Score two texts using token-level LCS.\n * Returns 0.0\u20131.0.\n */\nexport function tokenLcsScore(a: string, b: string): number {\n const tokA = tokenize(a);\n const tokB = tokenize(b);\n if (tokA.length === 0 && tokB.length === 0) return 1.0;\n if (tokA.length === 0 || tokB.length === 0) return 0.0;\n const lcs = lcsLength(tokA, tokB);\n return lcs / Math.max(tokA.length, tokB.length);\n}\n\n// ---------------------------------------------------------------------------\n// Character-level Levenshtein score\n// ---------------------------------------------------------------------------\n\n/**\n * Normalized Levenshtein similarity 0.0\u20131.0.\n */\nexport function levenshteinScore(a: string, b: string): number {\n if (a.length === 0 && b.length === 0) return 1.0;\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1.0;\n const dist = levenshtein(a, b);\n return 1 - dist / maxLen;\n}\n\n// ---------------------------------------------------------------------------\n// Combined fuzzy scoring\n// ---------------------------------------------------------------------------\n\n/**\n * Compute a combined similarity score between two text fragments.\n * Blends token LCS (structural) and Levenshtein (character-level).\n */\nexport function combinedScore(needle: string, candidate: string): number {\n const tScore = tokenLcsScore(needle, candidate);\n\n // Full Levenshtein is expensive for long texts; only use for short ones\n let lScore: number;\n if (needle.length < 500 && candidate.length < 500) {\n lScore = levenshteinScore(needle, candidate);\n } else {\n lScore = tScore; // fall back to token score only\n }\n\n // Weight: 60% token LCS, 40% Levenshtein\n return tScore * 0.6 + lScore * 0.4;\n}\n\n// ---------------------------------------------------------------------------\n// Fuzzy search across document\n// ---------------------------------------------------------------------------\n\n/**\n * Search the document for fuzzy matches of `needle`.\n *\n * @param lines 1-based line array (index 0 unused).\n * @param needle The original selected_text.\n * @param threshold Minimum score to include (0.0\u20131.0).\n * @param hintLine Optional original line number for proximity scoring.\n */\nexport function fuzzySearch(\n lines: string[],\n needle: string,\n threshold: number = 0.6,\n hintLine?: number,\n): FuzzyCandidate[] {\n if (!needle) return [];\n\n const needleLines = needle.split(\"\\n\");\n const needleLineCount = needleLines.length;\n const candidates: FuzzyCandidate[] = [];\n\n // Window sizes: \u00B130% of original line count, minimum 1\n const minWindow = Math.max(1, Math.floor(needleLineCount * 0.7));\n const maxWindow = Math.min(\n lines.length - 1,\n Math.ceil(needleLineCount * 1.3) + 1,\n );\n\n for (let winSize = minWindow; winSize <= maxWindow; winSize++) {\n for (let startLine = 1; startLine + winSize - 1 < lines.length; startLine++) {\n const windowLines = lines.slice(startLine, startLine + winSize);\n const windowText = windowLines.join(\"\\n\");\n\n const score = combinedScore(needle, windowText);\n\n if (score >= threshold) {\n candidates.push({\n text: windowText,\n line: startLine,\n endLine: startLine + winSize - 1,\n startColumn: 0,\n endColumn: windowLines[windowLines.length - 1].length,\n score,\n });\n }\n }\n }\n\n // For single-line needles, also try substring matching within each line\n if (needleLineCount === 1 && needle.length < 200) {\n for (let lineNum = 1; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n if (!line) continue;\n\n // Sliding window within line\n const winLen = needle.length;\n const minWinLen = Math.max(3, Math.floor(winLen * 0.7));\n const maxWinLen = Math.min(line.length, Math.ceil(winLen * 1.3));\n\n for (let len = minWinLen; len <= maxWinLen; len++) {\n for (let col = 0; col + len <= line.length; col++) {\n const sub = line.substring(col, col + len);\n const score = combinedScore(needle, sub);\n if (score >= threshold) {\n candidates.push({\n text: sub,\n line: lineNum,\n endLine: lineNum,\n startColumn: col,\n endColumn: col + len,\n score,\n });\n }\n }\n }\n }\n }\n\n // Deduplicate and sort\n let deduped = deduplicateCandidates(candidates);\n\n // Apply proximity bonus if hintLine is provided\n if (hintLine != null) {\n deduped = deduped.map((c) => {\n const dist = Math.abs(c.line - hintLine);\n // Small bonus for proximity (up to 0.1 for exact line match)\n const proximityBonus = 0.1 * Math.max(0, 1 - dist / 50);\n return { ...c, score: Math.min(1.0, c.score + proximityBonus) };\n });\n }\n\n return deduped.sort((a, b) => b.score - a.score);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction deduplicateCandidates(\n candidates: FuzzyCandidate[],\n): FuzzyCandidate[] {\n const seen = new Map<string, FuzzyCandidate>();\n for (const c of candidates) {\n const key = `${c.line}:${c.startColumn}:${c.endLine}:${c.endColumn}`;\n const existing = seen.get(key);\n if (!existing || c.score > existing.score) {\n seen.set(key, c);\n }\n }\n return Array.from(seen.values());\n}\n", "import { v4 as uuidv4 } from \"uuid\";\n\nexport interface ParsedAuthor {\n name: string;\n handle?: string;\n}\n\nexport function formatAuthor(name: string, handle?: string): string {\n const trimmedName = name.trim();\n const trimmedHandle = handle?.trim();\n return trimmedHandle ? `${trimmedName} (${trimmedHandle})` : trimmedName;\n}\n\nexport function parseAuthor(author: string): ParsedAuthor {\n const trimmed = author.trim();\n const match = /^(.*?)\\s*\\(([^()]*)\\)\\s*$/.exec(trimmed);\n if (!match) return { name: trimmed };\n\n const name = match[1].trim();\n const handle = match[2].trim();\n return handle ? { name, handle } : { name };\n}\n\n/**\n * Create a collision-resistant MRSF comment id.\n * ULID is also permitted by the spec; UUIDv4 is the default for this package.\n */\nexport function newCommentId(): string {\n return uuidv4();\n}\n", "import type {\n AnchorPosition,\n Comment,\n DiffHunk,\n FuzzyCandidate,\n MrsfDocument,\n ReanchorResult,\n} from \"./types.js\";\nimport {\n exactMatch,\n fuzzySearch,\n normalizedMatch,\n} from \"./fuzzy.js\";\n\nexport const HIGH_THRESHOLD = 0.8;\nexport const DEFAULT_THRESHOLD = 0.6;\n\n/**\n * Default proximity window (in lines) for the \u00A77.4 step 1a relocation guard.\n *\n * A lone exact match of `selected_text` that lands farther than this many\n * lines from the comment's original `line` \u2014 while the text at the original\n * position has changed \u2014 is treated as an in-place edit rather than a\n * confident relocation. See {@link isImplausibleExactRelocation}.\n */\nexport const DEFAULT_PROXIMITY_WINDOW = 5;\n\nexport function toReanchorLines(documentText: string): string[] {\n return [\"\", ...documentText.replace(/\\r\\n/g, \"\\n\").split(\"\\n\")];\n}\n\nexport function reanchorComment(\n comment: Comment,\n documentLines: string[],\n opts: {\n diffHunks?: DiffHunk[];\n threshold?: number;\n commitIsStale?: boolean;\n proximityWindow?: number;\n } = {},\n): ReanchorResult {\n const threshold = opts.threshold ?? DEFAULT_THRESHOLD;\n const proximityWindow = opts.proximityWindow ?? DEFAULT_PROXIMITY_WINDOW;\n const commentId = comment.id;\n const selectedText = comment.selected_text;\n\n if (!selectedText && comment.line == null) {\n return {\n commentId,\n status: \"anchored\",\n score: 1.0,\n reason: \"Document-level comment (no anchor needed).\",\n };\n }\n\n if (comment.line != null && opts.diffHunks?.length) {\n const { shift, modified } = getLineShift(opts.diffHunks, comment.line);\n\n if (!selectedText) {\n const shiftedLine = comment.line + shift;\n const lineSpan =\n comment.end_line != null ? comment.end_line - comment.line : 0;\n const shiftedEndLine =\n comment.end_line != null ? shiftedLine + lineSpan : undefined;\n return {\n commentId,\n status: shift === 0 ? \"anchored\" : \"shifted\",\n score: 1.0,\n newLine: shiftedLine,\n newEndLine: shiftedEndLine,\n reason:\n shift === 0\n ? \"Line-only comment unchanged (diff confirms position).\"\n : `Line-only comment shifted by ${shift > 0 ? \"+\" : \"\"}${shift} line(s) via diff.`,\n };\n }\n\n if (!modified) {\n const shiftedLine = comment.line + shift;\n const lineSpan =\n comment.end_line != null ? comment.end_line - comment.line : 0;\n const shiftedEndLine =\n comment.end_line != null ? shiftedLine + lineSpan : undefined;\n\n const textAtShifted = extractText(\n documentLines,\n shiftedLine,\n shiftedEndLine,\n comment.start_column,\n comment.end_column,\n );\n\n if (textAtShifted === selectedText) {\n return {\n commentId,\n status: shift === 0 ? \"anchored\" : \"shifted\",\n score: 1.0,\n newLine: shiftedLine,\n newEndLine: shiftedEndLine,\n reason:\n shift === 0\n ? \"Diff confirms text unchanged at original position.\"\n : `Diff shifted by ${shift > 0 ? \"+\" : \"\"}${shift} line(s).`,\n };\n }\n }\n }\n\n if (selectedText) {\n const exactCandidates = exactMatch(documentLines, selectedText);\n\n // Pick the best exact candidate: the only one, or \u2014 when several remain \u2014\n // the one nearest to the original line (\u00A77.4 step 1b).\n let chosen: FuzzyCandidate | undefined;\n let chosenReason = \"\";\n if (exactCandidates.length === 1) {\n chosen = exactCandidates[0];\n chosenReason = \"Exact text match (unique).\";\n } else if (exactCandidates.length > 1 && comment.line != null) {\n chosen = closestToLine(exactCandidates, comment.line);\n chosenReason = `Exact text match (${exactCandidates.length} occurrences; chose nearest to original line ${comment.line}).`;\n }\n\n if (chosen) {\n // \u00A77.4 step 1a proximity guard: a lone/closest exact match that lands far\n // from the original position \u2014 while the text at the original position no\n // longer equals selected_text \u2014 most likely indicates an in-place edit of\n // the anchored text, not a genuine relocation. Keep the comment at its\n // original position and flag it for re-anchoring instead of teleporting it\n // onto an unrelated identical token with full confidence.\n if (isImplausibleExactRelocation(comment, chosen, documentLines, proximityWindow)) {\n const textAtOrigin = extractText(\n documentLines,\n comment.line as number,\n comment.end_line,\n comment.start_column,\n comment.end_column,\n );\n return {\n commentId,\n status: \"fuzzy\",\n score: 0.5,\n newLine: comment.line,\n newEndLine: comment.end_line,\n newStartColumn: comment.start_column,\n newEndColumn: comment.end_column,\n anchoredText: textAtOrigin ?? undefined,\n previousSelectedText: selectedText,\n reason:\n `Lone exact match at line ${chosen.line} is beyond the proximity window ` +\n `(\u00B1${proximityWindow}) of original line ${comment.line} and the text at the ` +\n `original position changed; kept at original position, needs re-anchoring.`,\n };\n }\n\n return {\n commentId,\n status: \"anchored\",\n score: 1.0,\n newLine: chosen.line,\n newEndLine: chosen.endLine,\n newStartColumn: chosen.startColumn,\n newEndColumn: chosen.endColumn,\n reason: chosenReason,\n };\n }\n\n const normCandidates = normalizedMatch(documentLines, selectedText);\n if (normCandidates.length === 1) {\n const candidate = normCandidates[0];\n return {\n commentId,\n status: \"fuzzy\",\n score: candidate.score,\n newLine: candidate.line,\n newEndLine: candidate.endLine,\n newStartColumn: candidate.startColumn,\n newEndColumn: candidate.endColumn,\n anchoredText: candidate.text,\n previousSelectedText: selectedText,\n reason: \"Normalized whitespace match.\",\n };\n }\n\n const fuzzyCandidates = fuzzySearch(\n documentLines,\n selectedText,\n HIGH_THRESHOLD,\n comment.line,\n );\n\n if (fuzzyCandidates.length === 1 || (fuzzyCandidates.length > 0 && fuzzyCandidates[0].score >= HIGH_THRESHOLD)) {\n const best =\n fuzzyCandidates.length === 1\n ? fuzzyCandidates[0]\n : closestToLine(fuzzyCandidates, comment.line ?? 1);\n return {\n commentId,\n status: \"fuzzy\",\n score: best.score,\n newLine: best.line,\n newEndLine: best.endLine,\n newStartColumn: best.startColumn,\n newEndColumn: best.endColumn,\n anchoredText: best.text,\n previousSelectedText: selectedText,\n reason: `High-confidence fuzzy match (score ${best.score.toFixed(3)}).`,\n };\n }\n }\n\n if (comment.line != null) {\n const lineIdx = comment.line;\n if (lineIdx > 0 && lineIdx < documentLines.length) {\n const qualifier = opts.commitIsStale\n ? \" (commit is stale \u2014 line may have shifted)\"\n : \"\";\n\n if (selectedText) {\n const lineText = documentLines[lineIdx];\n const candidates = fuzzySearch([\"\", lineText], selectedText, DEFAULT_THRESHOLD);\n if (candidates.length > 0) {\n return {\n commentId,\n status: \"fuzzy\",\n score: candidates[0].score,\n newLine: comment.line,\n newEndLine: comment.end_line,\n anchoredText: candidates[0].text,\n previousSelectedText: selectedText,\n reason: `Line-fallback with fuzzy text match (score ${candidates[0].score.toFixed(3)})${qualifier}.`,\n };\n }\n }\n\n const isLineOnly = !selectedText;\n return {\n commentId,\n status: isLineOnly ? \"anchored\" : (opts.commitIsStale ? \"ambiguous\" : \"anchored\"),\n score: isLineOnly ? 1.0 : (opts.commitIsStale ? 0.5 : 0.8),\n newLine: comment.line,\n newEndLine: comment.end_line,\n reason: isLineOnly\n ? \"Line-only comment (no selected_text to verify).\"\n : `Line/column fallback${qualifier}.`,\n };\n }\n }\n\n if (selectedText) {\n const lowCandidates = fuzzySearch(\n documentLines,\n selectedText,\n threshold,\n comment.line,\n );\n\n if (lowCandidates.length === 1) {\n const candidate = lowCandidates[0];\n return {\n commentId,\n status: \"fuzzy\",\n score: candidate.score,\n newLine: candidate.line,\n newEndLine: candidate.endLine,\n newStartColumn: candidate.startColumn,\n newEndColumn: candidate.endColumn,\n anchoredText: candidate.text,\n previousSelectedText: selectedText,\n reason: `Low-threshold fuzzy match (score ${candidate.score.toFixed(3)}).`,\n };\n }\n\n if (lowCandidates.length > 1) {\n const best = lowCandidates[0];\n return {\n commentId,\n status: \"ambiguous\",\n score: best.score,\n newLine: best.line,\n newEndLine: best.endLine,\n reason: `Ambiguous: ${lowCandidates.length} fuzzy matches (best score ${best.score.toFixed(3)}).`,\n };\n }\n }\n\n return {\n commentId,\n status: \"orphaned\",\n score: 0,\n reason: \"No match found. Comment is orphaned.\",\n };\n}\n\nexport function reanchorDocumentLines(\n doc: MrsfDocument,\n documentLines: string[],\n opts: { threshold?: number; proximityWindow?: number } = {},\n): ReanchorResult[] {\n return doc.comments.map((comment) => reanchorComment(comment, documentLines, opts));\n}\n\nexport function reanchorDocumentText(\n doc: MrsfDocument,\n documentText: string,\n opts: { threshold?: number; proximityWindow?: number } = {},\n): ReanchorResult[] {\n return reanchorDocumentLines(doc, toReanchorLines(documentText), opts);\n}\n\nexport function resolveAnchor(\n comment: Comment,\n documentText: string,\n opts: { threshold?: number; proximityWindow?: number } = {},\n): AnchorPosition {\n const normalizedText = documentText.replace(/\\r\\n/g, \"\\n\");\n const documentLines = toReanchorLines(documentText);\n const result = reanchorComment(comment, documentLines, opts);\n\n if (result.status === \"orphaned\") {\n return {\n status: \"orphaned\",\n score: result.score,\n reason: result.reason,\n };\n }\n\n const line = result.newLine ?? comment.line;\n if (line == null) {\n return {\n status: result.status,\n score: result.score,\n reason: result.reason,\n };\n }\n\n const rawLines = normalizedText.split(\"\\n\");\n const lineStarts = computeLineStarts(rawLines);\n const endLine = result.newEndLine ?? comment.end_line ?? line;\n const startColumn = result.newStartColumn ?? comment.start_column ?? 0;\n const endColumn = result.newEndColumn ?? comment.end_column;\n const from = offsetFor(lineStarts, rawLines, line, startColumn);\n const selectedText = comment.selected_text?.replace(/\\r\\n/g, \"\\n\");\n const to =\n endColumn != null\n ? offsetFor(lineStarts, rawLines, endLine, endColumn)\n : selectedText\n ? from + selectedText.length\n : offsetFor(lineStarts, rawLines, endLine, rawLines[endLine - 1]?.length ?? 0);\n\n return {\n status: result.status,\n score: result.score,\n from,\n to,\n line,\n endLine,\n startColumn,\n endColumn: endColumn ?? columnForOffset(lineStarts, rawLines, endLine, to),\n reason: result.reason,\n };\n}\n\nfunction computeLineStarts(lines: string[]): number[] {\n const starts = [0];\n let offset = 0;\n for (const line of lines) {\n starts.push(offset);\n offset += line.length + 1;\n }\n return starts;\n}\n\nfunction offsetFor(\n lineStarts: number[],\n lines: string[],\n line: number,\n column: number,\n): number {\n const start = lineStarts[line] ?? 0;\n const maxColumn = lines[line - 1]?.length ?? 0;\n return start + Math.max(0, Math.min(column, maxColumn));\n}\n\nfunction columnForOffset(\n lineStarts: number[],\n lines: string[],\n line: number,\n offset: number,\n): number {\n const start = lineStarts[line] ?? 0;\n const maxColumn = lines[line - 1]?.length ?? 0;\n return Math.max(0, Math.min(offset - start, maxColumn));\n}\n\nexport function applyReanchorResults(\n doc: MrsfDocument,\n results: ReanchorResult[],\n opts: { updateText?: boolean; force?: boolean; headCommit?: string } = {},\n): number {\n let changed = 0;\n const resultMap = new Map(results.map((result) => [result.commentId, result]));\n\n for (const comment of doc.comments) {\n const result = resultMap.get(comment.id);\n if (!result) continue;\n\n let isChanged = false;\n\n if (result.newLine != null && result.newLine !== comment.line) {\n comment.line = result.newLine;\n isChanged = true;\n }\n if (result.newEndLine != null && result.newEndLine !== comment.end_line) {\n comment.end_line = result.newEndLine;\n isChanged = true;\n }\n if (result.newStartColumn != null && result.newStartColumn !== comment.start_column) {\n comment.start_column = result.newStartColumn;\n isChanged = true;\n }\n if (result.newEndColumn != null && result.newEndColumn !== comment.end_column) {\n comment.end_column = result.newEndColumn;\n isChanged = true;\n }\n\n if (result.anchoredText != null && result.anchoredText !== comment.selected_text) {\n if (opts.updateText) {\n comment.selected_text = result.anchoredText;\n delete comment.anchored_text;\n } else {\n comment.anchored_text = result.anchoredText;\n }\n isChanged = true;\n } else if (result.anchoredText != null && result.anchoredText === comment.selected_text) {\n if (comment.anchored_text) {\n delete comment.anchored_text;\n isChanged = true;\n }\n }\n\n if (isChanged || result.status !== \"anchored\") {\n comment.x_reanchor_status = result.status;\n comment.x_reanchor_score = result.score;\n }\n\n if (\n opts.force\n && opts.headCommit\n && (result.status === \"anchored\" || result.status === \"shifted\")\n && result.score >= HIGH_THRESHOLD\n ) {\n comment.commit = opts.headCommit;\n delete comment.x_reanchor_status;\n delete comment.x_reanchor_score;\n if (comment.anchored_text && comment.anchored_text === comment.selected_text) {\n delete comment.anchored_text;\n }\n isChanged = true;\n }\n\n if (isChanged) {\n changed += 1;\n }\n }\n\n return changed;\n}\n\nfunction extractText(\n lines: string[],\n line: number,\n endLine?: number,\n startColumn?: number,\n endColumn?: number,\n): string | null {\n const startIdx = line;\n const endIdx = endLine ?? line;\n\n if (startIdx < 1 || endIdx >= lines.length) return null;\n\n if (startIdx === endIdx) {\n const text = lines[startIdx];\n if (startColumn != null && endColumn != null) {\n return text.slice(startColumn, endColumn);\n }\n return text;\n }\n\n const result: string[] = [];\n for (let index = startIdx; index <= endIdx; index += 1) {\n let currentLine = lines[index];\n if (index === startIdx && startColumn != null) currentLine = currentLine.slice(startColumn);\n if (index === endIdx && endColumn != null) currentLine = currentLine.slice(0, endColumn);\n result.push(currentLine);\n }\n return result.join(\"\\n\");\n}\n\nfunction closestToLine<T extends { line: number }>(candidates: T[], targetLine: number): T {\n return candidates.reduce((best, candidate) =>\n Math.abs(candidate.line - targetLine) < Math.abs(best.line - targetLine) ? candidate : best,\n );\n}\n\n/**\n * \u00A77.4 step 1a relocation guard.\n *\n * Returns true when a chosen exact-match candidate is an *implausible*\n * full-confidence relocation: the original `line` still exists in the document,\n * the candidate is farther than `proximityWindow` lines away, and the text now\n * at the original position no longer equals `selected_text`. This is the\n * signature of an in-place edit of the anchored text (which removed the\n * original occurrence) rather than a genuine move of the selection.\n *\n * When the original line no longer exists (the document shrank or the section\n * was removed) or no positional anchor is available, relocation is treated as a\n * legitimate \u00A77.4 step 3 contextual re-anchor and this returns false.\n */\nfunction isImplausibleExactRelocation(\n comment: Comment,\n candidate: FuzzyCandidate,\n lines: string[],\n proximityWindow: number,\n): boolean {\n if (comment.line == null) return false;\n\n // Original position must still exist to be a viable fallback anchor.\n if (comment.line <= 0 || comment.line >= lines.length) return false;\n\n // A nearby match is plausibly the same (or an adjacent) edit region.\n if (Math.abs(candidate.line - comment.line) <= proximityWindow) return false;\n\n // If the text at the original position still equals selected_text, the\n // original occurrence is intact and relocation is not a teleport.\n const textAtOrigin = extractText(\n lines,\n comment.line,\n comment.end_line,\n comment.start_column,\n comment.end_column,\n );\n if (textAtOrigin === comment.selected_text) return false;\n\n return true;\n}\n\nfunction getLineShift(diffHunks: DiffHunk[], line: number): { shift: number; modified: boolean } {\n let shift = 0;\n let modified = false;\n\n for (const hunk of diffHunks) {\n const oldStart = hunk.oldStart;\n const oldEnd = hunk.oldStart + Math.max(hunk.oldCount, 1) - 1;\n\n if (line >= oldStart && line <= oldEnd && hunk.oldCount > 0) {\n modified = true;\n }\n\n if (line > oldEnd || (hunk.oldCount === 0 && line >= oldStart)) {\n shift += hunk.newCount - hunk.oldCount;\n }\n }\n\n return { shift, modified };\n}", "import AjvModule from \"ajv\";\nimport addFormatsModule from \"ajv-formats\";\nimport { mrsfSchema } from \"./schema.js\";\nimport type {\n MrsfDocument,\n ValidationDiagnostic,\n ValidationResult,\n} from \"./types.js\";\n\nconst Ajv = (AjvModule as any).default ?? AjvModule;\nconst addFormats = (addFormatsModule as any).default ?? addFormatsModule;\n\nexport type HashFunction = (text: string) => string;\n\nexport function validateDocument(\n doc: MrsfDocument,\n schema: object = mrsfSchema,\n): ValidationResult {\n const errors: ValidationDiagnostic[] = [];\n const warnings: ValidationDiagnostic[] = [];\n\n validateSchema(doc, schema, errors);\n validateCrossFields(doc, errors, warnings);\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport function validateSchema(\n doc: MrsfDocument,\n rawSchema: object,\n errors: ValidationDiagnostic[],\n): void {\n const { $schema, ...schema } = rawSchema as Record<string, unknown>;\n void $schema;\n const ajv = new Ajv({ allErrors: true, strict: false });\n addFormats(ajv);\n const ajvValidate = ajv.compile(schema);\n const schemaValid = ajvValidate(doc);\n\n if (!schemaValid && ajvValidate.errors) {\n for (const err of ajvValidate.errors) {\n errors.push({\n severity: \"error\",\n code: \"schema-violation\",\n message: `${err.instancePath || \"/\"}: ${err.message ?? \"schema error\"}`,\n path: err.instancePath || \"/\",\n });\n }\n }\n}\n\nexport function validateCrossFields(\n doc: MrsfDocument,\n errors: ValidationDiagnostic[],\n warnings: ValidationDiagnostic[],\n hash?: HashFunction,\n): void {\n if (!Array.isArray(doc.comments)) return;\n\n const ids = new Set<string>();\n const allIds = doc.comments.map((x) => x.id);\n\n for (let i = 0; i < doc.comments.length; i++) {\n const c = doc.comments[i];\n const prefix = `/comments/${i}`;\n\n if (c.id) {\n if (ids.has(c.id)) {\n errors.push({\n severity: \"error\",\n code: \"duplicate-id\",\n message: `Duplicate comment id \"${c.id}\"`,\n path: `${prefix}/id`,\n commentId: c.id,\n });\n }\n ids.add(c.id);\n }\n\n if (c.line != null && c.end_line != null && c.end_line < c.line) {\n errors.push({\n severity: \"error\",\n code: \"end-line-before-line\",\n message: `end_line (${c.end_line}) must be \u2265 line (${c.line})`,\n path: `${prefix}/end_line`,\n commentId: c.id,\n });\n }\n\n if (\n c.start_column != null &&\n c.end_column != null &&\n (c.line == null || c.end_line == null || c.line === c.end_line) &&\n c.end_column < c.start_column\n ) {\n errors.push({\n severity: \"error\",\n code: \"end-column-before-start-column\",\n message: `end_column (${c.end_column}) must be \u2265 start_column (${c.start_column}) on the same line`,\n path: `${prefix}/end_column`,\n commentId: c.id,\n });\n }\n\n if (c.selected_text && c.selected_text.length > 4096) {\n errors.push({\n severity: \"error\",\n code: \"selected-text-too-long\",\n message: `selected_text exceeds 4096 characters (${c.selected_text.length})`,\n path: `${prefix}/selected_text`,\n commentId: c.id,\n });\n }\n\n if (c.text && c.text.length > 16384) {\n warnings.push({\n severity: \"warning\",\n code: \"text-too-long\",\n message: `text exceeds recommended 16384 characters (${c.text.length})`,\n path: `${prefix}/text`,\n commentId: c.id,\n });\n }\n\n // Browser-safe callers do not get the Node SHA-256 implementation.\n // The hash check runs only when a hash function is injected by the Node validator.\n if (hash && c.selected_text && c.selected_text_hash) {\n const expected = hash(c.selected_text);\n if (c.selected_text_hash !== expected) {\n warnings.push({\n severity: \"warning\",\n code: \"hash-mismatch\",\n message: `selected_text_hash mismatch (expected ${expected.slice(0, 12)}\u2026, got ${c.selected_text_hash.slice(0, 12)}\u2026)`,\n path: `${prefix}/selected_text_hash`,\n commentId: c.id,\n });\n }\n }\n\n if (c.reply_to && !ids.has(c.reply_to) && !allIds.includes(c.reply_to)) {\n warnings.push({\n severity: \"warning\",\n code: \"unresolved-reply-to\",\n message: `reply_to \"${c.reply_to}\" does not resolve to any comment id in this file`,\n path: `${prefix}/reply_to`,\n commentId: c.id,\n });\n }\n\n if (c.line != null && !c.selected_text) {\n warnings.push({\n severity: \"warning\",\n code: \"missing-selected-text\",\n message: \"Comment has line anchors but no selected_text \u2014 anchoring will be fragile across edits\",\n path: `${prefix}/selected_text`,\n commentId: c.id,\n });\n }\n }\n}\n", "\n{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://github.com/wictorwilen/MRSF/raw/main/mrsf.schema.json\",\n \"title\": \"Markdown Review Sidecar Format (MRSF) v1.0\",\n \"description\": \"Schema for MRSF review sidecar files. See MRSF-v1.0.md for the full specification.\",\n \"type\": \"object\",\n \"required\": [\"mrsf_version\", \"document\", \"comments\"],\n \"additionalProperties\": true,\n \"properties\": {\n \"mrsf_version\": {\n \"type\": \"string\",\n \"pattern\": \"^1\\\\.\\\\d+$\",\n \"description\": \"MRSF format version. MUST be a supported major.minor version (e.g., 1.0).\"\n },\n \"document\": {\n \"type\": \"string\",\n \"description\": \"Relative path to the Markdown document being reviewed.\"\n },\n \"comments\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\"id\", \"author\", \"timestamp\", \"text\", \"resolved\"],\n \"additionalProperties\": true,\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Globally unique, opaque, collision-resistant identifier for the comment.\"\n },\n \"author\": {\n \"type\": \"string\",\n \"description\": \"Creator of the comment. SHOULD follow the convention 'Display Name (identifier)'.\"\n },\n \"timestamp\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"description\": \"ISO 8601 / RFC 3339 timestamp of comment creation; SHOULD include timezone offset.\"\n },\n \"text\": {\n \"type\": \"string\",\n \"maxLength\": 16384,\n \"description\": \"The content of the review comment. MUST be plain text.\"\n },\n \"resolved\": {\n \"type\": \"boolean\",\n \"description\": \"Whether the comment has been resolved.\"\n },\n \"commit\": {\n \"type\": \"string\",\n \"description\": \"Git commit hash associated with the comment. SHOULD be the full (long) SHA.\"\n },\n \"type\": {\n \"type\": \"string\",\n \"description\": \"Categorization of the comment. Recommended values listed in examples.\",\n \"examples\": [\n \"suggestion\",\n \"issue\",\n \"question\",\n \"accuracy\",\n \"style\",\n \"clarity\"\n ]\n },\n \"severity\": {\n \"type\": \"string\",\n \"description\": \"Importance level of the comment.\",\n \"enum\": [\"low\", \"medium\", \"high\"]\n },\n \"reply_to\": {\n \"type\": \"string\",\n \"description\": \"ID of another comment in the same file that this comment replies to.\"\n },\n \"line\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Starting line number (1-based) in the target document.\"\n },\n \"end_line\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Ending line number (inclusive, 1-based). MUST be >= line.\"\n },\n \"start_column\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Starting column index (0-based) within the starting line.\"\n },\n \"end_column\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Ending column index. MUST be >= start_column when on the same line.\"\n },\n \"selected_text\": {\n \"type\": \"string\",\n \"maxLength\": 4096,\n \"description\": \"Exact text selected by the reviewer. SHOULD NOT be modified by re-anchoring tools. SHOULD NOT exceed 4096 characters.\"\n },\n \"anchored_text\": {\n \"type\": \"string\",\n \"maxLength\": 4096,\n \"description\": \"Text currently found at the resolved anchor position. Populated by re-anchoring tools when the document text differs from selected_text. SHOULD be omitted when identical to selected_text.\"\n },\n \"selected_text_hash\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-f0-9]{64}$\",\n \"description\": \"Hex-encoded SHA-256 hash of selected_text. Immutable after creation; used for fast exact-match detection during re-anchoring, integrity verification, and staleness checks. SHOULD NOT be modified by re-anchoring tools unless selected_text is also replaced (opt-in behaviour), in which case it MUST be recomputed.\"\n }\n }\n }\n }\n }\n}\n", "import mrsfSchemaJson from \"../../mrsf.schema.json\" with { type: \"json\" };\n\nexport const mrsfSchema = mrsfSchemaJson;\n", "/**\n * MRSF string (de)serialization \u2014 pure, dependency-light helpers that parse and\n * serialize MRSF sidecar content to/from strings.\n *\n * This module intentionally has **no Node-only imports** (no `node:fs`,\n * `node:path`, `node:crypto`, \u2026) so it can be consumed from browser/host\n * adapters via the slim `@mrsf/cli/browser` entry point. Filesystem-bound\n * helpers (read/discover/write a file) live in `parser.ts` / `writer.ts`.\n */\n\nimport yaml from \"js-yaml\";\nimport { Document } from \"yaml\";\nimport type { MrsfDocument, Comment } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Lenient parse result\n// ---------------------------------------------------------------------------\n\n/** Result from a lenient (non-throwing) parse attempt. */\nexport interface LenientParseResult {\n /** Fully parsed document, or null if parsing failed entirely. */\n doc: MrsfDocument | null;\n /** If parsing failed or produced warnings, the error message. */\n error?: string;\n /** Comments that could be salvaged from a partially-corrupted sidecar. */\n partialComments?: Comment[];\n}\n\n// ---------------------------------------------------------------------------\n// Parsing (string \u2192 document)\n// ---------------------------------------------------------------------------\n\n/**\n * Parse MRSF sidecar content from a string.\n * Detects JSON vs YAML based on content or optional filename hint.\n */\nexport function parseSidecarContent(\n content: string,\n filenameHint?: string,\n): MrsfDocument {\n const trimmed = content.trim();\n\n let parsed: unknown;\n\n // Detect JSON by content or filename\n const isJson =\n trimmed.startsWith(\"{\") ||\n (filenameHint && filenameHint.endsWith(\".review.json\"));\n\n if (isJson) {\n try {\n parsed = JSON.parse(trimmed);\n } catch (e) {\n throw new Error(`Failed to parse JSON: ${(e as Error).message}`);\n }\n } else {\n try {\n parsed = yaml.load(trimmed, { schema: yaml.JSON_SCHEMA });\n } catch (e) {\n throw new Error(`Failed to parse YAML: ${(e as Error).message}`);\n }\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"MRSF sidecar must be a YAML/JSON object\");\n }\n\n return parsed as MrsfDocument;\n}\n\n/**\n * Lenient parse from string content.\n */\nexport function parseSidecarContentLenient(\n content: string,\n filenameHint?: string,\n): LenientParseResult {\n const trimmed = content.trim();\n if (!trimmed) {\n return { doc: null, error: \"File is empty\" };\n }\n\n const isJson =\n trimmed.startsWith(\"{\") ||\n (filenameHint && filenameHint.endsWith(\".review.json\"));\n\n // First, try a normal parse\n let parsed: unknown;\n try {\n parsed = isJson ? JSON.parse(trimmed) : yaml.load(trimmed, { schema: yaml.JSON_SCHEMA });\n } catch (e) {\n // Total parse failure \u2014 try to salvage what we can from YAML\n if (!isJson) {\n return salvageYaml(trimmed);\n }\n return { doc: null, error: `Failed to parse JSON: ${(e as Error).message}` };\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return { doc: null, error: \"MRSF sidecar must be a YAML/JSON object\" };\n }\n\n const obj = parsed as Record<string, unknown>;\n const doc: MrsfDocument = {\n mrsf_version: typeof obj.mrsf_version === \"string\" ? obj.mrsf_version : \"1.0\",\n document: typeof obj.document === \"string\" ? obj.document : \"unknown\",\n comments: [],\n };\n\n if (!Array.isArray(obj.comments)) {\n return {\n doc,\n error: \"comments field is not an array \u2014 file may be corrupted\",\n };\n }\n\n // Validate each comment individually\n const good: Comment[] = [];\n const bad: number[] = [];\n\n for (let i = 0; i < obj.comments.length; i++) {\n const c = obj.comments[i];\n if (c && typeof c === \"object\" && !Array.isArray(c) && typeof (c as Record<string, unknown>).id === \"string\") {\n good.push(c as Comment);\n } else {\n bad.push(i);\n }\n }\n\n doc.comments = good;\n\n if (bad.length > 0) {\n return {\n doc,\n error: `${bad.length} comment(s) at indices [${bad.join(\", \")}] were malformed and skipped`,\n partialComments: good,\n };\n }\n\n return { doc };\n}\n\n/**\n * Attempt to extract individual comment blocks from corrupted YAML by\n * splitting on `- id:` patterns and parsing each block independently.\n */\nfunction salvageYaml(content: string): LenientParseResult {\n const salvaged: Comment[] = [];\n let mrsf_version = \"1.0\";\n let document = \"unknown\";\n\n // Try to extract top-level fields from the beginning\n const versionMatch = content.match(/^mrsf_version:\\s*[\"']?([^\"'\\n]+)/m);\n if (versionMatch) mrsf_version = versionMatch[1].trim();\n\n const docMatch = content.match(/^document:\\s*[\"']?([^\"'\\n]+)/m);\n if (docMatch) document = docMatch[1].trim();\n\n // Split on comment block boundaries (- id: ...)\n const blocks = content.split(/(?=^ - id:\\s)/m);\n\n for (const block of blocks) {\n const trimmed = block.trim();\n if (!trimmed.startsWith(\"- id:\")) continue;\n\n // Wrap in a minimal YAML array context and try to parse\n try {\n const parsed = yaml.load(trimmed, { schema: yaml.JSON_SCHEMA });\n if (Array.isArray(parsed) && parsed.length > 0) {\n const c = parsed[0];\n if (c && typeof c === \"object\" && typeof (c as Record<string, unknown>).id === \"string\") {\n salvaged.push(c as Comment);\n }\n } else if (parsed && typeof parsed === \"object\" && typeof (parsed as Record<string, unknown>).id === \"string\") {\n salvaged.push(parsed as Comment);\n }\n } catch {\n // This block is unparseable \u2014 skip\n }\n }\n\n const doc: MrsfDocument = {\n mrsf_version,\n document,\n comments: salvaged,\n };\n\n return {\n doc: salvaged.length > 0 ? doc : null,\n error: `YAML parse failed. Salvaged ${salvaged.length} comment(s) from raw content.`,\n partialComments: salvaged.length > 0 ? salvaged : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Serialization (document \u2192 string)\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize an MrsfDocument to YAML (for new files / non-round-trip use).\n */\nexport function toYaml(doc: MrsfDocument): string {\n const yamlDoc = new Document(doc);\n return yamlDoc.toString({ lineWidth: 0 });\n}\n\n/**\n * Serialize an MrsfDocument to JSON.\n */\nexport function toJson(doc: MrsfDocument): string {\n return JSON.stringify(doc, null, 2) + \"\\n\";\n}\n"],
5
- "mappings": "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",
6
- "names": ["DEFAULT_THRESHOLD", "HIGH_THRESHOLD", "applyReanchorResults", "combinedScore", "exactMatch", "formatAuthor", "fuzzySearch", "levenshteinScore", "newCommentId", "normalizedMatch", "parseAuthor", "parseSidecarContent", "parseSidecarContentLenient", "reanchorComment", "reanchorDocumentLines", "reanchorDocumentText", "resolveAnchor", "toJson", "toReanchorLines", "toYaml", "tokenLcsScore", "validateDocument", "levenshtein", "uuidv4", "AjvModule", "addFormatsModule", "yaml", "parseSidecarContent", "parseSidecarContentLenient", "toYaml", "toJson", "combinedScore", "exactMatch", "fuzzySearch", "levenshteinScore", "normalizedMatch", "tokenLcsScore", "applyReanchorResults", "DEFAULT_THRESHOLD", "HIGH_THRESHOLD", "reanchorComment", "reanchorDocumentLines", "reanchorDocumentText", "resolveAnchor", "toReanchorLines", "validateDocument", "formatAuthor", "parseAuthor", "newCommentId"]
3
+ "sources": ["../src/browser.ts", "../src/lib/fuzzy.ts", "../src/lib/identity.ts", "../src/lib/revision-projection.ts", "../src/lib/anchor-context.ts", "../src/lib/confidence-calibration.ts", "../src/lib/reanchor-core.ts", "../src/lib/global-reconciliation.ts", "../src/lib/validate-core.ts", "../mrsf.schema.json", "../src/lib/schema.ts", "../src/lib/serialize.ts"],
4
+ "sourcesContent": ["import * as fuzzy from \"./lib/fuzzy.js\";\nimport * as identity from \"./lib/identity.js\";\nimport * as reanchorCore from \"./lib/reanchor-core.js\";\nimport * as anchorContext from \"./lib/anchor-context.js\";\nimport * as globalReconciliation from \"./lib/global-reconciliation.js\";\nimport * as revisionProjection from \"./lib/revision-projection.js\";\nimport * as confidenceCalibration from \"./lib/confidence-calibration.js\";\nimport * as validateCore from \"./lib/validate-core.js\";\nimport * as serialize from \"./lib/serialize.js\";\nimport { mrsfSchema } from \"./lib/schema.js\";\n\nexport type {\n AnchorPosition,\n Comment,\n DiffHunk,\n FuzzyCandidate,\n MrsfDocument,\n ReanchorResult,\n ReanchorStatus,\n ValidationDiagnostic,\n ValidationResult,\n DiagnosticSeverity,\n} from \"./lib/types.js\";\nexport type { ParsedAuthor } from \"./lib/identity.js\";\nexport type { LenientParseResult } from \"./lib/serialize.js\";\n\n// Parse / serialize (pure string \u21C4 document; no filesystem or argv deps).\nexport const parseSidecarContent = serialize.parseSidecarContent;\nexport const parseSidecarContentLenient = serialize.parseSidecarContentLenient;\nexport const toYaml = serialize.toYaml;\nexport const toJson = serialize.toJson;\n\nexport const combinedScore = fuzzy.combinedScore;\nexport const exactMatch = fuzzy.exactMatch;\nexport const fuzzySearch = fuzzy.fuzzySearch;\nexport const levenshteinScore = fuzzy.levenshteinScore;\nexport const normalizedMatch = fuzzy.normalizedMatch;\nexport const tokenLcsScore = fuzzy.tokenLcsScore;\n\nexport const applyReanchorResults = reanchorCore.applyReanchorResults;\nexport const DEFAULT_THRESHOLD = reanchorCore.DEFAULT_THRESHOLD;\nexport const HIGH_THRESHOLD = reanchorCore.HIGH_THRESHOLD;\nexport const reanchorComment = reanchorCore.reanchorComment;\nexport const reanchorDocumentLines = reanchorCore.reanchorDocumentLines;\nexport const reanchorDocumentText = reanchorCore.reanchorDocumentText;\nexport const resolveAnchor = reanchorCore.resolveAnchor;\nexport const toReanchorLines = reanchorCore.toReanchorLines;\nexport const createAnchorContextIndex = anchorContext.createAnchorContextIndex;\nexport const reconcileCommentAnchors =\n globalReconciliation.reconcileCommentAnchors;\nexport const createRevisionProjection =\n revisionProjection.createRevisionProjection;\nexport const calibrateAnchorEvidence =\n confidenceCalibration.calibrateAnchorEvidence;\nexport type {\n AnchorContextIndex,\n ContextAnchorCandidate,\n ContextAnchorResolution,\n} from \"./lib/anchor-context.js\";\nexport type {\n ProjectedAnchor,\n RevisionProjectionIndex,\n} from \"./lib/revision-projection.js\";\nexport type {\n CalibratedAnchor,\n ConfidenceBand,\n} from \"./lib/confidence-calibration.js\";\n\nexport const validateDocument = validateCore.validateDocument;\nexport { mrsfSchema };\n\nexport const formatAuthor = identity.formatAuthor;\nexport const parseAuthor = identity.parseAuthor;\nexport const newCommentId = identity.newCommentId;\n", "/**\n * MRSF Fuzzy Matching Engine\n *\n * Provides exact, normalized, token-level LCS, and character-level\n * Levenshtein matching for re-anchoring selected_text.\n */\n\nimport { distance as levenshtein } from \"fastest-levenshtein\";\nimport type { FuzzyCandidate } from \"./types.js\";\n\nexport const MAX_FUZZY_CANDIDATE_LINES = 64;\n\nexport interface FuzzySearchIndex {\n lines: string[];\n tokenPostings: Map<string, number[]>;\n trigramPostings: Map<string, number[]>;\n}\n\nexport function createFuzzySearchIndex(lines: string[]): FuzzySearchIndex {\n const tokenPostings = new Map<string, number[]>();\n const trigramPostings = new Map<string, number[]>();\n for (let line = 1; line < lines.length; line += 1) {\n addPostingSignals(tokenPostings, lexicalTokens(lines[line]), line);\n addPostingSignals(trigramPostings, characterTrigrams(lines[line]), line);\n }\n return { lines, tokenPostings, trigramPostings };\n}\n\n// ---------------------------------------------------------------------------\n// Exact matching\n// ---------------------------------------------------------------------------\n\n/**\n * Find all exact occurrences of `needle` in lines (1-based array).\n */\nexport function exactMatch(\n lines: string[],\n needle: string,\n): FuzzyCandidate[] {\n if (!needle) return [];\n\n const results: FuzzyCandidate[] = [];\n const needleLines = needle.split(\"\\n\");\n const needleLineCount = needleLines.length;\n\n // Slide a window across the document\n for (let startLine = 1; startLine <= lines.length - needleLineCount; startLine++) {\n // Build the text for this window\n const windowLines = lines.slice(startLine, startLine + needleLineCount);\n const windowText = windowLines.join(\"\\n\");\n\n // Check if the needle appears anywhere within this window (for single-line)\n if (needleLineCount === 1) {\n let col = 0;\n const line = windowLines[0];\n while (col < line.length) {\n const idx = line.indexOf(needle, col);\n if (idx === -1) break;\n results.push({\n text: needle,\n line: startLine,\n endLine: startLine,\n startColumn: idx,\n endColumn: idx + needle.length,\n score: 1.0,\n });\n col = idx + 1;\n }\n } else {\n // Multi-line: check if the window contains the exact needle\n const idx = windowText.indexOf(needle);\n if (idx !== -1) {\n // Calculate start column\n const beforeMatch = windowText.slice(0, idx);\n const linesBeforeEnd = beforeMatch.split(\"\\n\");\n const startCol = linesBeforeEnd[linesBeforeEnd.length - 1].length;\n\n // Calculate end column\n const afterMatch = needle.split(\"\\n\");\n const endCol = afterMatch[afterMatch.length - 1].length;\n if (startCol === 0 || linesBeforeEnd.length === 1) {\n results.push({\n text: needle,\n line: startLine + linesBeforeEnd.length - 1,\n endLine: startLine + linesBeforeEnd.length - 1 + afterMatch.length - 1,\n startColumn: startCol,\n endColumn: endCol,\n score: 1.0,\n });\n }\n }\n }\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Normalized matching (collapse whitespace)\n// ---------------------------------------------------------------------------\n\nfunction normalize(text: string): string {\n return text.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Find matches after normalizing whitespace.\n */\nexport function normalizedMatch(\n lines: string[],\n needle: string,\n): FuzzyCandidate[] {\n const normNeedle = normalize(needle);\n if (!normNeedle) return [];\n\n const results: FuzzyCandidate[] = [];\n\n // Try expanding windows of varying sizes\n const needleLineEstimate = needle.split(\"\\n\").length;\n const minWindow = Math.max(1, needleLineEstimate - 1);\n const maxWindow = Math.min(lines.length - 1, needleLineEstimate + 2);\n\n for (let winSize = minWindow; winSize <= maxWindow; winSize++) {\n for (let startLine = 1; startLine + winSize - 1 < lines.length; startLine++) {\n const windowLines = lines.slice(startLine, startLine + winSize);\n const windowText = windowLines.join(\"\\n\");\n const normWindow = normalize(windowText);\n\n if (normWindow.includes(normNeedle)) {\n results.push({\n text: windowText,\n line: startLine,\n endLine: startLine + winSize - 1,\n startColumn: 0,\n endColumn: windowLines[windowLines.length - 1].length,\n score: 0.95,\n });\n }\n }\n }\n\n return deduplicateCandidates(results);\n}\n\n// ---------------------------------------------------------------------------\n// Token-level LCS\n// ---------------------------------------------------------------------------\n\nfunction tokenize(text: string): string[] {\n return text.split(/\\s+/).filter((t) => t.length > 0);\n}\n\n/**\n * Longest Common Subsequence length of two token arrays.\n */\nfunction lcsLength(a: string[], b: string[]): number {\n const m = a.length;\n const n = b.length;\n // Optimize: use two rows instead of full matrix\n let prev = new Array<number>(n + 1).fill(0);\n let curr = new Array<number>(n + 1).fill(0);\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (a[i - 1] === b[j - 1]) {\n curr[j] = prev[j - 1] + 1;\n } else {\n curr[j] = Math.max(prev[j], curr[j - 1]);\n }\n }\n [prev, curr] = [curr, prev];\n curr.fill(0);\n }\n\n return prev[n];\n}\n\n/**\n * Score two texts using token-level LCS.\n * Returns 0.0\u20131.0.\n */\nexport function tokenLcsScore(a: string, b: string): number {\n const tokA = tokenize(a);\n const tokB = tokenize(b);\n if (tokA.length === 0 && tokB.length === 0) return 1.0;\n if (tokA.length === 0 || tokB.length === 0) return 0.0;\n const lcs = lcsLength(tokA, tokB);\n return lcs / Math.max(tokA.length, tokB.length);\n}\n\n// ---------------------------------------------------------------------------\n// Character-level Levenshtein score\n// ---------------------------------------------------------------------------\n\n/**\n * Normalized Levenshtein similarity 0.0\u20131.0.\n */\nexport function levenshteinScore(a: string, b: string): number {\n if (a.length === 0 && b.length === 0) return 1.0;\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1.0;\n const dist = levenshtein(a, b);\n return 1 - dist / maxLen;\n}\n\n// ---------------------------------------------------------------------------\n// Combined fuzzy scoring\n// ---------------------------------------------------------------------------\n\n/**\n * Compute a combined similarity score between two text fragments.\n * Blends token LCS (structural) and Levenshtein (character-level).\n */\nexport function combinedScore(needle: string, candidate: string): number {\n const tScore = tokenLcsScore(needle, candidate);\n\n // Full Levenshtein is expensive for long texts; only use for short ones\n let lScore: number;\n if (needle.length < 500 && candidate.length < 500) {\n lScore = levenshteinScore(needle, candidate);\n } else {\n lScore = tScore; // fall back to token score only\n }\n\n // Weight: 60% token LCS, 40% Levenshtein\n return tScore * 0.6 + lScore * 0.4;\n}\n\n// ---------------------------------------------------------------------------\n// Fuzzy search across document\n// ---------------------------------------------------------------------------\n\n/**\n * Search the document for fuzzy matches of `needle`.\n *\n * @param lines 1-based line array (index 0 unused).\n * @param needle The original selected_text.\n * @param threshold Minimum score to include (0.0\u20131.0).\n * @param hintLine Optional original line number for proximity scoring.\n */\nexport function fuzzySearch(\n lines: string[],\n needle: string,\n threshold: number = 0.6,\n hintLine?: number,\n index?: FuzzySearchIndex,\n): FuzzyCandidate[] {\n return fuzzySearchThresholds(\n lines,\n needle,\n [threshold],\n hintLine,\n index,\n ).get(threshold) ?? [];\n}\n\n/**\n * Compute fuzzy candidates once and partition them by their unadjusted\n * similarity thresholds. Proximity remains a ranking bonus and does not make\n * a candidate eligible for a threshold it did not originally satisfy.\n */\nexport function fuzzySearchThresholds(\n lines: string[],\n needle: string,\n thresholds: number[],\n hintLine?: number,\n index: FuzzySearchIndex = createFuzzySearchIndex(lines),\n): Map<number, FuzzyCandidate[]> {\n const uniqueThresholds = [...new Set(thresholds)];\n const results = new Map<number, FuzzyCandidate[]>();\n if (uniqueThresholds.length === 0) return results;\n if (!needle) {\n for (const threshold of uniqueThresholds) results.set(threshold, []);\n return results;\n }\n\n const needleLines = needle.split(\"\\n\");\n const needleLineCount = needleLines.length;\n const candidates: FuzzyCandidate[] = [];\n const minimumThreshold = Math.min(...uniqueThresholds);\n const candidateLines = retrieveCandidateLines(index, needle, hintLine);\n\n // Window sizes: \u00B130% of original line count, minimum 1\n const minWindow = Math.max(1, Math.floor(needleLineCount * 0.7));\n const maxWindow = Math.min(\n lines.length - 1,\n Math.ceil(needleLineCount * 1.3) + 1,\n );\n\n for (let winSize = minWindow; winSize <= maxWindow; winSize++) {\n const startLines = new Set<number>();\n for (const candidateLine of candidateLines) {\n for (let offset = 0; offset < winSize; offset += 1) {\n const startLine = candidateLine - offset;\n if (startLine >= 1 && startLine + winSize - 1 < lines.length) {\n startLines.add(startLine);\n }\n }\n }\n for (const startLine of startLines) {\n const windowLines = lines.slice(startLine, startLine + winSize);\n const windowText = windowLines.join(\"\\n\");\n\n const score = combinedScore(needle, windowText);\n\n if (score >= minimumThreshold) {\n candidates.push({\n text: windowText,\n line: startLine,\n endLine: startLine + winSize - 1,\n startColumn: 0,\n endColumn: windowLines[windowLines.length - 1].length,\n score,\n });\n }\n }\n }\n\n // For single-line needles, also try substring matching within each line\n if (needleLineCount === 1 && needle.length < 200) {\n for (const lineNum of candidateLines) {\n const line = lines[lineNum];\n if (!line) continue;\n\n const winLen = needle.length;\n const minWinLen = Math.max(3, Math.floor(winLen * 0.7));\n const maxWinLen = Math.min(line.length, Math.ceil(winLen * 1.3));\n const lengths = evenlySpacedIntegers(minWinLen, maxWinLen, 7);\n for (const len of lengths) {\n for (let col = 0; col + len <= line.length; col++) {\n const sub = line.substring(col, col + len);\n const score = combinedScore(needle, sub);\n if (score >= minimumThreshold) {\n candidates.push({\n text: sub,\n line: lineNum,\n endLine: lineNum,\n startColumn: col,\n endColumn: col + len,\n score,\n });\n }\n }\n }\n }\n }\n\n const deduped = deduplicateCandidates(candidates);\n const scored = deduped.map((candidate) => ({\n baseScore: candidate.score,\n candidate: applyProximityBonus(candidate, hintLine),\n }));\n\n for (const threshold of uniqueThresholds) {\n results.set(\n threshold,\n scored\n .filter((item) => item.baseScore >= threshold)\n .map((item) => item.candidate)\n .sort((left, right) => right.score - left.score),\n );\n }\n\n return results;\n}\n\nfunction retrieveCandidateLines(\n index: FuzzySearchIndex,\n needle: string,\n hintLine?: number,\n): number[] {\n const votes = new Map<number, number>();\n const lineCount = Math.max(0, index.lines.length - 1);\n const signals = [\n ...postingSignals(index.tokenPostings, lexicalTokens(needle), 2),\n ...postingSignals(index.trigramPostings, characterTrigrams(needle), 1),\n ]\n .sort((left, right) => left.postings.length - right.postings.length)\n .slice(0, 16);\n\n for (const signal of signals) {\n const rarity = Math.log1p(lineCount / signal.postings.length);\n for (const line of signal.postings) {\n votes.set(line, (votes.get(line) ?? 0) + signal.weight * rarity);\n }\n }\n\n if (hintLine != null) {\n for (let offset = -4; offset <= 4; offset += 1) {\n const line = hintLine + offset;\n if (line >= 1 && line <= lineCount) {\n votes.set(line, (votes.get(line) ?? 0) + 0.25);\n }\n }\n }\n\n if (votes.size === 0) {\n return Array.from({ length: lineCount }, (_, index) => index + 1);\n }\n\n return [...votes.entries()]\n .sort((left, right) =>\n right[1] - left[1]\n || distanceFromHint(left[0], hintLine) - distanceFromHint(right[0], hintLine)\n || left[0] - right[0]\n )\n .slice(0, MAX_FUZZY_CANDIDATE_LINES)\n .map(([line]) => line);\n}\n\nfunction postingSignals(\n postings: Map<string, number[]>,\n values: string[],\n weight: number,\n): Array<{ postings: number[]; weight: number }> {\n return [...new Set(values)]\n .map((value) => ({ postings: postings.get(value) ?? [], weight }))\n .filter((signal) => signal.postings.length > 0);\n}\n\nfunction addPostingSignals(\n postings: Map<string, number[]>,\n values: string[],\n line: number,\n): void {\n for (const value of new Set(values)) {\n const lines = postings.get(value);\n if (lines) {\n lines.push(line);\n } else {\n postings.set(value, [line]);\n }\n }\n}\n\nfunction lexicalTokens(text: string): string[] {\n return text.toLowerCase().match(/[\\p{L}\\p{N}_-]+/gu) ?? [];\n}\n\nfunction characterTrigrams(text: string): string[] {\n const normalized = text.toLowerCase().replace(/\\s+/g, \" \").trim();\n const characters = [...normalized];\n if (characters.length < 3) return normalized ? [normalized] : [];\n const trigrams: string[] = [];\n for (let index = 0; index <= characters.length - 3; index += 1) {\n trigrams.push(characters.slice(index, index + 3).join(\"\"));\n }\n return trigrams;\n}\n\nfunction evenlySpacedIntegers(\n minimum: number,\n maximum: number,\n count: number,\n): number[] {\n if (maximum <= minimum) return [minimum];\n const values = new Set<number>();\n for (let index = 0; index < count; index += 1) {\n values.add(Math.round(minimum + (maximum - minimum) * index / (count - 1)));\n }\n return [...values];\n}\n\nfunction distanceFromHint(line: number, hintLine?: number): number {\n return hintLine == null ? 0 : Math.abs(line - hintLine);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction deduplicateCandidates(\n candidates: FuzzyCandidate[],\n): FuzzyCandidate[] {\n const seen = new Map<string, FuzzyCandidate>();\n for (const c of candidates) {\n const key = `${c.line}:${c.startColumn}:${c.endLine}:${c.endColumn}`;\n const existing = seen.get(key);\n if (!existing || c.score > existing.score) {\n seen.set(key, c);\n }\n }\n return Array.from(seen.values());\n}\n\nfunction applyProximityBonus(\n candidate: FuzzyCandidate,\n hintLine?: number,\n): FuzzyCandidate {\n if (hintLine == null) return candidate;\n\n const distance = Math.abs(candidate.line - hintLine);\n const proximityBonus = 0.1 * Math.max(0, 1 - distance / 50);\n return {\n ...candidate,\n score: Math.min(1.0, candidate.score + proximityBonus),\n };\n}\n", "import { v4 as uuidv4 } from \"uuid\";\n\nexport interface ParsedAuthor {\n name: string;\n handle?: string;\n}\n\nexport function formatAuthor(name: string, handle?: string): string {\n const trimmedName = name.trim();\n const trimmedHandle = handle?.trim();\n return trimmedHandle ? `${trimmedName} (${trimmedHandle})` : trimmedName;\n}\n\nexport function parseAuthor(author: string): ParsedAuthor {\n const trimmed = author.trim();\n const match = /^(.*?)\\s*\\(([^()]*)\\)\\s*$/.exec(trimmed);\n if (!match) return { name: trimmed };\n\n const name = match[1].trim();\n const handle = match[2].trim();\n return handle ? { name, handle } : { name };\n}\n\n/**\n * Create a collision-resistant MRSF comment id.\n * ULID is also permitted by the spec; UUIDv4 is the default for this package.\n */\nexport function newCommentId(): string {\n return uuidv4();\n}\n", "import { combinedScore, exactMatch } from \"./fuzzy.js\";\nimport type { Comment } from \"./types.js\";\n\nconst CONTEXT_RADIUS = 8;\n\nexport interface RevisionProjectionIndex {\n sourceLines: string[];\n targetLines: string[];\n lineMap: Map<number, number>;\n}\n\nexport interface ProjectedAnchor {\n line: number;\n endLine: number;\n startColumn?: number;\n endColumn?: number;\n text: string;\n score: number;\n exact: boolean;\n contextSupport: number;\n contextMargin: number;\n reason: string;\n}\n\nexport function createRevisionProjection(\n sourceLines: string[],\n targetLines: string[],\n): RevisionProjectionIndex {\n const sourceOccurrences = collectLineOccurrences(sourceLines);\n const targetOccurrences = collectLineOccurrences(targetLines);\n const lineMap = new Map<number, number>();\n\n for (const [text, sourceLineNumbers] of sourceOccurrences) {\n const targetLineNumbers = targetOccurrences.get(text);\n if (sourceLineNumbers.length === 1 && targetLineNumbers?.length === 1) {\n lineMap.set(sourceLineNumbers[0], targetLineNumbers[0]);\n }\n }\n\n return { sourceLines, targetLines, lineMap };\n}\n\nexport function projectCommentAnchor(\n comment: Comment,\n projection: RevisionProjectionIndex,\n threshold: number,\n): ProjectedAnchor | undefined {\n if (comment.line == null || !comment.selected_text) return undefined;\n\n const sourceText = extractText(\n projection.sourceLines,\n comment.line,\n comment.end_line,\n comment.start_column,\n comment.end_column,\n );\n if (sourceText !== comment.selected_text) return undefined;\n\n const exactCandidates = exactMatch(\n projection.targetLines,\n comment.selected_text,\n );\n if (exactCandidates.length === 1) {\n const candidate = exactCandidates[0];\n const contextSupport = countIndependentExactSupport(\n comment,\n candidate.line,\n projection,\n );\n if (contextSupport >= 2) {\n return {\n line: candidate.line,\n endLine: candidate.endLine,\n startColumn: candidate.startColumn,\n endColumn: candidate.endColumn,\n text: candidate.text,\n score: 1,\n exact: true,\n contextSupport,\n contextMargin: 1,\n reason: \"Source revision and neighboring line evidence confirm exact relocation.\",\n };\n }\n }\n if (exactCandidates.length > 0) return undefined;\n\n const projected = projectLineFromContext(comment, projection);\n if (projected == null) return undefined;\n const projectedLine = projected.line;\n\n const lineSpan = (comment.end_line ?? comment.line) - comment.line;\n const projectedEndLine = projectedLine + lineSpan;\n if (\n projectedLine < 1\n || projectedEndLine >= projection.targetLines.length\n ) {\n return undefined;\n }\n\n const columns = projectColumns(comment, projection, projectedLine);\n const targetText = extractText(\n projection.targetLines,\n projectedLine,\n projectedEndLine,\n columns.startColumn,\n columns.endColumn,\n );\n if (targetText == null) return undefined;\n\n const score = Math.min(\n 1,\n combinedScore(comment.selected_text, targetText) + 0.1,\n );\n if (score < threshold) return undefined;\n\n return {\n line: projectedLine,\n endLine: projectedEndLine,\n startColumn: columns.startColumn,\n endColumn: columns.endColumn,\n text: targetText,\n score,\n exact: targetText === comment.selected_text,\n contextSupport: projected.support,\n contextMargin: projected.margin,\n reason: \"Source revision context projects the edited anchor range.\",\n };\n}\n\nfunction collectLineOccurrences(lines: string[]): Map<string, number[]> {\n const occurrences = new Map<string, number[]>();\n\n for (let line = 1; line < lines.length; line += 1) {\n const text = lines[line];\n if (!text.trim()) continue;\n const existing = occurrences.get(text);\n if (existing) {\n existing.push(line);\n } else {\n occurrences.set(text, [line]);\n }\n }\n\n return occurrences;\n}\n\nfunction countIndependentExactSupport(\n comment: Comment,\n candidateLine: number,\n projection: RevisionProjectionIndex,\n): number {\n const sourceEndLine = comment.end_line ?? (comment.line as number);\n const expectedShift = candidateLine - (comment.line as number);\n\n if (\n comment.start_column != null\n || comment.end_column != null\n ) {\n const mappedContainerLine = projection.lineMap.get(comment.line as number);\n if (mappedContainerLine === candidateLine) return 2;\n }\n\n let support = 0;\n for (\n let distance = 1;\n distance <= CONTEXT_RADIUS;\n distance += 1\n ) {\n for (const sourceLine of [\n (comment.line as number) - distance,\n sourceEndLine + distance,\n ]) {\n if (sourceLine < 1 || sourceLine >= projection.sourceLines.length) {\n continue;\n }\n const targetLine = projection.lineMap.get(sourceLine);\n if (targetLine != null && targetLine - sourceLine === expectedShift) {\n support += 1;\n }\n }\n }\n\n return support;\n}\n\nfunction projectLineFromContext(\n comment: Comment,\n projection: RevisionProjectionIndex,\n): { line: number; support: number; margin: number } | undefined {\n const sourceLine = comment.line as number;\n const sourceEndLine = comment.end_line ?? sourceLine;\n const votes = new Map<number, { count: number; nearest: number }>();\n\n for (let distance = 1; distance <= CONTEXT_RADIUS; distance += 1) {\n for (const contextLine of [\n sourceLine - distance,\n sourceEndLine + distance,\n ]) {\n if (contextLine < 1 || contextLine >= projection.sourceLines.length) {\n continue;\n }\n const targetLine = projection.lineMap.get(contextLine);\n if (targetLine == null) continue;\n const shift = targetLine - contextLine;\n const vote = votes.get(shift);\n if (vote) {\n vote.count += 1;\n vote.nearest = Math.min(vote.nearest, distance);\n } else {\n votes.set(shift, { count: 1, nearest: distance });\n }\n }\n }\n\n const ranked = [...votes.entries()].sort((left, right) =>\n right[1].count - left[1].count\n || left[1].nearest - right[1].nearest\n || Math.abs(left[0]) - Math.abs(right[0])\n );\n const best = ranked[0];\n if (!best) return undefined;\n if (best[1].count < 2 && best[1].nearest > 3) return undefined;\n if (\n ranked[1]\n && ranked[1][1].count === best[1].count\n && ranked[1][1].nearest === best[1].nearest\n ) {\n return undefined;\n }\n\n const runnerUpCount = ranked[1]?.[1].count ?? 0;\n return {\n line: sourceLine + best[0],\n support: best[1].count,\n margin: (best[1].count - runnerUpCount) / best[1].count,\n };\n}\n\nfunction projectColumns(\n comment: Comment,\n projection: RevisionProjectionIndex,\n targetLine: number,\n): { startColumn?: number; endColumn?: number } {\n if (\n comment.line == null\n || (comment.end_line != null && comment.end_line !== comment.line)\n || comment.start_column == null\n || comment.end_column == null\n ) {\n return {\n startColumn: comment.start_column,\n endColumn: comment.end_column,\n };\n }\n\n const sourceLine = projection.sourceLines[comment.line];\n const targetLineText = projection.targetLines[targetLine];\n const prefix = sourceLine.slice(0, comment.start_column);\n const suffix = sourceLine.slice(comment.end_column);\n const startColumn = targetLineText.startsWith(prefix)\n ? prefix.length\n : Math.min(comment.start_column, targetLineText.length);\n const endColumn = targetLineText.endsWith(suffix)\n ? targetLineText.length - suffix.length\n : Math.min(\n targetLineText.length,\n startColumn + (comment.end_column - comment.start_column),\n );\n\n return { startColumn, endColumn };\n}\n\nfunction extractText(\n lines: string[],\n line: number,\n endLine?: number,\n startColumn?: number,\n endColumn?: number,\n): string | null {\n const finalLine = endLine ?? line;\n if (line < 1 || finalLine >= lines.length) return null;\n\n if (line === finalLine) {\n const text = lines[line];\n return startColumn != null && endColumn != null\n ? text.slice(startColumn, endColumn)\n : text;\n }\n\n const result: string[] = [];\n for (let current = line; current <= finalLine; current += 1) {\n let text = lines[current];\n if (current === line && startColumn != null) text = text.slice(startColumn);\n if (current === finalLine && endColumn != null) text = text.slice(0, endColumn);\n result.push(text);\n }\n return result.join(\"\\n\");\n}\n", "import { combinedScore } from \"./fuzzy.js\";\nimport type { Comment, ReanchorStatus } from \"./types.js\";\n\nconst MATCH_THRESHOLD = 0.35;\nconst AMBIGUITY_MARGIN = 0.03;\nexport const MAX_CONTEXT_CANDIDATE_BLOCKS = 64;\n\ntype BlockType =\n | \"heading\"\n | \"code\"\n | \"list\"\n | \"table\"\n | \"blockquote\"\n | \"paragraph\";\n\ninterface MarkdownBlock {\n startLine: number;\n endLine: number;\n type: BlockType;\n text: string;\n headingPath: string[];\n}\n\ninterface DocumentBlockIndex {\n lines: string[];\n blocks: MarkdownBlock[];\n lineToBlock: Map<number, number>;\n tokenPostings: Map<string, number[]>;\n}\n\ninterface CandidateWindow {\n startBlock: number;\n endBlock: number;\n startLine: number;\n endLine: number;\n type: BlockType;\n text: string;\n headingPath: string[];\n score: number;\n}\n\nexport interface AnchorContextIndex {\n source: DocumentBlockIndex;\n target: DocumentBlockIndex;\n}\n\nexport interface ContextAnchorResolution {\n status: Extract<ReanchorStatus, \"anchored\" | \"fuzzy\" | \"ambiguous\" | \"orphaned\">;\n score: number;\n line?: number;\n endLine?: number;\n startColumn?: number;\n endColumn?: number;\n text?: string;\n candidateMargin: number;\n reason: string;\n}\n\nexport interface ContextAnchorCandidate {\n score: number;\n line: number;\n endLine: number;\n startColumn?: number;\n endColumn?: number;\n text: string;\n exact: boolean;\n}\n\nexport function createAnchorContextIndex(\n sourceLines: string[],\n targetLines: string[],\n): AnchorContextIndex {\n return {\n source: createDocumentBlockIndex(sourceLines),\n target: createDocumentBlockIndex(targetLines),\n };\n}\n\nexport function resolveContextAnchor(\n comment: Comment,\n index: AnchorContextIndex,\n): ContextAnchorResolution | undefined {\n if (comment.line == null || !comment.selected_text) return undefined;\n const sourceBlockIndex = index.source.lineToBlock.get(comment.line);\n if (sourceBlockIndex == null) return undefined;\n const sourceBlock = index.source.blocks[sourceBlockIndex];\n const sourceText = extractText(\n index.source.lines,\n comment.line,\n comment.end_line,\n comment.start_column,\n comment.end_column,\n );\n if (sourceText !== comment.selected_text) return undefined;\n const textAtCurrentPosition = extractText(\n index.target.lines,\n comment.line,\n comment.end_line,\n comment.start_column,\n comment.end_column,\n );\n if (textAtCurrentPosition === comment.selected_text) {\n return {\n status: \"anchored\",\n score: 1,\n line: comment.line,\n endLine: comment.end_line ?? comment.line,\n startColumn: comment.start_column,\n endColumn: comment.end_column,\n text: comment.selected_text,\n candidateMargin: 1,\n reason: \"Source-verified anchor remains exact at its stored position.\",\n };\n }\n\n const candidates = findContextAnchorCandidates(comment, index);\n const best = candidates[0];\n if (!best) {\n if (\n index.target.lines.slice(1).join(\"\\n\").includes(comment.selected_text)\n ) {\n return undefined;\n }\n return {\n status: \"orphaned\",\n score: 0,\n candidateMargin: 1,\n reason: \"Source block has no plausible structural or contextual match.\",\n };\n }\n\n if (candidates[1] && best.score - candidates[1].score < AMBIGUITY_MARGIN) {\n return {\n status: \"ambiguous\",\n score: best.score,\n line: best.line,\n endLine: best.endLine,\n candidateMargin: best.score - candidates[1].score,\n reason:\n `Structural candidates are too close (${best.score.toFixed(3)} vs `\n + `${candidates[1].score.toFixed(3)}).`,\n };\n }\n\n const repeatedExactText = best.exact\n && countOccurrences(\n index.target.lines.slice(1).join(\"\\n\"),\n comment.selected_text,\n ) > 1;\n return {\n status: best.exact && !repeatedExactText ? \"anchored\" : \"fuzzy\",\n score: best.exact && !repeatedExactText ? 1 : best.score,\n line: best.line,\n endLine: best.endLine,\n startColumn: best.startColumn,\n endColumn: best.endColumn,\n text: best.text,\n candidateMargin: candidates[1] ? best.score - candidates[1].score : 1,\n reason: best.exact && !repeatedExactText\n ? \"Markdown structure and bidirectional context disambiguate the exact anchor.\"\n : repeatedExactText\n ? \"Markdown context selects one repeated exact anchor tentatively.\"\n : \"Markdown structure and bidirectional context locate the edited anchor.\",\n };\n}\n\nexport function findContextAnchorCandidates(\n comment: Comment,\n index: AnchorContextIndex,\n): ContextAnchorCandidate[] {\n if (comment.line == null || !comment.selected_text) return [];\n const sourceBlockIndex = index.source.lineToBlock.get(comment.line);\n if (sourceBlockIndex == null) return [];\n const sourceBlock = index.source.blocks[sourceBlockIndex];\n const sourceText = extractText(\n index.source.lines,\n comment.line,\n comment.end_line,\n comment.start_column,\n comment.end_column,\n );\n if (sourceText !== comment.selected_text) return [];\n\n return createCandidateWindows(\n sourceBlock,\n sourceBlockIndex,\n comment.line,\n index,\n )\n .map((candidate) => ({\n ...candidate,\n score: scoreCandidate(\n sourceBlock,\n sourceBlockIndex,\n candidate,\n index,\n comment.line as number,\n ),\n }))\n .filter((candidate) => candidate.score >= MATCH_THRESHOLD)\n .sort((left, right) =>\n right.score - left.score\n || Math.abs(left.startLine - (comment.line as number))\n - Math.abs(right.startLine - (comment.line as number))\n )\n .map((candidate) => {\n const range = resolveCandidateRange(\n comment,\n sourceBlock,\n candidate,\n index.target,\n );\n return {\n score: candidate.score,\n line: range.line,\n endLine: range.endLine,\n startColumn: range.startColumn,\n endColumn: range.endColumn,\n text: range.text,\n exact: range.text === comment.selected_text,\n };\n });\n}\n\nexport function getAnchorContextScope(\n comment: Comment,\n index: AnchorContextIndex,\n): string | undefined {\n if (comment.line == null) return undefined;\n const blockIndex = index.source.lineToBlock.get(comment.line);\n if (blockIndex == null) return undefined;\n return index.source.blocks[blockIndex].headingPath.join(\"\\u001f\");\n}\n\nfunction createDocumentBlockIndex(lines: string[]): DocumentBlockIndex {\n const blocks: MarkdownBlock[] = [];\n const lineToBlock = new Map<number, number>();\n const headings: Array<{ level: number; title: string }> = [];\n let line = 1;\n\n while (line < lines.length) {\n if (!lines[line].trim()) {\n line += 1;\n continue;\n }\n\n const startLine = line;\n const marker = classifyLine(lines[line]);\n if (marker.type === \"heading\") {\n while (\n headings.length > 0\n && headings[headings.length - 1].level >= marker.headingLevel\n ) {\n headings.pop();\n }\n const block = makeBlock(\n lines,\n startLine,\n startLine,\n \"heading\",\n headings.map((heading) => heading.title),\n );\n blocks.push(block);\n headings.push({ level: marker.headingLevel, title: marker.headingTitle });\n line += 1;\n continue;\n }\n\n if (marker.type === \"code\") {\n line += 1;\n while (line < lines.length && !lines[line].trimStart().startsWith(\"```\")) {\n line += 1;\n }\n if (line < lines.length) line += 1;\n } else {\n line += 1;\n while (\n line < lines.length\n && lines[line].trim()\n && continuesBlock(marker.type, lines[line])\n ) {\n line += 1;\n }\n }\n\n blocks.push(makeBlock(\n lines,\n startLine,\n line - 1,\n marker.type,\n headings.map((heading) => heading.title),\n ));\n }\n\n for (const [blockIndex, block] of blocks.entries()) {\n for (let blockLine = block.startLine; blockLine <= block.endLine; blockLine += 1) {\n lineToBlock.set(blockLine, blockIndex);\n }\n }\n\n return {\n lines,\n blocks,\n lineToBlock,\n tokenPostings: createTokenPostings(blocks),\n };\n}\n\nfunction makeBlock(\n lines: string[],\n startLine: number,\n endLine: number,\n type: BlockType,\n headingPath: string[],\n): MarkdownBlock {\n return {\n startLine,\n endLine,\n type,\n text: lines.slice(startLine, endLine + 1).join(\"\\n\"),\n headingPath,\n };\n}\n\nfunction classifyLine(line: string): {\n type: BlockType;\n headingLevel: number;\n headingTitle: string;\n} {\n const heading = line.match(/^(#{1,6})\\s+(.+)$/);\n if (heading) {\n return {\n type: \"heading\",\n headingLevel: heading[1].length,\n headingTitle: heading[2].trim(),\n };\n }\n if (line.trimStart().startsWith(\"```\")) {\n return { type: \"code\", headingLevel: 0, headingTitle: \"\" };\n }\n if (/^\\s*(?:[-*+]|\\d+\\.)\\s+/.test(line)) {\n return { type: \"list\", headingLevel: 0, headingTitle: \"\" };\n }\n if (/^\\s*\\|/.test(line)) {\n return { type: \"table\", headingLevel: 0, headingTitle: \"\" };\n }\n if (/^\\s*>/.test(line)) {\n return { type: \"blockquote\", headingLevel: 0, headingTitle: \"\" };\n }\n return { type: \"paragraph\", headingLevel: 0, headingTitle: \"\" };\n}\n\nfunction continuesBlock(type: BlockType, line: string): boolean {\n if (type === \"list\") return /^\\s*(?:[-*+]|\\d+\\.)\\s+/.test(line);\n if (type === \"table\") return /^\\s*\\|/.test(line);\n if (type === \"blockquote\") return /^\\s*>/.test(line);\n if (type === \"paragraph\") {\n const next = classifyLine(line);\n return next.type === \"paragraph\";\n }\n return false;\n}\n\nfunction createCandidateWindows(\n sourceBlock: MarkdownBlock,\n sourceBlockIndex: number,\n originalLine: number,\n index: AnchorContextIndex,\n): CandidateWindow[] {\n const target = index.target;\n const candidates: CandidateWindow[] = [];\n\n for (const start of retrieveCandidateBlocks(\n sourceBlock,\n sourceBlockIndex,\n originalLine,\n index,\n )) {\n const block = target.blocks[start];\n candidates.push(toCandidateWindow(target, start, start));\n\n if (\n sourceBlock.type === \"paragraph\"\n && block.type === \"paragraph\"\n && target.blocks[start + 1]?.type === \"paragraph\"\n && samePath(block.headingPath, target.blocks[start + 1].headingPath)\n ) {\n candidates.push(toCandidateWindow(target, start, start + 1));\n }\n }\n\n return candidates;\n}\n\nfunction createTokenPostings(\n blocks: MarkdownBlock[],\n): Map<string, number[]> {\n const postings = new Map<string, number[]>();\n for (const [blockIndex, block] of blocks.entries()) {\n for (const token of new Set(tokenize(block.text))) {\n const blocksForToken = postings.get(token);\n if (blocksForToken) {\n blocksForToken.push(blockIndex);\n } else {\n postings.set(token, [blockIndex]);\n }\n }\n }\n return postings;\n}\n\n/**\n * Retrieve a small candidate pool using rare content tokens and directional\n * neighbor evidence. Expensive similarity scoring is bounded to this pool.\n */\nfunction retrieveCandidateBlocks(\n sourceBlock: MarkdownBlock,\n sourceBlockIndex: number,\n originalLine: number,\n index: AnchorContextIndex,\n): number[] {\n const votes = new Map<number, number>();\n const targetCount = index.target.blocks.length;\n const addEvidence = (\n text: string | undefined,\n targetOffset: number,\n weight: number,\n ): void => {\n if (!text) return;\n const rankedTokens = [...new Set(tokenize(text))]\n .map((token) => ({\n token,\n postings: index.target.tokenPostings.get(token) ?? [],\n }))\n .filter((item) => item.postings.length > 0)\n .sort((left, right) => left.postings.length - right.postings.length)\n .slice(0, 12);\n\n for (const { postings } of rankedTokens) {\n const rarity = Math.log1p(targetCount / postings.length);\n for (const posting of postings) {\n const candidate = posting + targetOffset;\n if (candidate >= 0 && candidate < targetCount) {\n votes.set(candidate, (votes.get(candidate) ?? 0) + weight * rarity);\n }\n }\n }\n };\n\n addEvidence(sourceBlock.text, 0, 1);\n addEvidence(index.source.blocks[sourceBlockIndex - 1]?.text, 1, 0.7);\n addEvidence(index.source.blocks[sourceBlockIndex + 1]?.text, -1, 0.7);\n\n const nearbyBlock = closestBlockToLine(index.target.blocks, originalLine);\n if (nearbyBlock != null) {\n for (let offset = -2; offset <= 2; offset += 1) {\n const candidate = nearbyBlock + offset;\n if (candidate >= 0 && candidate < targetCount) {\n votes.set(candidate, (votes.get(candidate) ?? 0) + 0.25);\n }\n }\n }\n\n return [...votes.entries()]\n .sort((left, right) =>\n right[1] - left[1]\n || Math.abs(index.target.blocks[left[0]].startLine - originalLine)\n - Math.abs(index.target.blocks[right[0]].startLine - originalLine)\n || left[0] - right[0]\n )\n .slice(0, MAX_CONTEXT_CANDIDATE_BLOCKS)\n .map(([blockIndex]) => blockIndex);\n}\n\nfunction closestBlockToLine(\n blocks: MarkdownBlock[],\n line: number,\n): number | undefined {\n if (blocks.length === 0) return undefined;\n let low = 0;\n let high = blocks.length - 1;\n while (low <= high) {\n const middle = Math.floor((low + high) / 2);\n const block = blocks[middle];\n if (line < block.startLine) {\n high = middle - 1;\n } else if (line > block.endLine) {\n low = middle + 1;\n } else {\n return middle;\n }\n }\n if (low >= blocks.length) return blocks.length - 1;\n if (high < 0) return 0;\n return Math.abs(blocks[low].startLine - line)\n < Math.abs(blocks[high].endLine - line)\n ? low\n : high;\n}\n\nfunction toCandidateWindow(\n target: DocumentBlockIndex,\n startBlock: number,\n endBlock: number,\n): CandidateWindow {\n const first = target.blocks[startBlock];\n const last = target.blocks[endBlock];\n return {\n startBlock,\n endBlock,\n startLine: first.startLine,\n endLine: last.endLine,\n type: first.type,\n text: target.lines.slice(first.startLine, last.endLine + 1).join(\"\\n\"),\n headingPath: first.headingPath,\n score: 0,\n };\n}\n\nfunction scoreCandidate(\n sourceBlock: MarkdownBlock,\n sourceBlockIndex: number,\n candidate: CandidateWindow,\n index: AnchorContextIndex,\n originalLine: number,\n): number {\n const content = textSimilarity(sourceBlock.text, candidate.text);\n const type = sourceBlock.type === candidate.type ? 1 : 0;\n const heading = pathSimilarity(sourceBlock.headingPath, candidate.headingPath);\n const previous = neighborSimilarity(\n index.source.blocks[sourceBlockIndex - 1],\n index.target.blocks[candidate.startBlock - 1],\n );\n const next = neighborSimilarity(\n index.source.blocks[sourceBlockIndex + 1],\n index.target.blocks[candidate.endBlock + 1],\n );\n const proximity = Math.max(\n 0,\n 1 - Math.abs(candidate.startLine - originalLine) / 100,\n );\n\n return Math.min(\n 1,\n content * 0.45\n + type * 0.1\n + heading * 0.1\n + previous * 0.15\n + next * 0.15\n + proximity * 0.05,\n );\n}\n\nfunction neighborSimilarity(\n source: MarkdownBlock | undefined,\n target: MarkdownBlock | undefined,\n): number {\n if (!source || !target) return 0;\n return textSimilarity(source.text, target.text);\n}\n\nfunction textSimilarity(left: string, right: string): number {\n return Math.max(\n tokenDice(left, right),\n combinedScore(normalizeText(left), normalizeText(right)),\n );\n}\n\nfunction pathSimilarity(left: string[], right: string[]): number {\n if (left.length === 0 || right.length === 0) return 0;\n return tokenDice(left.join(\" \"), right.join(\" \"));\n}\n\nfunction tokenDice(left: string, right: string): number {\n const leftTokens = tokenize(left);\n const rightTokens = tokenize(right);\n if (leftTokens.length === 0 || rightTokens.length === 0) return 0;\n const remaining = new Map<string, number>();\n for (const token of rightTokens) {\n remaining.set(token, (remaining.get(token) ?? 0) + 1);\n }\n let overlap = 0;\n for (const token of leftTokens) {\n const count = remaining.get(token) ?? 0;\n if (count > 0) {\n overlap += 1;\n remaining.set(token, count - 1);\n }\n }\n return (2 * overlap) / (leftTokens.length + rightTokens.length);\n}\n\nfunction tokenize(text: string): string[] {\n return normalizeText(text).match(/[\\p{L}\\p{N}_-]+/gu) ?? [];\n}\n\nfunction normalizeText(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\nfunction samePath(left: string[], right: string[]): boolean {\n return left.length === right.length\n && left.every((item, index) => item === right[index]);\n}\n\nfunction resolveCandidateRange(\n comment: Comment,\n sourceBlock: MarkdownBlock,\n candidate: CandidateWindow,\n target: DocumentBlockIndex,\n): {\n line: number;\n endLine: number;\n startColumn?: number;\n endColumn?: number;\n text: string;\n} {\n const exactIndex = candidate.text.indexOf(comment.selected_text as string);\n const selectedIsWholeBlock =\n comment.line === sourceBlock.startLine\n && (comment.end_line ?? comment.line) === sourceBlock.endLine\n && comment.start_column == null\n && comment.end_column == null\n && comment.selected_text === sourceBlock.text;\n const sourceOccurrenceIsUnique =\n countOccurrences(sourceBlock.text, comment.selected_text as string) === 1;\n if (exactIndex >= 0 && (selectedIsWholeBlock || sourceOccurrenceIsUnique)) {\n return exactRange(\n candidate.startLine,\n candidate.text,\n comment.selected_text as string,\n exactIndex,\n );\n }\n\n if (selectedIsWholeBlock) {\n return {\n line: candidate.startLine,\n endLine: candidate.endLine,\n text: candidate.text,\n };\n }\n\n const relativeLine = (comment.line as number) - sourceBlock.startLine;\n const line = Math.min(candidate.endLine, candidate.startLine + relativeLine);\n const lineSpan = (comment.end_line ?? comment.line as number)\n - (comment.line as number);\n const endLine = Math.min(candidate.endLine, line + lineSpan);\n const startColumn = comment.start_column;\n const endColumn = comment.end_column;\n return {\n line,\n endLine,\n startColumn,\n endColumn,\n text: extractText(\n target.lines,\n line,\n endLine,\n startColumn,\n endColumn,\n ) ?? \"\",\n };\n}\n\nfunction countOccurrences(text: string, needle: string): number {\n if (!needle) return 0;\n let count = 0;\n let offset = 0;\n while (offset <= text.length - needle.length) {\n const index = text.indexOf(needle, offset);\n if (index < 0) break;\n count += 1;\n offset = index + 1;\n }\n return count;\n}\n\nfunction exactRange(\n startLine: number,\n candidateText: string,\n selectedText: string,\n index: number,\n): {\n line: number;\n endLine: number;\n startColumn: number;\n endColumn: number;\n text: string;\n} {\n const before = candidateText.slice(0, index).split(\"\\n\");\n const selectedLines = selectedText.split(\"\\n\");\n const line = startLine + before.length - 1;\n const startColumn = before.at(-1)?.length ?? 0;\n const finalSelectedLineLength = selectedLines.at(-1)?.length ?? 0;\n return {\n line,\n endLine: line + selectedLines.length - 1,\n startColumn,\n endColumn: selectedLines.length === 1\n ? startColumn + finalSelectedLineLength\n : finalSelectedLineLength,\n text: selectedText,\n };\n}\n\nfunction extractText(\n lines: string[],\n line: number,\n endLine?: number,\n startColumn?: number,\n endColumn?: number,\n): string | null {\n const finalLine = endLine ?? line;\n if (line < 1 || finalLine >= lines.length) return null;\n if (line === finalLine) {\n const text = lines[line];\n return startColumn != null && endColumn != null\n ? text.slice(startColumn, endColumn)\n : text;\n }\n\n const result: string[] = [];\n for (let current = line; current <= finalLine; current += 1) {\n let text = lines[current];\n if (current === line && startColumn != null) text = text.slice(startColumn);\n if (current === finalLine && endColumn != null) text = text.slice(0, endColumn);\n result.push(text);\n }\n return result.join(\"\\n\");\n}\n", "import type { ContextAnchorResolution } from \"./anchor-context.js\";\nimport type { ProjectedAnchor } from \"./revision-projection.js\";\nimport type { ReanchorResult } from \"./types.js\";\n\nexport type ConfidenceBand =\n | \"certain\"\n | \"probable\"\n | \"ambiguous\"\n | \"orphaned\";\n\nexport interface CalibratedAnchor {\n band: ConfidenceBand;\n result: ReanchorResult;\n}\n\n/**\n * Calibrate independent revision and structural evidence into a public result.\n *\n * Exact evidence is certain. Edited anchors are probable only when evidence\n * agrees or one source has a decisive margin; conflicting evidence abstains.\n */\nexport function calibrateAnchorEvidence(\n commentId: string,\n selectedText: string,\n projected?: ProjectedAnchor,\n contextual?: ContextAnchorResolution,\n): CalibratedAnchor | undefined {\n if (projected?.exact) {\n return {\n band: \"certain\",\n result: projectedResult(commentId, selectedText, projected),\n };\n }\n if (contextual?.status === \"anchored\") {\n return {\n band: \"certain\",\n result: contextualResult(commentId, selectedText, contextual),\n };\n }\n\n if (projected && contextual) {\n if (sameRange(projected, contextual)) {\n const result = contextualResult(commentId, selectedText, contextual);\n result.status = \"fuzzy\";\n result.score = combineIndependentScores(projected.score, contextual.score);\n result.reason =\n `Probable anchor: revision projection and Markdown context agree `\n + `(confidence ${result.score.toFixed(3)}).`;\n return { band: \"probable\", result };\n }\n\n if (contextual.status === \"orphaned\" && !isStrongProjection(projected)) {\n return {\n band: \"orphaned\",\n result: contextualResult(commentId, selectedText, contextual),\n };\n }\n\n if (\n contextual.status === \"fuzzy\"\n && contextual.candidateMargin >= 0.15\n && contextual.score >= projected.score + 0.1\n ) {\n return {\n band: \"probable\",\n result: contextualResult(commentId, selectedText, contextual),\n };\n }\n\n return {\n band: \"ambiguous\",\n result: {\n commentId,\n status: \"ambiguous\",\n score: Math.max(projected.score, contextual.score),\n reason:\n `Ambiguous evidence: revision projection points to line `\n + `${projected.line}, while Markdown context points to `\n + `${contextual.line ?? \"no location\"}.`,\n },\n };\n }\n\n if (contextual) {\n const band = contextual.status === \"orphaned\"\n ? \"orphaned\"\n : contextual.status === \"ambiguous\"\n ? \"ambiguous\"\n : \"probable\";\n return {\n band,\n result: contextualResult(commentId, selectedText, contextual),\n };\n }\n\n if (projected) {\n if (!isStrongProjection(projected)) return undefined;\n return {\n band: \"probable\",\n result: projectedResult(commentId, selectedText, projected),\n };\n }\n\n return undefined;\n}\n\nfunction isStrongProjection(projected: ProjectedAnchor): boolean {\n return projected.contextSupport >= 3\n || (projected.contextSupport >= 2 && projected.contextMargin >= 0.5);\n}\n\nfunction sameRange(\n projected: ProjectedAnchor,\n contextual: ContextAnchorResolution,\n): boolean {\n return projected.line === contextual.line\n && projected.endLine === contextual.endLine;\n}\n\nfunction combineIndependentScores(left: number, right: number): number {\n return Math.min(0.95, (left + right) / 2 + 0.05);\n}\n\nfunction projectedResult(\n commentId: string,\n selectedText: string,\n projected: ProjectedAnchor,\n): ReanchorResult {\n return {\n commentId,\n status: projected.exact ? \"anchored\" : \"fuzzy\",\n score: projected.score,\n newLine: projected.line,\n newEndLine: projected.endLine,\n newStartColumn: projected.startColumn,\n newEndColumn: projected.endColumn,\n anchoredText: projected.exact ? undefined : projected.text,\n previousSelectedText: projected.exact ? undefined : selectedText,\n reason: projected.reason,\n };\n}\n\nfunction contextualResult(\n commentId: string,\n selectedText: string,\n contextual: ContextAnchorResolution,\n): ReanchorResult {\n return {\n commentId,\n status: contextual.status,\n score: contextual.score,\n newLine: contextual.line,\n newEndLine: contextual.endLine,\n newStartColumn: contextual.startColumn,\n newEndColumn: contextual.endColumn,\n anchoredText: contextual.status === \"fuzzy\"\n ? contextual.text\n : undefined,\n previousSelectedText: contextual.status === \"fuzzy\"\n ? selectedText\n : undefined,\n reason: contextual.reason,\n };\n}\n", "import type {\n AnchorPosition,\n Comment,\n DiffHunk,\n FuzzyCandidate,\n MrsfDocument,\n ReanchorResult,\n} from \"./types.js\";\nimport {\n createFuzzySearchIndex,\n exactMatch,\n fuzzySearch,\n fuzzySearchThresholds,\n normalizedMatch,\n type FuzzySearchIndex,\n} from \"./fuzzy.js\";\nimport {\n projectCommentAnchor,\n type RevisionProjectionIndex,\n} from \"./revision-projection.js\";\nimport {\n resolveContextAnchor,\n type AnchorContextIndex,\n} from \"./anchor-context.js\";\nimport { calibrateAnchorEvidence } from \"./confidence-calibration.js\";\n\nexport const HIGH_THRESHOLD = 0.8;\nexport const DEFAULT_THRESHOLD = 0.6;\n\n/**\n * Default proximity window (in lines) for the \u00A77.4 step 1a relocation guard.\n *\n * A lone exact match of `selected_text` that lands farther than this many\n * lines from the comment's original `line` \u2014 while the text at the original\n * position has changed \u2014 is treated as an in-place edit rather than a\n * confident relocation. See {@link isImplausibleExactRelocation}.\n */\nexport const DEFAULT_PROXIMITY_WINDOW = 5;\n\nexport function toReanchorLines(documentText: string): string[] {\n return [\"\", ...documentText.replace(/\\r\\n/g, \"\\n\").split(\"\\n\")];\n}\n\nexport function reanchorComment(\n comment: Comment,\n documentLines: string[],\n opts: {\n diffHunks?: DiffHunk[];\n threshold?: number;\n commitIsStale?: boolean;\n proximityWindow?: number;\n revisionProjection?: RevisionProjectionIndex;\n anchorContext?: AnchorContextIndex;\n fuzzySearchIndex?: FuzzySearchIndex;\n getFuzzySearchIndex?: () => FuzzySearchIndex;\n } = {},\n): ReanchorResult {\n const threshold = opts.threshold ?? DEFAULT_THRESHOLD;\n const proximityWindow = opts.proximityWindow ?? DEFAULT_PROXIMITY_WINDOW;\n const commentId = comment.id;\n const selectedText = comment.selected_text;\n let fuzzyCandidateSets: Map<number, FuzzyCandidate[]> | undefined;\n let fuzzySearchIndex = opts.fuzzySearchIndex;\n const getFuzzySearchIndex = (): FuzzySearchIndex => {\n fuzzySearchIndex ??= opts.getFuzzySearchIndex?.()\n ?? createFuzzySearchIndex(documentLines);\n return fuzzySearchIndex;\n };\n\n if (!selectedText && comment.line == null) {\n return {\n commentId,\n status: \"anchored\",\n score: 1.0,\n reason: \"Document-level comment (no anchor needed).\",\n };\n }\n\n if (comment.line != null && opts.diffHunks?.length) {\n const { shift, modified } = getLineShift(opts.diffHunks, comment.line);\n\n if (!selectedText) {\n const shiftedLine = comment.line + shift;\n const lineSpan =\n comment.end_line != null ? comment.end_line - comment.line : 0;\n const shiftedEndLine =\n comment.end_line != null ? shiftedLine + lineSpan : undefined;\n return {\n commentId,\n status: shift === 0 ? \"anchored\" : \"shifted\",\n score: 1.0,\n newLine: shiftedLine,\n newEndLine: shiftedEndLine,\n reason:\n shift === 0\n ? \"Line-only comment unchanged (diff confirms position).\"\n : `Line-only comment shifted by ${shift > 0 ? \"+\" : \"\"}${shift} line(s) via diff.`,\n };\n }\n\n if (!modified) {\n const shiftedLine = comment.line + shift;\n const lineSpan =\n comment.end_line != null ? comment.end_line - comment.line : 0;\n const shiftedEndLine =\n comment.end_line != null ? shiftedLine + lineSpan : undefined;\n\n const textAtShifted = extractText(\n documentLines,\n shiftedLine,\n shiftedEndLine,\n comment.start_column,\n comment.end_column,\n );\n\n if (textAtShifted === selectedText) {\n return {\n commentId,\n status: shift === 0 ? \"anchored\" : \"shifted\",\n score: 1.0,\n newLine: shiftedLine,\n newEndLine: shiftedEndLine,\n reason:\n shift === 0\n ? \"Diff confirms text unchanged at original position.\"\n : `Diff shifted by ${shift > 0 ? \"+\" : \"\"}${shift} line(s).`,\n };\n }\n }\n }\n\n const projected = selectedText && opts.revisionProjection\n ? projectCommentAnchor(\n comment,\n opts.revisionProjection,\n threshold,\n )\n : undefined;\n if (selectedText && projected?.exact) {\n const exactCalibration = calibrateAnchorEvidence(\n commentId,\n selectedText,\n projected,\n );\n if (exactCalibration) return exactCalibration.result;\n }\n const contextual = selectedText && opts.anchorContext\n ? resolveContextAnchor(comment, opts.anchorContext)\n : undefined;\n if (selectedText && (projected || contextual)) {\n const calibrated = calibrateAnchorEvidence(\n commentId,\n selectedText,\n projected,\n contextual,\n );\n if (calibrated) return calibrated.result;\n }\n\n if (selectedText) {\n const exactCandidates = exactMatch(documentLines, selectedText);\n if (exactCandidates.length > 1 && comment.line == null) {\n return {\n commentId,\n status: \"ambiguous\",\n score: 1,\n reason:\n `Ambiguous: ${exactCandidates.length} exact matches and no position `\n + \"or source context to disambiguate them.\",\n };\n }\n\n // Pick the best exact candidate: the only one, or \u2014 when several remain \u2014\n // the one nearest to the original line (\u00A77.4 step 1b).\n let chosen: FuzzyCandidate | undefined;\n let chosenReason = \"\";\n if (exactCandidates.length === 1) {\n chosen = exactCandidates[0];\n chosenReason = \"Exact text match (unique).\";\n } else if (exactCandidates.length > 1 && comment.line != null) {\n chosen = closestToLine(exactCandidates, comment.line);\n chosenReason = `Exact text match (${exactCandidates.length} occurrences; chose nearest to original line ${comment.line}).`;\n }\n\n if (chosen) {\n // \u00A77.4 step 1a proximity guard: a lone/closest exact match that lands far\n // from the original position \u2014 while the text at the original position no\n // longer equals selected_text \u2014 most likely indicates an in-place edit of\n // the anchored text, not a genuine relocation. Keep the comment at its\n // original position and flag it for re-anchoring instead of teleporting it\n // onto an unrelated identical token with full confidence.\n if (isImplausibleExactRelocation(comment, chosen, documentLines, proximityWindow)) {\n const textAtOrigin = extractText(\n documentLines,\n comment.line as number,\n comment.end_line,\n comment.start_column,\n comment.end_column,\n );\n return {\n commentId,\n status: \"fuzzy\",\n score: 0.5,\n newLine: comment.line,\n newEndLine: comment.end_line,\n newStartColumn: comment.start_column,\n newEndColumn: comment.end_column,\n anchoredText: textAtOrigin ?? undefined,\n previousSelectedText: selectedText,\n reason:\n `Lone exact match at line ${chosen.line} is beyond the proximity window ` +\n `(\u00B1${proximityWindow}) of original line ${comment.line} and the text at the ` +\n `original position changed; kept at original position, needs re-anchoring.`,\n };\n }\n\n return {\n commentId,\n status: \"anchored\",\n score: 1.0,\n newLine: chosen.line,\n newEndLine: chosen.endLine,\n newStartColumn: chosen.startColumn,\n newEndColumn: chosen.endColumn,\n reason: chosenReason,\n };\n }\n\n const normCandidates = normalizedMatch(documentLines, selectedText);\n if (normCandidates.length === 1) {\n const candidate = normCandidates[0];\n return {\n commentId,\n status: \"fuzzy\",\n score: candidate.score,\n newLine: candidate.line,\n newEndLine: candidate.endLine,\n newStartColumn: candidate.startColumn,\n newEndColumn: candidate.endColumn,\n anchoredText: candidate.text,\n previousSelectedText: selectedText,\n reason: \"Normalized whitespace match.\",\n };\n }\n\n fuzzyCandidateSets = fuzzySearchThresholds(\n documentLines,\n selectedText,\n [HIGH_THRESHOLD, threshold],\n comment.line,\n getFuzzySearchIndex(),\n );\n const fuzzyCandidates = fuzzyCandidateSets.get(HIGH_THRESHOLD) ?? [];\n\n if (fuzzyCandidates.length === 1 || (fuzzyCandidates.length > 0 && fuzzyCandidates[0].score >= HIGH_THRESHOLD)) {\n const best =\n fuzzyCandidates.length === 1\n ? fuzzyCandidates[0]\n : closestToLine(fuzzyCandidates, comment.line ?? 1);\n return {\n commentId,\n status: \"fuzzy\",\n score: best.score,\n newLine: best.line,\n newEndLine: best.endLine,\n newStartColumn: best.startColumn,\n newEndColumn: best.endColumn,\n anchoredText: best.text,\n previousSelectedText: selectedText,\n reason: `High-confidence fuzzy match (score ${best.score.toFixed(3)}).`,\n };\n }\n }\n\n if (comment.line != null) {\n const lineIdx = comment.line;\n if (lineIdx > 0 && lineIdx < documentLines.length) {\n const qualifier = opts.commitIsStale\n ? \" (commit is stale \u2014 line may have shifted)\"\n : \"\";\n\n if (selectedText) {\n const lineText = documentLines[lineIdx];\n const candidates = fuzzySearch([\"\", lineText], selectedText, DEFAULT_THRESHOLD);\n if (candidates.length > 0) {\n return {\n commentId,\n status: \"fuzzy\",\n score: candidates[0].score,\n newLine: comment.line,\n newEndLine: comment.end_line,\n anchoredText: candidates[0].text,\n previousSelectedText: selectedText,\n reason: `Line-fallback with fuzzy text match (score ${candidates[0].score.toFixed(3)})${qualifier}.`,\n };\n }\n }\n\n const isLineOnly = !selectedText;\n return {\n commentId,\n status: isLineOnly ? \"anchored\" : (opts.commitIsStale ? \"ambiguous\" : \"anchored\"),\n score: isLineOnly ? 1.0 : (opts.commitIsStale ? 0.5 : 0.8),\n newLine: comment.line,\n newEndLine: comment.end_line,\n reason: isLineOnly\n ? \"Line-only comment (no selected_text to verify).\"\n : `Line/column fallback${qualifier}.`,\n };\n }\n }\n\n if (selectedText) {\n const lowCandidates = fuzzyCandidateSets?.get(threshold)\n ?? fuzzySearch(\n documentLines,\n selectedText,\n threshold,\n comment.line,\n getFuzzySearchIndex(),\n );\n\n if (lowCandidates.length === 1) {\n const candidate = lowCandidates[0];\n return {\n commentId,\n status: \"fuzzy\",\n score: candidate.score,\n newLine: candidate.line,\n newEndLine: candidate.endLine,\n newStartColumn: candidate.startColumn,\n newEndColumn: candidate.endColumn,\n anchoredText: candidate.text,\n previousSelectedText: selectedText,\n reason: `Low-threshold fuzzy match (score ${candidate.score.toFixed(3)}).`,\n };\n }\n\n if (lowCandidates.length > 1) {\n const best = lowCandidates[0];\n return {\n commentId,\n status: \"ambiguous\",\n score: best.score,\n newLine: best.line,\n newEndLine: best.endLine,\n reason: `Ambiguous: ${lowCandidates.length} fuzzy matches (best score ${best.score.toFixed(3)}).`,\n };\n }\n }\n\n return {\n commentId,\n status: \"orphaned\",\n score: 0,\n reason: \"No match found. Comment is orphaned.\",\n };\n}\n\nexport function reanchorDocumentLines(\n doc: MrsfDocument,\n documentLines: string[],\n opts: { threshold?: number; proximityWindow?: number } = {},\n): ReanchorResult[] {\n let fuzzySearchIndex: FuzzySearchIndex | undefined;\n const getFuzzySearchIndex = (): FuzzySearchIndex => {\n fuzzySearchIndex ??= createFuzzySearchIndex(documentLines);\n return fuzzySearchIndex;\n };\n return doc.comments.map((comment) =>\n reanchorComment(comment, documentLines, { ...opts, getFuzzySearchIndex })\n );\n}\n\nexport function reanchorDocumentText(\n doc: MrsfDocument,\n documentText: string,\n opts: { threshold?: number; proximityWindow?: number } = {},\n): ReanchorResult[] {\n return reanchorDocumentLines(doc, toReanchorLines(documentText), opts);\n}\n\nexport function resolveAnchor(\n comment: Comment,\n documentText: string,\n opts: { threshold?: number; proximityWindow?: number } = {},\n): AnchorPosition {\n const normalizedText = documentText.replace(/\\r\\n/g, \"\\n\");\n const documentLines = toReanchorLines(documentText);\n const result = reanchorComment(comment, documentLines, opts);\n\n if (result.status === \"orphaned\") {\n return {\n status: \"orphaned\",\n score: result.score,\n reason: result.reason,\n };\n }\n\n const line = result.newLine ?? comment.line;\n if (line == null) {\n return {\n status: result.status,\n score: result.score,\n reason: result.reason,\n };\n }\n\n const rawLines = normalizedText.split(\"\\n\");\n const lineStarts = computeLineStarts(rawLines);\n const endLine = result.newEndLine ?? comment.end_line ?? line;\n const startColumn = result.newStartColumn ?? comment.start_column ?? 0;\n const endColumn = result.newEndColumn ?? comment.end_column;\n const from = offsetFor(lineStarts, rawLines, line, startColumn);\n const selectedText = comment.selected_text?.replace(/\\r\\n/g, \"\\n\");\n const to =\n endColumn != null\n ? offsetFor(lineStarts, rawLines, endLine, endColumn)\n : selectedText\n ? from + selectedText.length\n : offsetFor(lineStarts, rawLines, endLine, rawLines[endLine - 1]?.length ?? 0);\n\n return {\n status: result.status,\n score: result.score,\n from,\n to,\n line,\n endLine,\n startColumn,\n endColumn: endColumn ?? columnForOffset(lineStarts, rawLines, endLine, to),\n reason: result.reason,\n };\n}\n\nfunction computeLineStarts(lines: string[]): number[] {\n const starts = [0];\n let offset = 0;\n for (const line of lines) {\n starts.push(offset);\n offset += line.length + 1;\n }\n return starts;\n}\n\nfunction offsetFor(\n lineStarts: number[],\n lines: string[],\n line: number,\n column: number,\n): number {\n const start = lineStarts[line] ?? 0;\n const maxColumn = lines[line - 1]?.length ?? 0;\n return start + Math.max(0, Math.min(column, maxColumn));\n}\n\nfunction columnForOffset(\n lineStarts: number[],\n lines: string[],\n line: number,\n offset: number,\n): number {\n const start = lineStarts[line] ?? 0;\n const maxColumn = lines[line - 1]?.length ?? 0;\n return Math.max(0, Math.min(offset - start, maxColumn));\n}\n\nexport function applyReanchorResults(\n doc: MrsfDocument,\n results: ReanchorResult[],\n opts: { updateText?: boolean; force?: boolean; headCommit?: string } = {},\n): number {\n let changed = 0;\n const resultMap = new Map(results.map((result) => [result.commentId, result]));\n\n for (const comment of doc.comments) {\n const result = resultMap.get(comment.id);\n if (!result) continue;\n\n let isChanged = false;\n\n if (result.newLine != null && result.newLine !== comment.line) {\n comment.line = result.newLine;\n isChanged = true;\n }\n if (result.newEndLine != null && result.newEndLine !== comment.end_line) {\n comment.end_line = result.newEndLine;\n isChanged = true;\n }\n if (result.newStartColumn != null && result.newStartColumn !== comment.start_column) {\n comment.start_column = result.newStartColumn;\n isChanged = true;\n }\n if (result.newEndColumn != null && result.newEndColumn !== comment.end_column) {\n comment.end_column = result.newEndColumn;\n isChanged = true;\n }\n\n if (result.anchoredText != null && result.anchoredText !== comment.selected_text) {\n if (opts.updateText) {\n comment.selected_text = result.anchoredText;\n delete comment.anchored_text;\n } else {\n comment.anchored_text = result.anchoredText;\n }\n isChanged = true;\n } else if (result.anchoredText != null && result.anchoredText === comment.selected_text) {\n if (comment.anchored_text) {\n delete comment.anchored_text;\n isChanged = true;\n }\n }\n\n if (isChanged || result.status !== \"anchored\") {\n comment.x_reanchor_status = result.status;\n comment.x_reanchor_score = result.score;\n }\n\n if (\n opts.force\n && opts.headCommit\n && (result.status === \"anchored\" || result.status === \"shifted\")\n && result.score >= HIGH_THRESHOLD\n ) {\n comment.commit = opts.headCommit;\n delete comment.x_reanchor_status;\n delete comment.x_reanchor_score;\n if (comment.anchored_text && comment.anchored_text === comment.selected_text) {\n delete comment.anchored_text;\n }\n isChanged = true;\n }\n\n if (isChanged) {\n changed += 1;\n }\n }\n\n return changed;\n}\n\nfunction extractText(\n lines: string[],\n line: number,\n endLine?: number,\n startColumn?: number,\n endColumn?: number,\n): string | null {\n const startIdx = line;\n const endIdx = endLine ?? line;\n\n if (startIdx < 1 || endIdx >= lines.length) return null;\n\n if (startIdx === endIdx) {\n const text = lines[startIdx];\n if (startColumn != null && endColumn != null) {\n return text.slice(startColumn, endColumn);\n }\n return text;\n }\n\n const result: string[] = [];\n for (let index = startIdx; index <= endIdx; index += 1) {\n let currentLine = lines[index];\n if (index === startIdx && startColumn != null) currentLine = currentLine.slice(startColumn);\n if (index === endIdx && endColumn != null) currentLine = currentLine.slice(0, endColumn);\n result.push(currentLine);\n }\n return result.join(\"\\n\");\n}\n\nfunction closestToLine<T extends { line: number }>(candidates: T[], targetLine: number): T {\n return candidates.reduce((best, candidate) =>\n Math.abs(candidate.line - targetLine) < Math.abs(best.line - targetLine) ? candidate : best,\n );\n}\n\n/**\n * \u00A77.4 step 1a relocation guard.\n *\n * Returns true when a chosen exact-match candidate is an *implausible*\n * full-confidence relocation: the original `line` still exists in the document,\n * the candidate is farther than `proximityWindow` lines away, and the text now\n * at the original position no longer equals `selected_text`. This is the\n * signature of an in-place edit of the anchored text (which removed the\n * original occurrence) rather than a genuine move of the selection.\n *\n * When the original line no longer exists (the document shrank or the section\n * was removed) or no positional anchor is available, relocation is treated as a\n * legitimate \u00A77.4 step 3 contextual re-anchor and this returns false.\n */\nfunction isImplausibleExactRelocation(\n comment: Comment,\n candidate: FuzzyCandidate,\n lines: string[],\n proximityWindow: number,\n): boolean {\n if (comment.line == null) return false;\n\n // Original position must still exist to be a viable fallback anchor.\n if (comment.line <= 0 || comment.line >= lines.length) return false;\n\n // A nearby match is plausibly the same (or an adjacent) edit region.\n if (Math.abs(candidate.line - comment.line) <= proximityWindow) return false;\n\n // If the text at the original position still equals selected_text, the\n // original occurrence is intact and relocation is not a teleport.\n const textAtOrigin = extractText(\n lines,\n comment.line,\n comment.end_line,\n comment.start_column,\n comment.end_column,\n );\n if (textAtOrigin === comment.selected_text) return false;\n\n return true;\n}\n\nfunction getLineShift(diffHunks: DiffHunk[], line: number): { shift: number; modified: boolean } {\n let shift = 0;\n let modified = false;\n\n for (const hunk of diffHunks) {\n const oldStart = hunk.oldStart;\n const oldEnd = hunk.oldStart + Math.max(hunk.oldCount, 1) - 1;\n\n if (line >= oldStart && line <= oldEnd && hunk.oldCount > 0) {\n modified = true;\n }\n\n if (line > oldEnd || (hunk.oldCount === 0 && line >= oldStart)) {\n shift += hunk.newCount - hunk.oldCount;\n }\n }\n\n return { shift, modified };\n}", "import {\n findContextAnchorCandidates,\n getAnchorContextScope,\n type AnchorContextIndex,\n type ContextAnchorCandidate,\n} from \"./anchor-context.js\";\nimport type { Comment, ReanchorResult } from \"./types.js\";\n\nconst LOCAL_LANDMARK_WINDOW = 30;\nconst MIN_LANDMARK_SUPPORT = 0.65;\nconst MIN_SUPPORTING_LANDMARKS = 2;\nconst MIN_GLOBAL_MARGIN = 0.08;\nconst MAX_RECONCILIATION_ROUNDS = 4;\n\ninterface Landmark {\n sourceLine: number;\n targetLine: number;\n scope: string;\n}\n\ninterface ScoredCandidate {\n candidate: ContextAnchorCandidate;\n globalScore: number;\n support: number;\n supportingLandmarks: number;\n}\n\n/**\n * Resolve uncertain comments from nearby high-confidence anchors.\n *\n * Each landmark votes for a local source-to-target displacement rather than\n * global document order, allowing whole sections to move independently.\n * Newly confirmed exact anchors become landmarks in subsequent rounds.\n */\nexport function reconcileCommentAnchors(\n comments: Comment[],\n results: ReanchorResult[],\n anchorContext: AnchorContextIndex,\n): ReanchorResult[] {\n const reconciled = results.map((result) => ({ ...result }));\n if (\n comments.length < MIN_SUPPORTING_LANDMARKS + 1\n || !reconciled.some((result) => result.status === \"ambiguous\")\n ) {\n return reconciled;\n }\n const resultIndexes = new Map(\n reconciled.map((result, index) => [result.commentId, index]),\n );\n const landmarks = collectLandmarks(comments, reconciled, anchorContext);\n const landmarkCounts = new Map<string, number>();\n for (const landmark of landmarks) {\n landmarkCounts.set(\n landmark.scope,\n (landmarkCounts.get(landmark.scope) ?? 0) + 1,\n );\n }\n\n for (let round = 0; round < MAX_RECONCILIATION_ROUNDS; round += 1) {\n let changed = false;\n for (const comment of comments) {\n if (comment.line == null || !comment.selected_text) continue;\n const scope = getAnchorContextScope(comment, anchorContext);\n if (scope == null) continue;\n if ((landmarkCounts.get(scope) ?? 0) < MIN_SUPPORTING_LANDMARKS) {\n continue;\n }\n const resultIndex = resultIndexes.get(comment.id);\n if (resultIndex == null) continue;\n const result = reconciled[resultIndex];\n if (result.status !== \"ambiguous\") continue;\n\n const candidates = deduplicateCandidates(\n findContextAnchorCandidates(comment, anchorContext),\n ).slice(0, 8);\n if (candidates.length < 2) continue;\n const ranked = candidates\n .map((candidate) =>\n scoreWithLandmarks(\n comment.line as number,\n scope,\n candidate,\n landmarks,\n )\n )\n .sort((left, right) =>\n right.globalScore - left.globalScore\n || right.candidate.score - left.candidate.score\n || left.candidate.line - right.candidate.line\n );\n const best = ranked[0];\n const second = ranked[1];\n if (\n !best.candidate.exact\n || best.supportingLandmarks < MIN_SUPPORTING_LANDMARKS\n || best.support < MIN_LANDMARK_SUPPORT\n || best.globalScore - second.globalScore < MIN_GLOBAL_MARGIN\n ) {\n continue;\n }\n\n reconciled[resultIndex] = {\n commentId: comment.id,\n status: \"anchored\",\n score: Math.min(0.99, 0.8 + best.support * 0.19),\n newLine: best.candidate.line,\n newEndLine: best.candidate.endLine,\n newStartColumn: best.candidate.startColumn,\n newEndColumn: best.candidate.endColumn,\n reason:\n `Global reconciliation selected this candidate from `\n + `${best.supportingLandmarks} nearby landmark(s) `\n + `(support ${best.support.toFixed(3)}, margin `\n + `${(best.globalScore - second.globalScore).toFixed(3)}).`,\n };\n changed = true;\n\n landmarks.push({\n sourceLine: comment.line,\n targetLine: best.candidate.line,\n scope,\n });\n landmarkCounts.set(scope, (landmarkCounts.get(scope) ?? 0) + 1);\n }\n if (!changed) break;\n }\n\n return reconciled;\n}\n\nfunction collectLandmarks(\n comments: Comment[],\n results: ReanchorResult[],\n anchorContext: AnchorContextIndex,\n): Landmark[] {\n const resultMap = new Map(results.map((result) => [result.commentId, result]));\n return comments.flatMap((comment): Landmark[] => {\n const result = resultMap.get(comment.id);\n if (\n comment.line == null\n || result?.newLine == null\n || (result.status !== \"anchored\" && result.status !== \"shifted\")\n || result.score < 0.99\n ) {\n return [];\n }\n const scope = getAnchorContextScope(comment, anchorContext);\n return scope == null\n ? []\n : [{ sourceLine: comment.line, targetLine: result.newLine, scope }];\n });\n}\n\nfunction scoreWithLandmarks(\n sourceLine: number,\n scope: string,\n candidate: ContextAnchorCandidate,\n landmarks: Landmark[],\n): ScoredCandidate {\n let weightedSupport = 0;\n let totalWeight = 0;\n let supportingLandmarks = 0;\n const candidateShift = candidate.line - sourceLine;\n\n for (const landmark of landmarks) {\n if (landmark.scope !== scope) continue;\n const sourceDistance = Math.abs(sourceLine - landmark.sourceLine);\n if (sourceDistance === 0 || sourceDistance > LOCAL_LANDMARK_WINDOW) continue;\n const landmarkShift = landmark.targetLine - landmark.sourceLine;\n const shiftError = Math.abs(candidateShift - landmarkShift);\n const agreement = Math.max(0, 1 - shiftError / 8);\n const weight = 1 / (1 + sourceDistance / 4);\n weightedSupport += agreement * weight;\n totalWeight += weight;\n if (agreement >= MIN_LANDMARK_SUPPORT) supportingLandmarks += 1;\n }\n\n const support = totalWeight > 0 ? weightedSupport / totalWeight : 0;\n return {\n candidate,\n globalScore:\n candidate.score * 0.5 + support * 0.45 + (candidate.exact ? 0.05 : 0),\n support,\n supportingLandmarks,\n };\n}\n\nfunction deduplicateCandidates(\n candidates: ContextAnchorCandidate[],\n): ContextAnchorCandidate[] {\n const unique = new Map<string, ContextAnchorCandidate>();\n for (const candidate of candidates) {\n const key = [\n candidate.line,\n candidate.endLine,\n candidate.startColumn ?? \"\",\n candidate.endColumn ?? \"\",\n ].join(\":\");\n const existing = unique.get(key);\n if (!existing || candidate.score > existing.score) {\n unique.set(key, candidate);\n }\n }\n return [...unique.values()].sort((left, right) =>\n right.score - left.score || left.line - right.line\n );\n}\n", "import AjvModule from \"ajv\";\nimport addFormatsModule from \"ajv-formats\";\nimport { mrsfSchema } from \"./schema.js\";\nimport type {\n MrsfDocument,\n ValidationDiagnostic,\n ValidationResult,\n} from \"./types.js\";\n\nconst Ajv = (AjvModule as any).default ?? AjvModule;\nconst addFormats = (addFormatsModule as any).default ?? addFormatsModule;\n\nexport type HashFunction = (text: string) => string;\n\nexport function validateDocument(\n doc: MrsfDocument,\n schema: object = mrsfSchema,\n): ValidationResult {\n const errors: ValidationDiagnostic[] = [];\n const warnings: ValidationDiagnostic[] = [];\n\n validateSchema(doc, schema, errors);\n validateCrossFields(doc, errors, warnings);\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport function validateSchema(\n doc: MrsfDocument,\n rawSchema: object,\n errors: ValidationDiagnostic[],\n): void {\n const { $schema, ...schema } = rawSchema as Record<string, unknown>;\n void $schema;\n const ajv = new Ajv({ allErrors: true, strict: false });\n addFormats(ajv);\n const ajvValidate = ajv.compile(schema);\n const schemaValid = ajvValidate(doc);\n\n if (!schemaValid && ajvValidate.errors) {\n for (const err of ajvValidate.errors) {\n errors.push({\n severity: \"error\",\n code: \"schema-violation\",\n message: `${err.instancePath || \"/\"}: ${err.message ?? \"schema error\"}`,\n path: err.instancePath || \"/\",\n });\n }\n }\n}\n\nexport function validateCrossFields(\n doc: MrsfDocument,\n errors: ValidationDiagnostic[],\n warnings: ValidationDiagnostic[],\n hash?: HashFunction,\n): void {\n if (!Array.isArray(doc.comments)) return;\n\n const ids = new Set<string>();\n const allIds = doc.comments.map((x) => x.id);\n\n for (let i = 0; i < doc.comments.length; i++) {\n const c = doc.comments[i];\n const prefix = `/comments/${i}`;\n\n if (c.id) {\n if (ids.has(c.id)) {\n errors.push({\n severity: \"error\",\n code: \"duplicate-id\",\n message: `Duplicate comment id \"${c.id}\"`,\n path: `${prefix}/id`,\n commentId: c.id,\n });\n }\n ids.add(c.id);\n }\n\n if (c.line != null && c.end_line != null && c.end_line < c.line) {\n errors.push({\n severity: \"error\",\n code: \"end-line-before-line\",\n message: `end_line (${c.end_line}) must be \u2265 line (${c.line})`,\n path: `${prefix}/end_line`,\n commentId: c.id,\n });\n }\n\n if (\n c.start_column != null &&\n c.end_column != null &&\n (c.line == null || c.end_line == null || c.line === c.end_line) &&\n c.end_column < c.start_column\n ) {\n errors.push({\n severity: \"error\",\n code: \"end-column-before-start-column\",\n message: `end_column (${c.end_column}) must be \u2265 start_column (${c.start_column}) on the same line`,\n path: `${prefix}/end_column`,\n commentId: c.id,\n });\n }\n\n if (c.selected_text && c.selected_text.length > 4096) {\n errors.push({\n severity: \"error\",\n code: \"selected-text-too-long\",\n message: `selected_text exceeds 4096 characters (${c.selected_text.length})`,\n path: `${prefix}/selected_text`,\n commentId: c.id,\n });\n }\n\n if (c.text && c.text.length > 16384) {\n warnings.push({\n severity: \"warning\",\n code: \"text-too-long\",\n message: `text exceeds recommended 16384 characters (${c.text.length})`,\n path: `${prefix}/text`,\n commentId: c.id,\n });\n }\n\n // Browser-safe callers do not get the Node SHA-256 implementation.\n // The hash check runs only when a hash function is injected by the Node validator.\n if (hash && c.selected_text && c.selected_text_hash) {\n const expected = hash(c.selected_text);\n if (c.selected_text_hash !== expected) {\n warnings.push({\n severity: \"warning\",\n code: \"hash-mismatch\",\n message: `selected_text_hash mismatch (expected ${expected.slice(0, 12)}\u2026, got ${c.selected_text_hash.slice(0, 12)}\u2026)`,\n path: `${prefix}/selected_text_hash`,\n commentId: c.id,\n });\n }\n }\n\n if (c.reply_to && !ids.has(c.reply_to) && !allIds.includes(c.reply_to)) {\n warnings.push({\n severity: \"warning\",\n code: \"unresolved-reply-to\",\n message: `reply_to \"${c.reply_to}\" does not resolve to any comment id in this file`,\n path: `${prefix}/reply_to`,\n commentId: c.id,\n });\n }\n\n if (c.line != null && !c.selected_text) {\n warnings.push({\n severity: \"warning\",\n code: \"missing-selected-text\",\n message: \"Comment has line anchors but no selected_text \u2014 anchoring will be fragile across edits\",\n path: `${prefix}/selected_text`,\n commentId: c.id,\n });\n }\n }\n}\n", "\n{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://github.com/wictorwilen/MRSF/raw/main/mrsf.schema.json\",\n \"title\": \"Markdown Review Sidecar Format (MRSF) v1.0\",\n \"description\": \"Schema for MRSF review sidecar files. See MRSF-v1.0.md for the full specification.\",\n \"type\": \"object\",\n \"required\": [\"mrsf_version\", \"document\", \"comments\"],\n \"additionalProperties\": true,\n \"properties\": {\n \"mrsf_version\": {\n \"type\": \"string\",\n \"pattern\": \"^1\\\\.\\\\d+$\",\n \"description\": \"MRSF format version. MUST be a supported major.minor version (e.g., 1.0).\"\n },\n \"document\": {\n \"type\": \"string\",\n \"description\": \"Relative path to the Markdown document being reviewed.\"\n },\n \"comments\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\"id\", \"author\", \"timestamp\", \"text\", \"resolved\"],\n \"additionalProperties\": true,\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Globally unique, opaque, collision-resistant identifier for the comment.\"\n },\n \"author\": {\n \"type\": \"string\",\n \"description\": \"Creator of the comment. SHOULD follow the convention 'Display Name (identifier)'.\"\n },\n \"timestamp\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"description\": \"ISO 8601 / RFC 3339 timestamp of comment creation; SHOULD include timezone offset.\"\n },\n \"text\": {\n \"type\": \"string\",\n \"maxLength\": 16384,\n \"description\": \"The content of the review comment. MUST be plain text.\"\n },\n \"resolved\": {\n \"type\": \"boolean\",\n \"description\": \"Whether the comment has been resolved.\"\n },\n \"commit\": {\n \"type\": \"string\",\n \"description\": \"Git commit hash associated with the comment. SHOULD be the full (long) SHA.\"\n },\n \"type\": {\n \"type\": \"string\",\n \"description\": \"Categorization of the comment. Recommended values listed in examples.\",\n \"examples\": [\n \"suggestion\",\n \"issue\",\n \"question\",\n \"accuracy\",\n \"style\",\n \"clarity\"\n ]\n },\n \"severity\": {\n \"type\": \"string\",\n \"description\": \"Importance level of the comment.\",\n \"enum\": [\"low\", \"medium\", \"high\"]\n },\n \"reply_to\": {\n \"type\": \"string\",\n \"description\": \"ID of another comment in the same file that this comment replies to.\"\n },\n \"line\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Starting line number (1-based) in the target document.\"\n },\n \"end_line\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Ending line number (inclusive, 1-based). MUST be >= line.\"\n },\n \"start_column\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Starting column index (0-based) within the starting line.\"\n },\n \"end_column\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Ending column index. MUST be >= start_column when on the same line.\"\n },\n \"selected_text\": {\n \"type\": \"string\",\n \"maxLength\": 4096,\n \"description\": \"Exact text selected by the reviewer. SHOULD NOT be modified by re-anchoring tools. SHOULD NOT exceed 4096 characters.\"\n },\n \"anchored_text\": {\n \"type\": \"string\",\n \"maxLength\": 4096,\n \"description\": \"Text currently found at the resolved anchor position. Populated by re-anchoring tools when the document text differs from selected_text. SHOULD be omitted when identical to selected_text.\"\n },\n \"selected_text_hash\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-f0-9]{64}$\",\n \"description\": \"Hex-encoded SHA-256 hash of selected_text. Immutable after creation; used for fast exact-match detection during re-anchoring, integrity verification, and staleness checks. SHOULD NOT be modified by re-anchoring tools unless selected_text is also replaced (opt-in behaviour), in which case it MUST be recomputed.\"\n }\n }\n }\n }\n }\n}\n", "import mrsfSchemaJson from \"../../mrsf.schema.json\" with { type: \"json\" };\n\nexport const mrsfSchema = mrsfSchemaJson;\n", "/**\n * MRSF string (de)serialization \u2014 pure, dependency-light helpers that parse and\n * serialize MRSF sidecar content to/from strings.\n *\n * This module intentionally has **no Node-only imports** (no `node:fs`,\n * `node:path`, `node:crypto`, \u2026) so it can be consumed from browser/host\n * adapters via the slim `@mrsf/cli/browser` entry point. Filesystem-bound\n * helpers (read/discover/write a file) live in `parser.ts` / `writer.ts`.\n */\n\nimport yaml from \"js-yaml\";\nimport { Document } from \"yaml\";\nimport type { MrsfDocument, Comment } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Lenient parse result\n// ---------------------------------------------------------------------------\n\n/** Result from a lenient (non-throwing) parse attempt. */\nexport interface LenientParseResult {\n /** Fully parsed document, or null if parsing failed entirely. */\n doc: MrsfDocument | null;\n /** If parsing failed or produced warnings, the error message. */\n error?: string;\n /** Comments that could be salvaged from a partially-corrupted sidecar. */\n partialComments?: Comment[];\n}\n\n// ---------------------------------------------------------------------------\n// Parsing (string \u2192 document)\n// ---------------------------------------------------------------------------\n\n/**\n * Parse MRSF sidecar content from a string.\n * Detects JSON vs YAML based on content or optional filename hint.\n */\nexport function parseSidecarContent(\n content: string,\n filenameHint?: string,\n): MrsfDocument {\n const trimmed = content.trim();\n\n let parsed: unknown;\n\n // Detect JSON by content or filename\n const isJson =\n trimmed.startsWith(\"{\") ||\n (filenameHint && filenameHint.endsWith(\".review.json\"));\n\n if (isJson) {\n try {\n parsed = JSON.parse(trimmed);\n } catch (e) {\n throw new Error(`Failed to parse JSON: ${(e as Error).message}`);\n }\n } else {\n try {\n parsed = yaml.load(trimmed, { schema: yaml.JSON_SCHEMA });\n } catch (e) {\n throw new Error(`Failed to parse YAML: ${(e as Error).message}`);\n }\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"MRSF sidecar must be a YAML/JSON object\");\n }\n\n return parsed as MrsfDocument;\n}\n\n/**\n * Lenient parse from string content.\n */\nexport function parseSidecarContentLenient(\n content: string,\n filenameHint?: string,\n): LenientParseResult {\n const trimmed = content.trim();\n if (!trimmed) {\n return { doc: null, error: \"File is empty\" };\n }\n\n const isJson =\n trimmed.startsWith(\"{\") ||\n (filenameHint && filenameHint.endsWith(\".review.json\"));\n\n // First, try a normal parse\n let parsed: unknown;\n try {\n parsed = isJson ? JSON.parse(trimmed) : yaml.load(trimmed, { schema: yaml.JSON_SCHEMA });\n } catch (e) {\n // Total parse failure \u2014 try to salvage what we can from YAML\n if (!isJson) {\n return salvageYaml(trimmed);\n }\n return { doc: null, error: `Failed to parse JSON: ${(e as Error).message}` };\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return { doc: null, error: \"MRSF sidecar must be a YAML/JSON object\" };\n }\n\n const obj = parsed as Record<string, unknown>;\n const doc: MrsfDocument = {\n mrsf_version: typeof obj.mrsf_version === \"string\" ? obj.mrsf_version : \"1.0\",\n document: typeof obj.document === \"string\" ? obj.document : \"unknown\",\n comments: [],\n };\n\n if (!Array.isArray(obj.comments)) {\n return {\n doc,\n error: \"comments field is not an array \u2014 file may be corrupted\",\n };\n }\n\n // Validate each comment individually\n const good: Comment[] = [];\n const bad: number[] = [];\n\n for (let i = 0; i < obj.comments.length; i++) {\n const c = obj.comments[i];\n if (c && typeof c === \"object\" && !Array.isArray(c) && typeof (c as Record<string, unknown>).id === \"string\") {\n good.push(c as Comment);\n } else {\n bad.push(i);\n }\n }\n\n doc.comments = good;\n\n if (bad.length > 0) {\n return {\n doc,\n error: `${bad.length} comment(s) at indices [${bad.join(\", \")}] were malformed and skipped`,\n partialComments: good,\n };\n }\n\n return { doc };\n}\n\n/**\n * Attempt to extract individual comment blocks from corrupted YAML by\n * splitting on `- id:` patterns and parsing each block independently.\n */\nfunction salvageYaml(content: string): LenientParseResult {\n const salvaged: Comment[] = [];\n let mrsf_version = \"1.0\";\n let document = \"unknown\";\n\n // Try to extract top-level fields from the beginning\n const versionMatch = content.match(/^mrsf_version:\\s*[\"']?([^\"'\\n]+)/m);\n if (versionMatch) mrsf_version = versionMatch[1].trim();\n\n const docMatch = content.match(/^document:\\s*[\"']?([^\"'\\n]+)/m);\n if (docMatch) document = docMatch[1].trim();\n\n // Split on comment block boundaries (- id: ...)\n const blocks = content.split(/(?=^ - id:\\s)/m);\n\n for (const block of blocks) {\n const trimmed = block.trim();\n if (!trimmed.startsWith(\"- id:\")) continue;\n\n // Wrap in a minimal YAML array context and try to parse\n try {\n const parsed = yaml.load(trimmed, { schema: yaml.JSON_SCHEMA });\n if (Array.isArray(parsed) && parsed.length > 0) {\n const c = parsed[0];\n if (c && typeof c === \"object\" && typeof (c as Record<string, unknown>).id === \"string\") {\n salvaged.push(c as Comment);\n }\n } else if (parsed && typeof parsed === \"object\" && typeof (parsed as Record<string, unknown>).id === \"string\") {\n salvaged.push(parsed as Comment);\n }\n } catch {\n // This block is unparseable \u2014 skip\n }\n }\n\n const doc: MrsfDocument = {\n mrsf_version,\n document,\n comments: salvaged,\n };\n\n return {\n doc: salvaged.length > 0 ? doc : null,\n error: `YAML parse failed. Salvaged ${salvaged.length} comment(s) from raw content.`,\n partialComments: salvaged.length > 0 ? salvaged : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Serialization (document \u2192 string)\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize an MrsfDocument to YAML (for new files / non-round-trip use).\n */\nexport function toYaml(doc: MrsfDocument): string {\n const yamlDoc = new Document(doc);\n return yamlDoc.toString({ lineWidth: 0 });\n}\n\n/**\n * Serialize an MrsfDocument to JSON.\n */\nexport function toJson(doc: MrsfDocument): string {\n return JSON.stringify(doc, null, 2) + \"\\n\";\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["DEFAULT_THRESHOLD", "HIGH_THRESHOLD", "applyReanchorResults", "calibrateAnchorEvidence", "combinedScore", "createAnchorContextIndex", "createRevisionProjection", "exactMatch", "formatAuthor", "fuzzySearch", "levenshteinScore", "newCommentId", "normalizedMatch", "parseAuthor", "parseSidecarContent", "parseSidecarContentLenient", "reanchorComment", "reanchorDocumentLines", "reanchorDocumentText", "reconcileCommentAnchors", "resolveAnchor", "toJson", "toReanchorLines", "toYaml", "tokenLcsScore", "validateDocument", "levenshtein", "index", "uuidv4", "extractText", "tokenize", "extractText", "deduplicateCandidates", "AjvModule", "addFormatsModule", "yaml", "parseSidecarContent", "parseSidecarContentLenient", "toYaml", "toJson", "combinedScore", "exactMatch", "fuzzySearch", "levenshteinScore", "normalizedMatch", "tokenLcsScore", "applyReanchorResults", "DEFAULT_THRESHOLD", "HIGH_THRESHOLD", "reanchorComment", "reanchorDocumentLines", "reanchorDocumentText", "resolveAnchor", "toReanchorLines", "createAnchorContextIndex", "reconcileCommentAnchors", "createRevisionProjection", "calibrateAnchorEvidence", "validateDocument", "formatAuthor", "parseAuthor", "newCommentId"]
7
7
  }
package/dist/browser.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import * as fuzzy from "./lib/fuzzy.js";
2
2
  import * as identity from "./lib/identity.js";
3
3
  import * as reanchorCore from "./lib/reanchor-core.js";
4
+ import * as anchorContext from "./lib/anchor-context.js";
5
+ import * as globalReconciliation from "./lib/global-reconciliation.js";
6
+ import * as revisionProjection from "./lib/revision-projection.js";
7
+ import * as confidenceCalibration from "./lib/confidence-calibration.js";
4
8
  import * as validateCore from "./lib/validate-core.js";
5
9
  import * as serialize from "./lib/serialize.js";
6
10
  import { mrsfSchema } from "./lib/schema.js";
@@ -25,6 +29,13 @@ export declare const reanchorDocumentLines: typeof reanchorCore.reanchorDocument
25
29
  export declare const reanchorDocumentText: typeof reanchorCore.reanchorDocumentText;
26
30
  export declare const resolveAnchor: typeof reanchorCore.resolveAnchor;
27
31
  export declare const toReanchorLines: typeof reanchorCore.toReanchorLines;
32
+ export declare const createAnchorContextIndex: typeof anchorContext.createAnchorContextIndex;
33
+ export declare const reconcileCommentAnchors: typeof globalReconciliation.reconcileCommentAnchors;
34
+ export declare const createRevisionProjection: typeof revisionProjection.createRevisionProjection;
35
+ export declare const calibrateAnchorEvidence: typeof confidenceCalibration.calibrateAnchorEvidence;
36
+ export type { AnchorContextIndex, ContextAnchorCandidate, ContextAnchorResolution, } from "./lib/anchor-context.js";
37
+ export type { ProjectedAnchor, RevisionProjectionIndex, } from "./lib/revision-projection.js";
38
+ export type { CalibratedAnchor, ConfidenceBand, } from "./lib/confidence-calibration.js";
28
39
  export declare const validateDocument: typeof validateCore.validateDocument;
29
40
  export { mrsfSchema };
30
41
  export declare const formatAuthor: typeof identity.formatAuthor;
package/dist/browser.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import * as fuzzy from "./lib/fuzzy.js";
2
2
  import * as identity from "./lib/identity.js";
3
3
  import * as reanchorCore from "./lib/reanchor-core.js";
4
+ import * as anchorContext from "./lib/anchor-context.js";
5
+ import * as globalReconciliation from "./lib/global-reconciliation.js";
6
+ import * as revisionProjection from "./lib/revision-projection.js";
7
+ import * as confidenceCalibration from "./lib/confidence-calibration.js";
4
8
  import * as validateCore from "./lib/validate-core.js";
5
9
  import * as serialize from "./lib/serialize.js";
6
10
  import { mrsfSchema } from "./lib/schema.js";
@@ -23,6 +27,10 @@ export const reanchorDocumentLines = reanchorCore.reanchorDocumentLines;
23
27
  export const reanchorDocumentText = reanchorCore.reanchorDocumentText;
24
28
  export const resolveAnchor = reanchorCore.resolveAnchor;
25
29
  export const toReanchorLines = reanchorCore.toReanchorLines;
30
+ export const createAnchorContextIndex = anchorContext.createAnchorContextIndex;
31
+ export const reconcileCommentAnchors = globalReconciliation.reconcileCommentAnchors;
32
+ export const createRevisionProjection = revisionProjection.createRevisionProjection;
33
+ export const calibrateAnchorEvidence = confidenceCalibration.calibrateAnchorEvidence;
26
34
  export const validateDocument = validateCore.validateDocument;
27
35
  export { mrsfSchema };
28
36
  export const formatAuthor = identity.formatAuthor;