@mrsf/cli 0.5.0 → 0.7.0

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 (45) hide show
  1. package/README.md +10 -7
  2. package/dist/browser.cjs +1273 -37
  3. package/dist/browser.cjs.map +4 -4
  4. package/dist/browser.d.ts +18 -1
  5. package/dist/browser.js +14 -0
  6. package/dist/commands/reanchor.js +3 -0
  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 +1307 -85
  20. package/dist/index.cjs.map +4 -4
  21. package/dist/index.d.ts +12 -0
  22. package/dist/index.js +9 -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 +2 -0
  30. package/dist/lib/git.js +12 -0
  31. package/dist/lib/global-reconciliation.d.ts +11 -0
  32. package/dist/lib/global-reconciliation.js +145 -0
  33. package/dist/lib/parser.d.ts +4 -19
  34. package/dist/lib/parser.js +4 -140
  35. package/dist/lib/reanchor-core.d.ts +20 -0
  36. package/dist/lib/reanchor-core.js +123 -20
  37. package/dist/lib/reanchor.js +85 -12
  38. package/dist/lib/revision-projection.d.ts +21 -0
  39. package/dist/lib/revision-projection.js +203 -0
  40. package/dist/lib/serialize.d.ts +37 -0
  41. package/dist/lib/serialize.js +170 -0
  42. package/dist/lib/types.d.ts +7 -0
  43. package/dist/lib/writer.d.ts +1 -8
  44. package/dist/lib/writer.js +5 -14
  45. package/package.json +5 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/lib/parser.ts", "../src/index.ts", "../src/lib/discovery.ts", "../src/lib/resolve-files.ts", "../src/lib/writer.ts", "../src/lib/validator.ts", "../src/lib/validate-core.ts", "../mrsf.schema.json", "../src/lib/schema.ts", "../src/lib/fuzzy.ts", "../src/lib/git.ts", "../src/lib/reanchor-core.ts", "../src/lib/reanchor.ts", "../src/lib/identity.ts", "../src/lib/comments.ts"],
4
- "sourcesContent": ["/**\n * MRSF Parser \u2014 load and parse MRSF sidecar files (YAML or JSON).\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport yaml from \"js-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 * Parse an MRSF sidecar file from disk.\n */\nexport async function parseSidecar(filePath: string): Promise<MrsfDocument> {\n const abs = path.resolve(filePath);\n const content = await readFile(abs, \"utf-8\");\n return parseSidecarContent(content, abs);\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: attempts to parse a sidecar file from disk without\n * throwing. On complete failure, returns `{ doc: null, error }`.\n * On success, returns `{ doc }`. For partially-corrupted YAML (where\n * the top-level parses but some comments are malformed), attempts to\n * salvage individual well-formed comments.\n */\nexport async function parseSidecarLenient(\n filePath: string,\n): Promise<LenientParseResult> {\n const abs = path.resolve(filePath);\n let content: string;\n try {\n content = await readFile(abs, \"utf-8\");\n } catch (e) {\n return { doc: null, error: `Cannot read file: ${(e as Error).message}` };\n }\n\n return parseSidecarContentLenient(content, abs);\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 * Read a Markdown document from disk and return its lines.\n * Lines are 1-indexed in the returned array (index 0 is unused).\n */\nexport async function readDocumentLines(\n filePath: string,\n): Promise<string[]> {\n const content = await readFile(path.resolve(filePath), \"utf-8\");\n const lines = content.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n // Prepend empty element so lines[1] = first line (1-based)\n return [\"\", ...lines];\n}\n", "/**\n * MRSF \u2014 Public API (library surface).\n *\n * Usage:\n * import { validate, reanchorFile, addComment, ... } from \"mrsf\";\n */\n\nimport * as discovery from \"./lib/discovery.js\";\nimport * as resolveFiles from \"./lib/resolve-files.js\";\nimport * as parser from \"./lib/parser.js\";\nimport * as writer from \"./lib/writer.js\";\nimport * as validator from \"./lib/validator.js\";\nimport * as fuzzy from \"./lib/fuzzy.js\";\nimport * as git from \"./lib/git.js\";\nimport * as reanchor from \"./lib/reanchor.js\";\nimport * as comments from \"./lib/comments.js\";\nimport * as identity from \"./lib/identity.js\";\nimport * as validateCore from \"./lib/validate-core.js\";\nimport { mrsfSchema } from \"./lib/schema.js\";\n\n// Types\nexport type {\n MrsfDocument,\n Comment,\n CommentExtensions,\n CommentExtensionValue,\n MrsfConfig,\n DiagnosticSeverity,\n ValidationDiagnostic,\n ValidationResult,\n ReanchorStatus,\n ReanchorResult,\n AnchorPosition,\n FuzzyCandidate,\n DiffHunk,\n AddCommentOptions,\n EditCommentOptions,\n CommentFilter,\n AnchorHealth,\n StatusResult,\n BaseOptions,\n ReanchorOptions,\n ValidateOptions,\n} from \"./lib/types.js\";\n\n// Discovery\nexport const findWorkspaceRoot = discovery.findWorkspaceRoot;\nexport const loadConfig = discovery.loadConfig;\nexport const discoverSidecar = discovery.discoverSidecar;\nexport const sidecarToDocument = discovery.sidecarToDocument;\nexport const discoverAllSidecars = discovery.discoverAllSidecars;\n\n// File resolution\nexport const resolveSidecarPaths = resolveFiles.resolveSidecarPaths;\n\n// Parsing\nexport const parseSidecar = parser.parseSidecar;\nexport const parseSidecarContent = parser.parseSidecarContent;\nexport const parseSidecarLenient = parser.parseSidecarLenient;\nexport const parseSidecarContentLenient = parser.parseSidecarContentLenient;\nexport const readDocumentLines = parser.readDocumentLines;\n\nexport type { LenientParseResult } from \"./lib/parser.js\";\n\n// Writing\nexport const computeHash = writer.computeHash;\nexport const syncHash = writer.syncHash;\nexport const toYaml = writer.toYaml;\nexport const toJson = writer.toJson;\nexport const writeSidecar = writer.writeSidecar;\n\n// Validation\nexport const validate = validator.validate;\nexport const validateFile = validator.validateFile;\nexport const validateDocument = validateCore.validateDocument;\nexport { mrsfSchema };\n\n// Fuzzy matching\nexport const exactMatch = fuzzy.exactMatch;\nexport const normalizedMatch = fuzzy.normalizedMatch;\nexport const fuzzySearch = fuzzy.fuzzySearch;\nexport const combinedScore = fuzzy.combinedScore;\n\n// Git\nexport const isGitAvailable = git.isGitAvailable;\nexport const findRepoRoot = git.findRepoRoot;\nexport const getCurrentCommit = git.getCurrentCommit;\nexport const isStale = git.isStale;\nexport const getDiff = git.getDiff;\nexport const getLineShift = git.getLineShift;\nexport const getFileAtCommit = git.getFileAtCommit;\nexport const getStagedFiles = git.getStagedFiles;\nexport const detectRenames = git.detectRenames;\nexport const parseDiffHunks = git.parseDiffHunks;\n\n// Re-anchoring\nexport const DEFAULT_THRESHOLD = reanchor.DEFAULT_THRESHOLD;\nexport const HIGH_THRESHOLD = reanchor.HIGH_THRESHOLD;\nexport const reanchorComment = reanchor.reanchorComment;\nexport const reanchorDocumentLines = reanchor.reanchorDocumentLines;\nexport const reanchorDocumentText = reanchor.reanchorDocumentText;\nexport const toReanchorLines = reanchor.toReanchorLines;\nexport const resolveAnchor = reanchor.resolveAnchor;\nexport const reanchorDocument = reanchor.reanchorDocument;\nexport const applyReanchorResults = reanchor.applyReanchorResults;\nexport const reanchorFile = reanchor.reanchorFile;\n\n// Comments\nexport const addComment = comments.addComment;\nexport const editComment = comments.editComment;\nexport const normalizeCommentExtensions = comments.normalizeCommentExtensions;\nexport const populateSelectedText = comments.populateSelectedText;\nexport const resolveComment = comments.resolveComment;\nexport const unresolveComment = comments.unresolveComment;\nexport const removeComment = comments.removeComment;\nexport const filterComments = comments.filterComments;\nexport const getThreads = comments.getThreads;\nexport const summarize = comments.summarize;\nexport type { CommentSummary, RemoveCommentOptions } from \"./lib/comments.js\";\n\n// Identity\nexport const formatAuthor = identity.formatAuthor;\nexport const parseAuthor = identity.parseAuthor;\nexport const newCommentId = identity.newCommentId;\nexport type { ParsedAuthor } from \"./lib/identity.js\";\n", "/**\n * MRSF Discovery \u2014 resolve sidecar file paths per \u00A73.3.\n *\n * Discovery order:\n * 1. Check for .mrsf.yaml at repo/workspace root \u2192 use sidecar_root if defined.\n * 2. Otherwise, co-located sidecar next to the Markdown file.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"js-yaml\";\nimport type { MrsfConfig } from \"./types.js\";\n\nconst CONFIG_FILENAME = \".mrsf.yaml\";\nconst SIDECAR_SUFFIX = \".review.yaml\";\nconst SIDECAR_SUFFIX_JSON = \".review.json\";\n\n/**\n * Find the workspace / repo root by walking up from `startDir` looking for\n * `.mrsf.yaml` or `.git`.\n */\nexport function findWorkspaceRoot(startDir: string): string {\n let dir = path.resolve(startDir);\n const { root } = path.parse(dir);\n while (dir !== root) {\n if (\n existsSync(path.join(dir, CONFIG_FILENAME)) ||\n existsSync(path.join(dir, \".git\"))\n ) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return path.resolve(startDir);\n}\n\n/**\n * Load and validate .mrsf.yaml config. Returns null if not found.\n */\nexport async function loadConfig(\n workspaceRoot: string,\n configPath?: string,\n): Promise<MrsfConfig | null> {\n const cfgPath = configPath\n ? path.resolve(configPath)\n : path.join(workspaceRoot, CONFIG_FILENAME);\n\n if (!existsSync(cfgPath)) return null;\n\n const raw = await readFile(cfgPath, \"utf-8\");\n const parsed = yaml.load(raw, { schema: yaml.JSON_SCHEMA }) as Record<string, unknown> | null;\n\n if (!parsed || typeof parsed !== \"object\") return null;\n\n const config: MrsfConfig = {};\n\n if (typeof parsed.sidecar_root === \"string\") {\n const sr = parsed.sidecar_root;\n\n // Reject absolute paths\n if (path.isAbsolute(sr)) {\n throw new Error(\n `.mrsf.yaml: sidecar_root must be a relative path (got \"${sr}\")`,\n );\n }\n\n // Reject path traversal\n if (sr.includes(\"..\")) {\n throw new Error(\n `.mrsf.yaml: sidecar_root must not contain \"..\" (got \"${sr}\")`,\n );\n }\n\n config.sidecar_root = sr;\n }\n\n return config;\n}\n\n/**\n * Given a Markdown document path (relative to workspace root), resolve the\n * sidecar file path according to \u00A73.3 discovery order.\n *\n * Returns an absolute path to the sidecar.\n */\nexport async function discoverSidecar(\n documentPath: string,\n options: { cwd?: string; configPath?: string } = {},\n): Promise<string> {\n const cwd = options.cwd ?? process.cwd();\n const workspaceRoot = findWorkspaceRoot(cwd);\n const config = await loadConfig(workspaceRoot, options.configPath);\n\n // Normalize to a workspace-relative path\n const relDoc = path.isAbsolute(documentPath)\n ? path.relative(workspaceRoot, documentPath)\n : documentPath;\n\n if (config?.sidecar_root) {\n // \u00A73.2 \u2014 alternate sidecar location\n return path.join(workspaceRoot, config.sidecar_root, relDoc + SIDECAR_SUFFIX);\n }\n\n // \u00A73.1 \u2014 co-located\n return path.join(workspaceRoot, relDoc + SIDECAR_SUFFIX);\n}\n\n/**\n * Given a sidecar file path, resolve the Markdown document path.\n * Strips .review.yaml or .review.json suffix.\n * Returns an absolute path to the document.\n */\nexport function sidecarToDocument(\n sidecarPath: string,\n options: { cwd?: string } = {},\n): string {\n const abs = path.resolve(sidecarPath);\n\n if (abs.endsWith(SIDECAR_SUFFIX)) {\n return abs.slice(0, -SIDECAR_SUFFIX.length);\n } else if (abs.endsWith(SIDECAR_SUFFIX_JSON)) {\n return abs.slice(0, -SIDECAR_SUFFIX_JSON.length);\n }\n\n return abs;\n}\n\n/**\n * Discover all sidecar files in a directory (recursive).\n */\nexport async function discoverAllSidecars(\n dirPath: string,\n): Promise<string[]> {\n const { readdir, stat } = await import(\"node:fs/promises\");\n const results: string[] = [];\n\n async function walk(dir: string): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name === \"node_modules\" || entry.name === \".git\") continue;\n await walk(full);\n } else if (\n entry.name.endsWith(SIDECAR_SUFFIX) ||\n entry.name.endsWith(SIDECAR_SUFFIX_JSON)\n ) {\n results.push(full);\n }\n }\n }\n\n const s = await stat(dirPath);\n if (s.isFile()) {\n results.push(path.resolve(dirPath));\n } else {\n await walk(path.resolve(dirPath));\n }\n\n return results;\n}\n", "/**\n * Shared helper for resolving CLI file arguments.\n *\n * When a user passes a Markdown document path (e.g. `docs/api.md`) instead of\n * a sidecar path, we auto-discover the corresponding sidecar. This avoids\n * the confusing \"Failed to parse YAML\" error on raw Markdown files.\n */\n\nimport path from \"node:path\";\nimport { discoverSidecar, findWorkspaceRoot, discoverAllSidecars } from \"../lib/discovery.js\";\n\nconst SIDECAR_EXTENSIONS = [\".review.yaml\", \".review.json\"];\n\nfunction isSidecarPath(file: string): boolean {\n return SIDECAR_EXTENSIONS.some((ext) => file.endsWith(ext));\n}\n\n/**\n * Resolve a list of CLI file arguments to sidecar paths.\n *\n * - If `files` is empty, discover all sidecars from the workspace root.\n * - If a file already looks like a sidecar (`.review.yaml`/`.review.json`),\n * resolve it to an absolute path.\n * - If a file ends in `.md` (or any non-sidecar extension), treat it as a\n * document path and discover its sidecar via \u00A73.3.\n */\nexport async function resolveSidecarPaths(\n files: string[],\n cwd: string,\n): Promise<string[]> {\n if (files.length === 0) {\n const root = findWorkspaceRoot(cwd);\n return discoverAllSidecars(root ?? cwd);\n }\n\n const resolved: string[] = [];\n for (const f of files) {\n const abs = path.resolve(cwd, f);\n if (isSidecarPath(abs)) {\n resolved.push(abs);\n } else {\n // Treat as a document path \u2192 discover its sidecar\n const sidecar = await discoverSidecar(abs, { cwd });\n resolved.push(sidecar);\n }\n }\n return resolved;\n}\n", "/**\n * MRSF Writer \u2014 serialize MrsfDocument back to YAML or JSON.\n *\n * Uses CST-level (Concrete Syntax Tree) round-trip editing via the `yaml`\n * library so that unchanged content is byte-identical to the original file.\n * - Preserves YAML comments (#)\n * - Preserves scalar styles (>, |, quotes)\n * - Preserves key ordering and whitespace\n * - Only modifies values that actually changed\n *\n * Auto-computes selected_text_hash when selected_text changes.\n */\n\nimport { readFile, writeFile, rename, unlink } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport path from \"node:path\";\nimport { Document, Parser, CST, parse as yamlParse } from \"yaml\";\nimport type { MrsfDocument, Comment } from \"./types.js\";\n\n/* ------------------------------------------------------------------ */\n/* Per-file write serialization */\n/* ------------------------------------------------------------------ */\n\n/**\n * Map of absolute file paths to pending write promises.\n * Ensures that concurrent writes to the same sidecar file are serialized\n * (queued), preventing race conditions during the read-modify-write cycle.\n */\nconst writeQueue = new Map<string, Promise<void>>();\n\n/**\n * Enqueue a write operation for the given file path, ensuring only one\n * write executes at a time per file.\n */\nfunction enqueueWrite(abs: string, fn: () => Promise<void>): Promise<void> {\n const prev = writeQueue.get(abs) ?? Promise.resolve();\n const next = prev.then(fn, fn); // run fn even if previous write failed\n writeQueue.set(abs, next);\n // Clean up map entry when the queue drains\n next.then(() => {\n if (writeQueue.get(abs) === next) writeQueue.delete(abs);\n }, () => {\n if (writeQueue.get(abs) === next) writeQueue.delete(abs);\n });\n return next;\n}\n\n/* ------------------------------------------------------------------ */\n/* Atomic file write */\n/* ------------------------------------------------------------------ */\n\n/**\n * Atomically write content to a file by writing to a temporary file in\n * the same directory, then renaming. On POSIX this is atomic; on\n * Windows it replaces the target.\n */\nasync function atomicWriteFile(\n filePath: string,\n content: string,\n): Promise<void> {\n const tmp = filePath + \".\" + randomBytes(6).toString(\"hex\") + \".tmp\";\n try {\n await writeFile(tmp, content, \"utf-8\");\n await rename(tmp, filePath);\n } catch (err) {\n // Clean up temp file on failure\n try { await unlink(tmp); } catch { /* ignore */ }\n throw err;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Hash helpers */\n/* ------------------------------------------------------------------ */\n\n/**\n * Compute SHA-256 hex hash of a string (UTF-8).\n */\nexport function computeHash(text: string): string {\n return createHash(\"sha256\").update(text, \"utf-8\").digest(\"hex\");\n}\n\n/**\n * Ensure selected_text_hash is consistent for a comment.\n * If selected_text is present, computes/updates the hash.\n * If selected_text is absent, removes the hash.\n */\nexport function syncHash(comment: Comment): Comment {\n if (comment.selected_text != null && comment.selected_text.length > 0) {\n comment.selected_text_hash = computeHash(comment.selected_text);\n } else {\n delete comment.selected_text_hash;\n }\n return comment;\n}\n\n/* ------------------------------------------------------------------ */\n/* CST round-trip helpers */\n/* ------------------------------------------------------------------ */\n\n/** Any CST token \u2014 the `yaml` library doesn't export fine-grained types. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype CstNode = any;\n\n/**\n * Known comment field keys in preferred output order (for new comments).\n */\nconst COMMENT_KEY_ORDER = [\n \"id\", \"author\", \"timestamp\", \"text\", \"type\", \"severity\",\n \"resolved\", \"reply_to\", \"line\", \"end_line\", \"start_column\", \"end_column\",\n \"selected_text\", \"selected_text_hash\", \"anchored_text\", \"commit\",\n];\n\n/* \u00B7\u00B7 value serialisation \u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 */\n\n/**\n * Convert a JS value to its YAML source text representation.\n * Strings that require quoting get double-quoted; numbers and booleans\n * are plain scalars.\n *\n * Uses an allowlist approach: only strings that consist entirely of\n * \"safe\" characters are emitted as bare scalars. Everything else is\n * double-quoted via JSON.stringify, which is always valid YAML.\n */\nfunction valueToSource(v: unknown): string {\n if (v instanceof Date) return JSON.stringify(v.toISOString());\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n if (typeof v === \"string\") {\n // Empty string must be quoted\n if (v === \"\") return JSON.stringify(v);\n\n // YAML reserved words / null aliases must be quoted\n if (\n v === \"true\" || v === \"false\" || v === \"null\" ||\n v === \"True\" || v === \"False\" || v === \"Null\" ||\n v === \"TRUE\" || v === \"FALSE\" || v === \"NULL\" ||\n v === \"yes\" || v === \"no\" || v === \"on\" || v === \"off\" ||\n v === \"Yes\" || v === \"No\" || v === \"On\" || v === \"Off\" ||\n v === \"YES\" || v === \"NO\" || v === \"ON\" || v === \"OFF\" ||\n v === \"~\" || v === \".inf\" || v === \"-.inf\" || v === \".nan\"\n ) {\n return JSON.stringify(v);\n }\n\n // Strings starting with digits (could be parsed as number) must be quoted\n if (/^\\d/.test(v)) return JSON.stringify(v);\n\n // Allowlist: safe plain scalars consist of word chars, hyphens (not\n // leading), dots, slashes, spaces (not leading/trailing), parentheses,\n // and @ \u2014 but NO YAML indicators or ambiguous sequences.\n // A safe string:\n // \u2022 starts with a letter, underscore\n // \u2022 contains only [A-Za-z0-9 _./()@+-] (note: hyphen mid-string is OK)\n // \u2022 does NOT contain \" #\" (inline comment)\n // \u2022 does NOT start with \"- \" or end with \":\"\n // \u2022 has no leading/trailing whitespace\n // \u2022 contains no newlines or tabs\n if (/^[A-Za-z_][A-Za-z0-9 _./()\\-@+]*$/.test(v) && !v.includes(\" #\") && !/\\s$/.test(v)) {\n return v;\n }\n\n // Everything else: double-quote (JSON.stringify handles escaping)\n return JSON.stringify(v);\n }\n return String(v);\n}\n\n/** Return the CST scalar type for a value. */\nfunction valueType(v: unknown): string {\n return valueToSource(v).startsWith('\"') ? \"double-quoted-scalar\" : \"scalar\";\n}\n\nfunction isStructuredValue(value: unknown): boolean {\n if (value == null) return false;\n if (Array.isArray(value)) return true;\n return typeof value === \"object\" && !(value instanceof Date);\n}\n\nfunction hasStructuredCommentExtensions(doc: MrsfDocument): boolean {\n return doc.comments.some((comment) =>\n Object.entries(comment).some(([key, value]) =>\n !COMMENT_KEY_ORDER.includes(key) && value !== undefined && isStructuredValue(value),\n ),\n );\n}\n\n/* \u00B7\u00B7 CST node construction \u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 */\n\nconst NL = \"\\n\";\n\n/**\n * Build a CST map-item (key: value\\n) suitable for insertion into a\n * block-map's `items` array.\n *\n * @param isFirst If true, omit leading indent (first item in a block-map\n * inherits indent from the parent seq-item-ind).\n */\nfunction makeCstMapItem(\n key: string,\n value: unknown,\n indent: number,\n isFirst: boolean,\n): CstNode {\n const start = isFirst\n ? []\n : [{ type: \"space\", offset: 0, indent: 0, source: \" \".repeat(indent) }];\n return {\n start,\n key: { type: \"scalar\", offset: 0, indent, source: key },\n sep: [\n { type: \"map-value-ind\", offset: 0, indent, source: \":\" },\n { type: \"space\", offset: 0, indent, source: \" \" },\n ],\n value: {\n type: valueType(value),\n offset: 0,\n indent,\n source: valueToSource(value),\n end: [{ type: \"newline\", offset: 0, indent, source: NL }],\n },\n };\n}\n\n/**\n * Build a complete CST seq-item for a brand-new Comment (block-map inside\n * a block-seq).\n */\nfunction makeCstSeqItem(comment: Comment, seqIndent: number): CstNode {\n const mapIndent = seqIndent + 2;\n const items: CstNode[] = [];\n\n // Preferred key order first\n for (const key of COMMENT_KEY_ORDER) {\n const val = (comment as Record<string, unknown>)[key];\n if (val !== undefined) {\n items.push(makeCstMapItem(key, val, mapIndent, items.length === 0));\n }\n }\n // Extension / extra fields\n for (const key of Object.keys(comment)) {\n if (\n !COMMENT_KEY_ORDER.includes(key) &&\n (comment as Record<string, unknown>)[key] !== undefined\n ) {\n items.push(\n makeCstMapItem(\n key,\n (comment as Record<string, unknown>)[key],\n mapIndent,\n items.length === 0,\n ),\n );\n }\n }\n\n return {\n start: [\n { type: \"newline\", offset: 0, indent: 0, source: NL },\n { type: \"space\", offset: 0, indent: 0, source: \" \".repeat(seqIndent) },\n { type: \"seq-item-ind\", offset: 0, indent: seqIndent, source: \"-\" },\n { type: \"space\", offset: 0, indent: seqIndent, source: \" \" },\n ],\n value: { type: \"block-map\", offset: 0, indent: mapIndent, items },\n };\n}\n\n/* \u00B7\u00B7 CST navigation \u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 */\n\n/** Find the document token in a CST token stream. */\nfunction findCstDocument(tokens: CstNode[]): CstNode | null {\n return tokens.find((t: CstNode) => t.type === \"document\") ?? null;\n}\n\n/** Find an item in a block-map by key source text. */\nfunction findCstMapEntry(\n blockMap: CstNode,\n keyName: string,\n): CstNode | null {\n return (\n blockMap.items?.find(\n (item: CstNode) => item.key?.source === keyName,\n ) ?? null\n );\n}\n\n/** Get the index of a map entry by key source text (\u22121 if missing). */\nfunction findCstMapIndex(blockMap: CstNode, keyName: string): number {\n return (\n blockMap.items?.findIndex(\n (item: CstNode) => item.key?.source === keyName,\n ) ?? -1\n );\n}\n\n/** Read the plain-text id from a CST block-map (comment). */\nfunction cstCommentId(blockMap: CstNode): string | null {\n const entry = findCstMapEntry(blockMap, \"id\");\n if (!entry?.value?.source) return null;\n const src: string = entry.value.source;\n // Strip quotes if present\n if (src.startsWith('\"') && src.endsWith('\"')) {\n return src.slice(1, -1);\n }\n return src;\n}\n\n/* \u00B7\u00B7 CST mutation \u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 */\n\n/**\n * Update an existing scalar CST value's source text.\n * Returns true if the source was actually changed.\n */\nfunction updateCstScalar(entry: CstNode, newValue: unknown): boolean {\n const newSrc = valueToSource(newValue);\n if (entry.value?.source === newSrc) return false;\n entry.value.source = newSrc;\n // If type changed (e.g. plain \u2192 quoted), update it too\n entry.value.type = valueType(newValue);\n return true;\n}\n\n/**\n * Synchronize a plain Comment object into a CST block-map, preserving\n * untouched scalars byte-for-byte.\n *\n * @param blockMap CST block-map node for the comment\n * @param comment New model values to write\n * @param currentValues Already-parsed values from the existing YAML\n * (used to detect real changes vs source-format\n * differences like quoted vs folded scalars)\n */\nfunction syncCommentToCst(\n blockMap: CstNode,\n comment: Comment,\n currentValues: Record<string, unknown>,\n): void {\n const commentRec = comment as Record<string, unknown>;\n\n // Collect existing key names\n const existingKeys = new Set<string>();\n for (const item of blockMap.items ?? []) {\n if (item.key?.source) existingKeys.add(item.key.source as string);\n }\n\n const allKeys = new Set([...existingKeys, ...Object.keys(comment)]);\n const indent = blockMap.indent ?? 4;\n\n for (const key of allKeys) {\n const newVal = commentRec[key];\n\n if (newVal === undefined) {\n // Removed from model \u2192 delete from CST\n if (existingKeys.has(key)) {\n const idx = findCstMapIndex(blockMap, key);\n if (idx >= 0) blockMap.items.splice(idx, 1);\n }\n continue;\n }\n\n const entry = findCstMapEntry(blockMap, key);\n if (entry) {\n // Existing key \u2014 compare PARSED values (not source text) to detect\n // real semantic changes. This avoids touching block scalars, quoted\n // strings, etc. whose source representation differs but whose parsed\n // value is identical.\n const currentVal = currentValues[key];\n if (deepEqual(currentVal, newVal)) {\n // Value unchanged \u2014 leave the CST node byte-for-byte\n continue;\n }\n // Value really changed \u2014 update source\n updateCstScalar(entry, newVal);\n } else {\n // New key \u2014 insert at end\n blockMap.items.push(makeCstMapItem(key, newVal, indent, false));\n }\n }\n}\n\n/**\n * Simple deep-equal for scalars and basic types (sufficient for MRSF\n * Comment field values which are strings, numbers, and booleans).\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== typeof b) return false;\n // Handle number comparison with potential string/number mismatch from YAML\n if (typeof a === \"number\" && typeof b === \"number\") return a === b;\n return false;\n}\n\n/* ------------------------------------------------------------------ */\n/* Public API */\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\n/**\n * Write an MrsfDocument to disk.\n *\n * When a YAML file already exists on disk, performs a **CST-level** round-trip\n * merge that preserves YAML comments, scalar styles, key ordering, and\n * whitespace byte-for-byte for unchanged content.\n *\n * For new files or JSON, writes from scratch.\n *\n * Writes to the same file path are serialized (queued) to prevent race\n * conditions from concurrent calls. All writes are atomic (temp + rename).\n */\nexport async function writeSidecar(\n filePath: string,\n doc: MrsfDocument,\n): Promise<void> {\n const abs = path.resolve(filePath);\n return enqueueWrite(abs, () => writeSidecarInternal(abs, doc));\n}\n\n/**\n * Internal implementation of writeSidecar (runs inside the per-file queue).\n */\nasync function writeSidecarInternal(\n abs: string,\n doc: MrsfDocument,\n): Promise<void> {\n const isJson = abs.endsWith(\".review.json\");\n\n for (const comment of doc.comments) syncHash(comment);\n\n if (isJson) {\n // For JSON, always write fresh\n await atomicWriteFile(abs, toJson(doc));\n return;\n }\n\n // The CST patcher only supports scalar map values. Fall back to full YAML\n // serialisation when comment extensions include arrays or objects.\n if (hasStructuredCommentExtensions(doc)) {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n // \u2500\u2500 YAML round-trip path \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (!existsSync(abs)) {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n let raw: string;\n try {\n raw = await readFile(abs, \"utf-8\");\n } catch {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n // Parse to CST tokens\n let tokens: CstNode[];\n try {\n tokens = [...new Parser().parse(raw)];\n } catch {\n // Unparseable \u2014 write fresh\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n // Also parse to plain JS object for value comparison (so we compare\n // parsed values, not source-text representations)\n let currentDoc: MrsfDocument | null = null;\n try {\n currentDoc = yamlParse(raw) as MrsfDocument;\n } catch {\n // ignore \u2014 we'll fall through to source-level comparison\n }\n\n // \u2500\u2500 Structural validation of parsed YAML \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // If CST parsed OK but the content isn't a valid MrsfDocument shape\n // (e.g. comments is not an array due to injection), discard and write fresh.\n if (currentDoc && (!Array.isArray(currentDoc.comments))) {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n // Build lookup of current parsed values by comment id\n const currentById = new Map<string, Record<string, unknown>>();\n if (currentDoc?.comments) {\n for (const c of currentDoc.comments) {\n if (c.id) currentById.set(c.id, c as Record<string, unknown>);\n }\n }\n\n // Sync hashes: for existing comments, only add selected_text_hash\n // if selected_text actually changed or hash was already present.\n // For new comments, always sync.\n for (const comment of doc.comments) {\n const cur = currentById.get(comment.id);\n if (!cur) {\n // New comment \u2014 always sync hash\n syncHash(comment);\n } else {\n // Existing comment \u2014 only sync hash if text changed or hash\n // was already tracked in the original\n const textChanged = !deepEqual(cur.selected_text, comment.selected_text);\n const hadHash = cur.selected_text_hash !== undefined;\n if (textChanged || hadHash) {\n syncHash(comment);\n } else {\n // Don't inject a hash that wasn't there before\n delete comment.selected_text_hash;\n }\n }\n }\n\n const docToken = findCstDocument(tokens);\n if (!docToken?.value || docToken.value.type !== \"block-map\") {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n const body: CstNode = docToken.value;\n\n // \u2500\u2500 Update top-level scalars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const versionEntry = findCstMapEntry(body, \"mrsf_version\");\n if (versionEntry && !deepEqual(currentDoc?.mrsf_version, doc.mrsf_version)) {\n updateCstScalar(versionEntry, doc.mrsf_version);\n }\n\n const documentEntry = findCstMapEntry(body, \"document\");\n if (documentEntry && !deepEqual(currentDoc?.document, doc.document)) {\n updateCstScalar(documentEntry, doc.document);\n }\n\n // \u2500\u2500 Merge comments \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const commentsEntry = findCstMapEntry(body, \"comments\");\n if (!commentsEntry?.value || commentsEntry.value.type !== \"block-seq\") {\n // No existing comments seq \u2014 write fresh\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n const seq: CstNode = commentsEntry.value;\n const seqIndent: number = seq.indent ?? 2;\n\n // Index existing CST comments by id\n const existingById = new Map<string, { index: number; map: CstNode }>();\n for (let i = 0; i < seq.items.length; i++) {\n const item = seq.items[i];\n const map = item.value;\n if (map?.type === \"block-map\") {\n const id = cstCommentId(map);\n if (id) existingById.set(id, { index: i, map });\n }\n }\n\n // Build new seq items list, preserving existing CST nodes (and their\n // YAML comments / formatting) for comments that still exist.\n const idsInDoc = new Set(doc.comments.map((c) => c.id));\n const newSeqItems: CstNode[] = [];\n\n for (const comment of doc.comments) {\n const existing = existingById.get(comment.id);\n if (existing) {\n // Round-trip: sync changes into the existing CST block-map\n const currentValues = currentById.get(comment.id) ?? {};\n syncCommentToCst(existing.map, comment, currentValues);\n // Re-use the original seq item (preserves preceding YAML comments\n // in the item's `start` tokens)\n newSeqItems.push(seq.items[existing.index]);\n } else {\n // Brand new comment \u2014 construct CST from scratch\n newSeqItems.push(makeCstSeqItem(comment, seqIndent));\n }\n }\n\n seq.items = newSeqItems;\n\n // \u2500\u2500 Fix first-item indentation after reorder / removal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // In the YAML CST, the `comments:` map-entry's `sep` array often\n // contains trailing whitespace (space tokens) that provide the indent\n // *before* the first seq-item indicator (`-`). Non-first seq items\n // carry their own leading space tokens in `start`.\n //\n // When the original first item is removed and a formerly non-first\n // item becomes the new first, those extra space tokens stack with\n // the sep whitespace, doubling the indent. We fix this by stripping\n // any leading space tokens (before the `seq-item-ind`) from the new\n // first item's start \u2014 the sep already provides that whitespace.\n //\n // We also ensure the previous item's value ends with a newline so\n // subsequent items render on their own line.\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (newSeqItems.length > 0) {\n const originalFirstIdx = seq.items === newSeqItems ? 0 : -1; // always true after assignment\n const origFirstItem = existingById.size > 0\n ? [...existingById.values()].find((e) => e.index === 0)\n : undefined;\n\n const newFirst = newSeqItems[0];\n\n // Check if the new first item is NOT the original first item\n const isOriginalFirst =\n origFirstItem &&\n seq.items[0]?.value === origFirstItem.map;\n\n if (!isOriginalFirst && newFirst.start) {\n // Strip leading space tokens before the seq-item-ind\n const dashIdx = newFirst.start.findIndex(\n (t: CstNode) => t.type === \"seq-item-ind\",\n );\n if (dashIdx > 0) {\n // Remove all tokens before the dash that are space/newline\n const toRemove = newFirst.start\n .slice(0, dashIdx)\n .every((t: CstNode) => t.type === \"space\" || t.type === \"newline\");\n if (toRemove) {\n newFirst.start.splice(0, dashIdx);\n }\n }\n }\n }\n // \u2500\u2500 Stringify via CST (byte-identical for untouched content) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const result = tokens.map((t: CstNode) => CST.stringify(t)).join(\"\");\n await atomicWriteFile(abs, result);\n}\n", "/**\n * MRSF Validator \u2014 JSON Schema + cross-field validation per \u00A710.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { computeHash } from \"./writer.js\";\nimport { validateCrossFields, validateSchema } from \"./validate-core.js\";\nimport type {\n MrsfDocument,\n ValidationResult,\n ValidationDiagnostic,\n ValidateOptions,\n} from \"./types.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nlet _schemaCache: object | null = null;\n\nasync function loadSchema(): Promise<object> {\n if (_schemaCache) return _schemaCache;\n\n // The schema lives at the repo root, two levels up from dist/lib/\n // When installed as a package, it's at the package root (cli/)\n const candidates = [\n path.resolve(__dirname, \"mrsf.schema.json\"), // same dir (esbuild bundle, e.g. MCP server)\n path.resolve(__dirname, \"../../mrsf.schema.json\"), // from dist/lib/ \u2192 cli/ (installed package)\n path.resolve(__dirname, \"../../../mrsf.schema.json\"), // from dist/lib/ \u2192 repo root (dev)\n path.resolve(__dirname, \"../../../../mrsf.schema.json\"), // fallback\n path.resolve(process.cwd(), \"mrsf.schema.json\"), // cwd fallback\n ];\n\n for (const candidate of candidates) {\n try {\n const raw = await readFile(candidate, \"utf-8\");\n _schemaCache = JSON.parse(raw);\n return _schemaCache!;\n } catch {\n // try next\n }\n }\n\n throw new Error(\"Could not locate mrsf.schema.json\");\n}\n\n/**\n * Validate an MRSF document (parsed object).\n */\nexport async function validate(\n doc: MrsfDocument,\n options: ValidateOptions = {},\n): Promise<ValidationResult> {\n const errors: ValidationDiagnostic[] = [];\n const warnings: ValidationDiagnostic[] = [];\n\n // \u2500\u2500 JSON Schema validation \u2500\u2500\n const rawSchema = await loadSchema();\n validateSchema(doc, rawSchema, errors);\n\n // \u2500\u2500 Cross-field validation (\u00A710) \u2500\u2500\n validateCrossFields(doc, errors, warnings, computeHash);\n\n const valid = errors.length === 0 && (!options.strict || warnings.length === 0);\n\n return { valid, errors, warnings };\n}\n\n/**\n * Validate from a file path \u2014 convenience wrapper.\n */\nexport async function validateFile(\n filePath: string,\n options: ValidateOptions = {},\n): Promise<ValidationResult> {\n const { parseSidecar } = await import(\"./parser.js\");\n try {\n const doc = await parseSidecar(filePath);\n return validate(doc, options);\n } catch (e) {\n return {\n valid: false,\n errors: [\n {\n severity: \"error\",\n code: \"parse-error\",\n message: `Failed to parse: ${(e as Error).message}`,\n },\n ],\n warnings: [],\n };\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 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", "/**\n * MRSF Git Integration \u2014 Git-aware operations for re-anchoring and discovery.\n *\n * Uses child_process.execFile (no shell) for safety.\n * All functions degrade gracefully when Git is unavailable.\n */\n\nimport { execFile as execFileCb } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport path from \"node:path\";\nimport type { DiffHunk } from \"./types.js\";\n\nconst execFile = promisify(execFileCb);\n\nconst GIT_TIMEOUT = 10_000; // 10s\n\n// ---------------------------------------------------------------------------\n// Availability\n// ---------------------------------------------------------------------------\n\nlet _gitAvailable: boolean | null = null;\n\n/**\n * Check whether `git` is available on PATH.\n */\nexport async function isGitAvailable(): Promise<boolean> {\n if (_gitAvailable != null) return _gitAvailable;\n try {\n await execFile(\"git\", [\"--version\"], { timeout: GIT_TIMEOUT });\n _gitAvailable = true;\n } catch {\n _gitAvailable = false;\n }\n return _gitAvailable;\n}\n\n/** Reset cached availability (for testing). */\nexport function resetGitCache(): void {\n _gitAvailable = null;\n}\n\n// ---------------------------------------------------------------------------\n// Repository info\n// ---------------------------------------------------------------------------\n\n/**\n * Find the Git repository root from a given directory.\n * Returns null if not in a Git repo.\n */\nexport async function findRepoRoot(cwd?: string): Promise<string | null> {\n if (!(await isGitAvailable())) return null;\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"rev-parse\", \"--show-toplevel\"],\n { cwd: cwd ?? process.cwd(), timeout: GIT_TIMEOUT },\n );\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Get the full HEAD commit SHA.\n */\nexport async function getCurrentCommit(repoRoot: string): Promise<string | null> {\n if (!(await isGitAvailable())) return null;\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"rev-parse\", \"HEAD\"],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a commit hash is the same as HEAD.\n */\nexport async function isStale(\n commentCommit: string,\n repoRoot: string,\n): Promise<boolean> {\n const head = await getCurrentCommit(repoRoot);\n if (!head) return false; // can't tell, assume not stale\n // Normalize: compare by prefix match (short vs long SHA)\n const minLen = Math.min(commentCommit.length, head.length);\n return commentCommit.slice(0, minLen) !== head.slice(0, minLen);\n}\n\n// ---------------------------------------------------------------------------\n// Diff operations\n// ---------------------------------------------------------------------------\n\n/**\n * Parse unified diff output into structured hunks.\n */\nexport function parseDiffHunks(diffOutput: string): DiffHunk[] {\n const hunks: DiffHunk[] = [];\n const lines = diffOutput.split(\"\\n\");\n let current: DiffHunk | null = null;\n\n for (const line of lines) {\n const hunkMatch = line.match(\n /^@@\\s+-(\\d+)(?:,(\\d+))?\\s+\\+(\\d+)(?:,(\\d+))?\\s+@@/,\n );\n if (hunkMatch) {\n current = {\n oldStart: parseInt(hunkMatch[1], 10),\n oldCount: hunkMatch[2] != null ? parseInt(hunkMatch[2], 10) : 1,\n newStart: parseInt(hunkMatch[3], 10),\n newCount: hunkMatch[4] != null ? parseInt(hunkMatch[4], 10) : 1,\n lines: [],\n };\n hunks.push(current);\n continue;\n }\n if (current && (line.startsWith(\"+\") || line.startsWith(\"-\") || line.startsWith(\" \"))) {\n current.lines.push(line);\n }\n }\n\n return hunks;\n}\n\n/**\n * Get diff hunks between two commits for a specific file.\n */\nexport async function getDiff(\n fromCommit: string,\n toCommit: string,\n filePath: string,\n repoRoot: string,\n): Promise<DiffHunk[]> {\n if (!(await isGitAvailable())) return [];\n try {\n const { stdout } = await execFile(\n \"git\",\n [\n \"diff\",\n `${fromCommit}..${toCommit}`,\n \"--unified=0\",\n \"--no-color\",\n \"--\",\n filePath,\n ],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return parseDiffHunks(stdout);\n } catch {\n return [];\n }\n}\n\n/**\n * Calculate the net line shift for a given original line number\n * based on diff hunks.\n *\n * Returns the number of lines to add to the original line number,\n * or null if the line itself was modified/deleted.\n */\nexport function getLineShift(\n hunks: DiffHunk[],\n originalLine: number,\n): { shift: number; modified: boolean } {\n let cumulativeShift = 0;\n\n for (const hunk of hunks) {\n const oldEnd = hunk.oldStart + hunk.oldCount - 1;\n\n // Hunk is entirely after our line \u2014 stop\n if (hunk.oldStart > originalLine) break;\n\n // Our line falls within this hunk \u2014 it was modified\n if (originalLine >= hunk.oldStart && originalLine <= oldEnd) {\n return { shift: cumulativeShift, modified: true };\n }\n\n // Hunk is entirely before our line \u2014 accumulate shift\n if (oldEnd < originalLine) {\n cumulativeShift += hunk.newCount - hunk.oldCount;\n }\n }\n\n return { shift: cumulativeShift, modified: false };\n}\n\n// ---------------------------------------------------------------------------\n// File at commit\n// ---------------------------------------------------------------------------\n\n/**\n * Get the contents of a file at a specific commit.\n * Returns null if unavailable.\n */\nexport async function getFileAtCommit(\n commit: string,\n filePath: string,\n repoRoot: string,\n): Promise<string | null> {\n if (!(await isGitAvailable())) return null;\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"show\", `${commit}:${filePath}`],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return stdout;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Staged files\n// ---------------------------------------------------------------------------\n\n/**\n * Get list of staged files matching a pattern.\n */\nexport async function getStagedFiles(\n repoRoot: string,\n pattern?: string,\n): Promise<string[]> {\n if (!(await isGitAvailable())) return [];\n try {\n const args = [\"diff\", \"--cached\", \"--name-only\", \"--diff-filter=d\"];\n if (pattern) args.push(\"--\", pattern);\n const { stdout } = await execFile(\"git\", args, {\n cwd: repoRoot,\n timeout: GIT_TIMEOUT,\n });\n return stdout\n .trim()\n .split(\"\\n\")\n .filter((f) => f.length > 0);\n } catch {\n return [];\n }\n}\n\n/**\n * Get staged diff hunks for a specific file.\n */\nexport async function getStagedDiff(\n filePath: string,\n repoRoot: string,\n): Promise<DiffHunk[]> {\n if (!(await isGitAvailable())) return [];\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"diff\", \"--cached\", \"--unified=0\", \"--no-color\", \"--\", filePath],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return parseDiffHunks(stdout);\n } catch {\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rename detection\n// ---------------------------------------------------------------------------\n\n/**\n * Detect file renames between two commits.\n * Returns a map of old path \u2192 new path.\n */\nexport async function detectRenames(\n fromCommit: string,\n toCommit: string,\n repoRoot: string,\n): Promise<Map<string, string>> {\n if (!(await isGitAvailable())) return new Map();\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"diff\", \"--name-status\", \"-M\", `${fromCommit}..${toCommit}`],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n\n const renames = new Map<string, string>();\n for (const line of stdout.trim().split(\"\\n\")) {\n const match = line.match(/^R\\d*\\t(.+)\\t(.+)$/);\n if (match) {\n renames.set(match[1], match[2]);\n }\n }\n return renames;\n } catch {\n return new Map();\n }\n}\n\n/**\n * Stage a file for commit.\n */\nexport async function stageFile(\n filePath: string,\n repoRoot: string,\n): Promise<void> {\n if (!(await isGitAvailable())) return;\n await execFile(\"git\", [\"add\", filePath], {\n cwd: repoRoot,\n timeout: GIT_TIMEOUT,\n });\n}\n", "import type {\n AnchorPosition,\n Comment,\n DiffHunk,\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\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 } = {},\n): ReanchorResult {\n const threshold = opts.threshold ?? DEFAULT_THRESHOLD;\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 if (exactCandidates.length === 1) {\n const candidate = exactCandidates[0];\n return {\n commentId,\n status: \"anchored\",\n score: 1.0,\n newLine: candidate.line,\n newEndLine: candidate.endLine,\n newStartColumn: candidate.startColumn,\n newEndColumn: candidate.endColumn,\n reason: \"Exact text match (unique).\",\n };\n }\n\n if (exactCandidates.length > 1 && comment.line != null) {\n const best = closestToLine(exactCandidates, comment.line);\n return {\n commentId,\n status: \"anchored\",\n score: 1.0,\n newLine: best.line,\n newEndLine: best.endLine,\n newStartColumn: best.startColumn,\n newEndColumn: best.endColumn,\n reason: `Exact text match (${exactCandidates.length} occurrences; chose nearest to original line ${comment.line}).`,\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 } = {},\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 } = {},\n): ReanchorResult[] {\n return reanchorDocumentLines(doc, toReanchorLines(documentText), opts);\n}\n\nexport function resolveAnchor(\n comment: Comment,\n documentText: string,\n opts: { threshold?: 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\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}", "/**\n * MRSF Re-anchor Engine \u2014 \u00A77.4 Anchoring Resolution Procedure.\n *\n * Implements a four-step algorithm to re-locate each comment's\n * anchor within the current document revision:\n *\n * Step 0 \u2013 diff-based shift (git + commit available)\n * Step 1 \u2013 exact text match\n * Step 1.5\u2013 fuzzy match \u2265 high threshold (0.8)\n * Step 2 \u2013 line/column fallback (commit-aware staleness)\n * Step 3 \u2013 lower-threshold fuzzy \u2265 configured threshold (0.6)\n * Step 4 \u2013 orphan\n */\n\nimport type {\n MrsfDocument,\n ReanchorOptions,\n ReanchorResult,\n DiffHunk,\n} from \"./types.js\";\nimport {\n findRepoRoot,\n getCurrentCommit,\n getDiff,\n getFileAtCommit,\n getLineShift,\n isGitAvailable,\n parseDiffHunks,\n} from \"./git.js\";\nimport {\n applyReanchorResults,\n DEFAULT_THRESHOLD,\n reanchorComment,\n reanchorDocumentLines,\n} from \"./reanchor-core.js\";\nimport { readDocumentLines } from \"./parser.js\";\nimport { discoverSidecar, sidecarToDocument } from \"./discovery.js\";\nimport { parseSidecar } from \"./parser.js\";\nimport { writeSidecar } from \"./writer.js\";\nimport path from \"node:path\";\n\nexport {\n applyReanchorResults,\n DEFAULT_THRESHOLD,\n HIGH_THRESHOLD,\n reanchorComment,\n reanchorDocumentLines,\n reanchorDocumentText,\n resolveAnchor,\n toReanchorLines,\n} from \"./reanchor-core.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Batch re-anchoring\n// ---------------------------------------------------------------------------\n\n/**\n * Re-anchor all comments in an MRSF document.\n */\nexport async function reanchorDocument(\n doc: MrsfDocument,\n documentLines: string[],\n opts: ReanchorOptions & {\n documentPath?: string;\n repoRoot?: string;\n } = {},\n): Promise<ReanchorResult[]> {\n const results: ReanchorResult[] = [];\n const threshold = opts.threshold ?? DEFAULT_THRESHOLD;\n\n // Determine git context\n let diffHunks: DiffHunk[] | undefined;\n let commitIsStale = false;\n\n if (!opts.noGit && (await isGitAvailable())) {\n const repoRoot = opts.repoRoot ?? (await findRepoRoot(opts.cwd));\n if (repoRoot && opts.documentPath) {\n const relPath = path.relative(repoRoot, opts.documentPath);\n const head = await getCurrentCommit(repoRoot);\n\n // Use a shared fromCommit for all comments, or per-comment\n const globalFrom = opts.fromCommit;\n\n for (const comment of doc.comments) {\n const commentCommit = globalFrom ?? comment.commit;\n if (commentCommit && head && commentCommit !== head) {\n commitIsStale = true;\n // Get diff for this commit range\n const hunks = await getDiff(commentCommit, head, relPath, repoRoot);\n const result = reanchorComment(comment, documentLines, {\n diffHunks: hunks,\n threshold,\n commitIsStale: true,\n });\n results.push(result);\n continue;\n }\n\n // non-stale or no commit\n results.push(\n reanchorComment(comment, documentLines, { threshold, commitIsStale: false }),\n );\n }\n\n return results;\n }\n }\n\n return reanchorDocumentLines(doc, documentLines, { threshold });\n}\n\n/**\n * High-level re-anchor for a single sidecar file path.\n */\nexport async function reanchorFile(\n sidecarPath: string,\n opts: ReanchorOptions = {},\n): Promise<{\n results: ReanchorResult[];\n changed: number;\n written: boolean;\n}> {\n const doc = await parseSidecar(sidecarPath);\n const docPath = sidecarToDocument(sidecarPath);\n const documentLines = await readDocumentLines(docPath);\n\n const repoRoot = !opts.noGit ? await findRepoRoot(opts.cwd) : null;\n const headCommit = repoRoot ? await getCurrentCommit(repoRoot) : undefined;\n\n const results = await reanchorDocument(doc, documentLines, {\n ...opts,\n documentPath: docPath,\n repoRoot: repoRoot ?? undefined,\n });\n\n let changed = 0;\n let written = false;\n\n if (!opts.dryRun) {\n changed = applyReanchorResults(doc, results, {\n updateText: opts.updateText,\n force: opts.force,\n headCommit: headCommit ?? undefined,\n });\n if (changed > 0 || opts.autoUpdate) {\n await writeSidecar(sidecarPath, doc);\n written = true;\n }\n }\n\n return { results, changed, written };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\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", "/**\n * MRSF Comment Operations \u2014 CRUD for sidecar comments.\n */\n\nimport type {\n AddCommentOptions,\n Comment,\n CommentFilter,\n CommentExtensions,\n CommentExtensionValue,\n EditCommentOptions,\n MrsfDocument,\n} from \"./types.js\";\nimport { newCommentId } from \"./identity.js\";\nimport { computeHash } from \"./writer.js\";\nimport { getCurrentCommit, findRepoRoot, isGitAvailable } from \"./git.js\";\n\n// ---------------------------------------------------------------------------\n// Add\n// ---------------------------------------------------------------------------\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction isCommentExtensionValue(value: unknown): value is CommentExtensionValue {\n if (value == null) return true;\n\n switch (typeof value) {\n case \"boolean\":\n case \"string\":\n return true;\n case \"number\":\n return Number.isFinite(value);\n case \"object\": {\n if (Array.isArray(value)) {\n return value.every((item) => isCommentExtensionValue(item));\n }\n\n if (!isPlainObject(value)) {\n return false;\n }\n\n return Object.values(value).every((item) => isCommentExtensionValue(item));\n }\n default:\n return false;\n }\n}\n\nexport function normalizeCommentExtensions(\n extensions?: Record<string, unknown>,\n): CommentExtensions {\n if (!extensions) return {} as CommentExtensions;\n\n const normalizedEntries: Array<[`x_${string}`, CommentExtensionValue]> = [];\n\n for (const [key, value] of Object.entries(extensions)) {\n if (!key.startsWith(\"x_\")) {\n throw new Error(`Comment extension key '${key}' must start with 'x_'.`);\n }\n\n if (!isCommentExtensionValue(value)) {\n throw new Error(\n `Comment extension '${key}' must be JSON-serializable (null, boolean, finite number, string, array, or plain object).`,\n );\n }\n\n normalizedEntries.push([key as `x_${string}`, value]);\n }\n\n return Object.fromEntries(normalizedEntries) as CommentExtensions;\n}\n\n/**\n * Add a new comment to a document. Mutates doc.comments in place.\n * Returns the created comment.\n */\nexport async function addComment(\n doc: MrsfDocument,\n opts: AddCommentOptions,\n repoRoot?: string,\n): Promise<Comment> {\n const id = opts.id ?? newCommentId();\n const timestamp = opts.timestamp ?? new Date().toISOString();\n\n // Auto-detect commit from HEAD when git is available\n let commit = opts.commit;\n if (!commit && repoRoot && (await isGitAvailable())) {\n commit = (await getCurrentCommit(repoRoot)) ?? undefined;\n }\n\n const comment: Comment = {\n id,\n author: opts.author,\n timestamp,\n text: opts.text,\n resolved: false,\n };\n\n // Optional anchoring fields\n if (opts.line != null) comment.line = opts.line;\n if (opts.end_line != null) comment.end_line = opts.end_line;\n if (opts.start_column != null) comment.start_column = opts.start_column;\n if (opts.end_column != null) comment.end_column = opts.end_column;\n if (opts.type) comment.type = opts.type;\n if (opts.severity) comment.severity = opts.severity;\n if (opts.reply_to) comment.reply_to = opts.reply_to;\n if (commit) comment.commit = commit;\n\n Object.assign(comment, normalizeCommentExtensions(opts.extensions));\n\n doc.comments.push(comment);\n return comment;\n}\n\n/**\n * Populate selected_text from document lines (reads the file content region).\n * Should be called after addComment if the caller provides line info but not selected_text.\n */\nexport function populateSelectedText(\n comment: Comment,\n documentLines: string[],\n): void {\n if (comment.selected_text) return; // already set\n if (comment.line == null) return;\n\n const startIdx = comment.line - 1;\n const endIdx = (comment.end_line ?? comment.line) - 1;\n\n if (startIdx < 0 || endIdx >= documentLines.length) return;\n\n if (startIdx === endIdx) {\n let line = documentLines[startIdx];\n if (comment.start_column != null && comment.end_column != null) {\n line = line.slice(comment.start_column, comment.end_column);\n }\n comment.selected_text = line;\n } else {\n const lines: string[] = [];\n for (let i = startIdx; i <= endIdx; i++) {\n let l = documentLines[i];\n if (i === startIdx && comment.start_column != null) {\n l = l.slice(comment.start_column);\n }\n if (i === endIdx && comment.end_column != null) {\n l = l.slice(0, comment.end_column);\n }\n lines.push(l);\n }\n comment.selected_text = lines.join(\"\\n\");\n }\n\n // Also set the hash\n if (comment.selected_text) {\n comment.selected_text_hash = computeHash(comment.selected_text);\n }\n}\n\nexport function editComment(\n doc: MrsfDocument,\n commentId: string,\n opts: EditCommentOptions,\n): Comment {\n const comment = doc.comments.find((entry) => entry.id === commentId);\n if (!comment) {\n throw new Error(`Unknown comment '${commentId}'.`);\n }\n if (opts.actor && comment.author !== opts.actor) {\n throw new Error(\"Only the comment author can edit this comment.\");\n }\n if (opts.text.trim().length === 0) {\n throw new Error(\"Comment text cannot be empty.\");\n }\n\n comment.text = opts.text;\n return comment;\n}\n\n// ---------------------------------------------------------------------------\n// Resolve / Unresolve\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a comment by id. Per \u00A79, resolving a parent does NOT\n * automatically resolve its replies.\n *\n * Returns true if the comment was found and updated.\n */\nexport function resolveComment(\n doc: MrsfDocument,\n commentId: string,\n cascade = false,\n): boolean {\n const comment = doc.comments.find((c) => c.id === commentId);\n if (!comment) return false;\n\n comment.resolved = true;\n\n if (cascade) {\n // Cascade to direct replies only\n for (const c of doc.comments) {\n if (c.reply_to === commentId) {\n c.resolved = true;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Unresolve a comment by id.\n */\nexport function unresolveComment(\n doc: MrsfDocument,\n commentId: string,\n): boolean {\n const comment = doc.comments.find((c) => c.id === commentId);\n if (!comment) return false;\n comment.resolved = false;\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Remove\n// ---------------------------------------------------------------------------\n\n/** Anchor fields that a reply may inherit from its parent on deletion. */\nconst ANCHOR_FIELDS = [\n \"line\",\n \"end_line\",\n \"start_column\",\n \"end_column\",\n \"selected_text\",\n \"selected_text_hash\",\n \"anchored_text\",\n \"commit\",\n] as const;\n\nexport interface RemoveCommentOptions {\n /**\n * When true, also delete all direct replies instead of promoting them.\n * Default: false (promote replies per \u00A79.1).\n */\n cascade?: boolean;\n}\n\n/**\n * Remove a comment by id. Per \u00A79.1, direct replies are promoted:\n * their anchor fields are inherited from the parent (when absent),\n * and their `reply_to` is re-pointed to the parent's parent (or cleared).\n *\n * If `cascade` is true, direct replies are removed along with the parent.\n *\n * Returns true if the comment was found and removed.\n */\nexport function removeComment(\n doc: MrsfDocument,\n commentId: string,\n opts?: RemoveCommentOptions,\n): boolean {\n const comment = doc.comments.find((c) => c.id === commentId);\n if (!comment) return false;\n\n if (opts?.cascade) {\n // Remove direct replies first\n doc.comments = doc.comments.filter(\n (c) => c.id === commentId || c.reply_to !== commentId,\n );\n } else {\n // Promote direct replies (\u00A79.1)\n for (const c of doc.comments) {\n if (c.reply_to !== commentId) continue;\n\n // Copy missing anchor fields from the parent\n for (const field of ANCHOR_FIELDS) {\n if (c[field] == null && comment[field] != null) {\n (c as Record<string, unknown>)[field] = comment[field];\n }\n }\n\n // Re-point reply_to to grandparent (or clear if parent was root)\n if (comment.reply_to) {\n c.reply_to = comment.reply_to;\n } else {\n delete c.reply_to;\n }\n }\n }\n\n // Remove the parent comment itself\n const idx = doc.comments.findIndex((c) => c.id === commentId);\n if (idx !== -1) doc.comments.splice(idx, 1);\n\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// List / Filter\n// ---------------------------------------------------------------------------\n\n/**\n * Filter comments based on criteria.\n */\nexport function filterComments(\n comments: Comment[],\n filter: CommentFilter,\n): Comment[] {\n return comments.filter((c) => {\n if (filter.open === true && c.resolved) return false;\n if (filter.resolved === true && !c.resolved) return false;\n if (filter.author && c.author !== filter.author) return false;\n if (filter.type && c.type !== filter.type) return false;\n if (filter.severity && c.severity !== filter.severity) return false;\n if (filter.orphaned === true && c.x_reanchor_status !== \"orphaned\") return false;\n if (filter.orphaned === false && c.x_reanchor_status === \"orphaned\") return false;\n return true;\n });\n}\n\n/**\n * Get a list of threads \u2014 groups of comments by their root ID via reply_to.\n * Returns a map of root comment ID \u2192 [root, ...replies in order].\n */\nexport function getThreads(\n comments: Comment[],\n): Map<string, Comment[]> {\n const threads = new Map<string, Comment[]>();\n const replyMap = new Map<string, string>(); // child id \u2192 root id\n\n // First pass: find all roots and build reply chains\n for (const c of comments) {\n if (!c.reply_to) {\n threads.set(c.id, [c]);\n } else {\n replyMap.set(c.id, c.reply_to);\n }\n }\n\n // Resolve transitive reply_to chains to roots\n function findRoot(id: string): string {\n const parent = replyMap.get(id);\n if (!parent) return id;\n return findRoot(parent);\n }\n\n // Second pass: attach replies to their root thread\n for (const c of comments) {\n if (c.reply_to) {\n const rootId = findRoot(c.id);\n if (!threads.has(rootId)) {\n threads.set(rootId, []);\n }\n threads.get(rootId)!.push(c);\n }\n }\n\n return threads;\n}\n\n// ---------------------------------------------------------------------------\n// Summary\n// ---------------------------------------------------------------------------\n\nexport interface CommentSummary {\n total: number;\n open: number;\n resolved: number;\n orphaned: number;\n threads: number;\n byType: Record<string, number>;\n bySeverity: Record<string, number>;\n}\n\n/**\n * Generate summary statistics for a comment list.\n */\nexport function summarize(comments: Comment[]): CommentSummary {\n const summary: CommentSummary = {\n total: comments.length,\n open: 0,\n resolved: 0,\n orphaned: 0,\n threads: 0,\n byType: {},\n bySeverity: {},\n };\n\n const roots = new Set<string>();\n\n for (const c of comments) {\n if (c.resolved) summary.resolved++;\n else summary.open++;\n\n if (c.x_reanchor_status === \"orphaned\") summary.orphaned++;\n\n if (c.type) {\n summary.byType[c.type] = (summary.byType[c.type] ?? 0) + 1;\n }\n if (c.severity) {\n summary.bySeverity[c.severity] = (summary.bySeverity[c.severity] ?? 0) + 1;\n }\n\n if (!c.reply_to) roots.add(c.id);\n }\n\n summary.threads = roots.size;\n return summary;\n}\n"],
5
- "mappings": "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",
6
- "names": ["path", "yaml", "import_promises", "import_node_path", "import_js_yaml", "DEFAULT_THRESHOLD", "HIGH_THRESHOLD", "addComment", "applyReanchorResults", "combinedScore", "computeHash", "detectRenames", "discoverAllSidecars", "discoverSidecar", "editComment", "exactMatch", "filterComments", "findRepoRoot", "findWorkspaceRoot", "formatAuthor", "fuzzySearch", "getCurrentCommit", "getDiff", "getFileAtCommit", "getLineShift", "getStagedFiles", "getThreads", "isGitAvailable", "isStale", "loadConfig", "newCommentId", "normalizeCommentExtensions", "normalizedMatch", "parseAuthor", "parseDiffHunks", "parseSidecar", "parseSidecarContent", "parseSidecarContentLenient", "parseSidecarLenient", "populateSelectedText", "readDocumentLines", "reanchorComment", "reanchorDocument", "reanchorDocumentLines", "reanchorDocumentText", "reanchorFile", "removeComment", "resolveAnchor", "resolveComment", "resolveSidecarPaths", "sidecarToDocument", "summarize", "syncHash", "toJson", "toReanchorLines", "toYaml", "unresolveComment", "validate", "validateDocument", "validateFile", "writeSidecar", "path", "yaml", "import_node_path", "path", "import_promises", "import_node_fs", "import_node_path", "path", "yamlParse", "import_promises", "import_node_path", "AjvModule", "addFormatsModule", "path", "parseSidecar", "levenshtein", "execFileCb", "getLineShift", "import_node_path", "path", "uuidv4", "findWorkspaceRoot", "loadConfig", "discoverSidecar", "sidecarToDocument", "discoverAllSidecars", "resolveSidecarPaths", "parseSidecar", "parseSidecarContent", "parseSidecarLenient", "parseSidecarContentLenient", "readDocumentLines", "computeHash", "syncHash", "toYaml", "toJson", "writeSidecar", "validate", "validateFile", "validateDocument", "exactMatch", "normalizedMatch", "fuzzySearch", "combinedScore", "isGitAvailable", "findRepoRoot", "getCurrentCommit", "isStale", "getDiff", "getLineShift", "getFileAtCommit", "getStagedFiles", "detectRenames", "parseDiffHunks", "DEFAULT_THRESHOLD", "HIGH_THRESHOLD", "reanchorComment", "reanchorDocumentLines", "reanchorDocumentText", "toReanchorLines", "resolveAnchor", "reanchorDocument", "applyReanchorResults", "reanchorFile", "addComment", "editComment", "normalizeCommentExtensions", "populateSelectedText", "resolveComment", "unresolveComment", "removeComment", "filterComments", "getThreads", "summarize", "formatAuthor", "parseAuthor", "newCommentId"]
3
+ "sources": ["../src/lib/serialize.ts", "../src/lib/parser.ts", "../src/index.ts", "../src/lib/discovery.ts", "../src/lib/resolve-files.ts", "../src/lib/writer.ts", "../src/lib/validator.ts", "../src/lib/validate-core.ts", "../mrsf.schema.json", "../src/lib/schema.ts", "../src/lib/fuzzy.ts", "../src/lib/git.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/reanchor.ts", "../src/lib/identity.ts", "../src/lib/comments.ts"],
4
+ "sourcesContent": ["/**\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", "/**\n * MRSF Parser \u2014 load and parse MRSF sidecar files (YAML or JSON).\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { MrsfDocument } from \"./types.js\";\nimport {\n parseSidecarContent,\n parseSidecarContentLenient,\n type LenientParseResult,\n} from \"./serialize.js\";\n\n// Re-exported from the Node-free serialize module so existing\n// `@mrsf/cli` import paths keep working.\nexport {\n parseSidecarContent,\n parseSidecarContentLenient,\n} from \"./serialize.js\";\nexport type { LenientParseResult } from \"./serialize.js\";\n\n/**\n * Parse an MRSF sidecar file from disk.\n */\nexport async function parseSidecar(filePath: string): Promise<MrsfDocument> {\n const abs = path.resolve(filePath);\n const content = await readFile(abs, \"utf-8\");\n return parseSidecarContent(content, abs);\n}\n\n/**\n * Lenient parse: attempts to parse a sidecar file from disk without\n * throwing. On complete failure, returns `{ doc: null, error }`.\n * On success, returns `{ doc }`. For partially-corrupted YAML (where\n * the top-level parses but some comments are malformed), attempts to\n * salvage individual well-formed comments.\n */\nexport async function parseSidecarLenient(\n filePath: string,\n): Promise<LenientParseResult> {\n const abs = path.resolve(filePath);\n let content: string;\n try {\n content = await readFile(abs, \"utf-8\");\n } catch (e) {\n return { doc: null, error: `Cannot read file: ${(e as Error).message}` };\n }\n\n return parseSidecarContentLenient(content, abs);\n}\n\n/**\n * Read a Markdown document from disk and return its lines.\n * Lines are 1-indexed in the returned array (index 0 is unused).\n */\nexport async function readDocumentLines(\n filePath: string,\n): Promise<string[]> {\n const content = await readFile(path.resolve(filePath), \"utf-8\");\n const lines = content.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n // Prepend empty element so lines[1] = first line (1-based)\n return [\"\", ...lines];\n}\n", "/**\n * MRSF \u2014 Public API (library surface).\n *\n * Usage:\n * import { validate, reanchorFile, addComment, ... } from \"mrsf\";\n */\n\nimport * as discovery from \"./lib/discovery.js\";\nimport * as resolveFiles from \"./lib/resolve-files.js\";\nimport * as parser from \"./lib/parser.js\";\nimport * as writer from \"./lib/writer.js\";\nimport * as validator from \"./lib/validator.js\";\nimport * as fuzzy from \"./lib/fuzzy.js\";\nimport * as git from \"./lib/git.js\";\nimport * as reanchor from \"./lib/reanchor.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 comments from \"./lib/comments.js\";\nimport * as identity from \"./lib/identity.js\";\nimport * as validateCore from \"./lib/validate-core.js\";\nimport { mrsfSchema } from \"./lib/schema.js\";\n\n// Types\nexport type {\n MrsfDocument,\n Comment,\n CommentExtensions,\n CommentExtensionValue,\n MrsfConfig,\n DiagnosticSeverity,\n ValidationDiagnostic,\n ValidationResult,\n ReanchorStatus,\n ReanchorResult,\n AnchorPosition,\n FuzzyCandidate,\n DiffHunk,\n AddCommentOptions,\n EditCommentOptions,\n CommentFilter,\n AnchorHealth,\n StatusResult,\n BaseOptions,\n ReanchorOptions,\n ValidateOptions,\n} from \"./lib/types.js\";\n\n// Discovery\nexport const findWorkspaceRoot = discovery.findWorkspaceRoot;\nexport const loadConfig = discovery.loadConfig;\nexport const discoverSidecar = discovery.discoverSidecar;\nexport const sidecarToDocument = discovery.sidecarToDocument;\nexport const discoverAllSidecars = discovery.discoverAllSidecars;\n\n// File resolution\nexport const resolveSidecarPaths = resolveFiles.resolveSidecarPaths;\n\n// Parsing\nexport const parseSidecar = parser.parseSidecar;\nexport const parseSidecarContent = parser.parseSidecarContent;\nexport const parseSidecarLenient = parser.parseSidecarLenient;\nexport const parseSidecarContentLenient = parser.parseSidecarContentLenient;\nexport const readDocumentLines = parser.readDocumentLines;\n\nexport type { LenientParseResult } from \"./lib/parser.js\";\n\n// Writing\nexport const computeHash = writer.computeHash;\nexport const syncHash = writer.syncHash;\nexport const toYaml = writer.toYaml;\nexport const toJson = writer.toJson;\nexport const writeSidecar = writer.writeSidecar;\n\n// Validation\nexport const validate = validator.validate;\nexport const validateFile = validator.validateFile;\nexport const validateDocument = validateCore.validateDocument;\nexport { mrsfSchema };\n\n// Fuzzy matching\nexport const exactMatch = fuzzy.exactMatch;\nexport const normalizedMatch = fuzzy.normalizedMatch;\nexport const fuzzySearch = fuzzy.fuzzySearch;\nexport const combinedScore = fuzzy.combinedScore;\n\n// Git\nexport const isGitAvailable = git.isGitAvailable;\nexport const findRepoRoot = git.findRepoRoot;\nexport const getCurrentCommit = git.getCurrentCommit;\nexport const resolveCommit = git.resolveCommit;\nexport const isStale = git.isStale;\nexport const getDiff = git.getDiff;\nexport const getLineShift = git.getLineShift;\nexport const getFileAtCommit = git.getFileAtCommit;\nexport const getStagedFiles = git.getStagedFiles;\nexport const detectRenames = git.detectRenames;\nexport const parseDiffHunks = git.parseDiffHunks;\n\n// Re-anchoring\nexport const DEFAULT_THRESHOLD = reanchor.DEFAULT_THRESHOLD;\nexport const HIGH_THRESHOLD = reanchor.HIGH_THRESHOLD;\nexport const reanchorComment = reanchor.reanchorComment;\nexport const reanchorDocumentLines = reanchor.reanchorDocumentLines;\nexport const reanchorDocumentText = reanchor.reanchorDocumentText;\nexport const toReanchorLines = reanchor.toReanchorLines;\nexport const resolveAnchor = reanchor.resolveAnchor;\nexport const reanchorDocument = reanchor.reanchorDocument;\nexport const applyReanchorResults = reanchor.applyReanchorResults;\nexport const reanchorFile = reanchor.reanchorFile;\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\n// Comments\nexport const addComment = comments.addComment;\nexport const editComment = comments.editComment;\nexport const normalizeCommentExtensions = comments.normalizeCommentExtensions;\nexport const populateSelectedText = comments.populateSelectedText;\nexport const resolveComment = comments.resolveComment;\nexport const unresolveComment = comments.unresolveComment;\nexport const removeComment = comments.removeComment;\nexport const filterComments = comments.filterComments;\nexport const getThreads = comments.getThreads;\nexport const summarize = comments.summarize;\nexport type { CommentSummary, RemoveCommentOptions } from \"./lib/comments.js\";\n\n// Identity\nexport const formatAuthor = identity.formatAuthor;\nexport const parseAuthor = identity.parseAuthor;\nexport const newCommentId = identity.newCommentId;\nexport type { ParsedAuthor } from \"./lib/identity.js\";\n", "/**\n * MRSF Discovery \u2014 resolve sidecar file paths per \u00A73.3.\n *\n * Discovery order:\n * 1. Check for .mrsf.yaml at repo/workspace root \u2192 use sidecar_root if defined.\n * 2. Otherwise, co-located sidecar next to the Markdown file.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"js-yaml\";\nimport type { MrsfConfig } from \"./types.js\";\n\nconst CONFIG_FILENAME = \".mrsf.yaml\";\nconst SIDECAR_SUFFIX = \".review.yaml\";\nconst SIDECAR_SUFFIX_JSON = \".review.json\";\n\n/**\n * Find the workspace / repo root by walking up from `startDir` looking for\n * `.mrsf.yaml` or `.git`.\n */\nexport function findWorkspaceRoot(startDir: string): string {\n let dir = path.resolve(startDir);\n const { root } = path.parse(dir);\n while (dir !== root) {\n if (\n existsSync(path.join(dir, CONFIG_FILENAME)) ||\n existsSync(path.join(dir, \".git\"))\n ) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return path.resolve(startDir);\n}\n\n/**\n * Load and validate .mrsf.yaml config. Returns null if not found.\n */\nexport async function loadConfig(\n workspaceRoot: string,\n configPath?: string,\n): Promise<MrsfConfig | null> {\n const cfgPath = configPath\n ? path.resolve(configPath)\n : path.join(workspaceRoot, CONFIG_FILENAME);\n\n if (!existsSync(cfgPath)) return null;\n\n const raw = await readFile(cfgPath, \"utf-8\");\n const parsed = yaml.load(raw, { schema: yaml.JSON_SCHEMA }) as Record<string, unknown> | null;\n\n if (!parsed || typeof parsed !== \"object\") return null;\n\n const config: MrsfConfig = {};\n\n if (typeof parsed.sidecar_root === \"string\") {\n const sr = parsed.sidecar_root;\n\n // Reject absolute paths\n if (path.isAbsolute(sr)) {\n throw new Error(\n `.mrsf.yaml: sidecar_root must be a relative path (got \"${sr}\")`,\n );\n }\n\n // Reject path traversal\n if (sr.includes(\"..\")) {\n throw new Error(\n `.mrsf.yaml: sidecar_root must not contain \"..\" (got \"${sr}\")`,\n );\n }\n\n config.sidecar_root = sr;\n }\n\n return config;\n}\n\n/**\n * Given a Markdown document path (relative to workspace root), resolve the\n * sidecar file path according to \u00A73.3 discovery order.\n *\n * Returns an absolute path to the sidecar.\n */\nexport async function discoverSidecar(\n documentPath: string,\n options: { cwd?: string; configPath?: string } = {},\n): Promise<string> {\n const cwd = options.cwd ?? process.cwd();\n const workspaceRoot = findWorkspaceRoot(cwd);\n const config = await loadConfig(workspaceRoot, options.configPath);\n\n // Normalize to a workspace-relative path\n const relDoc = path.isAbsolute(documentPath)\n ? path.relative(workspaceRoot, documentPath)\n : documentPath;\n\n if (config?.sidecar_root) {\n // \u00A73.2 \u2014 alternate sidecar location\n return path.join(workspaceRoot, config.sidecar_root, relDoc + SIDECAR_SUFFIX);\n }\n\n // \u00A73.1 \u2014 co-located\n return path.join(workspaceRoot, relDoc + SIDECAR_SUFFIX);\n}\n\n/**\n * Given a sidecar file path, resolve the Markdown document path.\n * Strips .review.yaml or .review.json suffix.\n * Returns an absolute path to the document.\n */\nexport function sidecarToDocument(\n sidecarPath: string,\n options: { cwd?: string } = {},\n): string {\n const abs = path.resolve(sidecarPath);\n\n if (abs.endsWith(SIDECAR_SUFFIX)) {\n return abs.slice(0, -SIDECAR_SUFFIX.length);\n } else if (abs.endsWith(SIDECAR_SUFFIX_JSON)) {\n return abs.slice(0, -SIDECAR_SUFFIX_JSON.length);\n }\n\n return abs;\n}\n\n/**\n * Discover all sidecar files in a directory (recursive).\n */\nexport async function discoverAllSidecars(\n dirPath: string,\n): Promise<string[]> {\n const { readdir, stat } = await import(\"node:fs/promises\");\n const results: string[] = [];\n\n async function walk(dir: string): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name === \"node_modules\" || entry.name === \".git\") continue;\n await walk(full);\n } else if (\n entry.name.endsWith(SIDECAR_SUFFIX) ||\n entry.name.endsWith(SIDECAR_SUFFIX_JSON)\n ) {\n results.push(full);\n }\n }\n }\n\n const s = await stat(dirPath);\n if (s.isFile()) {\n results.push(path.resolve(dirPath));\n } else {\n await walk(path.resolve(dirPath));\n }\n\n return results;\n}\n", "/**\n * Shared helper for resolving CLI file arguments.\n *\n * When a user passes a Markdown document path (e.g. `docs/api.md`) instead of\n * a sidecar path, we auto-discover the corresponding sidecar. This avoids\n * the confusing \"Failed to parse YAML\" error on raw Markdown files.\n */\n\nimport path from \"node:path\";\nimport { discoverSidecar, findWorkspaceRoot, discoverAllSidecars } from \"../lib/discovery.js\";\n\nconst SIDECAR_EXTENSIONS = [\".review.yaml\", \".review.json\"];\n\nfunction isSidecarPath(file: string): boolean {\n return SIDECAR_EXTENSIONS.some((ext) => file.endsWith(ext));\n}\n\n/**\n * Resolve a list of CLI file arguments to sidecar paths.\n *\n * - If `files` is empty, discover all sidecars from the workspace root.\n * - If a file already looks like a sidecar (`.review.yaml`/`.review.json`),\n * resolve it to an absolute path.\n * - If a file ends in `.md` (or any non-sidecar extension), treat it as a\n * document path and discover its sidecar via \u00A73.3.\n */\nexport async function resolveSidecarPaths(\n files: string[],\n cwd: string,\n): Promise<string[]> {\n if (files.length === 0) {\n const root = findWorkspaceRoot(cwd);\n return discoverAllSidecars(root ?? cwd);\n }\n\n const resolved: string[] = [];\n for (const f of files) {\n const abs = path.resolve(cwd, f);\n if (isSidecarPath(abs)) {\n resolved.push(abs);\n } else {\n // Treat as a document path \u2192 discover its sidecar\n const sidecar = await discoverSidecar(abs, { cwd });\n resolved.push(sidecar);\n }\n }\n return resolved;\n}\n", "/**\n * MRSF Writer \u2014 serialize MrsfDocument back to YAML or JSON.\n *\n * Uses CST-level (Concrete Syntax Tree) round-trip editing via the `yaml`\n * library so that unchanged content is byte-identical to the original file.\n * - Preserves YAML comments (#)\n * - Preserves scalar styles (>, |, quotes)\n * - Preserves key ordering and whitespace\n * - Only modifies values that actually changed\n *\n * Auto-computes selected_text_hash when selected_text changes.\n */\n\nimport { readFile, writeFile, rename, unlink } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport path from \"node:path\";\nimport { Parser, CST, parse as yamlParse } from \"yaml\";\nimport type { MrsfDocument, Comment } from \"./types.js\";\nimport { toYaml, toJson } from \"./serialize.js\";\n\n/* ------------------------------------------------------------------ */\n/* Per-file write serialization */\n/* ------------------------------------------------------------------ */\n\n/**\n * Map of absolute file paths to pending write promises.\n * Ensures that concurrent writes to the same sidecar file are serialized\n * (queued), preventing race conditions during the read-modify-write cycle.\n */\nconst writeQueue = new Map<string, Promise<void>>();\n\n/**\n * Enqueue a write operation for the given file path, ensuring only one\n * write executes at a time per file.\n */\nfunction enqueueWrite(abs: string, fn: () => Promise<void>): Promise<void> {\n const prev = writeQueue.get(abs) ?? Promise.resolve();\n const next = prev.then(fn, fn); // run fn even if previous write failed\n writeQueue.set(abs, next);\n // Clean up map entry when the queue drains\n next.then(() => {\n if (writeQueue.get(abs) === next) writeQueue.delete(abs);\n }, () => {\n if (writeQueue.get(abs) === next) writeQueue.delete(abs);\n });\n return next;\n}\n\n/* ------------------------------------------------------------------ */\n/* Atomic file write */\n/* ------------------------------------------------------------------ */\n\n/**\n * Atomically write content to a file by writing to a temporary file in\n * the same directory, then renaming. On POSIX this is atomic; on\n * Windows it replaces the target.\n */\nasync function atomicWriteFile(\n filePath: string,\n content: string,\n): Promise<void> {\n const tmp = filePath + \".\" + randomBytes(6).toString(\"hex\") + \".tmp\";\n try {\n await writeFile(tmp, content, \"utf-8\");\n await rename(tmp, filePath);\n } catch (err) {\n // Clean up temp file on failure\n try { await unlink(tmp); } catch { /* ignore */ }\n throw err;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Hash helpers */\n/* ------------------------------------------------------------------ */\n\n/**\n * Compute SHA-256 hex hash of a string (UTF-8).\n */\nexport function computeHash(text: string): string {\n return createHash(\"sha256\").update(text, \"utf-8\").digest(\"hex\");\n}\n\n/**\n * Ensure selected_text_hash is consistent for a comment.\n * If selected_text is present, computes/updates the hash.\n * If selected_text is absent, removes the hash.\n */\nexport function syncHash(comment: Comment): Comment {\n if (comment.selected_text != null && comment.selected_text.length > 0) {\n comment.selected_text_hash = computeHash(comment.selected_text);\n } else {\n delete comment.selected_text_hash;\n }\n return comment;\n}\n\n/* ------------------------------------------------------------------ */\n/* CST round-trip helpers */\n/* ------------------------------------------------------------------ */\n\n/** Any CST token \u2014 the `yaml` library doesn't export fine-grained types. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype CstNode = any;\n\n/**\n * Known comment field keys in preferred output order (for new comments).\n */\nconst COMMENT_KEY_ORDER = [\n \"id\", \"author\", \"timestamp\", \"text\", \"type\", \"severity\",\n \"resolved\", \"reply_to\", \"line\", \"end_line\", \"start_column\", \"end_column\",\n \"selected_text\", \"selected_text_hash\", \"anchored_text\", \"commit\",\n];\n\n/* \u00B7\u00B7 value serialisation \u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 */\n\n/**\n * Convert a JS value to its YAML source text representation.\n * Strings that require quoting get double-quoted; numbers and booleans\n * are plain scalars.\n *\n * Uses an allowlist approach: only strings that consist entirely of\n * \"safe\" characters are emitted as bare scalars. Everything else is\n * double-quoted via JSON.stringify, which is always valid YAML.\n */\nfunction valueToSource(v: unknown): string {\n if (v instanceof Date) return JSON.stringify(v.toISOString());\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n if (typeof v === \"string\") {\n // Empty string must be quoted\n if (v === \"\") return JSON.stringify(v);\n\n // YAML reserved words / null aliases must be quoted\n if (\n v === \"true\" || v === \"false\" || v === \"null\" ||\n v === \"True\" || v === \"False\" || v === \"Null\" ||\n v === \"TRUE\" || v === \"FALSE\" || v === \"NULL\" ||\n v === \"yes\" || v === \"no\" || v === \"on\" || v === \"off\" ||\n v === \"Yes\" || v === \"No\" || v === \"On\" || v === \"Off\" ||\n v === \"YES\" || v === \"NO\" || v === \"ON\" || v === \"OFF\" ||\n v === \"~\" || v === \".inf\" || v === \"-.inf\" || v === \".nan\"\n ) {\n return JSON.stringify(v);\n }\n\n // Strings starting with digits (could be parsed as number) must be quoted\n if (/^\\d/.test(v)) return JSON.stringify(v);\n\n // Allowlist: safe plain scalars consist of word chars, hyphens (not\n // leading), dots, slashes, spaces (not leading/trailing), parentheses,\n // and @ \u2014 but NO YAML indicators or ambiguous sequences.\n // A safe string:\n // \u2022 starts with a letter, underscore\n // \u2022 contains only [A-Za-z0-9 _./()@+-] (note: hyphen mid-string is OK)\n // \u2022 does NOT contain \" #\" (inline comment)\n // \u2022 does NOT start with \"- \" or end with \":\"\n // \u2022 has no leading/trailing whitespace\n // \u2022 contains no newlines or tabs\n if (/^[A-Za-z_][A-Za-z0-9 _./()\\-@+]*$/.test(v) && !v.includes(\" #\") && !/\\s$/.test(v)) {\n return v;\n }\n\n // Everything else: double-quote (JSON.stringify handles escaping)\n return JSON.stringify(v);\n }\n return String(v);\n}\n\n/** Return the CST scalar type for a value. */\nfunction valueType(v: unknown): string {\n return valueToSource(v).startsWith('\"') ? \"double-quoted-scalar\" : \"scalar\";\n}\n\nfunction isStructuredValue(value: unknown): boolean {\n if (value == null) return false;\n if (Array.isArray(value)) return true;\n return typeof value === \"object\" && !(value instanceof Date);\n}\n\nfunction hasStructuredCommentExtensions(doc: MrsfDocument): boolean {\n return doc.comments.some((comment) =>\n Object.entries(comment).some(([key, value]) =>\n !COMMENT_KEY_ORDER.includes(key) && value !== undefined && isStructuredValue(value),\n ),\n );\n}\n\n/* \u00B7\u00B7 CST node construction \u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 */\n\nconst NL = \"\\n\";\n\n/**\n * Build a CST map-item (key: value\\n) suitable for insertion into a\n * block-map's `items` array.\n *\n * @param isFirst If true, omit leading indent (first item in a block-map\n * inherits indent from the parent seq-item-ind).\n */\nfunction makeCstMapItem(\n key: string,\n value: unknown,\n indent: number,\n isFirst: boolean,\n): CstNode {\n const start = isFirst\n ? []\n : [{ type: \"space\", offset: 0, indent: 0, source: \" \".repeat(indent) }];\n return {\n start,\n key: { type: \"scalar\", offset: 0, indent, source: key },\n sep: [\n { type: \"map-value-ind\", offset: 0, indent, source: \":\" },\n { type: \"space\", offset: 0, indent, source: \" \" },\n ],\n value: {\n type: valueType(value),\n offset: 0,\n indent,\n source: valueToSource(value),\n end: [{ type: \"newline\", offset: 0, indent, source: NL }],\n },\n };\n}\n\n/**\n * Build a complete CST seq-item for a brand-new Comment (block-map inside\n * a block-seq).\n */\nfunction makeCstSeqItem(comment: Comment, seqIndent: number): CstNode {\n const mapIndent = seqIndent + 2;\n const items: CstNode[] = [];\n\n // Preferred key order first\n for (const key of COMMENT_KEY_ORDER) {\n const val = (comment as Record<string, unknown>)[key];\n if (val !== undefined) {\n items.push(makeCstMapItem(key, val, mapIndent, items.length === 0));\n }\n }\n // Extension / extra fields\n for (const key of Object.keys(comment)) {\n if (\n !COMMENT_KEY_ORDER.includes(key) &&\n (comment as Record<string, unknown>)[key] !== undefined\n ) {\n items.push(\n makeCstMapItem(\n key,\n (comment as Record<string, unknown>)[key],\n mapIndent,\n items.length === 0,\n ),\n );\n }\n }\n\n return {\n start: [\n { type: \"newline\", offset: 0, indent: 0, source: NL },\n { type: \"space\", offset: 0, indent: 0, source: \" \".repeat(seqIndent) },\n { type: \"seq-item-ind\", offset: 0, indent: seqIndent, source: \"-\" },\n { type: \"space\", offset: 0, indent: seqIndent, source: \" \" },\n ],\n value: { type: \"block-map\", offset: 0, indent: mapIndent, items },\n };\n}\n\n/* \u00B7\u00B7 CST navigation \u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 */\n\n/** Find the document token in a CST token stream. */\nfunction findCstDocument(tokens: CstNode[]): CstNode | null {\n return tokens.find((t: CstNode) => t.type === \"document\") ?? null;\n}\n\n/** Find an item in a block-map by key source text. */\nfunction findCstMapEntry(\n blockMap: CstNode,\n keyName: string,\n): CstNode | null {\n return (\n blockMap.items?.find(\n (item: CstNode) => item.key?.source === keyName,\n ) ?? null\n );\n}\n\n/** Get the index of a map entry by key source text (\u22121 if missing). */\nfunction findCstMapIndex(blockMap: CstNode, keyName: string): number {\n return (\n blockMap.items?.findIndex(\n (item: CstNode) => item.key?.source === keyName,\n ) ?? -1\n );\n}\n\n/** Read the plain-text id from a CST block-map (comment). */\nfunction cstCommentId(blockMap: CstNode): string | null {\n const entry = findCstMapEntry(blockMap, \"id\");\n if (!entry?.value?.source) return null;\n const src: string = entry.value.source;\n // Strip quotes if present\n if (src.startsWith('\"') && src.endsWith('\"')) {\n return src.slice(1, -1);\n }\n return src;\n}\n\n/* \u00B7\u00B7 CST mutation \u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 */\n\n/**\n * Update an existing scalar CST value's source text.\n * Returns true if the source was actually changed.\n */\nfunction updateCstScalar(entry: CstNode, newValue: unknown): boolean {\n const newSrc = valueToSource(newValue);\n if (entry.value?.source === newSrc) return false;\n entry.value.source = newSrc;\n // If type changed (e.g. plain \u2192 quoted), update it too\n entry.value.type = valueType(newValue);\n return true;\n}\n\n/**\n * Synchronize a plain Comment object into a CST block-map, preserving\n * untouched scalars byte-for-byte.\n *\n * @param blockMap CST block-map node for the comment\n * @param comment New model values to write\n * @param currentValues Already-parsed values from the existing YAML\n * (used to detect real changes vs source-format\n * differences like quoted vs folded scalars)\n */\nfunction syncCommentToCst(\n blockMap: CstNode,\n comment: Comment,\n currentValues: Record<string, unknown>,\n): void {\n const commentRec = comment as Record<string, unknown>;\n\n // Collect existing key names\n const existingKeys = new Set<string>();\n for (const item of blockMap.items ?? []) {\n if (item.key?.source) existingKeys.add(item.key.source as string);\n }\n\n const allKeys = new Set([...existingKeys, ...Object.keys(comment)]);\n const indent = blockMap.indent ?? 4;\n\n for (const key of allKeys) {\n const newVal = commentRec[key];\n\n if (newVal === undefined) {\n // Removed from model \u2192 delete from CST\n if (existingKeys.has(key)) {\n const idx = findCstMapIndex(blockMap, key);\n if (idx >= 0) blockMap.items.splice(idx, 1);\n }\n continue;\n }\n\n const entry = findCstMapEntry(blockMap, key);\n if (entry) {\n // Existing key \u2014 compare PARSED values (not source text) to detect\n // real semantic changes. This avoids touching block scalars, quoted\n // strings, etc. whose source representation differs but whose parsed\n // value is identical.\n const currentVal = currentValues[key];\n if (deepEqual(currentVal, newVal)) {\n // Value unchanged \u2014 leave the CST node byte-for-byte\n continue;\n }\n // Value really changed \u2014 update source\n updateCstScalar(entry, newVal);\n } else {\n // New key \u2014 insert at end\n blockMap.items.push(makeCstMapItem(key, newVal, indent, false));\n }\n }\n}\n\n/**\n * Simple deep-equal for scalars and basic types (sufficient for MRSF\n * Comment field values which are strings, numbers, and booleans).\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== typeof b) return false;\n // Handle number comparison with potential string/number mismatch from YAML\n if (typeof a === \"number\" && typeof b === \"number\") return a === b;\n return false;\n}\n\n/* ------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------ */\n\n// `toYaml` / `toJson` now live in the Node-free serialize module; re-exported\n// here so existing `@mrsf/cli` import paths keep working.\nexport { toYaml, toJson } from \"./serialize.js\";\n\n/**\n * Write an MrsfDocument to disk.\n *\n * When a YAML file already exists on disk, performs a **CST-level** round-trip\n * merge that preserves YAML comments, scalar styles, key ordering, and\n * whitespace byte-for-byte for unchanged content.\n *\n * For new files or JSON, writes from scratch.\n *\n * Writes to the same file path are serialized (queued) to prevent race\n * conditions from concurrent calls. All writes are atomic (temp + rename).\n */\nexport async function writeSidecar(\n filePath: string,\n doc: MrsfDocument,\n): Promise<void> {\n const abs = path.resolve(filePath);\n return enqueueWrite(abs, () => writeSidecarInternal(abs, doc));\n}\n\n/**\n * Internal implementation of writeSidecar (runs inside the per-file queue).\n */\nasync function writeSidecarInternal(\n abs: string,\n doc: MrsfDocument,\n): Promise<void> {\n const isJson = abs.endsWith(\".review.json\");\n\n for (const comment of doc.comments) syncHash(comment);\n\n if (isJson) {\n // For JSON, always write fresh\n await atomicWriteFile(abs, toJson(doc));\n return;\n }\n\n // The CST patcher only supports scalar map values. Fall back to full YAML\n // serialisation when comment extensions include arrays or objects.\n if (hasStructuredCommentExtensions(doc)) {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n // \u2500\u2500 YAML round-trip path \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (!existsSync(abs)) {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n let raw: string;\n try {\n raw = await readFile(abs, \"utf-8\");\n } catch {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n // Parse to CST tokens\n let tokens: CstNode[];\n try {\n tokens = [...new Parser().parse(raw)];\n } catch {\n // Unparseable \u2014 write fresh\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n // Also parse to plain JS object for value comparison (so we compare\n // parsed values, not source-text representations)\n let currentDoc: MrsfDocument | null = null;\n try {\n currentDoc = yamlParse(raw) as MrsfDocument;\n } catch {\n // ignore \u2014 we'll fall through to source-level comparison\n }\n\n // \u2500\u2500 Structural validation of parsed YAML \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // If CST parsed OK but the content isn't a valid MrsfDocument shape\n // (e.g. comments is not an array due to injection), discard and write fresh.\n if (currentDoc && (!Array.isArray(currentDoc.comments))) {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n // Build lookup of current parsed values by comment id\n const currentById = new Map<string, Record<string, unknown>>();\n if (currentDoc?.comments) {\n for (const c of currentDoc.comments) {\n if (c.id) currentById.set(c.id, c as Record<string, unknown>);\n }\n }\n\n // Sync hashes: for existing comments, only add selected_text_hash\n // if selected_text actually changed or hash was already present.\n // For new comments, always sync.\n for (const comment of doc.comments) {\n const cur = currentById.get(comment.id);\n if (!cur) {\n // New comment \u2014 always sync hash\n syncHash(comment);\n } else {\n // Existing comment \u2014 only sync hash if text changed or hash\n // was already tracked in the original\n const textChanged = !deepEqual(cur.selected_text, comment.selected_text);\n const hadHash = cur.selected_text_hash !== undefined;\n if (textChanged || hadHash) {\n syncHash(comment);\n } else {\n // Don't inject a hash that wasn't there before\n delete comment.selected_text_hash;\n }\n }\n }\n\n const docToken = findCstDocument(tokens);\n if (!docToken?.value || docToken.value.type !== \"block-map\") {\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n const body: CstNode = docToken.value;\n\n // \u2500\u2500 Update top-level scalars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const versionEntry = findCstMapEntry(body, \"mrsf_version\");\n if (versionEntry && !deepEqual(currentDoc?.mrsf_version, doc.mrsf_version)) {\n updateCstScalar(versionEntry, doc.mrsf_version);\n }\n\n const documentEntry = findCstMapEntry(body, \"document\");\n if (documentEntry && !deepEqual(currentDoc?.document, doc.document)) {\n updateCstScalar(documentEntry, doc.document);\n }\n\n // \u2500\u2500 Merge comments \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const commentsEntry = findCstMapEntry(body, \"comments\");\n if (!commentsEntry?.value || commentsEntry.value.type !== \"block-seq\") {\n // No existing comments seq \u2014 write fresh\n await atomicWriteFile(abs, toYaml(doc));\n return;\n }\n\n const seq: CstNode = commentsEntry.value;\n const seqIndent: number = seq.indent ?? 2;\n\n // Index existing CST comments by id\n const existingById = new Map<string, { index: number; map: CstNode }>();\n for (let i = 0; i < seq.items.length; i++) {\n const item = seq.items[i];\n const map = item.value;\n if (map?.type === \"block-map\") {\n const id = cstCommentId(map);\n if (id) existingById.set(id, { index: i, map });\n }\n }\n\n // Build new seq items list, preserving existing CST nodes (and their\n // YAML comments / formatting) for comments that still exist.\n const idsInDoc = new Set(doc.comments.map((c) => c.id));\n const newSeqItems: CstNode[] = [];\n\n for (const comment of doc.comments) {\n const existing = existingById.get(comment.id);\n if (existing) {\n // Round-trip: sync changes into the existing CST block-map\n const currentValues = currentById.get(comment.id) ?? {};\n syncCommentToCst(existing.map, comment, currentValues);\n // Re-use the original seq item (preserves preceding YAML comments\n // in the item's `start` tokens)\n newSeqItems.push(seq.items[existing.index]);\n } else {\n // Brand new comment \u2014 construct CST from scratch\n newSeqItems.push(makeCstSeqItem(comment, seqIndent));\n }\n }\n\n seq.items = newSeqItems;\n\n // \u2500\u2500 Fix first-item indentation after reorder / removal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // In the YAML CST, the `comments:` map-entry's `sep` array often\n // contains trailing whitespace (space tokens) that provide the indent\n // *before* the first seq-item indicator (`-`). Non-first seq items\n // carry their own leading space tokens in `start`.\n //\n // When the original first item is removed and a formerly non-first\n // item becomes the new first, those extra space tokens stack with\n // the sep whitespace, doubling the indent. We fix this by stripping\n // any leading space tokens (before the `seq-item-ind`) from the new\n // first item's start \u2014 the sep already provides that whitespace.\n //\n // We also ensure the previous item's value ends with a newline so\n // subsequent items render on their own line.\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (newSeqItems.length > 0) {\n const originalFirstIdx = seq.items === newSeqItems ? 0 : -1; // always true after assignment\n const origFirstItem = existingById.size > 0\n ? [...existingById.values()].find((e) => e.index === 0)\n : undefined;\n\n const newFirst = newSeqItems[0];\n\n // Check if the new first item is NOT the original first item\n const isOriginalFirst =\n origFirstItem &&\n seq.items[0]?.value === origFirstItem.map;\n\n if (!isOriginalFirst && newFirst.start) {\n // Strip leading space tokens before the seq-item-ind\n const dashIdx = newFirst.start.findIndex(\n (t: CstNode) => t.type === \"seq-item-ind\",\n );\n if (dashIdx > 0) {\n // Remove all tokens before the dash that are space/newline\n const toRemove = newFirst.start\n .slice(0, dashIdx)\n .every((t: CstNode) => t.type === \"space\" || t.type === \"newline\");\n if (toRemove) {\n newFirst.start.splice(0, dashIdx);\n }\n }\n }\n }\n // \u2500\u2500 Stringify via CST (byte-identical for untouched content) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const result = tokens.map((t: CstNode) => CST.stringify(t)).join(\"\");\n await atomicWriteFile(abs, result);\n}\n", "/**\n * MRSF Validator \u2014 JSON Schema + cross-field validation per \u00A710.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { computeHash } from \"./writer.js\";\nimport { validateCrossFields, validateSchema } from \"./validate-core.js\";\nimport type {\n MrsfDocument,\n ValidationResult,\n ValidationDiagnostic,\n ValidateOptions,\n} from \"./types.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nlet _schemaCache: object | null = null;\n\nasync function loadSchema(): Promise<object> {\n if (_schemaCache) return _schemaCache;\n\n // The schema lives at the repo root, two levels up from dist/lib/\n // When installed as a package, it's at the package root (cli/)\n const candidates = [\n path.resolve(__dirname, \"mrsf.schema.json\"), // same dir (esbuild bundle, e.g. MCP server)\n path.resolve(__dirname, \"../../mrsf.schema.json\"), // from dist/lib/ \u2192 cli/ (installed package)\n path.resolve(__dirname, \"../../../mrsf.schema.json\"), // from dist/lib/ \u2192 repo root (dev)\n path.resolve(__dirname, \"../../../../mrsf.schema.json\"), // fallback\n path.resolve(process.cwd(), \"mrsf.schema.json\"), // cwd fallback\n ];\n\n for (const candidate of candidates) {\n try {\n const raw = await readFile(candidate, \"utf-8\");\n _schemaCache = JSON.parse(raw);\n return _schemaCache!;\n } catch {\n // try next\n }\n }\n\n throw new Error(\"Could not locate mrsf.schema.json\");\n}\n\n/**\n * Validate an MRSF document (parsed object).\n */\nexport async function validate(\n doc: MrsfDocument,\n options: ValidateOptions = {},\n): Promise<ValidationResult> {\n const errors: ValidationDiagnostic[] = [];\n const warnings: ValidationDiagnostic[] = [];\n\n // \u2500\u2500 JSON Schema validation \u2500\u2500\n const rawSchema = await loadSchema();\n validateSchema(doc, rawSchema, errors);\n\n // \u2500\u2500 Cross-field validation (\u00A710) \u2500\u2500\n validateCrossFields(doc, errors, warnings, computeHash);\n\n const valid = errors.length === 0 && (!options.strict || warnings.length === 0);\n\n return { valid, errors, warnings };\n}\n\n/**\n * Validate from a file path \u2014 convenience wrapper.\n */\nexport async function validateFile(\n filePath: string,\n options: ValidateOptions = {},\n): Promise<ValidationResult> {\n const { parseSidecar } = await import(\"./parser.js\");\n try {\n const doc = await parseSidecar(filePath);\n return validate(doc, options);\n } catch (e) {\n return {\n valid: false,\n errors: [\n {\n severity: \"error\",\n code: \"parse-error\",\n message: `Failed to parse: ${(e as Error).message}`,\n },\n ],\n warnings: [],\n };\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 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", "/**\n * MRSF Git Integration \u2014 Git-aware operations for re-anchoring and discovery.\n *\n * Uses child_process.execFile (no shell) for safety.\n * All functions degrade gracefully when Git is unavailable.\n */\n\nimport { execFile as execFileCb } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport path from \"node:path\";\nimport type { DiffHunk } from \"./types.js\";\n\nconst execFile = promisify(execFileCb);\n\nconst GIT_TIMEOUT = 10_000; // 10s\n\n// ---------------------------------------------------------------------------\n// Availability\n// ---------------------------------------------------------------------------\n\nlet _gitAvailable: boolean | null = null;\n\n/**\n * Check whether `git` is available on PATH.\n */\nexport async function isGitAvailable(): Promise<boolean> {\n if (_gitAvailable != null) return _gitAvailable;\n try {\n await execFile(\"git\", [\"--version\"], { timeout: GIT_TIMEOUT });\n _gitAvailable = true;\n } catch {\n _gitAvailable = false;\n }\n return _gitAvailable;\n}\n\n/** Reset cached availability (for testing). */\nexport function resetGitCache(): void {\n _gitAvailable = null;\n}\n\n// ---------------------------------------------------------------------------\n// Repository info\n// ---------------------------------------------------------------------------\n\n/**\n * Find the Git repository root from a given directory.\n * Returns null if not in a Git repo.\n */\nexport async function findRepoRoot(cwd?: string): Promise<string | null> {\n if (!(await isGitAvailable())) return null;\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"rev-parse\", \"--show-toplevel\"],\n { cwd: cwd ?? process.cwd(), timeout: GIT_TIMEOUT },\n );\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Get the full HEAD commit SHA.\n */\nexport async function getCurrentCommit(repoRoot: string): Promise<string | null> {\n if (!(await isGitAvailable())) return null;\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"rev-parse\", \"HEAD\"],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/** Resolve a revision name or abbreviated SHA to its canonical commit SHA. */\nexport async function resolveCommit(\n revision: string,\n repoRoot: string,\n): Promise<string | null> {\n if (!(await isGitAvailable())) return null;\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"rev-parse\", \"--verify\", `${revision}^{commit}`],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a commit hash is the same as HEAD.\n */\nexport async function isStale(\n commentCommit: string,\n repoRoot: string,\n): Promise<boolean> {\n const head = await getCurrentCommit(repoRoot);\n if (!head) return false; // can't tell, assume not stale\n // Normalize: compare by prefix match (short vs long SHA)\n const minLen = Math.min(commentCommit.length, head.length);\n return commentCommit.slice(0, minLen) !== head.slice(0, minLen);\n}\n\n// ---------------------------------------------------------------------------\n// Diff operations\n// ---------------------------------------------------------------------------\n\n/**\n * Parse unified diff output into structured hunks.\n */\nexport function parseDiffHunks(diffOutput: string): DiffHunk[] {\n const hunks: DiffHunk[] = [];\n const lines = diffOutput.split(\"\\n\");\n let current: DiffHunk | null = null;\n\n for (const line of lines) {\n const hunkMatch = line.match(\n /^@@\\s+-(\\d+)(?:,(\\d+))?\\s+\\+(\\d+)(?:,(\\d+))?\\s+@@/,\n );\n if (hunkMatch) {\n current = {\n oldStart: parseInt(hunkMatch[1], 10),\n oldCount: hunkMatch[2] != null ? parseInt(hunkMatch[2], 10) : 1,\n newStart: parseInt(hunkMatch[3], 10),\n newCount: hunkMatch[4] != null ? parseInt(hunkMatch[4], 10) : 1,\n lines: [],\n };\n hunks.push(current);\n continue;\n }\n if (current && (line.startsWith(\"+\") || line.startsWith(\"-\") || line.startsWith(\" \"))) {\n current.lines.push(line);\n }\n }\n\n return hunks;\n}\n\n/**\n * Get diff hunks between two commits for a specific file.\n */\nexport async function getDiff(\n fromCommit: string,\n toCommit: string,\n filePath: string,\n repoRoot: string,\n): Promise<DiffHunk[]> {\n if (!(await isGitAvailable())) return [];\n try {\n const { stdout } = await execFile(\n \"git\",\n [\n \"diff\",\n `${fromCommit}..${toCommit}`,\n \"--unified=0\",\n \"--no-color\",\n \"--\",\n filePath,\n ],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return parseDiffHunks(stdout);\n } catch {\n return [];\n }\n}\n\n/**\n * Calculate the net line shift for a given original line number\n * based on diff hunks.\n *\n * Returns the number of lines to add to the original line number,\n * or null if the line itself was modified/deleted.\n */\nexport function getLineShift(\n hunks: DiffHunk[],\n originalLine: number,\n): { shift: number; modified: boolean } {\n let cumulativeShift = 0;\n\n for (const hunk of hunks) {\n const oldEnd = hunk.oldStart + hunk.oldCount - 1;\n\n // Hunk is entirely after our line \u2014 stop\n if (hunk.oldStart > originalLine) break;\n\n // Our line falls within this hunk \u2014 it was modified\n if (originalLine >= hunk.oldStart && originalLine <= oldEnd) {\n return { shift: cumulativeShift, modified: true };\n }\n\n // Hunk is entirely before our line \u2014 accumulate shift\n if (oldEnd < originalLine) {\n cumulativeShift += hunk.newCount - hunk.oldCount;\n }\n }\n\n return { shift: cumulativeShift, modified: false };\n}\n\n// ---------------------------------------------------------------------------\n// File at commit\n// ---------------------------------------------------------------------------\n\n/**\n * Get the contents of a file at a specific commit.\n * Returns null if unavailable.\n */\nexport async function getFileAtCommit(\n commit: string,\n filePath: string,\n repoRoot: string,\n): Promise<string | null> {\n if (!(await isGitAvailable())) return null;\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"show\", `${commit}:${filePath}`],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return stdout;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Staged files\n// ---------------------------------------------------------------------------\n\n/**\n * Get list of staged files matching a pattern.\n */\nexport async function getStagedFiles(\n repoRoot: string,\n pattern?: string,\n): Promise<string[]> {\n if (!(await isGitAvailable())) return [];\n try {\n const args = [\"diff\", \"--cached\", \"--name-only\", \"--diff-filter=d\"];\n if (pattern) args.push(\"--\", pattern);\n const { stdout } = await execFile(\"git\", args, {\n cwd: repoRoot,\n timeout: GIT_TIMEOUT,\n });\n return stdout\n .trim()\n .split(\"\\n\")\n .filter((f) => f.length > 0);\n } catch {\n return [];\n }\n}\n\n/**\n * Get staged diff hunks for a specific file.\n */\nexport async function getStagedDiff(\n filePath: string,\n repoRoot: string,\n): Promise<DiffHunk[]> {\n if (!(await isGitAvailable())) return [];\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"diff\", \"--cached\", \"--unified=0\", \"--no-color\", \"--\", filePath],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n return parseDiffHunks(stdout);\n } catch {\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rename detection\n// ---------------------------------------------------------------------------\n\n/**\n * Detect file renames between two commits.\n * Returns a map of old path \u2192 new path.\n */\nexport async function detectRenames(\n fromCommit: string,\n toCommit: string,\n repoRoot: string,\n): Promise<Map<string, string>> {\n if (!(await isGitAvailable())) return new Map();\n try {\n const { stdout } = await execFile(\n \"git\",\n [\"diff\", \"--name-status\", \"-M\", `${fromCommit}..${toCommit}`],\n { cwd: repoRoot, timeout: GIT_TIMEOUT },\n );\n\n const renames = new Map<string, string>();\n for (const line of stdout.trim().split(\"\\n\")) {\n const match = line.match(/^R\\d*\\t(.+)\\t(.+)$/);\n if (match) {\n renames.set(match[1], match[2]);\n }\n }\n return renames;\n } catch {\n return new Map();\n }\n}\n\n/**\n * Stage a file for commit.\n */\nexport async function stageFile(\n filePath: string,\n repoRoot: string,\n): Promise<void> {\n if (!(await isGitAvailable())) return;\n await execFile(\"git\", [\"add\", filePath], {\n cwd: repoRoot,\n timeout: GIT_TIMEOUT,\n });\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", "/**\n * MRSF Re-anchor Engine \u2014 \u00A77.4 Anchoring Resolution Procedure.\n *\n * Implements a four-step algorithm to re-locate each comment's\n * anchor within the current document revision:\n *\n * Step 0 \u2013 diff-based shift (git + commit available)\n * Step 1 \u2013 exact text match\n * Step 1.5\u2013 fuzzy match \u2265 high threshold (0.8)\n * Step 2 \u2013 line/column fallback (commit-aware staleness)\n * Step 3 \u2013 lower-threshold fuzzy \u2265 configured threshold (0.6)\n * Step 4 \u2013 orphan\n */\n\nimport type {\n MrsfDocument,\n ReanchorOptions,\n ReanchorResult,\n DiffHunk,\n} from \"./types.js\";\nimport {\n findRepoRoot,\n getCurrentCommit,\n getDiff,\n getFileAtCommit,\n getLineShift,\n isGitAvailable,\n parseDiffHunks,\n resolveCommit,\n} from \"./git.js\";\nimport {\n applyReanchorResults,\n DEFAULT_THRESHOLD,\n reanchorComment,\n reanchorDocumentLines,\n toReanchorLines,\n} from \"./reanchor-core.js\";\nimport {\n createRevisionProjection,\n type RevisionProjectionIndex,\n} from \"./revision-projection.js\";\nimport {\n createAnchorContextIndex,\n type AnchorContextIndex,\n} from \"./anchor-context.js\";\nimport {\n createFuzzySearchIndex,\n type FuzzySearchIndex,\n} from \"./fuzzy.js\";\nimport { reconcileCommentAnchors } from \"./global-reconciliation.js\";\nimport { readDocumentLines } from \"./parser.js\";\nimport { discoverSidecar, sidecarToDocument } from \"./discovery.js\";\nimport { parseSidecar } from \"./parser.js\";\nimport { writeSidecar } from \"./writer.js\";\nimport path from \"node:path\";\n\nexport {\n applyReanchorResults,\n DEFAULT_THRESHOLD,\n HIGH_THRESHOLD,\n reanchorComment,\n reanchorDocumentLines,\n reanchorDocumentText,\n resolveAnchor,\n toReanchorLines,\n} from \"./reanchor-core.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Batch re-anchoring\n// ---------------------------------------------------------------------------\n\n/**\n * Re-anchor all comments in an MRSF document.\n */\nexport async function reanchorDocument(\n doc: MrsfDocument,\n documentLines: string[],\n opts: ReanchorOptions & {\n documentPath?: string;\n repoRoot?: string;\n } = {},\n): Promise<ReanchorResult[]> {\n const results: ReanchorResult[] = [];\n const threshold = opts.threshold ?? DEFAULT_THRESHOLD;\n const proximityWindow = opts.proximityWindow;\n let fuzzySearchIndex: FuzzySearchIndex | undefined;\n const getFuzzySearchIndex = (): FuzzySearchIndex => {\n fuzzySearchIndex ??= createFuzzySearchIndex(documentLines);\n return fuzzySearchIndex;\n };\n\n if (!opts.noGit && (await isGitAvailable())) {\n const repoRoot = opts.repoRoot ?? (await findRepoRoot(opts.cwd));\n if (repoRoot && opts.documentPath) {\n const relPath = path.relative(repoRoot, opts.documentPath);\n const head = await getCurrentCommit(repoRoot);\n\n // Use a shared fromCommit for all comments, or per-comment\n const globalFrom = opts.fromCommit;\n const diffCache = new Map<string, DiffHunk[]>();\n const projectionCache = new Map<\n string,\n RevisionProjectionIndex | undefined\n >();\n const contextCache = new Map<string, AnchorContextIndex | undefined>();\n const canonicalCommitCache = new Map<string, string>();\n const reconciliationGroups = new Map<\n string,\n {\n comments: MrsfDocument[\"comments\"];\n resultIndexes: number[];\n anchorContext: AnchorContextIndex;\n }\n >();\n\n for (const comment of doc.comments) {\n const rawCommentCommit = globalFrom ?? comment.commit;\n if (rawCommentCommit && head) {\n const cachedCommit = canonicalCommitCache.get(rawCommentCommit);\n const commentCommit = cachedCommit\n ?? await resolveCommit(rawCommentCommit, repoRoot)\n ?? rawCommentCommit;\n if (!cachedCommit) {\n canonicalCommitCache.set(rawCommentCommit, commentCommit);\n }\n if (commentCommit === head) {\n results.push(\n reanchorComment(comment, documentLines, {\n threshold,\n commitIsStale: false,\n proximityWindow,\n getFuzzySearchIndex,\n }),\n );\n continue;\n }\n let hunks = diffCache.get(commentCommit);\n if (!hunks) {\n hunks = await getDiff(commentCommit, head, relPath, repoRoot);\n diffCache.set(commentCommit, hunks);\n }\n let revisionProjection = projectionCache.get(commentCommit);\n let anchorContext = contextCache.get(commentCommit);\n if (!projectionCache.has(commentCommit)) {\n const sourceText = await getFileAtCommit(\n commentCommit,\n relPath,\n repoRoot,\n );\n revisionProjection = sourceText == null\n ? undefined\n : createRevisionProjection(\n toReanchorLines(sourceText),\n documentLines,\n );\n anchorContext = sourceText == null\n ? undefined\n : createAnchorContextIndex(\n toReanchorLines(sourceText),\n documentLines,\n );\n projectionCache.set(commentCommit, revisionProjection);\n contextCache.set(commentCommit, anchorContext);\n }\n const result = reanchorComment(comment, documentLines, {\n diffHunks: hunks,\n threshold,\n commitIsStale: true,\n proximityWindow,\n revisionProjection,\n anchorContext,\n getFuzzySearchIndex,\n });\n const resultIndex = results.length;\n results.push(result);\n if (anchorContext) {\n const group = reconciliationGroups.get(commentCommit);\n if (group) {\n group.comments.push(comment);\n group.resultIndexes.push(resultIndex);\n } else {\n reconciliationGroups.set(commentCommit, {\n comments: [comment],\n resultIndexes: [resultIndex],\n anchorContext,\n });\n }\n }\n continue;\n }\n\n // non-stale or no commit\n results.push(\n reanchorComment(comment, documentLines, {\n threshold,\n commitIsStale: false,\n proximityWindow,\n getFuzzySearchIndex,\n }),\n );\n }\n\n for (const group of reconciliationGroups.values()) {\n const reconciled = reconcileCommentAnchors(\n group.comments,\n group.resultIndexes.map((index) => results[index]),\n group.anchorContext,\n );\n for (const [offset, resultIndex] of group.resultIndexes.entries()) {\n results[resultIndex] = reconciled[offset];\n }\n }\n return results;\n }\n }\n\n return reanchorDocumentLines(doc, documentLines, { threshold, proximityWindow });\n}\n\n/**\n * High-level re-anchor for a single sidecar file path.\n */\nexport async function reanchorFile(\n sidecarPath: string,\n opts: ReanchorOptions = {},\n): Promise<{\n results: ReanchorResult[];\n changed: number;\n written: boolean;\n}> {\n const doc = await parseSidecar(sidecarPath);\n const docPath = sidecarToDocument(sidecarPath);\n const documentLines = await readDocumentLines(docPath);\n\n const repoRoot = !opts.noGit ? await findRepoRoot(opts.cwd) : null;\n const headCommit = repoRoot ? await getCurrentCommit(repoRoot) : undefined;\n\n const results = await reanchorDocument(doc, documentLines, {\n ...opts,\n documentPath: docPath,\n repoRoot: repoRoot ?? undefined,\n });\n\n let changed = 0;\n let written = false;\n\n if (!opts.dryRun) {\n changed = applyReanchorResults(doc, results, {\n updateText: opts.updateText,\n force: opts.force,\n headCommit: headCommit ?? undefined,\n });\n if (changed > 0 || opts.autoUpdate) {\n await writeSidecar(sidecarPath, doc);\n written = true;\n }\n }\n\n return { results, changed, written };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\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", "/**\n * MRSF Comment Operations \u2014 CRUD for sidecar comments.\n */\n\nimport type {\n AddCommentOptions,\n Comment,\n CommentFilter,\n CommentExtensions,\n CommentExtensionValue,\n EditCommentOptions,\n MrsfDocument,\n} from \"./types.js\";\nimport { newCommentId } from \"./identity.js\";\nimport { computeHash } from \"./writer.js\";\nimport { getCurrentCommit, findRepoRoot, isGitAvailable } from \"./git.js\";\n\n// ---------------------------------------------------------------------------\n// Add\n// ---------------------------------------------------------------------------\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction isCommentExtensionValue(value: unknown): value is CommentExtensionValue {\n if (value == null) return true;\n\n switch (typeof value) {\n case \"boolean\":\n case \"string\":\n return true;\n case \"number\":\n return Number.isFinite(value);\n case \"object\": {\n if (Array.isArray(value)) {\n return value.every((item) => isCommentExtensionValue(item));\n }\n\n if (!isPlainObject(value)) {\n return false;\n }\n\n return Object.values(value).every((item) => isCommentExtensionValue(item));\n }\n default:\n return false;\n }\n}\n\nexport function normalizeCommentExtensions(\n extensions?: Record<string, unknown>,\n): CommentExtensions {\n if (!extensions) return {} as CommentExtensions;\n\n const normalizedEntries: Array<[`x_${string}`, CommentExtensionValue]> = [];\n\n for (const [key, value] of Object.entries(extensions)) {\n if (!key.startsWith(\"x_\")) {\n throw new Error(`Comment extension key '${key}' must start with 'x_'.`);\n }\n\n if (!isCommentExtensionValue(value)) {\n throw new Error(\n `Comment extension '${key}' must be JSON-serializable (null, boolean, finite number, string, array, or plain object).`,\n );\n }\n\n normalizedEntries.push([key as `x_${string}`, value]);\n }\n\n return Object.fromEntries(normalizedEntries) as CommentExtensions;\n}\n\n/**\n * Add a new comment to a document. Mutates doc.comments in place.\n * Returns the created comment.\n */\nexport async function addComment(\n doc: MrsfDocument,\n opts: AddCommentOptions,\n repoRoot?: string,\n): Promise<Comment> {\n const id = opts.id ?? newCommentId();\n const timestamp = opts.timestamp ?? new Date().toISOString();\n\n // Auto-detect commit from HEAD when git is available\n let commit = opts.commit;\n if (!commit && repoRoot && (await isGitAvailable())) {\n commit = (await getCurrentCommit(repoRoot)) ?? undefined;\n }\n\n const comment: Comment = {\n id,\n author: opts.author,\n timestamp,\n text: opts.text,\n resolved: false,\n };\n\n // Optional anchoring fields\n if (opts.line != null) comment.line = opts.line;\n if (opts.end_line != null) comment.end_line = opts.end_line;\n if (opts.start_column != null) comment.start_column = opts.start_column;\n if (opts.end_column != null) comment.end_column = opts.end_column;\n if (opts.type) comment.type = opts.type;\n if (opts.severity) comment.severity = opts.severity;\n if (opts.reply_to) comment.reply_to = opts.reply_to;\n if (commit) comment.commit = commit;\n\n Object.assign(comment, normalizeCommentExtensions(opts.extensions));\n\n doc.comments.push(comment);\n return comment;\n}\n\n/**\n * Populate selected_text from document lines (reads the file content region).\n * Should be called after addComment if the caller provides line info but not selected_text.\n */\nexport function populateSelectedText(\n comment: Comment,\n documentLines: string[],\n): void {\n if (comment.selected_text) return; // already set\n if (comment.line == null) return;\n\n const startIdx = comment.line - 1;\n const endIdx = (comment.end_line ?? comment.line) - 1;\n\n if (startIdx < 0 || endIdx >= documentLines.length) return;\n\n if (startIdx === endIdx) {\n let line = documentLines[startIdx];\n if (comment.start_column != null && comment.end_column != null) {\n line = line.slice(comment.start_column, comment.end_column);\n }\n comment.selected_text = line;\n } else {\n const lines: string[] = [];\n for (let i = startIdx; i <= endIdx; i++) {\n let l = documentLines[i];\n if (i === startIdx && comment.start_column != null) {\n l = l.slice(comment.start_column);\n }\n if (i === endIdx && comment.end_column != null) {\n l = l.slice(0, comment.end_column);\n }\n lines.push(l);\n }\n comment.selected_text = lines.join(\"\\n\");\n }\n\n // Also set the hash\n if (comment.selected_text) {\n comment.selected_text_hash = computeHash(comment.selected_text);\n }\n}\n\nexport function editComment(\n doc: MrsfDocument,\n commentId: string,\n opts: EditCommentOptions,\n): Comment {\n const comment = doc.comments.find((entry) => entry.id === commentId);\n if (!comment) {\n throw new Error(`Unknown comment '${commentId}'.`);\n }\n if (opts.actor && comment.author !== opts.actor) {\n throw new Error(\"Only the comment author can edit this comment.\");\n }\n if (opts.text.trim().length === 0) {\n throw new Error(\"Comment text cannot be empty.\");\n }\n\n comment.text = opts.text;\n return comment;\n}\n\n// ---------------------------------------------------------------------------\n// Resolve / Unresolve\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a comment by id. Per \u00A79, resolving a parent does NOT\n * automatically resolve its replies.\n *\n * Returns true if the comment was found and updated.\n */\nexport function resolveComment(\n doc: MrsfDocument,\n commentId: string,\n cascade = false,\n): boolean {\n const comment = doc.comments.find((c) => c.id === commentId);\n if (!comment) return false;\n\n comment.resolved = true;\n\n if (cascade) {\n // Cascade to direct replies only\n for (const c of doc.comments) {\n if (c.reply_to === commentId) {\n c.resolved = true;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Unresolve a comment by id.\n */\nexport function unresolveComment(\n doc: MrsfDocument,\n commentId: string,\n): boolean {\n const comment = doc.comments.find((c) => c.id === commentId);\n if (!comment) return false;\n comment.resolved = false;\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// Remove\n// ---------------------------------------------------------------------------\n\n/** Anchor fields that a reply may inherit from its parent on deletion. */\nconst ANCHOR_FIELDS = [\n \"line\",\n \"end_line\",\n \"start_column\",\n \"end_column\",\n \"selected_text\",\n \"selected_text_hash\",\n \"anchored_text\",\n \"commit\",\n] as const;\n\nexport interface RemoveCommentOptions {\n /**\n * When true, also delete all direct replies instead of promoting them.\n * Default: false (promote replies per \u00A79.1).\n */\n cascade?: boolean;\n}\n\n/**\n * Remove a comment by id. Per \u00A79.1, direct replies are promoted:\n * their anchor fields are inherited from the parent (when absent),\n * and their `reply_to` is re-pointed to the parent's parent (or cleared).\n *\n * If `cascade` is true, direct replies are removed along with the parent.\n *\n * Returns true if the comment was found and removed.\n */\nexport function removeComment(\n doc: MrsfDocument,\n commentId: string,\n opts?: RemoveCommentOptions,\n): boolean {\n const comment = doc.comments.find((c) => c.id === commentId);\n if (!comment) return false;\n\n if (opts?.cascade) {\n // Remove direct replies first\n doc.comments = doc.comments.filter(\n (c) => c.id === commentId || c.reply_to !== commentId,\n );\n } else {\n // Promote direct replies (\u00A79.1)\n for (const c of doc.comments) {\n if (c.reply_to !== commentId) continue;\n\n // Copy missing anchor fields from the parent\n for (const field of ANCHOR_FIELDS) {\n if (c[field] == null && comment[field] != null) {\n (c as Record<string, unknown>)[field] = comment[field];\n }\n }\n\n // Re-point reply_to to grandparent (or clear if parent was root)\n if (comment.reply_to) {\n c.reply_to = comment.reply_to;\n } else {\n delete c.reply_to;\n }\n }\n }\n\n // Remove the parent comment itself\n const idx = doc.comments.findIndex((c) => c.id === commentId);\n if (idx !== -1) doc.comments.splice(idx, 1);\n\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// List / Filter\n// ---------------------------------------------------------------------------\n\n/**\n * Filter comments based on criteria.\n */\nexport function filterComments(\n comments: Comment[],\n filter: CommentFilter,\n): Comment[] {\n return comments.filter((c) => {\n if (filter.open === true && c.resolved) return false;\n if (filter.resolved === true && !c.resolved) return false;\n if (filter.author && c.author !== filter.author) return false;\n if (filter.type && c.type !== filter.type) return false;\n if (filter.severity && c.severity !== filter.severity) return false;\n if (filter.orphaned === true && c.x_reanchor_status !== \"orphaned\") return false;\n if (filter.orphaned === false && c.x_reanchor_status === \"orphaned\") return false;\n return true;\n });\n}\n\n/**\n * Get a list of threads \u2014 groups of comments by their root ID via reply_to.\n * Returns a map of root comment ID \u2192 [root, ...replies in order].\n */\nexport function getThreads(\n comments: Comment[],\n): Map<string, Comment[]> {\n const threads = new Map<string, Comment[]>();\n const replyMap = new Map<string, string>(); // child id \u2192 root id\n\n // First pass: find all roots and build reply chains\n for (const c of comments) {\n if (!c.reply_to) {\n threads.set(c.id, [c]);\n } else {\n replyMap.set(c.id, c.reply_to);\n }\n }\n\n // Resolve transitive reply_to chains to roots\n function findRoot(id: string): string {\n const parent = replyMap.get(id);\n if (!parent) return id;\n return findRoot(parent);\n }\n\n // Second pass: attach replies to their root thread\n for (const c of comments) {\n if (c.reply_to) {\n const rootId = findRoot(c.id);\n if (!threads.has(rootId)) {\n threads.set(rootId, []);\n }\n threads.get(rootId)!.push(c);\n }\n }\n\n return threads;\n}\n\n// ---------------------------------------------------------------------------\n// Summary\n// ---------------------------------------------------------------------------\n\nexport interface CommentSummary {\n total: number;\n open: number;\n resolved: number;\n orphaned: number;\n threads: number;\n byType: Record<string, number>;\n bySeverity: Record<string, number>;\n}\n\n/**\n * Generate summary statistics for a comment list.\n */\nexport function summarize(comments: Comment[]): CommentSummary {\n const summary: CommentSummary = {\n total: comments.length,\n open: 0,\n resolved: 0,\n orphaned: 0,\n threads: 0,\n byType: {},\n bySeverity: {},\n };\n\n const roots = new Set<string>();\n\n for (const c of comments) {\n if (c.resolved) summary.resolved++;\n else summary.open++;\n\n if (c.x_reanchor_status === \"orphaned\") summary.orphaned++;\n\n if (c.type) {\n summary.byType[c.type] = (summary.byType[c.type] ?? 0) + 1;\n }\n if (c.severity) {\n summary.bySeverity[c.severity] = (summary.bySeverity[c.severity] ?? 0) + 1;\n }\n\n if (!c.reply_to) roots.add(c.id);\n }\n\n summary.threads = roots.size;\n return summary;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["yaml", "import_js_yaml", "path", "import_promises", "import_node_path", "DEFAULT_THRESHOLD", "HIGH_THRESHOLD", "addComment", "applyReanchorResults", "calibrateAnchorEvidence", "combinedScore", "computeHash", "createAnchorContextIndex", "createRevisionProjection", "detectRenames", "discoverAllSidecars", "discoverSidecar", "editComment", "exactMatch", "filterComments", "findRepoRoot", "findWorkspaceRoot", "formatAuthor", "fuzzySearch", "getCurrentCommit", "getDiff", "getFileAtCommit", "getLineShift", "getStagedFiles", "getThreads", "isGitAvailable", "isStale", "loadConfig", "newCommentId", "normalizeCommentExtensions", "normalizedMatch", "parseAuthor", "parseDiffHunks", "parseSidecar", "parseSidecarContent", "parseSidecarContentLenient", "parseSidecarLenient", "populateSelectedText", "readDocumentLines", "reanchorComment", "reanchorDocument", "reanchorDocumentLines", "reanchorDocumentText", "reanchorFile", "reconcileCommentAnchors", "removeComment", "resolveAnchor", "resolveComment", "resolveCommit", "resolveSidecarPaths", "sidecarToDocument", "summarize", "syncHash", "toJson", "toReanchorLines", "toYaml", "unresolveComment", "validate", "validateDocument", "validateFile", "writeSidecar", "path", "yaml", "import_node_path", "path", "import_promises", "import_node_fs", "import_node_path", "import_yaml", "path", "yamlParse", "import_promises", "import_node_path", "AjvModule", "addFormatsModule", "path", "parseSidecar", "levenshtein", "index", "execFileCb", "extractText", "tokenize", "getLineShift", "extractText", "deduplicateCandidates", "import_node_path", "path", "uuidv4", "findWorkspaceRoot", "loadConfig", "discoverSidecar", "sidecarToDocument", "discoverAllSidecars", "resolveSidecarPaths", "parseSidecar", "parseSidecarContent", "parseSidecarLenient", "parseSidecarContentLenient", "readDocumentLines", "computeHash", "syncHash", "toYaml", "toJson", "writeSidecar", "validate", "validateFile", "validateDocument", "exactMatch", "normalizedMatch", "fuzzySearch", "combinedScore", "isGitAvailable", "findRepoRoot", "getCurrentCommit", "resolveCommit", "isStale", "getDiff", "getLineShift", "getFileAtCommit", "getStagedFiles", "detectRenames", "parseDiffHunks", "DEFAULT_THRESHOLD", "HIGH_THRESHOLD", "reanchorComment", "reanchorDocumentLines", "reanchorDocumentText", "toReanchorLines", "resolveAnchor", "reanchorDocument", "applyReanchorResults", "reanchorFile", "createAnchorContextIndex", "reconcileCommentAnchors", "createRevisionProjection", "calibrateAnchorEvidence", "addComment", "editComment", "normalizeCommentExtensions", "populateSelectedText", "resolveComment", "unresolveComment", "removeComment", "filterComments", "getThreads", "summarize", "formatAuthor", "parseAuthor", "newCommentId"]
7
7
  }