{
  "version": 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"],
  "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 getGitUserName = git.getGitUserName;\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 * Read the repository-local Git author name.\n *\n * Only `.git/config` is considered; global Git identity is intentionally\n * ignored so callers can distinguish repository identity from user defaults.\n */\nexport async function getGitUserName(repoRoot: string): Promise<string | null> {\n  if (!(await isGitAvailable())) return null;\n  try {\n    const { stdout } = await execFile(\n      \"git\",\n      [\"config\", \"--local\", \"--get\", \"user.name\"],\n      { cwd: repoRoot, timeout: GIT_TIMEOUT },\n    );\n    const name = stdout.trim();\n    return name || null;\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"],
  "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCO,SAAS,oBACd,SACA,cACc;AACd,QAAM,UAAU,QAAQ,KAAK;AAE7B,MAAI;AAGJ,QAAM,SACJ,QAAQ,WAAW,GAAG,KACrB,gBAAgB,aAAa,SAAS,cAAc;AAEvD,MAAI,QAAQ;AACV,QAAI;AACF,eAAS,KAAK,MAAM,OAAO;AAAA,IAC7B,SAAS,GAAG;AACV,YAAM,IAAI,MAAM,yBAA0B,EAAY,OAAO,EAAE;AAAA,IACjE;AAAA,EACF,OAAO;AACL,QAAI;AACF,eAAS,gBAAAA,QAAK,KAAK,SAAS,EAAE,QAAQ,gBAAAA,QAAK,YAAY,CAAC;AAAA,IAC1D,SAAS,GAAG;AACV,YAAM,IAAI,MAAM,yBAA0B,EAAY,OAAO,EAAE;AAAA,IACjE;AAAA,EACF;AAEA,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AAEA,SAAO;AACT;AAKO,SAAS,2BACd,SACA,cACoB;AACpB,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,KAAK,MAAM,OAAO,gBAAgB;AAAA,EAC7C;AAEA,QAAM,SACJ,QAAQ,WAAW,GAAG,KACrB,gBAAgB,aAAa,SAAS,cAAc;AAGvD,MAAI;AACJ,MAAI;AACF,aAAS,SAAS,KAAK,MAAM,OAAO,IAAI,gBAAAA,QAAK,KAAK,SAAS,EAAE,QAAQ,gBAAAA,QAAK,YAAY,CAAC;AAAA,EACzF,SAAS,GAAG;AAEV,QAAI,CAAC,QAAQ;AACX,aAAO,YAAY,OAAO;AAAA,IAC5B;AACA,WAAO,EAAE,KAAK,MAAM,OAAO,yBAA0B,EAAY,OAAO,GAAG;AAAA,EAC7E;AAEA,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,WAAO,EAAE,KAAK,MAAM,OAAO,0CAA0C;AAAA,EACvE;AAEA,QAAM,MAAM;AACZ,QAAM,MAAoB;AAAA,IACxB,cAAc,OAAO,IAAI,iBAAiB,WAAW,IAAI,eAAe;AAAA,IACxE,UAAU,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;AAAA,IAC5D,UAAU,CAAC;AAAA,EACb;AAEA,MAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAChC,WAAO;AAAA,MACL;AAAA,MACA,OAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,OAAkB,CAAC;AACzB,QAAM,MAAgB,CAAC;AAEvB,WAAS,IAAI,GAAG,IAAI,IAAI,SAAS,QAAQ,KAAK;AAC5C,UAAM,IAAI,IAAI,SAAS,CAAC;AACxB,QAAI,KAAK,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC,KAAK,OAAQ,EAA8B,OAAO,UAAU;AAC5G,WAAK,KAAK,CAAY;AAAA,IACxB,OAAO;AACL,UAAI,KAAK,CAAC;AAAA,IACZ;AAAA,EACF;AAEA,MAAI,WAAW;AAEf,MAAI,IAAI,SAAS,GAAG;AAClB,WAAO;AAAA,MACL;AAAA,MACA,OAAO,GAAG,IAAI,MAAM,2BAA2B,IAAI,KAAK,IAAI,CAAC;AAAA,MAC7D,iBAAiB;AAAA,IACnB;AAAA,EACF;AAEA,SAAO,EAAE,IAAI;AACf;AAMA,SAAS,YAAY,SAAqC;AACxD,QAAM,WAAsB,CAAC;AAC7B,MAAI,eAAe;AACnB,MAAI,WAAW;AAGf,QAAM,eAAe,QAAQ,MAAM,mCAAmC;AACtE,MAAI,aAAc,gBAAe,aAAa,CAAC,EAAE,KAAK;AAEtD,QAAM,WAAW,QAAQ,MAAM,+BAA+B;AAC9D,MAAI,SAAU,YAAW,SAAS,CAAC,EAAE,KAAK;AAG1C,QAAM,SAAS,QAAQ,MAAM,iBAAiB;AAE9C,aAAW,SAAS,QAAQ;AAC1B,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAQ,WAAW,OAAO,EAAG;AAGlC,QAAI;AACF,YAAM,SAAS,gBAAAA,QAAK,KAAK,SAAS,EAAE,QAAQ,gBAAAA,QAAK,YAAY,CAAC;AAC9D,UAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG;AAC9C,cAAM,IAAI,OAAO,CAAC;AAClB,YAAI,KAAK,OAAO,MAAM,YAAY,OAAQ,EAA8B,OAAO,UAAU;AACvF,mBAAS,KAAK,CAAY;AAAA,QAC5B;AAAA,MACF,WAAW,UAAU,OAAO,WAAW,YAAY,OAAQ,OAAmC,OAAO,UAAU;AAC7G,iBAAS,KAAK,MAAiB;AAAA,MACjC;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,MAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACZ;AAEA,SAAO;AAAA,IACL,KAAK,SAAS,SAAS,IAAI,MAAM;AAAA,IACjC,OAAO,+BAA+B,SAAS,MAAM;AAAA,IACrD,iBAAiB,SAAS,SAAS,IAAI,WAAW;AAAA,EACpD;AACF;AASO,SAAS,OAAO,KAA2B;AAChD,QAAM,UAAU,IAAI,qBAAS,GAAG;AAChC,SAAO,QAAQ,SAAS,EAAE,WAAW,EAAE,CAAC;AAC1C;AAKO,SAAS,OAAO,KAA2B;AAChD,SAAO,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI;AACxC;AAnNA,IAUAC,iBACA;AAXA;AAAA;AAAA;AAUA,IAAAA,kBAAiB;AACjB,kBAAyB;AAAA;AAAA;;;ACXzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBA,eAAsB,aAAa,UAAyC;AAC1E,QAAM,MAAM,kBAAAC,QAAK,QAAQ,QAAQ;AACjC,QAAM,UAAU,UAAM,2BAAS,KAAK,OAAO;AAC3C,SAAO,oBAAoB,SAAS,GAAG;AACzC;AASA,eAAsB,oBACpB,UAC6B;AAC7B,QAAM,MAAM,kBAAAA,QAAK,QAAQ,QAAQ;AACjC,MAAI;AACJ,MAAI;AACF,cAAU,UAAM,2BAAS,KAAK,OAAO;AAAA,EACvC,SAAS,GAAG;AACV,WAAO,EAAE,KAAK,MAAM,OAAO,qBAAsB,EAAY,OAAO,GAAG;AAAA,EACzE;AAEA,SAAO,2BAA2B,SAAS,GAAG;AAChD;AAMA,eAAsB,kBACpB,UACmB;AACnB,QAAM,UAAU,UAAM,2BAAS,kBAAAA,QAAK,QAAQ,QAAQ,GAAG,OAAO;AAC9D,QAAM,QAAQ,QAAQ,QAAQ,UAAU,IAAI,EAAE,MAAM,IAAI;AAExD,SAAO,CAAC,IAAI,GAAG,KAAK;AACtB;AA9DA,IAIAC,kBACAC;AALA;AAAA;AAAA;AAIA,IAAAD,mBAAyB;AACzB,IAAAC,oBAAiB;AAEjB;AAQA;AAAA;AAAA;;;ACfA;AAAA;AAAA,2BAAAC;AAAA,EAAA,sBAAAC;AAAA,EAAA,kBAAAC;AAAA,EAAA,4BAAAC;AAAA,EAAA,+BAAAC;AAAA,EAAA,qBAAAC;AAAA,EAAA,mBAAAC;AAAA,EAAA,gCAAAC;AAAA,EAAA,gCAAAC;AAAA,EAAA,qBAAAC;AAAA,EAAA,2BAAAC;AAAA,EAAA,uBAAAC;AAAA,EAAA,mBAAAC;AAAA,EAAA,kBAAAC;AAAA,EAAA,sBAAAC;AAAA,EAAA,oBAAAC;AAAA,EAAA,yBAAAC;AAAA,EAAA,oBAAAC;AAAA,EAAA,mBAAAC;AAAA,EAAA,wBAAAC;AAAA,EAAA,eAAAC;AAAA,EAAA,uBAAAC;AAAA,EAAA,sBAAAC;AAAA,EAAA,oBAAAC;AAAA,EAAA,sBAAAC;AAAA,EAAA,kBAAAC;AAAA,EAAA,sBAAAC;AAAA,EAAA,eAAAC;AAAA,EAAA,kBAAAC;AAAA,EAAA;AAAA,sBAAAC;AAAA,EAAA,kCAAAC;AAAA,EAAA,uBAAAC;AAAA,EAAA,mBAAAC;AAAA,EAAA,sBAAAC;AAAA,EAAA,oBAAAC;AAAA,EAAA,2BAAAC;AAAA,EAAA,kCAAAC;AAAA,EAAA,2BAAAC;AAAA,EAAA,4BAAAC;AAAA,EAAA,yBAAAC;AAAA,EAAA,uBAAAC;AAAA,EAAA,wBAAAC;AAAA,EAAA,6BAAAC;AAAA,EAAA,4BAAAC;AAAA,EAAA,oBAAAC;AAAA,EAAA,+BAAAC;AAAA,EAAA,qBAAAC;AAAA,EAAA,qBAAAC;AAAA,EAAA,sBAAAC;AAAA,EAAA,qBAAAC;AAAA,EAAA,2BAAAC;AAAA,EAAA,yBAAAC;AAAA,EAAA,iBAAAC;AAAA,EAAA,gBAAAC;AAAA,EAAA,cAAAC;AAAA,EAAA,uBAAAC;AAAA,EAAA,cAAAC;AAAA,EAAA,wBAAAC;AAAA,EAAA,gBAAAC;AAAA,EAAA,wBAAAC;AAAA,EAAA,oBAAAC;AAAA,EAAA,oBAAAC;AAAA;AAAA;;;ACQA,sBAAyB;AACzB,qBAA2B;AAC3B,uBAAiB;AACjB,qBAAiB;AAGjB,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAM,sBAAsB;AAMrB,SAAS,kBAAkB,UAA0B;AAC1D,MAAI,MAAM,iBAAAC,QAAK,QAAQ,QAAQ;AAC/B,QAAM,EAAE,KAAK,IAAI,iBAAAA,QAAK,MAAM,GAAG;AAC/B,SAAO,QAAQ,MAAM;AACnB,YACE,2BAAW,iBAAAA,QAAK,KAAK,KAAK,eAAe,CAAC,SAC1C,2BAAW,iBAAAA,QAAK,KAAK,KAAK,MAAM,CAAC,GACjC;AACA,aAAO;AAAA,IACT;AACA,UAAM,iBAAAA,QAAK,QAAQ,GAAG;AAAA,EACxB;AACA,SAAO,iBAAAA,QAAK,QAAQ,QAAQ;AAC9B;AAKA,eAAsB,WACpB,eACA,YAC4B;AAC5B,QAAM,UAAU,aACZ,iBAAAA,QAAK,QAAQ,UAAU,IACvB,iBAAAA,QAAK,KAAK,eAAe,eAAe;AAE5C,MAAI,KAAC,2BAAW,OAAO,EAAG,QAAO;AAEjC,QAAM,MAAM,UAAM,0BAAS,SAAS,OAAO;AAC3C,QAAM,SAAS,eAAAC,QAAK,KAAK,KAAK,EAAE,QAAQ,eAAAA,QAAK,YAAY,CAAC;AAE1D,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAElD,QAAM,SAAqB,CAAC;AAE5B,MAAI,OAAO,OAAO,iBAAiB,UAAU;AAC3C,UAAM,KAAK,OAAO;AAGlB,QAAI,iBAAAD,QAAK,WAAW,EAAE,GAAG;AACvB,YAAM,IAAI;AAAA,QACR,0DAA0D,EAAE;AAAA,MAC9D;AAAA,IACF;AAGA,QAAI,GAAG,SAAS,IAAI,GAAG;AACrB,YAAM,IAAI;AAAA,QACR,wDAAwD,EAAE;AAAA,MAC5D;AAAA,IACF;AAEA,WAAO,eAAe;AAAA,EACxB;AAEA,SAAO;AACT;AAQA,eAAsB,gBACpB,cACA,UAAiD,CAAC,GACjC;AACjB,QAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;AACvC,QAAM,gBAAgB,kBAAkB,GAAG;AAC3C,QAAM,SAAS,MAAM,WAAW,eAAe,QAAQ,UAAU;AAGjE,QAAM,SAAS,iBAAAA,QAAK,WAAW,YAAY,IACvC,iBAAAA,QAAK,SAAS,eAAe,YAAY,IACzC;AAEJ,MAAI,QAAQ,cAAc;AAExB,WAAO,iBAAAA,QAAK,KAAK,eAAe,OAAO,cAAc,SAAS,cAAc;AAAA,EAC9E;AAGA,SAAO,iBAAAA,QAAK,KAAK,eAAe,SAAS,cAAc;AACzD;AAOO,SAAS,kBACd,aACA,UAA4B,CAAC,GACrB;AACR,QAAM,MAAM,iBAAAA,QAAK,QAAQ,WAAW;AAEpC,MAAI,IAAI,SAAS,cAAc,GAAG;AAChC,WAAO,IAAI,MAAM,GAAG,CAAC,eAAe,MAAM;AAAA,EAC5C,WAAW,IAAI,SAAS,mBAAmB,GAAG;AAC5C,WAAO,IAAI,MAAM,GAAG,CAAC,oBAAoB,MAAM;AAAA,EACjD;AAEA,SAAO;AACT;AAKA,eAAsB,oBACpB,SACmB;AACnB,QAAM,EAAE,SAAS,KAAK,IAAI,MAAM,OAAO,kBAAkB;AACzD,QAAM,UAAoB,CAAC;AAE3B,iBAAe,KAAK,KAA4B;AAC9C,UAAM,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC;AAC1D,eAAW,SAAS,SAAS;AAC3B,YAAM,OAAO,iBAAAA,QAAK,KAAK,KAAK,MAAM,IAAI;AACtC,UAAI,MAAM,YAAY,GAAG;AACvB,YAAI,MAAM,SAAS,kBAAkB,MAAM,SAAS,OAAQ;AAC5D,cAAM,KAAK,IAAI;AAAA,MACjB,WACE,MAAM,KAAK,SAAS,cAAc,KAClC,MAAM,KAAK,SAAS,mBAAmB,GACvC;AACA,gBAAQ,KAAK,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,KAAK,OAAO;AAC5B,MAAI,EAAE,OAAO,GAAG;AACd,YAAQ,KAAK,iBAAAA,QAAK,QAAQ,OAAO,CAAC;AAAA,EACpC,OAAO;AACL,UAAM,KAAK,iBAAAA,QAAK,QAAQ,OAAO,CAAC;AAAA,EAClC;AAEA,SAAO;AACT;;;ACzJA,IAAAE,oBAAiB;AAGjB,IAAM,qBAAqB,CAAC,gBAAgB,cAAc;AAE1D,SAAS,cAAc,MAAuB;AAC5C,SAAO,mBAAmB,KAAK,CAAC,QAAQ,KAAK,SAAS,GAAG,CAAC;AAC5D;AAWA,eAAsB,oBACpB,OACA,KACmB;AACnB,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,OAAO,kBAAkB,GAAG;AAClC,WAAO,oBAAoB,QAAQ,GAAG;AAAA,EACxC;AAEA,QAAM,WAAqB,CAAC;AAC5B,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,kBAAAC,QAAK,QAAQ,KAAK,CAAC;AAC/B,QAAI,cAAc,GAAG,GAAG;AACtB,eAAS,KAAK,GAAG;AAAA,IACnB,OAAO;AAEL,YAAM,UAAU,MAAM,gBAAgB,KAAK,EAAE,IAAI,CAAC;AAClD,eAAS,KAAK,OAAO;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AACT;;;AFtCA;;;AGIA,IAAAC,mBAAoD;AACpD,IAAAC,kBAA2B;AAC3B,yBAAwC;AACxC,IAAAC,oBAAiB;AACjB,IAAAC,eAAgD;AAEhD;AA4XA;AAjXA,IAAM,aAAa,oBAAI,IAA2B;AAMlD,SAAS,aAAa,KAAa,IAAwC;AACzE,QAAM,OAAO,WAAW,IAAI,GAAG,KAAK,QAAQ,QAAQ;AACpD,QAAM,OAAO,KAAK,KAAK,IAAI,EAAE;AAC7B,aAAW,IAAI,KAAK,IAAI;AAExB,OAAK,KAAK,MAAM;AACd,QAAI,WAAW,IAAI,GAAG,MAAM,KAAM,YAAW,OAAO,GAAG;AAAA,EACzD,GAAG,MAAM;AACP,QAAI,WAAW,IAAI,GAAG,MAAM,KAAM,YAAW,OAAO,GAAG;AAAA,EACzD,CAAC;AACD,SAAO;AACT;AAWA,eAAe,gBACb,UACA,SACe;AACf,QAAM,MAAM,WAAW,UAAM,gCAAY,CAAC,EAAE,SAAS,KAAK,IAAI;AAC9D,MAAI;AACF,cAAM,4BAAU,KAAK,SAAS,OAAO;AACrC,cAAM,yBAAO,KAAK,QAAQ;AAAA,EAC5B,SAAS,KAAK;AAEZ,QAAI;AAAE,gBAAM,yBAAO,GAAG;AAAA,IAAG,QAAQ;AAAA,IAAe;AAChD,UAAM;AAAA,EACR;AACF;AASO,SAAS,YAAY,MAAsB;AAChD,aAAO,+BAAW,QAAQ,EAAE,OAAO,MAAM,OAAO,EAAE,OAAO,KAAK;AAChE;AAOO,SAAS,SAAS,SAA2B;AAClD,MAAI,QAAQ,iBAAiB,QAAQ,QAAQ,cAAc,SAAS,GAAG;AACrE,YAAQ,qBAAqB,YAAY,QAAQ,aAAa;AAAA,EAChE,OAAO;AACL,WAAO,QAAQ;AAAA,EACjB;AACA,SAAO;AACT;AAaA,IAAM,oBAAoB;AAAA,EACxB;AAAA,EAAM;AAAA,EAAU;AAAA,EAAa;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAC7C;AAAA,EAAY;AAAA,EAAY;AAAA,EAAQ;AAAA,EAAY;AAAA,EAAgB;AAAA,EAC5D;AAAA,EAAiB;AAAA,EAAsB;AAAA,EAAiB;AAC1D;AAaA,SAAS,cAAc,GAAoB;AACzC,MAAI,aAAa,KAAM,QAAO,KAAK,UAAU,EAAE,YAAY,CAAC;AAC5D,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAW,QAAO,OAAO,CAAC;AACpE,MAAI,OAAO,MAAM,UAAU;AAEzB,QAAI,MAAM,GAAI,QAAO,KAAK,UAAU,CAAC;AAGrC,QACE,MAAM,UAAU,MAAM,WAAW,MAAM,UACvC,MAAM,UAAU,MAAM,WAAW,MAAM,UACvC,MAAM,UAAU,MAAM,WAAW,MAAM,UACvC,MAAM,SAAS,MAAM,QAAQ,MAAM,QAAQ,MAAM,SACjD,MAAM,SAAS,MAAM,QAAQ,MAAM,QAAQ,MAAM,SACjD,MAAM,SAAS,MAAM,QAAQ,MAAM,QAAQ,MAAM,SACjD,MAAM,OAAO,MAAM,UAAU,MAAM,WAAW,MAAM,QACpD;AACA,aAAO,KAAK,UAAU,CAAC;AAAA,IACzB;AAGA,QAAI,MAAM,KAAK,CAAC,EAAG,QAAO,KAAK,UAAU,CAAC;AAY1C,QAAI,oCAAoC,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG;AACtF,aAAO;AAAA,IACT;AAGA,WAAO,KAAK,UAAU,CAAC;AAAA,EACzB;AACA,SAAO,OAAO,CAAC;AACjB;AAGA,SAAS,UAAU,GAAoB;AACrC,SAAO,cAAc,CAAC,EAAE,WAAW,GAAG,IAAI,yBAAyB;AACrE;AAEA,SAAS,kBAAkB,OAAyB;AAClD,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,SAAO,OAAO,UAAU,YAAY,EAAE,iBAAiB;AACzD;AAEA,SAAS,+BAA+B,KAA4B;AAClE,SAAO,IAAI,SAAS;AAAA,IAAK,CAAC,YACxB,OAAO,QAAQ,OAAO,EAAE;AAAA,MAAK,CAAC,CAAC,KAAK,KAAK,MACvC,CAAC,kBAAkB,SAAS,GAAG,KAAK,UAAU,UAAa,kBAAkB,KAAK;AAAA,IACpF;AAAA,EACF;AACF;AAIA,IAAM,KAAK;AASX,SAAS,eACP,KACA,OACA,QACA,SACS;AACT,QAAM,QAAQ,UACV,CAAC,IACD,CAAC,EAAE,MAAM,SAAS,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,OAAO,MAAM,EAAE,CAAC;AACxE,SAAO;AAAA,IACL;AAAA,IACA,KAAK,EAAE,MAAM,UAAU,QAAQ,GAAG,QAAQ,QAAQ,IAAI;AAAA,IACtD,KAAK;AAAA,MACH,EAAE,MAAM,iBAAiB,QAAQ,GAAG,QAAQ,QAAQ,IAAI;AAAA,MACxD,EAAE,MAAM,SAAS,QAAQ,GAAG,QAAQ,QAAQ,IAAI;AAAA,IAClD;AAAA,IACA,OAAO;AAAA,MACL,MAAM,UAAU,KAAK;AAAA,MACrB,QAAQ;AAAA,MACR;AAAA,MACA,QAAQ,cAAc,KAAK;AAAA,MAC3B,KAAK,CAAC,EAAE,MAAM,WAAW,QAAQ,GAAG,QAAQ,QAAQ,GAAG,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;AAMA,SAAS,eAAe,SAAkB,WAA4B;AACpE,QAAM,YAAY,YAAY;AAC9B,QAAM,QAAmB,CAAC;AAG1B,aAAW,OAAO,mBAAmB;AACnC,UAAM,MAAO,QAAoC,GAAG;AACpD,QAAI,QAAQ,QAAW;AACrB,YAAM,KAAK,eAAe,KAAK,KAAK,WAAW,MAAM,WAAW,CAAC,CAAC;AAAA,IACpE;AAAA,EACF;AAEA,aAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACtC,QACE,CAAC,kBAAkB,SAAS,GAAG,KAC9B,QAAoC,GAAG,MAAM,QAC9C;AACA,YAAM;AAAA,QACJ;AAAA,UACE;AAAA,UACC,QAAoC,GAAG;AAAA,UACxC;AAAA,UACA,MAAM,WAAW;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,MACL,EAAE,MAAM,WAAW,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG;AAAA,MACpD,EAAE,MAAM,SAAS,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,OAAO,SAAS,EAAE;AAAA,MACrE,EAAE,MAAM,gBAAgB,QAAQ,GAAG,QAAQ,WAAW,QAAQ,IAAI;AAAA,MAClE,EAAE,MAAM,SAAS,QAAQ,GAAG,QAAQ,WAAW,QAAQ,IAAI;AAAA,IAC7D;AAAA,IACA,OAAO,EAAE,MAAM,aAAa,QAAQ,GAAG,QAAQ,WAAW,MAAM;AAAA,EAClE;AACF;AAKA,SAAS,gBAAgB,QAAmC;AAC1D,SAAO,OAAO,KAAK,CAAC,MAAe,EAAE,SAAS,UAAU,KAAK;AAC/D;AAGA,SAAS,gBACP,UACA,SACgB;AAChB,SACE,SAAS,OAAO;AAAA,IACd,CAAC,SAAkB,KAAK,KAAK,WAAW;AAAA,EAC1C,KAAK;AAET;AAGA,SAAS,gBAAgB,UAAmB,SAAyB;AACnE,SACE,SAAS,OAAO;AAAA,IACd,CAAC,SAAkB,KAAK,KAAK,WAAW;AAAA,EAC1C,KAAK;AAET;AAGA,SAAS,aAAa,UAAkC;AACtD,QAAM,QAAQ,gBAAgB,UAAU,IAAI;AAC5C,MAAI,CAAC,OAAO,OAAO,OAAQ,QAAO;AAClC,QAAM,MAAc,MAAM,MAAM;AAEhC,MAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAG;AAC5C,WAAO,IAAI,MAAM,GAAG,EAAE;AAAA,EACxB;AACA,SAAO;AACT;AAQA,SAAS,gBAAgB,OAAgB,UAA4B;AACnE,QAAM,SAAS,cAAc,QAAQ;AACrC,MAAI,MAAM,OAAO,WAAW,OAAQ,QAAO;AAC3C,QAAM,MAAM,SAAS;AAErB,QAAM,MAAM,OAAO,UAAU,QAAQ;AACrC,SAAO;AACT;AAYA,SAAS,iBACP,UACA,SACA,eACM;AACN,QAAM,aAAa;AAGnB,QAAM,eAAe,oBAAI,IAAY;AACrC,aAAW,QAAQ,SAAS,SAAS,CAAC,GAAG;AACvC,QAAI,KAAK,KAAK,OAAQ,cAAa,IAAI,KAAK,IAAI,MAAgB;AAAA,EAClE;AAEA,QAAM,UAAU,oBAAI,IAAI,CAAC,GAAG,cAAc,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC;AAClE,QAAM,SAAS,SAAS,UAAU;AAElC,aAAW,OAAO,SAAS;AACzB,UAAM,SAAS,WAAW,GAAG;AAE7B,QAAI,WAAW,QAAW;AAExB,UAAI,aAAa,IAAI,GAAG,GAAG;AACzB,cAAM,MAAM,gBAAgB,UAAU,GAAG;AACzC,YAAI,OAAO,EAAG,UAAS,MAAM,OAAO,KAAK,CAAC;AAAA,MAC5C;AACA;AAAA,IACF;AAEA,UAAM,QAAQ,gBAAgB,UAAU,GAAG;AAC3C,QAAI,OAAO;AAKT,YAAM,aAAa,cAAc,GAAG;AACpC,UAAI,UAAU,YAAY,MAAM,GAAG;AAEjC;AAAA,MACF;AAEA,sBAAgB,OAAO,MAAM;AAAA,IAC/B,OAAO;AAEL,eAAS,MAAM,KAAK,eAAe,KAAK,QAAQ,QAAQ,KAAK,CAAC;AAAA,IAChE;AAAA,EACF;AACF;AAMA,SAAS,UAAU,GAAY,GAAqB;AAClD,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,OAAO,MAAM,OAAO,EAAG,QAAO;AAElC,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO,MAAM;AACjE,SAAO;AACT;AAsBA,eAAsB,aACpB,UACA,KACe;AACf,QAAM,MAAM,kBAAAC,QAAK,QAAQ,QAAQ;AACjC,SAAO,aAAa,KAAK,MAAM,qBAAqB,KAAK,GAAG,CAAC;AAC/D;AAKA,eAAe,qBACb,KACA,KACe;AACf,QAAM,SAAS,IAAI,SAAS,cAAc;AAE1C,aAAW,WAAW,IAAI,SAAU,UAAS,OAAO;AAEpD,MAAI,QAAQ;AAEV,UAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACtC;AAAA,EACF;AAIA,MAAI,+BAA+B,GAAG,GAAG;AACvC,UAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACtC;AAAA,EACF;AAIA,MAAI,KAAC,4BAAW,GAAG,GAAG;AACpB,UAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACtC;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,UAAM,2BAAS,KAAK,OAAO;AAAA,EACnC,QAAQ;AACN,UAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACtC;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AACF,aAAS,CAAC,GAAG,IAAI,oBAAO,EAAE,MAAM,GAAG,CAAC;AAAA,EACtC,QAAQ;AAEN,UAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACtC;AAAA,EACF;AAIA,MAAI,aAAkC;AACtC,MAAI;AACF,qBAAa,aAAAC,OAAU,GAAG;AAAA,EAC5B,QAAQ;AAAA,EAER;AAKA,MAAI,cAAe,CAAC,MAAM,QAAQ,WAAW,QAAQ,GAAI;AACvD,UAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACtC;AAAA,EACF;AAGA,QAAM,cAAc,oBAAI,IAAqC;AAC7D,MAAI,YAAY,UAAU;AACxB,eAAW,KAAK,WAAW,UAAU;AACnC,UAAI,EAAE,GAAI,aAAY,IAAI,EAAE,IAAI,CAA4B;AAAA,IAC9D;AAAA,EACF;AAKA,aAAW,WAAW,IAAI,UAAU;AAClC,UAAM,MAAM,YAAY,IAAI,QAAQ,EAAE;AACtC,QAAI,CAAC,KAAK;AAER,eAAS,OAAO;AAAA,IAClB,OAAO;AAGL,YAAM,cAAc,CAAC,UAAU,IAAI,eAAe,QAAQ,aAAa;AACvE,YAAM,UAAU,IAAI,uBAAuB;AAC3C,UAAI,eAAe,SAAS;AAC1B,iBAAS,OAAO;AAAA,MAClB,OAAO;AAEL,eAAO,QAAQ;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,gBAAgB,MAAM;AACvC,MAAI,CAAC,UAAU,SAAS,SAAS,MAAM,SAAS,aAAa;AAC3D,UAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACtC;AAAA,EACF;AAEA,QAAM,OAAgB,SAAS;AAI/B,QAAM,eAAe,gBAAgB,MAAM,cAAc;AACzD,MAAI,gBAAgB,CAAC,UAAU,YAAY,cAAc,IAAI,YAAY,GAAG;AAC1E,oBAAgB,cAAc,IAAI,YAAY;AAAA,EAChD;AAEA,QAAM,gBAAgB,gBAAgB,MAAM,UAAU;AACtD,MAAI,iBAAiB,CAAC,UAAU,YAAY,UAAU,IAAI,QAAQ,GAAG;AACnE,oBAAgB,eAAe,IAAI,QAAQ;AAAA,EAC7C;AAIA,QAAM,gBAAgB,gBAAgB,MAAM,UAAU;AACtD,MAAI,CAAC,eAAe,SAAS,cAAc,MAAM,SAAS,aAAa;AAErE,UAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACtC;AAAA,EACF;AAEA,QAAM,MAAe,cAAc;AACnC,QAAM,YAAoB,IAAI,UAAU;AAGxC,QAAM,eAAe,oBAAI,IAA6C;AACtE,WAAS,IAAI,GAAG,IAAI,IAAI,MAAM,QAAQ,KAAK;AACzC,UAAM,OAAO,IAAI,MAAM,CAAC;AACxB,UAAM,MAAM,KAAK;AACjB,QAAI,KAAK,SAAS,aAAa;AAC7B,YAAM,KAAK,aAAa,GAAG;AAC3B,UAAI,GAAI,cAAa,IAAI,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;AAAA,IAChD;AAAA,EACF;AAIA,QAAM,WAAW,IAAI,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACtD,QAAM,cAAyB,CAAC;AAEhC,aAAW,WAAW,IAAI,UAAU;AAClC,UAAM,WAAW,aAAa,IAAI,QAAQ,EAAE;AAC5C,QAAI,UAAU;AAEZ,YAAM,gBAAgB,YAAY,IAAI,QAAQ,EAAE,KAAK,CAAC;AACtD,uBAAiB,SAAS,KAAK,SAAS,aAAa;AAGrD,kBAAY,KAAK,IAAI,MAAM,SAAS,KAAK,CAAC;AAAA,IAC5C,OAAO;AAEL,kBAAY,KAAK,eAAe,SAAS,SAAS,CAAC;AAAA,IACrD;AAAA,EACF;AAEA,MAAI,QAAQ;AAmBZ,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,mBAAmB,IAAI,UAAU,cAAc,IAAI;AACzD,UAAM,gBAAgB,aAAa,OAAO,IACtC,CAAC,GAAG,aAAa,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,IACpD;AAEJ,UAAM,WAAW,YAAY,CAAC;AAG9B,UAAM,kBACJ,iBACA,IAAI,MAAM,CAAC,GAAG,UAAU,cAAc;AAExC,QAAI,CAAC,mBAAmB,SAAS,OAAO;AAEtC,YAAM,UAAU,SAAS,MAAM;AAAA,QAC7B,CAAC,MAAe,EAAE,SAAS;AAAA,MAC7B;AACA,UAAI,UAAU,GAAG;AAEf,cAAM,WAAW,SAAS,MACvB,MAAM,GAAG,OAAO,EAChB,MAAM,CAAC,MAAe,EAAE,SAAS,WAAW,EAAE,SAAS,SAAS;AACnE,YAAI,UAAU;AACZ,mBAAS,MAAM,OAAO,GAAG,OAAO;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,SAAS,OAAO,IAAI,CAAC,MAAe,iBAAI,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE;AACnE,QAAM,gBAAgB,KAAK,MAAM;AACnC;;;ACpnBA,IAAAC,mBAAyB;AACzB,IAAAC,oBAAiB;AACjB,sBAA8B;;;ACN9B,iBAAsB;AACtB,yBAA6B;;;ACA7B;AAAA,EACE,SAAW;AAAA,EACX,KAAO;AAAA,EACP,OAAS;AAAA,EACT,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,UAAY,CAAC,gBAAgB,YAAY,UAAU;AAAA,EACnD,sBAAwB;AAAA,EACxB,YAAc;AAAA,IACZ,cAAgB;AAAA,MACd,MAAQ;AAAA,MACR,SAAW;AAAA,MACX,aAAe;AAAA,IACjB;AAAA,IACA,UAAY;AAAA,MACV,MAAQ;AAAA,MACR,aAAe;AAAA,IACjB;AAAA,IACA,UAAY;AAAA,MACV,MAAQ;AAAA,MACR,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,UAAY,CAAC,MAAM,UAAU,aAAa,QAAQ,UAAU;AAAA,QAC5D,sBAAwB;AAAA,QACxB,YAAc;AAAA,UACZ,IAAM;AAAA,YACJ,MAAQ;AAAA,YACR,aAAe;AAAA,UACjB;AAAA,UACA,QAAU;AAAA,YACR,MAAQ;AAAA,YACR,aAAe;AAAA,UACjB;AAAA,UACA,WAAa;AAAA,YACX,MAAQ;AAAA,YACR,QAAU;AAAA,YACV,aAAe;AAAA,UACjB;AAAA,UACA,MAAQ;AAAA,YACN,MAAQ;AAAA,YACR,WAAa;AAAA,YACb,aAAe;AAAA,UACjB;AAAA,UACA,UAAY;AAAA,YACV,MAAQ;AAAA,YACR,aAAe;AAAA,UACjB;AAAA,UACA,QAAU;AAAA,YACR,MAAQ;AAAA,YACR,aAAe;AAAA,UACjB;AAAA,UACA,MAAQ;AAAA,YACN,MAAQ;AAAA,YACR,aAAe;AAAA,YACf,UAAY;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,UACA,UAAY;AAAA,YACV,MAAQ;AAAA,YACR,aAAe;AAAA,YACf,MAAQ,CAAC,OAAO,UAAU,MAAM;AAAA,UAClC;AAAA,UACA,UAAY;AAAA,YACV,MAAQ;AAAA,YACR,aAAe;AAAA,UACjB;AAAA,UACA,MAAQ;AAAA,YACN,MAAQ;AAAA,YACR,SAAW;AAAA,YACX,aAAe;AAAA,UACjB;AAAA,UACA,UAAY;AAAA,YACV,MAAQ;AAAA,YACR,SAAW;AAAA,YACX,aAAe;AAAA,UACjB;AAAA,UACA,cAAgB;AAAA,YACd,MAAQ;AAAA,YACR,SAAW;AAAA,YACX,aAAe;AAAA,UACjB;AAAA,UACA,YAAc;AAAA,YACZ,MAAQ;AAAA,YACR,SAAW;AAAA,YACX,aAAe;AAAA,UACjB;AAAA,UACA,eAAiB;AAAA,YACf,MAAQ;AAAA,YACR,WAAa;AAAA,YACb,aAAe;AAAA,UACjB;AAAA,UACA,eAAiB;AAAA,YACf,MAAQ;AAAA,YACR,WAAa;AAAA,YACb,aAAe;AAAA,UACjB;AAAA,UACA,oBAAsB;AAAA,YACpB,MAAQ;AAAA,YACR,SAAW;AAAA,YACX,aAAe;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC9GO,IAAM,aAAa;;;AFO1B,IAAM,MAAO,WAAAC,QAAkB,WAAW,WAAAA;AAC1C,IAAM,aAAc,mBAAAC,QAAyB,WAAW,mBAAAA;AAIjD,SAAS,iBACd,KACA,SAAiB,YACC;AAClB,QAAM,SAAiC,CAAC;AACxC,QAAM,WAAmC,CAAC;AAE1C,iBAAe,KAAK,QAAQ,MAAM;AAClC,sBAAoB,KAAK,QAAQ,QAAQ;AAEzC,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,eACd,KACA,WACA,QACM;AACN,QAAM,EAAE,SAAS,GAAG,OAAO,IAAI;AAC/B,OAAK;AACL,QAAM,MAAM,IAAI,IAAI,EAAE,WAAW,MAAM,QAAQ,MAAM,CAAC;AACtD,aAAW,GAAG;AACd,QAAM,cAAc,IAAI,QAAQ,MAAM;AACtC,QAAM,cAAc,YAAY,GAAG;AAEnC,MAAI,CAAC,eAAe,YAAY,QAAQ;AACtC,eAAW,OAAO,YAAY,QAAQ;AACpC,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,GAAG,IAAI,gBAAgB,GAAG,KAAK,IAAI,WAAW,cAAc;AAAA,QACrE,MAAM,IAAI,gBAAgB;AAAA,MAC5B,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,SAAS,oBACd,KACA,QACA,UACA,MACM;AACN,MAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,EAAG;AAElC,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,SAAS,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,EAAE;AAE3C,WAAS,IAAI,GAAG,IAAI,IAAI,SAAS,QAAQ,KAAK;AAC5C,UAAM,IAAI,IAAI,SAAS,CAAC;AACxB,UAAM,SAAS,aAAa,CAAC;AAE7B,QAAI,EAAE,IAAI;AACR,UAAI,IAAI,IAAI,EAAE,EAAE,GAAG;AACjB,eAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV,MAAM;AAAA,UACN,SAAS,yBAAyB,EAAE,EAAE;AAAA,UACtC,MAAM,GAAG,MAAM;AAAA,UACf,WAAW,EAAE;AAAA,QACf,CAAC;AAAA,MACH;AACA,UAAI,IAAI,EAAE,EAAE;AAAA,IACd;AAEA,QAAI,EAAE,QAAQ,QAAQ,EAAE,YAAY,QAAQ,EAAE,WAAW,EAAE,MAAM;AAC/D,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,aAAa,EAAE,QAAQ,0BAAqB,EAAE,IAAI;AAAA,QAC3D,MAAM,GAAG,MAAM;AAAA,QACf,WAAW,EAAE;AAAA,MACf,CAAC;AAAA,IACH;AAEA,QACE,EAAE,gBAAgB,QAClB,EAAE,cAAc,SACf,EAAE,QAAQ,QAAQ,EAAE,YAAY,QAAQ,EAAE,SAAS,EAAE,aACtD,EAAE,aAAa,EAAE,cACjB;AACA,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,eAAe,EAAE,UAAU,kCAA6B,EAAE,YAAY;AAAA,QAC/E,MAAM,GAAG,MAAM;AAAA,QACf,WAAW,EAAE;AAAA,MACf,CAAC;AAAA,IACH;AAEA,QAAI,EAAE,iBAAiB,EAAE,cAAc,SAAS,MAAM;AACpD,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,0CAA0C,EAAE,cAAc,MAAM;AAAA,QACzE,MAAM,GAAG,MAAM;AAAA,QACf,WAAW,EAAE;AAAA,MACf,CAAC;AAAA,IACH;AAEA,QAAI,EAAE,QAAQ,EAAE,KAAK,SAAS,OAAO;AACnC,eAAS,KAAK;AAAA,QACZ,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,8CAA8C,EAAE,KAAK,MAAM;AAAA,QACpE,MAAM,GAAG,MAAM;AAAA,QACf,WAAW,EAAE;AAAA,MACf,CAAC;AAAA,IACH;AAIA,QAAI,QAAQ,EAAE,iBAAiB,EAAE,oBAAoB;AACnD,YAAM,WAAW,KAAK,EAAE,aAAa;AACrC,UAAI,EAAE,uBAAuB,UAAU;AACrC,iBAAS,KAAK;AAAA,UACZ,UAAU;AAAA,UACV,MAAM;AAAA,UACN,SAAS,yCAAyC,SAAS,MAAM,GAAG,EAAE,CAAC,eAAU,EAAE,mBAAmB,MAAM,GAAG,EAAE,CAAC;AAAA,UAClH,MAAM,GAAG,MAAM;AAAA,UACf,WAAW,EAAE;AAAA,QACf,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,EAAE,YAAY,CAAC,IAAI,IAAI,EAAE,QAAQ,KAAK,CAAC,OAAO,SAAS,EAAE,QAAQ,GAAG;AACtE,eAAS,KAAK;AAAA,QACZ,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,aAAa,EAAE,QAAQ;AAAA,QAChC,MAAM,GAAG,MAAM;AAAA,QACf,WAAW,EAAE;AAAA,MACf,CAAC;AAAA,IACH;AAEA,QAAI,EAAE,QAAQ,QAAQ,CAAC,EAAE,eAAe;AACtC,eAAS,KAAK;AAAA,QACZ,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM,GAAG,MAAM;AAAA,QACf,WAAW,EAAE;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ADnJA,IAAM,YAAY,kBAAAC,QAAK,YAAQ,+BAAc,aAAe,CAAC;AAE7D,IAAI,eAA8B;AAElC,eAAe,aAA8B;AAC3C,MAAI,aAAc,QAAO;AAIzB,QAAM,aAAa;AAAA,IACjB,kBAAAA,QAAK,QAAQ,WAAW,kBAAkB;AAAA;AAAA,IAC1C,kBAAAA,QAAK,QAAQ,WAAW,wBAAwB;AAAA;AAAA,IAChD,kBAAAA,QAAK,QAAQ,WAAW,2BAA2B;AAAA;AAAA,IACnD,kBAAAA,QAAK,QAAQ,WAAW,8BAA8B;AAAA;AAAA,IACtD,kBAAAA,QAAK,QAAQ,QAAQ,IAAI,GAAG,kBAAkB;AAAA;AAAA,EAChD;AAEA,aAAW,aAAa,YAAY;AAClC,QAAI;AACF,YAAM,MAAM,UAAM,2BAAS,WAAW,OAAO;AAC7C,qBAAe,KAAK,MAAM,GAAG;AAC7B,aAAO;AAAA,IACT,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,mCAAmC;AACrD;AAKA,eAAsB,SACpB,KACA,UAA2B,CAAC,GACD;AAC3B,QAAM,SAAiC,CAAC;AACxC,QAAM,WAAmC,CAAC;AAG1C,QAAM,YAAY,MAAM,WAAW;AACnC,iBAAe,KAAK,WAAW,MAAM;AAGrC,sBAAoB,KAAK,QAAQ,UAAU,WAAW;AAEtD,QAAM,QAAQ,OAAO,WAAW,MAAM,CAAC,QAAQ,UAAU,SAAS,WAAW;AAE7E,SAAO,EAAE,OAAO,QAAQ,SAAS;AACnC;AAKA,eAAsB,aACpB,UACA,UAA2B,CAAC,GACD;AAC3B,QAAM,EAAE,cAAAC,cAAa,IAAI,MAAM;AAC/B,MAAI;AACF,UAAM,MAAM,MAAMA,cAAa,QAAQ;AACvC,WAAO,SAAS,KAAK,OAAO;AAAA,EAC9B,SAAS,GAAG;AACV,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN;AAAA,UACE,UAAU;AAAA,UACV,MAAM;AAAA,UACN,SAAS,oBAAqB,EAAY,OAAO;AAAA,QACnD;AAAA,MACF;AAAA,MACA,UAAU,CAAC;AAAA,IACb;AAAA,EACF;AACF;;;AIrFA,iCAAwC;AAGjC,IAAM,4BAA4B;AAQlC,SAAS,uBAAuB,OAAmC;AACxE,QAAM,gBAAgB,oBAAI,IAAsB;AAChD,QAAM,kBAAkB,oBAAI,IAAsB;AAClD,WAAS,OAAO,GAAG,OAAO,MAAM,QAAQ,QAAQ,GAAG;AACjD,sBAAkB,eAAe,cAAc,MAAM,IAAI,CAAC,GAAG,IAAI;AACjE,sBAAkB,iBAAiB,kBAAkB,MAAM,IAAI,CAAC,GAAG,IAAI;AAAA,EACzE;AACA,SAAO,EAAE,OAAO,eAAe,gBAAgB;AACjD;AASO,SAAS,WACd,OACA,QACkB;AAClB,MAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,QAAM,UAA4B,CAAC;AACnC,QAAM,cAAc,OAAO,MAAM,IAAI;AACrC,QAAM,kBAAkB,YAAY;AAGpC,WAAS,YAAY,GAAG,aAAa,MAAM,SAAS,iBAAiB,aAAa;AAEhF,UAAM,cAAc,MAAM,MAAM,WAAW,YAAY,eAAe;AACtE,UAAM,aAAa,YAAY,KAAK,IAAI;AAGxC,QAAI,oBAAoB,GAAG;AACzB,UAAI,MAAM;AACV,YAAM,OAAO,YAAY,CAAC;AAC1B,aAAO,MAAM,KAAK,QAAQ;AACxB,cAAM,MAAM,KAAK,QAAQ,QAAQ,GAAG;AACpC,YAAI,QAAQ,GAAI;AAChB,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,aAAa;AAAA,UACb,WAAW,MAAM,OAAO;AAAA,UACxB,OAAO;AAAA,QACT,CAAC;AACD,cAAM,MAAM;AAAA,MACd;AAAA,IACF,OAAO;AAEL,YAAM,MAAM,WAAW,QAAQ,MAAM;AACrC,UAAI,QAAQ,IAAI;AAEd,cAAM,cAAc,WAAW,MAAM,GAAG,GAAG;AAC3C,cAAM,iBAAiB,YAAY,MAAM,IAAI;AAC7C,cAAM,WAAW,eAAe,eAAe,SAAS,CAAC,EAAE;AAG3D,cAAM,aAAa,OAAO,MAAM,IAAI;AACpC,cAAM,SAAS,WAAW,WAAW,SAAS,CAAC,EAAE;AACjD,YAAI,aAAa,KAAK,eAAe,WAAW,GAAG;AACjD,kBAAQ,KAAK;AAAA,YACX,MAAM;AAAA,YACN,MAAM,YAAY,eAAe,SAAS;AAAA,YAC1C,SAAS,YAAY,eAAe,SAAS,IAAI,WAAW,SAAS;AAAA,YACrE,aAAa;AAAA,YACb,WAAW;AAAA,YACX,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,UAAU,MAAsB;AACvC,SAAO,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACxC;AAKO,SAAS,gBACd,OACA,QACkB;AAClB,QAAM,aAAa,UAAU,MAAM;AACnC,MAAI,CAAC,WAAY,QAAO,CAAC;AAEzB,QAAM,UAA4B,CAAC;AAGnC,QAAM,qBAAqB,OAAO,MAAM,IAAI,EAAE;AAC9C,QAAM,YAAY,KAAK,IAAI,GAAG,qBAAqB,CAAC;AACpD,QAAM,YAAY,KAAK,IAAI,MAAM,SAAS,GAAG,qBAAqB,CAAC;AAEnE,WAAS,UAAU,WAAW,WAAW,WAAW,WAAW;AAC7D,aAAS,YAAY,GAAG,YAAY,UAAU,IAAI,MAAM,QAAQ,aAAa;AAC3E,YAAM,cAAc,MAAM,MAAM,WAAW,YAAY,OAAO;AAC9D,YAAM,aAAa,YAAY,KAAK,IAAI;AACxC,YAAM,aAAa,UAAU,UAAU;AAEvC,UAAI,WAAW,SAAS,UAAU,GAAG;AACnC,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,YAAY,UAAU;AAAA,UAC/B,aAAa;AAAA,UACb,WAAW,YAAY,YAAY,SAAS,CAAC,EAAE;AAAA,UAC/C,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO,sBAAsB,OAAO;AACtC;AAMA,SAAS,SAAS,MAAwB;AACxC,SAAO,KAAK,MAAM,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AACrD;AAKA,SAAS,UAAU,GAAa,GAAqB;AACnD,QAAM,IAAI,EAAE;AACZ,QAAM,IAAI,EAAE;AAEZ,MAAI,OAAO,IAAI,MAAc,IAAI,CAAC,EAAE,KAAK,CAAC;AAC1C,MAAI,OAAO,IAAI,MAAc,IAAI,CAAC,EAAE,KAAK,CAAC;AAE1C,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,UAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG;AACzB,aAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;AAAA,MAC1B,OAAO;AACL,aAAK,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;AAAA,MACzC;AAAA,IACF;AACA,KAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI;AAC1B,SAAK,KAAK,CAAC;AAAA,EACb;AAEA,SAAO,KAAK,CAAC;AACf;AAMO,SAAS,cAAc,GAAW,GAAmB;AAC1D,QAAM,OAAO,SAAS,CAAC;AACvB,QAAM,OAAO,SAAS,CAAC;AACvB,MAAI,KAAK,WAAW,KAAK,KAAK,WAAW,EAAG,QAAO;AACnD,MAAI,KAAK,WAAW,KAAK,KAAK,WAAW,EAAG,QAAO;AACnD,QAAM,MAAM,UAAU,MAAM,IAAI;AAChC,SAAO,MAAM,KAAK,IAAI,KAAK,QAAQ,KAAK,MAAM;AAChD;AASO,SAAS,iBAAiB,GAAW,GAAmB;AAC7D,MAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EAAG,QAAO;AAC7C,QAAM,SAAS,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM;AAC1C,MAAI,WAAW,EAAG,QAAO;AACzB,QAAM,WAAO,2BAAAC,UAAY,GAAG,CAAC;AAC7B,SAAO,IAAI,OAAO;AACpB;AAUO,SAAS,cAAc,QAAgB,WAA2B;AACvE,QAAM,SAAS,cAAc,QAAQ,SAAS;AAG9C,MAAI;AACJ,MAAI,OAAO,SAAS,OAAO,UAAU,SAAS,KAAK;AACjD,aAAS,iBAAiB,QAAQ,SAAS;AAAA,EAC7C,OAAO;AACL,aAAS;AAAA,EACX;AAGA,SAAO,SAAS,MAAM,SAAS;AACjC;AAcO,SAAS,YACd,OACA,QACA,YAAoB,KACpB,UACA,OACkB;AAClB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,CAAC,SAAS;AAAA,IACV;AAAA,IACA;AAAA,EACF,EAAE,IAAI,SAAS,KAAK,CAAC;AACvB;AAOO,SAAS,sBACd,OACA,QACA,YACA,UACA,QAA0B,uBAAuB,KAAK,GACvB;AAC/B,QAAM,mBAAmB,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC;AAChD,QAAM,UAAU,oBAAI,IAA8B;AAClD,MAAI,iBAAiB,WAAW,EAAG,QAAO;AAC1C,MAAI,CAAC,QAAQ;AACX,eAAW,aAAa,iBAAkB,SAAQ,IAAI,WAAW,CAAC,CAAC;AACnE,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,OAAO,MAAM,IAAI;AACrC,QAAM,kBAAkB,YAAY;AACpC,QAAM,aAA+B,CAAC;AACtC,QAAM,mBAAmB,KAAK,IAAI,GAAG,gBAAgB;AACrD,QAAM,iBAAiB,uBAAuB,OAAO,QAAQ,QAAQ;AAGrE,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,kBAAkB,GAAG,CAAC;AAC/D,QAAM,YAAY,KAAK;AAAA,IACrB,MAAM,SAAS;AAAA,IACf,KAAK,KAAK,kBAAkB,GAAG,IAAI;AAAA,EACrC;AAEA,WAAS,UAAU,WAAW,WAAW,WAAW,WAAW;AAC7D,UAAM,aAAa,oBAAI,IAAY;AACnC,eAAW,iBAAiB,gBAAgB;AAC1C,eAAS,SAAS,GAAG,SAAS,SAAS,UAAU,GAAG;AAClD,cAAM,YAAY,gBAAgB;AAClC,YAAI,aAAa,KAAK,YAAY,UAAU,IAAI,MAAM,QAAQ;AAC5D,qBAAW,IAAI,SAAS;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AACA,eAAW,aAAa,YAAY;AAClC,YAAM,cAAc,MAAM,MAAM,WAAW,YAAY,OAAO;AAC9D,YAAM,aAAa,YAAY,KAAK,IAAI;AAExC,YAAM,QAAQ,cAAc,QAAQ,UAAU;AAE9C,UAAI,SAAS,kBAAkB;AAC7B,mBAAW,KAAK;AAAA,UACd,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,YAAY,UAAU;AAAA,UAC/B,aAAa;AAAA,UACb,WAAW,YAAY,YAAY,SAAS,CAAC,EAAE;AAAA,UAC/C;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,MAAI,oBAAoB,KAAK,OAAO,SAAS,KAAK;AAChD,eAAW,WAAW,gBAAgB;AACpC,YAAM,OAAO,MAAM,OAAO;AAC1B,UAAI,CAAC,KAAM;AAEX,YAAM,SAAS,OAAO;AACtB,YAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,GAAG,CAAC;AACtD,YAAM,YAAY,KAAK,IAAI,KAAK,QAAQ,KAAK,KAAK,SAAS,GAAG,CAAC;AAC/D,YAAM,UAAU,qBAAqB,WAAW,WAAW,CAAC;AAC5D,iBAAW,OAAO,SAAS;AACzB,iBAAS,MAAM,GAAG,MAAM,OAAO,KAAK,QAAQ,OAAO;AACjD,gBAAM,MAAM,KAAK,UAAU,KAAK,MAAM,GAAG;AACzC,gBAAM,QAAQ,cAAc,QAAQ,GAAG;AACvC,cAAI,SAAS,kBAAkB;AAC7B,uBAAW,KAAK;AAAA,cACd,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,cACT,aAAa;AAAA,cACb,WAAW,MAAM;AAAA,cACjB;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,sBAAsB,UAAU;AAChD,QAAM,SAAS,QAAQ,IAAI,CAAC,eAAe;AAAA,IACzC,WAAW,UAAU;AAAA,IACrB,WAAW,oBAAoB,WAAW,QAAQ;AAAA,EACpD,EAAE;AAEF,aAAW,aAAa,kBAAkB;AACxC,YAAQ;AAAA,MACN;AAAA,MACA,OACG,OAAO,CAAC,SAAS,KAAK,aAAa,SAAS,EAC5C,IAAI,CAAC,SAAS,KAAK,SAAS,EAC5B,KAAK,CAAC,MAAM,UAAU,MAAM,QAAQ,KAAK,KAAK;AAAA,IACnD;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,uBACP,OACA,QACA,UACU;AACV,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,YAAY,KAAK,IAAI,GAAG,MAAM,MAAM,SAAS,CAAC;AACpD,QAAM,UAAU;AAAA,IACd,GAAG,eAAe,MAAM,eAAe,cAAc,MAAM,GAAG,CAAC;AAAA,IAC/D,GAAG,eAAe,MAAM,iBAAiB,kBAAkB,MAAM,GAAG,CAAC;AAAA,EACvE,EACG,KAAK,CAAC,MAAM,UAAU,KAAK,SAAS,SAAS,MAAM,SAAS,MAAM,EAClE,MAAM,GAAG,EAAE;AAEd,aAAW,UAAU,SAAS;AAC5B,UAAM,SAAS,KAAK,MAAM,YAAY,OAAO,SAAS,MAAM;AAC5D,eAAW,QAAQ,OAAO,UAAU;AAClC,YAAM,IAAI,OAAO,MAAM,IAAI,IAAI,KAAK,KAAK,OAAO,SAAS,MAAM;AAAA,IACjE;AAAA,EACF;AAEA,MAAI,YAAY,MAAM;AACpB,aAAS,SAAS,IAAI,UAAU,GAAG,UAAU,GAAG;AAC9C,YAAM,OAAO,WAAW;AACxB,UAAI,QAAQ,KAAK,QAAQ,WAAW;AAClC,cAAM,IAAI,OAAO,MAAM,IAAI,IAAI,KAAK,KAAK,IAAI;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,MAAM,KAAK,EAAE,QAAQ,UAAU,GAAG,CAAC,GAAGC,WAAUA,SAAQ,CAAC;AAAA,EAClE;AAEA,SAAO,CAAC,GAAG,MAAM,QAAQ,CAAC,EACvB;AAAA,IAAK,CAAC,MAAM,UACX,MAAM,CAAC,IAAI,KAAK,CAAC,KACd,iBAAiB,KAAK,CAAC,GAAG,QAAQ,IAAI,iBAAiB,MAAM,CAAC,GAAG,QAAQ,KACzE,KAAK,CAAC,IAAI,MAAM,CAAC;AAAA,EACtB,EACC,MAAM,GAAG,yBAAyB,EAClC,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AACzB;AAEA,SAAS,eACP,UACA,QACA,QAC+C;AAC/C,SAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,EACvB,IAAI,CAAC,WAAW,EAAE,UAAU,SAAS,IAAI,KAAK,KAAK,CAAC,GAAG,OAAO,EAAE,EAChE,OAAO,CAAC,WAAW,OAAO,SAAS,SAAS,CAAC;AAClD;AAEA,SAAS,kBACP,UACA,QACA,MACM;AACN,aAAW,SAAS,IAAI,IAAI,MAAM,GAAG;AACnC,UAAM,QAAQ,SAAS,IAAI,KAAK;AAChC,QAAI,OAAO;AACT,YAAM,KAAK,IAAI;AAAA,IACjB,OAAO;AACL,eAAS,IAAI,OAAO,CAAC,IAAI,CAAC;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,SAAS,cAAc,MAAwB;AAC7C,SAAO,KAAK,YAAY,EAAE,MAAM,mBAAmB,KAAK,CAAC;AAC3D;AAEA,SAAS,kBAAkB,MAAwB;AACjD,QAAM,aAAa,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAChE,QAAM,aAAa,CAAC,GAAG,UAAU;AACjC,MAAI,WAAW,SAAS,EAAG,QAAO,aAAa,CAAC,UAAU,IAAI,CAAC;AAC/D,QAAM,WAAqB,CAAC;AAC5B,WAAS,QAAQ,GAAG,SAAS,WAAW,SAAS,GAAG,SAAS,GAAG;AAC9D,aAAS,KAAK,WAAW,MAAM,OAAO,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,qBACP,SACA,SACA,OACU;AACV,MAAI,WAAW,QAAS,QAAO,CAAC,OAAO;AACvC,QAAM,SAAS,oBAAI,IAAY;AAC/B,WAAS,QAAQ,GAAG,QAAQ,OAAO,SAAS,GAAG;AAC7C,WAAO,IAAI,KAAK,MAAM,WAAW,UAAU,WAAW,SAAS,QAAQ,EAAE,CAAC;AAAA,EAC5E;AACA,SAAO,CAAC,GAAG,MAAM;AACnB;AAEA,SAAS,iBAAiB,MAAc,UAA2B;AACjE,SAAO,YAAY,OAAO,IAAI,KAAK,IAAI,OAAO,QAAQ;AACxD;AAMA,SAAS,sBACP,YACkB;AAClB,QAAM,OAAO,oBAAI,IAA4B;AAC7C,aAAW,KAAK,YAAY;AAC1B,UAAM,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,WAAW,IAAI,EAAE,OAAO,IAAI,EAAE,SAAS;AAClE,UAAM,WAAW,KAAK,IAAI,GAAG;AAC7B,QAAI,CAAC,YAAY,EAAE,QAAQ,SAAS,OAAO;AACzC,WAAK,IAAI,KAAK,CAAC;AAAA,IACjB;AAAA,EACF;AACA,SAAO,MAAM,KAAK,KAAK,OAAO,CAAC;AACjC;AAEA,SAAS,oBACP,WACA,UACgB;AAChB,MAAI,YAAY,KAAM,QAAO;AAE7B,QAAM,WAAW,KAAK,IAAI,UAAU,OAAO,QAAQ;AACnD,QAAM,iBAAiB,MAAM,KAAK,IAAI,GAAG,IAAI,WAAW,EAAE;AAC1D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO,KAAK,IAAI,GAAK,UAAU,QAAQ,cAAc;AAAA,EACvD;AACF;;;AC1eA,gCAAuC;AACvC,uBAA0B;AAI1B,IAAM,eAAW,4BAAU,0BAAAC,QAAU;AAErC,IAAM,cAAc;AAMpB,IAAI,gBAAgC;AAKpC,eAAsB,iBAAmC;AACvD,MAAI,iBAAiB,KAAM,QAAO;AAClC,MAAI;AACF,UAAM,SAAS,OAAO,CAAC,WAAW,GAAG,EAAE,SAAS,YAAY,CAAC;AAC7D,oBAAgB;AAAA,EAClB,QAAQ;AACN,oBAAgB;AAAA,EAClB;AACA,SAAO;AACT;AAeA,eAAsB,aAAa,KAAsC;AACvE,MAAI,CAAE,MAAM,eAAe,EAAI,QAAO;AACtC,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,aAAa,iBAAiB;AAAA,MAC/B,EAAE,KAAK,OAAO,QAAQ,IAAI,GAAG,SAAS,YAAY;AAAA,IACpD;AACA,WAAO,OAAO,KAAK;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQA,eAAsB,eAAe,UAA0C;AAC7E,MAAI,CAAE,MAAM,eAAe,EAAI,QAAO;AACtC,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,UAAU,WAAW,SAAS,WAAW;AAAA,MAC1C,EAAE,KAAK,UAAU,SAAS,YAAY;AAAA,IACxC;AACA,UAAM,OAAO,OAAO,KAAK;AACzB,WAAO,QAAQ;AAAA,EACjB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAsB,iBAAiB,UAA0C;AAC/E,MAAI,CAAE,MAAM,eAAe,EAAI,QAAO;AACtC,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,aAAa,MAAM;AAAA,MACpB,EAAE,KAAK,UAAU,SAAS,YAAY;AAAA,IACxC;AACA,WAAO,OAAO,KAAK;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAsB,cACpB,UACA,UACwB;AACxB,MAAI,CAAE,MAAM,eAAe,EAAI,QAAO;AACtC,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,aAAa,YAAY,GAAG,QAAQ,WAAW;AAAA,MAChD,EAAE,KAAK,UAAU,SAAS,YAAY;AAAA,IACxC;AACA,WAAO,OAAO,KAAK;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAsB,QACpB,eACA,UACkB;AAClB,QAAM,OAAO,MAAM,iBAAiB,QAAQ;AAC5C,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,SAAS,KAAK,IAAI,cAAc,QAAQ,KAAK,MAAM;AACzD,SAAO,cAAc,MAAM,GAAG,MAAM,MAAM,KAAK,MAAM,GAAG,MAAM;AAChE;AASO,SAAS,eAAe,YAAgC;AAC7D,QAAM,QAAoB,CAAC;AAC3B,QAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,MAAI,UAA2B;AAE/B,aAAW,QAAQ,OAAO;AACxB,UAAM,YAAY,KAAK;AAAA,MACrB;AAAA,IACF;AACA,QAAI,WAAW;AACb,gBAAU;AAAA,QACR,UAAU,SAAS,UAAU,CAAC,GAAG,EAAE;AAAA,QACnC,UAAU,UAAU,CAAC,KAAK,OAAO,SAAS,UAAU,CAAC,GAAG,EAAE,IAAI;AAAA,QAC9D,UAAU,SAAS,UAAU,CAAC,GAAG,EAAE;AAAA,QACnC,UAAU,UAAU,CAAC,KAAK,OAAO,SAAS,UAAU,CAAC,GAAG,EAAE,IAAI;AAAA,QAC9D,OAAO,CAAC;AAAA,MACV;AACA,YAAM,KAAK,OAAO;AAClB;AAAA,IACF;AACA,QAAI,YAAY,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,IAAI;AACrF,cAAQ,MAAM,KAAK,IAAI;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,QACpB,YACA,UACA,UACA,UACqB;AACrB,MAAI,CAAE,MAAM,eAAe,EAAI,QAAO,CAAC;AACvC,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA;AAAA,QACE;AAAA,QACA,GAAG,UAAU,KAAK,QAAQ;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,EAAE,KAAK,UAAU,SAAS,YAAY;AAAA,IACxC;AACA,WAAO,eAAe,MAAM;AAAA,EAC9B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AASO,SAAS,aACd,OACA,cACsC;AACtC,MAAI,kBAAkB;AAEtB,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,KAAK,WAAW,KAAK,WAAW;AAG/C,QAAI,KAAK,WAAW,aAAc;AAGlC,QAAI,gBAAgB,KAAK,YAAY,gBAAgB,QAAQ;AAC3D,aAAO,EAAE,OAAO,iBAAiB,UAAU,KAAK;AAAA,IAClD;AAGA,QAAI,SAAS,cAAc;AACzB,yBAAmB,KAAK,WAAW,KAAK;AAAA,IAC1C;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,iBAAiB,UAAU,MAAM;AACnD;AAUA,eAAsB,gBACpB,QACA,UACA,UACwB;AACxB,MAAI,CAAE,MAAM,eAAe,EAAI,QAAO;AACtC,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,QAAQ,GAAG,MAAM,IAAI,QAAQ,EAAE;AAAA,MAChC,EAAE,KAAK,UAAU,SAAS,YAAY;AAAA,IACxC;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AASA,eAAsB,eACpB,UACA,SACmB;AACnB,MAAI,CAAE,MAAM,eAAe,EAAI,QAAO,CAAC;AACvC,MAAI;AACF,UAAM,OAAO,CAAC,QAAQ,YAAY,eAAe,iBAAiB;AAClE,QAAI,QAAS,MAAK,KAAK,MAAM,OAAO;AACpC,UAAM,EAAE,OAAO,IAAI,MAAM,SAAS,OAAO,MAAM;AAAA,MAC7C,KAAK;AAAA,MACL,SAAS;AAAA,IACX,CAAC;AACD,WAAO,OACJ,KAAK,EACL,MAAM,IAAI,EACV,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,EAC/B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AA8BA,eAAsB,cACpB,YACA,UACA,UAC8B;AAC9B,MAAI,CAAE,MAAM,eAAe,EAAI,QAAO,oBAAI,IAAI;AAC9C,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,QAAQ,iBAAiB,MAAM,GAAG,UAAU,KAAK,QAAQ,EAAE;AAAA,MAC5D,EAAE,KAAK,UAAU,SAAS,YAAY;AAAA,IACxC;AAEA,UAAM,UAAU,oBAAI,IAAoB;AACxC,eAAW,QAAQ,OAAO,KAAK,EAAE,MAAM,IAAI,GAAG;AAC5C,YAAM,QAAQ,KAAK,MAAM,oBAAoB;AAC7C,UAAI,OAAO;AACT,gBAAQ,IAAI,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AAAA,MAChC;AAAA,IACF;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,oBAAI,IAAI;AAAA,EACjB;AACF;;;AC7UA,IAAM,iBAAiB;AAqBhB,SAAS,yBACd,aACA,aACyB;AACzB,QAAM,oBAAoB,uBAAuB,WAAW;AAC5D,QAAM,oBAAoB,uBAAuB,WAAW;AAC5D,QAAM,UAAU,oBAAI,IAAoB;AAExC,aAAW,CAAC,MAAM,iBAAiB,KAAK,mBAAmB;AACzD,UAAM,oBAAoB,kBAAkB,IAAI,IAAI;AACpD,QAAI,kBAAkB,WAAW,KAAK,mBAAmB,WAAW,GAAG;AACrE,cAAQ,IAAI,kBAAkB,CAAC,GAAG,kBAAkB,CAAC,CAAC;AAAA,IACxD;AAAA,EACF;AAEA,SAAO,EAAE,aAAa,aAAa,QAAQ;AAC7C;AAEO,SAAS,qBACd,SACA,YACA,WAC6B;AAC7B,MAAI,QAAQ,QAAQ,QAAQ,CAAC,QAAQ,cAAe,QAAO;AAE3D,QAAM,aAAa;AAAA,IACjB,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,MAAI,eAAe,QAAQ,cAAe,QAAO;AAEjD,QAAM,kBAAkB;AAAA,IACtB,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AACA,MAAI,gBAAgB,WAAW,GAAG;AAChC,UAAM,YAAY,gBAAgB,CAAC;AACnC,UAAM,iBAAiB;AAAA,MACrB;AAAA,MACA,UAAU;AAAA,MACV;AAAA,IACF;AACA,QAAI,kBAAkB,GAAG;AACvB,aAAO;AAAA,QACL,MAAM,UAAU;AAAA,QAChB,SAAS,UAAU;AAAA,QACnB,aAAa,UAAU;AAAA,QACvB,WAAW,UAAU;AAAA,QACrB,MAAM,UAAU;AAAA,QAChB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,eAAe;AAAA,QACf,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACA,MAAI,gBAAgB,SAAS,EAAG,QAAO;AAEvC,QAAM,YAAY,uBAAuB,SAAS,UAAU;AAC5D,MAAI,aAAa,KAAM,QAAO;AAC9B,QAAM,gBAAgB,UAAU;AAEhC,QAAM,YAAY,QAAQ,YAAY,QAAQ,QAAQ,QAAQ;AAC9D,QAAM,mBAAmB,gBAAgB;AACzC,MACE,gBAAgB,KACb,oBAAoB,WAAW,YAAY,QAC9C;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,eAAe,SAAS,YAAY,aAAa;AACjE,QAAM,aAAa;AAAA,IACjB,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,MAAI,cAAc,KAAM,QAAO;AAE/B,QAAM,QAAQ,KAAK;AAAA,IACjB;AAAA,IACA,cAAc,QAAQ,eAAe,UAAU,IAAI;AAAA,EACrD;AACA,MAAI,QAAQ,UAAW,QAAO;AAE9B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,IACnB,MAAM;AAAA,IACN;AAAA,IACA,OAAO,eAAe,QAAQ;AAAA,IAC9B,gBAAgB,UAAU;AAAA,IAC1B,eAAe,UAAU;AAAA,IACzB,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,uBAAuB,OAAwC;AACtE,QAAM,cAAc,oBAAI,IAAsB;AAE9C,WAAS,OAAO,GAAG,OAAO,MAAM,QAAQ,QAAQ,GAAG;AACjD,UAAM,OAAO,MAAM,IAAI;AACvB,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,UAAM,WAAW,YAAY,IAAI,IAAI;AACrC,QAAI,UAAU;AACZ,eAAS,KAAK,IAAI;AAAA,IACpB,OAAO;AACL,kBAAY,IAAI,MAAM,CAAC,IAAI,CAAC;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,6BACP,SACA,eACA,YACQ;AACR,QAAM,gBAAgB,QAAQ,YAAa,QAAQ;AACnD,QAAM,gBAAgB,gBAAiB,QAAQ;AAE/C,MACE,QAAQ,gBAAgB,QACrB,QAAQ,cAAc,MACzB;AACA,UAAM,sBAAsB,WAAW,QAAQ,IAAI,QAAQ,IAAc;AACzE,QAAI,wBAAwB,cAAe,QAAO;AAAA,EACpD;AAEA,MAAI,UAAU;AACd,WACM,WAAW,GACf,YAAY,gBACZ,YAAY,GACZ;AACA,eAAW,cAAc;AAAA,MACtB,QAAQ,OAAkB;AAAA,MAC3B,gBAAgB;AAAA,IAClB,GAAG;AACD,UAAI,aAAa,KAAK,cAAc,WAAW,YAAY,QAAQ;AACjE;AAAA,MACF;AACA,YAAM,aAAa,WAAW,QAAQ,IAAI,UAAU;AACpD,UAAI,cAAc,QAAQ,aAAa,eAAe,eAAe;AACnE,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,uBACP,SACA,YAC+D;AAC/D,QAAM,aAAa,QAAQ;AAC3B,QAAM,gBAAgB,QAAQ,YAAY;AAC1C,QAAM,QAAQ,oBAAI,IAAgD;AAElE,WAAS,WAAW,GAAG,YAAY,gBAAgB,YAAY,GAAG;AAChE,eAAW,eAAe;AAAA,MACxB,aAAa;AAAA,MACb,gBAAgB;AAAA,IAClB,GAAG;AACD,UAAI,cAAc,KAAK,eAAe,WAAW,YAAY,QAAQ;AACnE;AAAA,MACF;AACA,YAAM,aAAa,WAAW,QAAQ,IAAI,WAAW;AACrD,UAAI,cAAc,KAAM;AACxB,YAAM,QAAQ,aAAa;AAC3B,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,MAAM;AACR,aAAK,SAAS;AACd,aAAK,UAAU,KAAK,IAAI,KAAK,SAAS,QAAQ;AAAA,MAChD,OAAO;AACL,cAAM,IAAI,OAAO,EAAE,OAAO,GAAG,SAAS,SAAS,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAE;AAAA,IAAK,CAAC,MAAM,UAC9C,MAAM,CAAC,EAAE,QAAQ,KAAK,CAAC,EAAE,SACtB,KAAK,CAAC,EAAE,UAAU,MAAM,CAAC,EAAE,WAC3B,KAAK,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,IAAI,MAAM,CAAC,CAAC;AAAA,EAC1C;AACA,QAAM,OAAO,OAAO,CAAC;AACrB,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,CAAC,EAAE,QAAQ,KAAK,KAAK,CAAC,EAAE,UAAU,EAAG,QAAO;AACrD,MACE,OAAO,CAAC,KACL,OAAO,CAAC,EAAE,CAAC,EAAE,UAAU,KAAK,CAAC,EAAE,SAC/B,OAAO,CAAC,EAAE,CAAC,EAAE,YAAY,KAAK,CAAC,EAAE,SACpC;AACA,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS;AAC9C,SAAO;AAAA,IACL,MAAM,aAAa,KAAK,CAAC;AAAA,IACzB,SAAS,KAAK,CAAC,EAAE;AAAA,IACjB,SAAS,KAAK,CAAC,EAAE,QAAQ,iBAAiB,KAAK,CAAC,EAAE;AAAA,EACpD;AACF;AAEA,SAAS,eACP,SACA,YACA,YAC8C;AAC9C,MACE,QAAQ,QAAQ,QACZ,QAAQ,YAAY,QAAQ,QAAQ,aAAa,QAAQ,QAC1D,QAAQ,gBAAgB,QACxB,QAAQ,cAAc,MACzB;AACA,WAAO;AAAA,MACL,aAAa,QAAQ;AAAA,MACrB,WAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,aAAa,WAAW,YAAY,QAAQ,IAAI;AACtD,QAAM,iBAAiB,WAAW,YAAY,UAAU;AACxD,QAAM,SAAS,WAAW,MAAM,GAAG,QAAQ,YAAY;AACvD,QAAM,SAAS,WAAW,MAAM,QAAQ,UAAU;AAClD,QAAM,cAAc,eAAe,WAAW,MAAM,IAChD,OAAO,SACP,KAAK,IAAI,QAAQ,cAAc,eAAe,MAAM;AACxD,QAAM,YAAY,eAAe,SAAS,MAAM,IAC5C,eAAe,SAAS,OAAO,SAC/B,KAAK;AAAA,IACL,eAAe;AAAA,IACf,eAAe,QAAQ,aAAa,QAAQ;AAAA,EAC9C;AAEF,SAAO,EAAE,aAAa,UAAU;AAClC;AAEA,SAAS,YACP,OACA,MACA,SACA,aACA,WACe;AACf,QAAM,YAAY,WAAW;AAC7B,MAAI,OAAO,KAAK,aAAa,MAAM,OAAQ,QAAO;AAElD,MAAI,SAAS,WAAW;AACtB,UAAM,OAAO,MAAM,IAAI;AACvB,WAAO,eAAe,QAAQ,aAAa,OACvC,KAAK,MAAM,aAAa,SAAS,IACjC;AAAA,EACN;AAEA,QAAM,SAAmB,CAAC;AAC1B,WAAS,UAAU,MAAM,WAAW,WAAW,WAAW,GAAG;AAC3D,QAAI,OAAO,MAAM,OAAO;AACxB,QAAI,YAAY,QAAQ,eAAe,KAAM,QAAO,KAAK,MAAM,WAAW;AAC1E,QAAI,YAAY,aAAa,aAAa,KAAM,QAAO,KAAK,MAAM,GAAG,SAAS;AAC9E,WAAO,KAAK,IAAI;AAAA,EAClB;AACA,SAAO,OAAO,KAAK,IAAI;AACzB;;;ACtSA,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AAClB,IAAM,+BAA+B;AA+DrC,SAAS,yBACd,aACA,aACoB;AACpB,SAAO;AAAA,IACL,QAAQ,yBAAyB,WAAW;AAAA,IAC5C,QAAQ,yBAAyB,WAAW;AAAA,EAC9C;AACF;AAEO,SAAS,qBACd,SACA,OACqC;AACrC,MAAI,QAAQ,QAAQ,QAAQ,CAAC,QAAQ,cAAe,QAAO;AAC3D,QAAM,mBAAmB,MAAM,OAAO,YAAY,IAAI,QAAQ,IAAI;AAClE,MAAI,oBAAoB,KAAM,QAAO;AACrC,QAAM,cAAc,MAAM,OAAO,OAAO,gBAAgB;AACxD,QAAM,aAAaC;AAAA,IACjB,MAAM,OAAO;AAAA,IACb,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,MAAI,eAAe,QAAQ,cAAe,QAAO;AACjD,QAAM,wBAAwBA;AAAA,IAC5B,MAAM,OAAO;AAAA,IACb,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,MAAI,0BAA0B,QAAQ,eAAe;AACnD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,MAAM,QAAQ;AAAA,MACd,SAAS,QAAQ,YAAY,QAAQ;AAAA,MACrC,aAAa,QAAQ;AAAA,MACrB,WAAW,QAAQ;AAAA,MACnB,MAAM,QAAQ;AAAA,MACd,iBAAiB;AAAA,MACjB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,aAAa,4BAA4B,SAAS,KAAK;AAC7D,QAAM,OAAO,WAAW,CAAC;AACzB,MAAI,CAAC,MAAM;AACT,QACE,MAAM,OAAO,MAAM,MAAM,CAAC,EAAE,KAAK,IAAI,EAAE,SAAS,QAAQ,aAAa,GACrE;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,iBAAiB;AAAA,MACjB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,WAAW,CAAC,KAAK,KAAK,QAAQ,WAAW,CAAC,EAAE,QAAQ,kBAAkB;AACxE,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,iBAAiB,KAAK,QAAQ,WAAW,CAAC,EAAE;AAAA,MAC5C,QACE,wCAAwC,KAAK,MAAM,QAAQ,CAAC,CAAC,OACxD,WAAW,CAAC,EAAE,MAAM,QAAQ,CAAC,CAAC;AAAA,IACvC;AAAA,EACF;AAEA,QAAM,oBAAoB,KAAK,SAC1B;AAAA,IACD,MAAM,OAAO,MAAM,MAAM,CAAC,EAAE,KAAK,IAAI;AAAA,IACrC,QAAQ;AAAA,EACV,IAAI;AACN,SAAO;AAAA,IACL,QAAQ,KAAK,SAAS,CAAC,oBAAoB,aAAa;AAAA,IACxD,OAAO,KAAK,SAAS,CAAC,oBAAoB,IAAI,KAAK;AAAA,IACnD,MAAM,KAAK;AAAA,IACX,SAAS,KAAK;AAAA,IACd,aAAa,KAAK;AAAA,IAClB,WAAW,KAAK;AAAA,IAChB,MAAM,KAAK;AAAA,IACX,iBAAiB,WAAW,CAAC,IAAI,KAAK,QAAQ,WAAW,CAAC,EAAE,QAAQ;AAAA,IACpE,QAAQ,KAAK,SAAS,CAAC,oBACnB,gFACA,oBACE,oEACA;AAAA,EACR;AACF;AAEO,SAAS,4BACd,SACA,OAC0B;AAC1B,MAAI,QAAQ,QAAQ,QAAQ,CAAC,QAAQ,cAAe,QAAO,CAAC;AAC5D,QAAM,mBAAmB,MAAM,OAAO,YAAY,IAAI,QAAQ,IAAI;AAClE,MAAI,oBAAoB,KAAM,QAAO,CAAC;AACtC,QAAM,cAAc,MAAM,OAAO,OAAO,gBAAgB;AACxD,QAAM,aAAaA;AAAA,IACjB,MAAM,OAAO;AAAA,IACb,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,MAAI,eAAe,QAAQ,cAAe,QAAO,CAAC;AAElD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EACF,EACG,IAAI,CAAC,eAAe;AAAA,IACnB,GAAG;AAAA,IACH,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF,EAAE,EACD,OAAO,CAAC,cAAc,UAAU,SAAS,eAAe,EACxD;AAAA,IAAK,CAAC,MAAM,UACX,MAAM,QAAQ,KAAK,SAChB,KAAK,IAAI,KAAK,YAAa,QAAQ,IAAe,IACjD,KAAK,IAAI,MAAM,YAAa,QAAQ,IAAe;AAAA,EACzD,EACC,IAAI,CAAC,cAAc;AAClB,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IACR;AACA,WAAO;AAAA,MACL,OAAO,UAAU;AAAA,MACjB,MAAM,MAAM;AAAA,MACZ,SAAS,MAAM;AAAA,MACf,aAAa,MAAM;AAAA,MACnB,WAAW,MAAM;AAAA,MACjB,MAAM,MAAM;AAAA,MACZ,OAAO,MAAM,SAAS,QAAQ;AAAA,IAChC;AAAA,EACF,CAAC;AACL;AAEO,SAAS,sBACd,SACA,OACoB;AACpB,MAAI,QAAQ,QAAQ,KAAM,QAAO;AACjC,QAAM,aAAa,MAAM,OAAO,YAAY,IAAI,QAAQ,IAAI;AAC5D,MAAI,cAAc,KAAM,QAAO;AAC/B,SAAO,MAAM,OAAO,OAAO,UAAU,EAAE,YAAY,KAAK,GAAQ;AAClE;AAEA,SAAS,yBAAyB,OAAqC;AACrE,QAAM,SAA0B,CAAC;AACjC,QAAM,cAAc,oBAAI,IAAoB;AAC5C,QAAM,WAAoD,CAAC;AAC3D,MAAI,OAAO;AAEX,SAAO,OAAO,MAAM,QAAQ;AAC1B,QAAI,CAAC,MAAM,IAAI,EAAE,KAAK,GAAG;AACvB,cAAQ;AACR;AAAA,IACF;AAEA,UAAM,YAAY;AAClB,UAAM,SAAS,aAAa,MAAM,IAAI,CAAC;AACvC,QAAI,OAAO,SAAS,WAAW;AAC7B,aACE,SAAS,SAAS,KACf,SAAS,SAAS,SAAS,CAAC,EAAE,SAAS,OAAO,cACjD;AACA,iBAAS,IAAI;AAAA,MACf;AACA,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,IAAI,CAAC,YAAY,QAAQ,KAAK;AAAA,MACzC;AACA,aAAO,KAAK,KAAK;AACjB,eAAS,KAAK,EAAE,OAAO,OAAO,cAAc,OAAO,OAAO,aAAa,CAAC;AACxE,cAAQ;AACR;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,QAAQ;AAC1B,cAAQ;AACR,aAAO,OAAO,MAAM,UAAU,CAAC,MAAM,IAAI,EAAE,UAAU,EAAE,WAAW,KAAK,GAAG;AACxE,gBAAQ;AAAA,MACV;AACA,UAAI,OAAO,MAAM,OAAQ,SAAQ;AAAA,IACnC,OAAO;AACL,cAAQ;AACR,aACE,OAAO,MAAM,UACV,MAAM,IAAI,EAAE,KAAK,KACjB,eAAe,OAAO,MAAM,MAAM,IAAI,CAAC,GAC1C;AACA,gBAAQ;AAAA,MACV;AAAA,IACF;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS,IAAI,CAAC,YAAY,QAAQ,KAAK;AAAA,IACzC,CAAC;AAAA,EACH;AAEA,aAAW,CAAC,YAAY,KAAK,KAAK,OAAO,QAAQ,GAAG;AAClD,aAAS,YAAY,MAAM,WAAW,aAAa,MAAM,SAAS,aAAa,GAAG;AAChF,kBAAY,IAAI,WAAW,UAAU;AAAA,IACvC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,oBAAoB,MAAM;AAAA,EAC3C;AACF;AAEA,SAAS,UACP,OACA,WACA,SACA,MACA,aACe;AACf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,MAAM,MAAM,WAAW,UAAU,CAAC,EAAE,KAAK,IAAI;AAAA,IACnD;AAAA,EACF;AACF;AAEA,SAAS,aAAa,MAIpB;AACA,QAAM,UAAU,KAAK,MAAM,mBAAmB;AAC9C,MAAI,SAAS;AACX,WAAO;AAAA,MACL,MAAM;AAAA,MACN,cAAc,QAAQ,CAAC,EAAE;AAAA,MACzB,cAAc,QAAQ,CAAC,EAAE,KAAK;AAAA,IAChC;AAAA,EACF;AACA,MAAI,KAAK,UAAU,EAAE,WAAW,KAAK,GAAG;AACtC,WAAO,EAAE,MAAM,QAAQ,cAAc,GAAG,cAAc,GAAG;AAAA,EAC3D;AACA,MAAI,yBAAyB,KAAK,IAAI,GAAG;AACvC,WAAO,EAAE,MAAM,QAAQ,cAAc,GAAG,cAAc,GAAG;AAAA,EAC3D;AACA,MAAI,SAAS,KAAK,IAAI,GAAG;AACvB,WAAO,EAAE,MAAM,SAAS,cAAc,GAAG,cAAc,GAAG;AAAA,EAC5D;AACA,MAAI,QAAQ,KAAK,IAAI,GAAG;AACtB,WAAO,EAAE,MAAM,cAAc,cAAc,GAAG,cAAc,GAAG;AAAA,EACjE;AACA,SAAO,EAAE,MAAM,aAAa,cAAc,GAAG,cAAc,GAAG;AAChE;AAEA,SAAS,eAAe,MAAiB,MAAuB;AAC9D,MAAI,SAAS,OAAQ,QAAO,yBAAyB,KAAK,IAAI;AAC9D,MAAI,SAAS,QAAS,QAAO,SAAS,KAAK,IAAI;AAC/C,MAAI,SAAS,aAAc,QAAO,QAAQ,KAAK,IAAI;AACnD,MAAI,SAAS,aAAa;AACxB,UAAM,OAAO,aAAa,IAAI;AAC9B,WAAO,KAAK,SAAS;AAAA,EACvB;AACA,SAAO;AACT;AAEA,SAAS,uBACP,aACA,kBACA,cACA,OACmB;AACnB,QAAM,SAAS,MAAM;AACrB,QAAM,aAAgC,CAAC;AAEvC,aAAW,SAAS;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG;AACD,UAAM,QAAQ,OAAO,OAAO,KAAK;AACjC,eAAW,KAAK,kBAAkB,QAAQ,OAAO,KAAK,CAAC;AAEvD,QACE,YAAY,SAAS,eAClB,MAAM,SAAS,eACf,OAAO,OAAO,QAAQ,CAAC,GAAG,SAAS,eACnC,SAAS,MAAM,aAAa,OAAO,OAAO,QAAQ,CAAC,EAAE,WAAW,GACnE;AACA,iBAAW,KAAK,kBAAkB,QAAQ,OAAO,QAAQ,CAAC,CAAC;AAAA,IAC7D;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,oBACP,QACuB;AACvB,QAAM,WAAW,oBAAI,IAAsB;AAC3C,aAAW,CAAC,YAAY,KAAK,KAAK,OAAO,QAAQ,GAAG;AAClD,eAAW,SAAS,IAAI,IAAIC,UAAS,MAAM,IAAI,CAAC,GAAG;AACjD,YAAM,iBAAiB,SAAS,IAAI,KAAK;AACzC,UAAI,gBAAgB;AAClB,uBAAe,KAAK,UAAU;AAAA,MAChC,OAAO;AACL,iBAAS,IAAI,OAAO,CAAC,UAAU,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,wBACP,aACA,kBACA,cACA,OACU;AACV,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,cAAc,MAAM,OAAO,OAAO;AACxC,QAAM,cAAc,CAClB,MACA,cACA,WACS;AACT,QAAI,CAAC,KAAM;AACX,UAAM,eAAe,CAAC,GAAG,IAAI,IAAIA,UAAS,IAAI,CAAC,CAAC,EAC7C,IAAI,CAAC,WAAW;AAAA,MACf;AAAA,MACA,UAAU,MAAM,OAAO,cAAc,IAAI,KAAK,KAAK,CAAC;AAAA,IACtD,EAAE,EACD,OAAO,CAAC,SAAS,KAAK,SAAS,SAAS,CAAC,EACzC,KAAK,CAAC,MAAM,UAAU,KAAK,SAAS,SAAS,MAAM,SAAS,MAAM,EAClE,MAAM,GAAG,EAAE;AAEd,eAAW,EAAE,SAAS,KAAK,cAAc;AACvC,YAAM,SAAS,KAAK,MAAM,cAAc,SAAS,MAAM;AACvD,iBAAW,WAAW,UAAU;AAC9B,cAAM,YAAY,UAAU;AAC5B,YAAI,aAAa,KAAK,YAAY,aAAa;AAC7C,gBAAM,IAAI,YAAY,MAAM,IAAI,SAAS,KAAK,KAAK,SAAS,MAAM;AAAA,QACpE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,cAAY,YAAY,MAAM,GAAG,CAAC;AAClC,cAAY,MAAM,OAAO,OAAO,mBAAmB,CAAC,GAAG,MAAM,GAAG,GAAG;AACnE,cAAY,MAAM,OAAO,OAAO,mBAAmB,CAAC,GAAG,MAAM,IAAI,GAAG;AAEpE,QAAM,cAAc,mBAAmB,MAAM,OAAO,QAAQ,YAAY;AACxE,MAAI,eAAe,MAAM;AACvB,aAAS,SAAS,IAAI,UAAU,GAAG,UAAU,GAAG;AAC9C,YAAM,YAAY,cAAc;AAChC,UAAI,aAAa,KAAK,YAAY,aAAa;AAC7C,cAAM,IAAI,YAAY,MAAM,IAAI,SAAS,KAAK,KAAK,IAAI;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,MAAM,QAAQ,CAAC,EACvB;AAAA,IAAK,CAAC,MAAM,UACX,MAAM,CAAC,IAAI,KAAK,CAAC,KACd,KAAK,IAAI,MAAM,OAAO,OAAO,KAAK,CAAC,CAAC,EAAE,YAAY,YAAY,IAC7D,KAAK,IAAI,MAAM,OAAO,OAAO,MAAM,CAAC,CAAC,EAAE,YAAY,YAAY,KAChE,KAAK,CAAC,IAAI,MAAM,CAAC;AAAA,EACtB,EACC,MAAM,GAAG,4BAA4B,EACrC,IAAI,CAAC,CAAC,UAAU,MAAM,UAAU;AACrC;AAEA,SAAS,mBACP,QACA,MACoB;AACpB,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,MAAI,MAAM;AACV,MAAI,OAAO,OAAO,SAAS;AAC3B,SAAO,OAAO,MAAM;AAClB,UAAM,SAAS,KAAK,OAAO,MAAM,QAAQ,CAAC;AAC1C,UAAM,QAAQ,OAAO,MAAM;AAC3B,QAAI,OAAO,MAAM,WAAW;AAC1B,aAAO,SAAS;AAAA,IAClB,WAAW,OAAO,MAAM,SAAS;AAC/B,YAAM,SAAS;AAAA,IACjB,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,OAAO,OAAO,OAAQ,QAAO,OAAO,SAAS;AACjD,MAAI,OAAO,EAAG,QAAO;AACrB,SAAO,KAAK,IAAI,OAAO,GAAG,EAAE,YAAY,IAAI,IACtC,KAAK,IAAI,OAAO,IAAI,EAAE,UAAU,IAAI,IACtC,MACA;AACN;AAEA,SAAS,kBACP,QACA,YACA,UACiB;AACjB,QAAM,QAAQ,OAAO,OAAO,UAAU;AACtC,QAAM,OAAO,OAAO,OAAO,QAAQ;AACnC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,MAAM;AAAA,IACjB,SAAS,KAAK;AAAA,IACd,MAAM,MAAM;AAAA,IACZ,MAAM,OAAO,MAAM,MAAM,MAAM,WAAW,KAAK,UAAU,CAAC,EAAE,KAAK,IAAI;AAAA,IACrE,aAAa,MAAM;AAAA,IACnB,OAAO;AAAA,EACT;AACF;AAEA,SAAS,eACP,aACA,kBACA,WACA,OACA,cACQ;AACR,QAAM,UAAU,eAAe,YAAY,MAAM,UAAU,IAAI;AAC/D,QAAM,OAAO,YAAY,SAAS,UAAU,OAAO,IAAI;AACvD,QAAM,UAAU,eAAe,YAAY,aAAa,UAAU,WAAW;AAC7E,QAAM,WAAW;AAAA,IACf,MAAM,OAAO,OAAO,mBAAmB,CAAC;AAAA,IACxC,MAAM,OAAO,OAAO,UAAU,aAAa,CAAC;AAAA,EAC9C;AACA,QAAM,OAAO;AAAA,IACX,MAAM,OAAO,OAAO,mBAAmB,CAAC;AAAA,IACxC,MAAM,OAAO,OAAO,UAAU,WAAW,CAAC;AAAA,EAC5C;AACA,QAAM,YAAY,KAAK;AAAA,IACrB;AAAA,IACA,IAAI,KAAK,IAAI,UAAU,YAAY,YAAY,IAAI;AAAA,EACrD;AAEA,SAAO,KAAK;AAAA,IACV;AAAA,IACA,UAAU,OACN,OAAO,MACP,UAAU,MACV,WAAW,OACX,OAAO,OACP,YAAY;AAAA,EAClB;AACF;AAEA,SAAS,mBACP,QACA,QACQ;AACR,MAAI,CAAC,UAAU,CAAC,OAAQ,QAAO;AAC/B,SAAO,eAAe,OAAO,MAAM,OAAO,IAAI;AAChD;AAEA,SAAS,eAAe,MAAc,OAAuB;AAC3D,SAAO,KAAK;AAAA,IACV,UAAU,MAAM,KAAK;AAAA,IACrB,cAAc,cAAc,IAAI,GAAG,cAAc,KAAK,CAAC;AAAA,EACzD;AACF;AAEA,SAAS,eAAe,MAAgB,OAAyB;AAC/D,MAAI,KAAK,WAAW,KAAK,MAAM,WAAW,EAAG,QAAO;AACpD,SAAO,UAAU,KAAK,KAAK,GAAG,GAAG,MAAM,KAAK,GAAG,CAAC;AAClD;AAEA,SAAS,UAAU,MAAc,OAAuB;AACtD,QAAM,aAAaA,UAAS,IAAI;AAChC,QAAM,cAAcA,UAAS,KAAK;AAClC,MAAI,WAAW,WAAW,KAAK,YAAY,WAAW,EAAG,QAAO;AAChE,QAAM,YAAY,oBAAI,IAAoB;AAC1C,aAAW,SAAS,aAAa;AAC/B,cAAU,IAAI,QAAQ,UAAU,IAAI,KAAK,KAAK,KAAK,CAAC;AAAA,EACtD;AACA,MAAI,UAAU;AACd,aAAW,SAAS,YAAY;AAC9B,UAAM,QAAQ,UAAU,IAAI,KAAK,KAAK;AACtC,QAAI,QAAQ,GAAG;AACb,iBAAW;AACX,gBAAU,IAAI,OAAO,QAAQ,CAAC;AAAA,IAChC;AAAA,EACF;AACA,SAAQ,IAAI,WAAY,WAAW,SAAS,YAAY;AAC1D;AAEA,SAASA,UAAS,MAAwB;AACxC,SAAO,cAAc,IAAI,EAAE,MAAM,mBAAmB,KAAK,CAAC;AAC5D;AAEA,SAAS,cAAc,MAAsB;AAC3C,SAAO,KAAK,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACtD;AAEA,SAAS,SAAS,MAAgB,OAA0B;AAC1D,SAAO,KAAK,WAAW,MAAM,UACxB,KAAK,MAAM,CAAC,MAAM,UAAU,SAAS,MAAM,KAAK,CAAC;AACxD;AAEA,SAAS,sBACP,SACA,aACA,WACA,QAOA;AACA,QAAM,aAAa,UAAU,KAAK,QAAQ,QAAQ,aAAuB;AACzE,QAAM,uBACJ,QAAQ,SAAS,YAAY,cACzB,QAAQ,YAAY,QAAQ,UAAU,YAAY,WACnD,QAAQ,gBAAgB,QACxB,QAAQ,cAAc,QACtB,QAAQ,kBAAkB,YAAY;AAC3C,QAAM,2BACJ,iBAAiB,YAAY,MAAM,QAAQ,aAAuB,MAAM;AAC1E,MAAI,cAAc,MAAM,wBAAwB,2BAA2B;AACzE,WAAO;AAAA,MACL,UAAU;AAAA,MACV,UAAU;AAAA,MACV,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,sBAAsB;AACxB,WAAO;AAAA,MACL,MAAM,UAAU;AAAA,MAChB,SAAS,UAAU;AAAA,MACnB,MAAM,UAAU;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,eAAgB,QAAQ,OAAkB,YAAY;AAC5D,QAAM,OAAO,KAAK,IAAI,UAAU,SAAS,UAAU,YAAY,YAAY;AAC3E,QAAM,YAAY,QAAQ,YAAY,QAAQ,QACzC,QAAQ;AACb,QAAM,UAAU,KAAK,IAAI,UAAU,SAAS,OAAO,QAAQ;AAC3D,QAAM,cAAc,QAAQ;AAC5B,QAAM,YAAY,QAAQ;AAC1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAMD;AAAA,MACJ,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,KAAK;AAAA,EACP;AACF;AAEA,SAAS,iBAAiB,MAAc,QAAwB;AAC9D,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,SAAO,UAAU,KAAK,SAAS,OAAO,QAAQ;AAC5C,UAAM,QAAQ,KAAK,QAAQ,QAAQ,MAAM;AACzC,QAAI,QAAQ,EAAG;AACf,aAAS;AACT,aAAS,QAAQ;AAAA,EACnB;AACA,SAAO;AACT;AAEA,SAAS,WACP,WACA,eACA,cACA,OAOA;AACA,QAAM,SAAS,cAAc,MAAM,GAAG,KAAK,EAAE,MAAM,IAAI;AACvD,QAAM,gBAAgB,aAAa,MAAM,IAAI;AAC7C,QAAM,OAAO,YAAY,OAAO,SAAS;AACzC,QAAM,cAAc,OAAO,GAAG,EAAE,GAAG,UAAU;AAC7C,QAAM,0BAA0B,cAAc,GAAG,EAAE,GAAG,UAAU;AAChE,SAAO;AAAA,IACL;AAAA,IACA,SAAS,OAAO,cAAc,SAAS;AAAA,IACvC;AAAA,IACA,WAAW,cAAc,WAAW,IAChC,cAAc,0BACd;AAAA,IACJ,MAAM;AAAA,EACR;AACF;AAEA,SAASA,aACP,OACA,MACA,SACA,aACA,WACe;AACf,QAAM,YAAY,WAAW;AAC7B,MAAI,OAAO,KAAK,aAAa,MAAM,OAAQ,QAAO;AAClD,MAAI,SAAS,WAAW;AACtB,UAAM,OAAO,MAAM,IAAI;AACvB,WAAO,eAAe,QAAQ,aAAa,OACvC,KAAK,MAAM,aAAa,SAAS,IACjC;AAAA,EACN;AAEA,QAAM,SAAmB,CAAC;AAC1B,WAAS,UAAU,MAAM,WAAW,WAAW,WAAW,GAAG;AAC3D,QAAI,OAAO,MAAM,OAAO;AACxB,QAAI,YAAY,QAAQ,eAAe,KAAM,QAAO,KAAK,MAAM,WAAW;AAC1E,QAAI,YAAY,aAAa,aAAa,KAAM,QAAO,KAAK,MAAM,GAAG,SAAS;AAC9E,WAAO,KAAK,IAAI;AAAA,EAClB;AACA,SAAO,OAAO,KAAK,IAAI;AACzB;;;ACrsBO,SAAS,wBACd,WACA,cACA,WACA,YAC8B;AAC9B,MAAI,WAAW,OAAO;AACpB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,gBAAgB,WAAW,cAAc,SAAS;AAAA,IAC5D;AAAA,EACF;AACA,MAAI,YAAY,WAAW,YAAY;AACrC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,iBAAiB,WAAW,cAAc,UAAU;AAAA,IAC9D;AAAA,EACF;AAEA,MAAI,aAAa,YAAY;AAC3B,QAAI,UAAU,WAAW,UAAU,GAAG;AACpC,YAAM,SAAS,iBAAiB,WAAW,cAAc,UAAU;AACnE,aAAO,SAAS;AAChB,aAAO,QAAQ,yBAAyB,UAAU,OAAO,WAAW,KAAK;AACzE,aAAO,SACL,+EACiB,OAAO,MAAM,QAAQ,CAAC,CAAC;AAC1C,aAAO,EAAE,MAAM,YAAY,OAAO;AAAA,IACpC;AAEA,QAAI,WAAW,WAAW,cAAc,CAAC,mBAAmB,SAAS,GAAG;AACtE,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,iBAAiB,WAAW,cAAc,UAAU;AAAA,MAC9D;AAAA,IACF;AAEA,QACE,WAAW,WAAW,WACnB,WAAW,mBAAmB,QAC9B,WAAW,SAAS,UAAU,QAAQ,KACzC;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,iBAAiB,WAAW,cAAc,UAAU;AAAA,MAC9D;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,QACN;AAAA,QACA,QAAQ;AAAA,QACR,OAAO,KAAK,IAAI,UAAU,OAAO,WAAW,KAAK;AAAA,QACjD,QACE,0DACK,UAAU,IAAI,sCACd,WAAW,QAAQ,aAAa;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY;AACd,UAAM,OAAO,WAAW,WAAW,aAC/B,aACA,WAAW,WAAW,cACpB,cACA;AACN,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,iBAAiB,WAAW,cAAc,UAAU;AAAA,IAC9D;AAAA,EACF;AAEA,MAAI,WAAW;AACb,QAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO;AAC3C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,gBAAgB,WAAW,cAAc,SAAS;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,mBAAmB,WAAqC;AAC/D,SAAO,UAAU,kBAAkB,KAC7B,UAAU,kBAAkB,KAAK,UAAU,iBAAiB;AACpE;AAEA,SAAS,UACP,WACA,YACS;AACT,SAAO,UAAU,SAAS,WAAW,QAChC,UAAU,YAAY,WAAW;AACxC;AAEA,SAAS,yBAAyB,MAAc,OAAuB;AACrE,SAAO,KAAK,IAAI,OAAO,OAAO,SAAS,IAAI,IAAI;AACjD;AAEA,SAAS,gBACP,WACA,cACA,WACgB;AAChB,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,UAAU,QAAQ,aAAa;AAAA,IACvC,OAAO,UAAU;AAAA,IACjB,SAAS,UAAU;AAAA,IACnB,YAAY,UAAU;AAAA,IACtB,gBAAgB,UAAU;AAAA,IAC1B,cAAc,UAAU;AAAA,IACxB,cAAc,UAAU,QAAQ,SAAY,UAAU;AAAA,IACtD,sBAAsB,UAAU,QAAQ,SAAY;AAAA,IACpD,QAAQ,UAAU;AAAA,EACpB;AACF;AAEA,SAAS,iBACP,WACA,cACA,YACgB;AAChB,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,WAAW;AAAA,IACnB,OAAO,WAAW;AAAA,IAClB,SAAS,WAAW;AAAA,IACpB,YAAY,WAAW;AAAA,IACvB,gBAAgB,WAAW;AAAA,IAC3B,cAAc,WAAW;AAAA,IACzB,cAAc,WAAW,WAAW,UAChC,WAAW,OACX;AAAA,IACJ,sBAAsB,WAAW,WAAW,UACxC,eACA;AAAA,IACJ,QAAQ,WAAW;AAAA,EACrB;AACF;;;ACzIO,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAU1B,IAAM,2BAA2B;AAEjC,SAAS,gBAAgB,cAAgC;AAC9D,SAAO,CAAC,IAAI,GAAG,aAAa,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI,CAAC;AAChE;AAEO,SAAS,gBACd,SACA,eACA,OASI,CAAC,GACW;AAChB,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,kBAAkB,KAAK,mBAAmB;AAChD,QAAM,YAAY,QAAQ;AAC1B,QAAM,eAAe,QAAQ;AAC7B,MAAI;AACJ,MAAI,mBAAmB,KAAK;AAC5B,QAAM,sBAAsB,MAAwB;AAClD,yBAAqB,KAAK,sBAAsB,KAC3C,uBAAuB,aAAa;AACzC,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,gBAAgB,QAAQ,QAAQ,MAAM;AACzC,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,QAAQ,QAAQ,QAAQ,KAAK,WAAW,QAAQ;AAClD,UAAM,EAAE,OAAO,SAAS,IAAIE,cAAa,KAAK,WAAW,QAAQ,IAAI;AAErE,QAAI,CAAC,cAAc;AACjB,YAAM,cAAc,QAAQ,OAAO;AACnC,YAAM,WACJ,QAAQ,YAAY,OAAO,QAAQ,WAAW,QAAQ,OAAO;AAC/D,YAAM,iBACJ,QAAQ,YAAY,OAAO,cAAc,WAAW;AACtD,aAAO;AAAA,QACL;AAAA,QACA,QAAQ,UAAU,IAAI,aAAa;AAAA,QACnC,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,QACE,UAAU,IACN,0DACA,gCAAgC,QAAQ,IAAI,MAAM,EAAE,GAAG,KAAK;AAAA,MACpE;AAAA,IACF;AAEA,QAAI,CAAC,UAAU;AACb,YAAM,cAAc,QAAQ,OAAO;AACnC,YAAM,WACJ,QAAQ,YAAY,OAAO,QAAQ,WAAW,QAAQ,OAAO;AAC/D,YAAM,iBACJ,QAAQ,YAAY,OAAO,cAAc,WAAW;AAEtD,YAAM,gBAAgBC;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAEA,UAAI,kBAAkB,cAAc;AAClC,eAAO;AAAA,UACL;AAAA,UACA,QAAQ,UAAU,IAAI,aAAa;AAAA,UACnC,OAAO;AAAA,UACP,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,QACE,UAAU,IACN,uDACA,mBAAmB,QAAQ,IAAI,MAAM,EAAE,GAAG,KAAK;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,gBAAgB,KAAK,qBACnC;AAAA,IACA;AAAA,IACA,KAAK;AAAA,IACL;AAAA,EACF,IACE;AACJ,MAAI,gBAAgB,WAAW,OAAO;AACpC,UAAM,mBAAmB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,iBAAkB,QAAO,iBAAiB;AAAA,EAChD;AACA,QAAM,aAAa,gBAAgB,KAAK,gBACpC,qBAAqB,SAAS,KAAK,aAAa,IAChD;AACJ,MAAI,iBAAiB,aAAa,aAAa;AAC7C,UAAM,aAAa;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,WAAY,QAAO,WAAW;AAAA,EACpC;AAEA,MAAI,cAAc;AAChB,UAAM,kBAAkB,WAAW,eAAe,YAAY;AAC9D,QAAI,gBAAgB,SAAS,KAAK,QAAQ,QAAQ,MAAM;AACtD,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,QACE,cAAc,gBAAgB,MAAM;AAAA,MAExC;AAAA,IACF;AAIA,QAAI;AACJ,QAAI,eAAe;AACnB,QAAI,gBAAgB,WAAW,GAAG;AAChC,eAAS,gBAAgB,CAAC;AAC1B,qBAAe;AAAA,IACjB,WAAW,gBAAgB,SAAS,KAAK,QAAQ,QAAQ,MAAM;AAC7D,eAAS,cAAc,iBAAiB,QAAQ,IAAI;AACpD,qBAAe,qBAAqB,gBAAgB,MAAM,gDAAgD,QAAQ,IAAI;AAAA,IACxH;AAEA,QAAI,QAAQ;AAOV,UAAI,6BAA6B,SAAS,QAAQ,eAAe,eAAe,GAAG;AACjF,cAAM,eAAeA;AAAA,UACnB;AAAA,UACA,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA,eAAO;AAAA,UACL;AAAA,UACA,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,SAAS,QAAQ;AAAA,UACjB,YAAY,QAAQ;AAAA,UACpB,gBAAgB,QAAQ;AAAA,UACxB,cAAc,QAAQ;AAAA,UACtB,cAAc,gBAAgB;AAAA,UAC9B,sBAAsB;AAAA,UACtB,QACE,4BAA4B,OAAO,IAAI,wCAClC,eAAe,sBAAsB,QAAQ,IAAI;AAAA,QAE1D;AAAA,MACF;AAEA,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,SAAS,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,QACnB,gBAAgB,OAAO;AAAA,QACvB,cAAc,OAAO;AAAA,QACrB,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,UAAM,iBAAiB,gBAAgB,eAAe,YAAY;AAClE,QAAI,eAAe,WAAW,GAAG;AAC/B,YAAM,YAAY,eAAe,CAAC;AAClC,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,OAAO,UAAU;AAAA,QACjB,SAAS,UAAU;AAAA,QACnB,YAAY,UAAU;AAAA,QACtB,gBAAgB,UAAU;AAAA,QAC1B,cAAc,UAAU;AAAA,QACxB,cAAc,UAAU;AAAA,QACxB,sBAAsB;AAAA,QACtB,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,yBAAqB;AAAA,MACnB;AAAA,MACA;AAAA,MACA,CAAC,gBAAgB,SAAS;AAAA,MAC1B,QAAQ;AAAA,MACR,oBAAoB;AAAA,IACtB;AACA,UAAM,kBAAkB,mBAAmB,IAAI,cAAc,KAAK,CAAC;AAEnE,QAAI,gBAAgB,WAAW,KAAM,gBAAgB,SAAS,KAAK,gBAAgB,CAAC,EAAE,SAAS,gBAAiB;AAC9G,YAAM,OACJ,gBAAgB,WAAW,IACvB,gBAAgB,CAAC,IACjB,cAAc,iBAAiB,QAAQ,QAAQ,CAAC;AACtD,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,QACd,YAAY,KAAK;AAAA,QACjB,gBAAgB,KAAK;AAAA,QACrB,cAAc,KAAK;AAAA,QACnB,cAAc,KAAK;AAAA,QACnB,sBAAsB;AAAA,QACtB,QAAQ,sCAAsC,KAAK,MAAM,QAAQ,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,QAAQ,MAAM;AACxB,UAAM,UAAU,QAAQ;AACxB,QAAI,UAAU,KAAK,UAAU,cAAc,QAAQ;AACjD,YAAM,YAAY,KAAK,gBACnB,oDACA;AAEJ,UAAI,cAAc;AAChB,cAAM,WAAW,cAAc,OAAO;AACtC,cAAM,aAAa,YAAY,CAAC,IAAI,QAAQ,GAAG,cAAc,iBAAiB;AAC9E,YAAI,WAAW,SAAS,GAAG;AACzB,iBAAO;AAAA,YACL;AAAA,YACA,QAAQ;AAAA,YACR,OAAO,WAAW,CAAC,EAAE;AAAA,YACrB,SAAS,QAAQ;AAAA,YACjB,YAAY,QAAQ;AAAA,YACpB,cAAc,WAAW,CAAC,EAAE;AAAA,YAC5B,sBAAsB;AAAA,YACtB,QAAQ,8CAA8C,WAAW,CAAC,EAAE,MAAM,QAAQ,CAAC,CAAC,IAAI,SAAS;AAAA,UACnG;AAAA,QACF;AAAA,MACF;AAEA,YAAM,aAAa,CAAC;AACpB,aAAO;AAAA,QACL;AAAA,QACA,QAAQ,aAAa,aAAc,KAAK,gBAAgB,cAAc;AAAA,QACtE,OAAO,aAAa,IAAO,KAAK,gBAAgB,MAAM;AAAA,QACtD,SAAS,QAAQ;AAAA,QACjB,YAAY,QAAQ;AAAA,QACpB,QAAQ,aACJ,oDACA,uBAAuB,SAAS;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,cAAc;AAChB,UAAM,gBAAgB,oBAAoB,IAAI,SAAS,KAClD;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR,oBAAoB;AAAA,IACtB;AAEF,QAAI,cAAc,WAAW,GAAG;AAC9B,YAAM,YAAY,cAAc,CAAC;AACjC,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,OAAO,UAAU;AAAA,QACjB,SAAS,UAAU;AAAA,QACnB,YAAY,UAAU;AAAA,QACtB,gBAAgB,UAAU;AAAA,QAC1B,cAAc,UAAU;AAAA,QACxB,cAAc,UAAU;AAAA,QACxB,sBAAsB;AAAA,QACtB,QAAQ,oCAAoC,UAAU,MAAM,QAAQ,CAAC,CAAC;AAAA,MACxE;AAAA,IACF;AAEA,QAAI,cAAc,SAAS,GAAG;AAC5B,YAAM,OAAO,cAAc,CAAC;AAC5B,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,QACd,YAAY,KAAK;AAAA,QACjB,QAAQ,cAAc,cAAc,MAAM,8BAA8B,KAAK,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC/F;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AACF;AAEO,SAAS,sBACd,KACA,eACA,OAAyD,CAAC,GACxC;AAClB,MAAI;AACJ,QAAM,sBAAsB,MAAwB;AAClD,yBAAqB,uBAAuB,aAAa;AACzD,WAAO;AAAA,EACT;AACA,SAAO,IAAI,SAAS;AAAA,IAAI,CAAC,YACvB,gBAAgB,SAAS,eAAe,EAAE,GAAG,MAAM,oBAAoB,CAAC;AAAA,EAC1E;AACF;AAEO,SAAS,qBACd,KACA,cACA,OAAyD,CAAC,GACxC;AAClB,SAAO,sBAAsB,KAAK,gBAAgB,YAAY,GAAG,IAAI;AACvE;AAEO,SAAS,cACd,SACA,cACA,OAAyD,CAAC,GAC1C;AAChB,QAAM,iBAAiB,aAAa,QAAQ,SAAS,IAAI;AACzD,QAAM,gBAAgB,gBAAgB,YAAY;AAClD,QAAM,SAAS,gBAAgB,SAAS,eAAe,IAAI;AAE3D,MAAI,OAAO,WAAW,YAAY;AAChC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,OAAO,OAAO,WAAW,QAAQ;AACvC,MAAI,QAAQ,MAAM;AAChB,WAAO;AAAA,MACL,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,WAAW,eAAe,MAAM,IAAI;AAC1C,QAAM,aAAa,kBAAkB,QAAQ;AAC7C,QAAM,UAAU,OAAO,cAAc,QAAQ,YAAY;AACzD,QAAM,cAAc,OAAO,kBAAkB,QAAQ,gBAAgB;AACrE,QAAM,YAAY,OAAO,gBAAgB,QAAQ;AACjD,QAAM,OAAO,UAAU,YAAY,UAAU,MAAM,WAAW;AAC9D,QAAM,eAAe,QAAQ,eAAe,QAAQ,SAAS,IAAI;AACjE,QAAM,KACJ,aAAa,OACT,UAAU,YAAY,UAAU,SAAS,SAAS,IAClD,eACE,OAAO,aAAa,SACpB,UAAU,YAAY,UAAU,SAAS,SAAS,UAAU,CAAC,GAAG,UAAU,CAAC;AAEnF,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,OAAO,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,aAAa,gBAAgB,YAAY,UAAU,SAAS,EAAE;AAAA,IACzE,QAAQ,OAAO;AAAA,EACjB;AACF;AAEA,SAAS,kBAAkB,OAA2B;AACpD,QAAM,SAAS,CAAC,CAAC;AACjB,MAAI,SAAS;AACb,aAAW,QAAQ,OAAO;AACxB,WAAO,KAAK,MAAM;AAClB,cAAU,KAAK,SAAS;AAAA,EAC1B;AACA,SAAO;AACT;AAEA,SAAS,UACP,YACA,OACA,MACA,QACQ;AACR,QAAM,QAAQ,WAAW,IAAI,KAAK;AAClC,QAAM,YAAY,MAAM,OAAO,CAAC,GAAG,UAAU;AAC7C,SAAO,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,SAAS,CAAC;AACxD;AAEA,SAAS,gBACP,YACA,OACA,MACA,QACQ;AACR,QAAM,QAAQ,WAAW,IAAI,KAAK;AAClC,QAAM,YAAY,MAAM,OAAO,CAAC,GAAG,UAAU;AAC7C,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,SAAS,OAAO,SAAS,CAAC;AACxD;AAEO,SAAS,qBACd,KACA,SACA,OAAuE,CAAC,GAChE;AACR,MAAI,UAAU;AACd,QAAM,YAAY,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AAE7E,aAAW,WAAW,IAAI,UAAU;AAClC,UAAM,SAAS,UAAU,IAAI,QAAQ,EAAE;AACvC,QAAI,CAAC,OAAQ;AAEb,QAAI,YAAY;AAEhB,QAAI,OAAO,WAAW,QAAQ,OAAO,YAAY,QAAQ,MAAM;AAC7D,cAAQ,OAAO,OAAO;AACtB,kBAAY;AAAA,IACd;AACA,QAAI,OAAO,cAAc,QAAQ,OAAO,eAAe,QAAQ,UAAU;AACvE,cAAQ,WAAW,OAAO;AAC1B,kBAAY;AAAA,IACd;AACA,QAAI,OAAO,kBAAkB,QAAQ,OAAO,mBAAmB,QAAQ,cAAc;AACnF,cAAQ,eAAe,OAAO;AAC9B,kBAAY;AAAA,IACd;AACA,QAAI,OAAO,gBAAgB,QAAQ,OAAO,iBAAiB,QAAQ,YAAY;AAC7E,cAAQ,aAAa,OAAO;AAC5B,kBAAY;AAAA,IACd;AAEA,QAAI,OAAO,gBAAgB,QAAQ,OAAO,iBAAiB,QAAQ,eAAe;AAChF,UAAI,KAAK,YAAY;AACnB,gBAAQ,gBAAgB,OAAO;AAC/B,eAAO,QAAQ;AAAA,MACjB,OAAO;AACL,gBAAQ,gBAAgB,OAAO;AAAA,MACjC;AACA,kBAAY;AAAA,IACd,WAAW,OAAO,gBAAgB,QAAQ,OAAO,iBAAiB,QAAQ,eAAe;AACvF,UAAI,QAAQ,eAAe;AACzB,eAAO,QAAQ;AACf,oBAAY;AAAA,MACd;AAAA,IACF;AAEA,QAAI,aAAa,OAAO,WAAW,YAAY;AAC7C,cAAQ,oBAAoB,OAAO;AACnC,cAAQ,mBAAmB,OAAO;AAAA,IACpC;AAEA,QACE,KAAK,SACF,KAAK,eACJ,OAAO,WAAW,cAAc,OAAO,WAAW,cACnD,OAAO,SAAS,gBACnB;AACA,cAAQ,SAAS,KAAK;AACtB,aAAO,QAAQ;AACf,aAAO,QAAQ;AACf,UAAI,QAAQ,iBAAiB,QAAQ,kBAAkB,QAAQ,eAAe;AAC5E,eAAO,QAAQ;AAAA,MACjB;AACA,kBAAY;AAAA,IACd;AAEA,QAAI,WAAW;AACb,iBAAW;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAASA,aACP,OACA,MACA,SACA,aACA,WACe;AACf,QAAM,WAAW;AACjB,QAAM,SAAS,WAAW;AAE1B,MAAI,WAAW,KAAK,UAAU,MAAM,OAAQ,QAAO;AAEnD,MAAI,aAAa,QAAQ;AACvB,UAAM,OAAO,MAAM,QAAQ;AAC3B,QAAI,eAAe,QAAQ,aAAa,MAAM;AAC5C,aAAO,KAAK,MAAM,aAAa,SAAS;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAmB,CAAC;AAC1B,WAAS,QAAQ,UAAU,SAAS,QAAQ,SAAS,GAAG;AACtD,QAAI,cAAc,MAAM,KAAK;AAC7B,QAAI,UAAU,YAAY,eAAe,KAAM,eAAc,YAAY,MAAM,WAAW;AAC1F,QAAI,UAAU,UAAU,aAAa,KAAM,eAAc,YAAY,MAAM,GAAG,SAAS;AACvF,WAAO,KAAK,WAAW;AAAA,EACzB;AACA,SAAO,OAAO,KAAK,IAAI;AACzB;AAEA,SAAS,cAA0C,YAAiB,YAAuB;AACzF,SAAO,WAAW;AAAA,IAAO,CAAC,MAAM,cAC9B,KAAK,IAAI,UAAU,OAAO,UAAU,IAAI,KAAK,IAAI,KAAK,OAAO,UAAU,IAAI,YAAY;AAAA,EACzF;AACF;AAgBA,SAAS,6BACP,SACA,WACA,OACA,iBACS;AACT,MAAI,QAAQ,QAAQ,KAAM,QAAO;AAGjC,MAAI,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,MAAM,OAAQ,QAAO;AAG9D,MAAI,KAAK,IAAI,UAAU,OAAO,QAAQ,IAAI,KAAK,gBAAiB,QAAO;AAIvE,QAAM,eAAeA;AAAA,IACnB;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,MAAI,iBAAiB,QAAQ,cAAe,QAAO;AAEnD,SAAO;AACT;AAEA,SAASD,cAAa,WAAuB,MAAoD;AAC/F,MAAI,QAAQ;AACZ,MAAI,WAAW;AAEf,aAAW,QAAQ,WAAW;AAC5B,UAAM,WAAW,KAAK;AACtB,UAAM,SAAS,KAAK,WAAW,KAAK,IAAI,KAAK,UAAU,CAAC,IAAI;AAE5D,QAAI,QAAQ,YAAY,QAAQ,UAAU,KAAK,WAAW,GAAG;AAC3D,iBAAW;AAAA,IACb;AAEA,QAAI,OAAO,UAAW,KAAK,aAAa,KAAK,QAAQ,UAAW;AAC9D,eAAS,KAAK,WAAW,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS;AAC3B;;;ACrnBA,IAAM,wBAAwB;AAC9B,IAAM,uBAAuB;AAC7B,IAAM,2BAA2B;AACjC,IAAM,oBAAoB;AAC1B,IAAM,4BAA4B;AAsB3B,SAAS,wBACd,UACA,SACA,eACkB;AAClB,QAAM,aAAa,QAAQ,IAAI,CAAC,YAAY,EAAE,GAAG,OAAO,EAAE;AAC1D,MACE,SAAS,SAAS,2BAA2B,KAC1C,CAAC,WAAW,KAAK,CAAC,WAAW,OAAO,WAAW,WAAW,GAC7D;AACA,WAAO;AAAA,EACT;AACA,QAAM,gBAAgB,IAAI;AAAA,IACxB,WAAW,IAAI,CAAC,QAAQ,UAAU,CAAC,OAAO,WAAW,KAAK,CAAC;AAAA,EAC7D;AACA,QAAM,YAAY,iBAAiB,UAAU,YAAY,aAAa;AACtE,QAAM,iBAAiB,oBAAI,IAAoB;AAC/C,aAAW,YAAY,WAAW;AAChC,mBAAe;AAAA,MACb,SAAS;AAAA,OACR,eAAe,IAAI,SAAS,KAAK,KAAK,KAAK;AAAA,IAC9C;AAAA,EACF;AAEA,WAAS,QAAQ,GAAG,QAAQ,2BAA2B,SAAS,GAAG;AACjE,QAAI,UAAU;AACd,eAAW,WAAW,UAAU;AAC9B,UAAI,QAAQ,QAAQ,QAAQ,CAAC,QAAQ,cAAe;AACpD,YAAM,QAAQ,sBAAsB,SAAS,aAAa;AAC1D,UAAI,SAAS,KAAM;AACnB,WAAK,eAAe,IAAI,KAAK,KAAK,KAAK,0BAA0B;AAC/D;AAAA,MACF;AACA,YAAM,cAAc,cAAc,IAAI,QAAQ,EAAE;AAChD,UAAI,eAAe,KAAM;AACzB,YAAM,SAAS,WAAW,WAAW;AACrC,UAAI,OAAO,WAAW,YAAa;AAEnC,YAAM,aAAaE;AAAA,QACjB,4BAA4B,SAAS,aAAa;AAAA,MACpD,EAAE,MAAM,GAAG,CAAC;AACZ,UAAI,WAAW,SAAS,EAAG;AAC3B,YAAM,SAAS,WACZ;AAAA,QAAI,CAAC,cACJ;AAAA,UACE,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,EACC;AAAA,QAAK,CAAC,MAAM,UACX,MAAM,cAAc,KAAK,eACtB,MAAM,UAAU,QAAQ,KAAK,UAAU,SACvC,KAAK,UAAU,OAAO,MAAM,UAAU;AAAA,MAC3C;AACF,YAAM,OAAO,OAAO,CAAC;AACrB,YAAM,SAAS,OAAO,CAAC;AACvB,UACE,CAAC,KAAK,UAAU,SACb,KAAK,sBAAsB,4BAC3B,KAAK,UAAU,wBACf,KAAK,cAAc,OAAO,cAAc,mBAC3C;AACA;AAAA,MACF;AAEA,iBAAW,WAAW,IAAI;AAAA,QACxB,WAAW,QAAQ;AAAA,QACnB,QAAQ;AAAA,QACR,OAAO,KAAK,IAAI,MAAM,MAAM,KAAK,UAAU,IAAI;AAAA,QAC/C,SAAS,KAAK,UAAU;AAAA,QACxB,YAAY,KAAK,UAAU;AAAA,QAC3B,gBAAgB,KAAK,UAAU;AAAA,QAC/B,cAAc,KAAK,UAAU;AAAA,QAC7B,QACE,sDACK,KAAK,mBAAmB,gCACf,KAAK,QAAQ,QAAQ,CAAC,CAAC,aAC/B,KAAK,cAAc,OAAO,aAAa,QAAQ,CAAC,CAAC;AAAA,MAC3D;AACA,gBAAU;AAEV,gBAAU,KAAK;AAAA,QACb,YAAY,QAAQ;AAAA,QACpB,YAAY,KAAK,UAAU;AAAA,QAC3B;AAAA,MACF,CAAC;AACD,qBAAe,IAAI,QAAQ,eAAe,IAAI,KAAK,KAAK,KAAK,CAAC;AAAA,IAChE;AACA,QAAI,CAAC,QAAS;AAAA,EAChB;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,UACA,SACA,eACY;AACZ,QAAM,YAAY,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AAC7E,SAAO,SAAS,QAAQ,CAAC,YAAwB;AAC/C,UAAM,SAAS,UAAU,IAAI,QAAQ,EAAE;AACvC,QACE,QAAQ,QAAQ,QACb,QAAQ,WAAW,QAClB,OAAO,WAAW,cAAc,OAAO,WAAW,aACnD,OAAO,QAAQ,MAClB;AACA,aAAO,CAAC;AAAA,IACV;AACA,UAAM,QAAQ,sBAAsB,SAAS,aAAa;AAC1D,WAAO,SAAS,OACZ,CAAC,IACD,CAAC,EAAE,YAAY,QAAQ,MAAM,YAAY,OAAO,SAAS,MAAM,CAAC;AAAA,EACtE,CAAC;AACH;AAEA,SAAS,mBACP,YACA,OACA,WACA,WACiB;AACjB,MAAI,kBAAkB;AACtB,MAAI,cAAc;AAClB,MAAI,sBAAsB;AAC1B,QAAM,iBAAiB,UAAU,OAAO;AAExC,aAAW,YAAY,WAAW;AAChC,QAAI,SAAS,UAAU,MAAO;AAC9B,UAAM,iBAAiB,KAAK,IAAI,aAAa,SAAS,UAAU;AAChE,QAAI,mBAAmB,KAAK,iBAAiB,sBAAuB;AACpE,UAAM,gBAAgB,SAAS,aAAa,SAAS;AACrD,UAAM,aAAa,KAAK,IAAI,iBAAiB,aAAa;AAC1D,UAAM,YAAY,KAAK,IAAI,GAAG,IAAI,aAAa,CAAC;AAChD,UAAM,SAAS,KAAK,IAAI,iBAAiB;AACzC,uBAAmB,YAAY;AAC/B,mBAAe;AACf,QAAI,aAAa,qBAAsB,wBAAuB;AAAA,EAChE;AAEA,QAAM,UAAU,cAAc,IAAI,kBAAkB,cAAc;AAClE,SAAO;AAAA,IACL;AAAA,IACA,aACE,UAAU,QAAQ,MAAM,UAAU,QAAQ,UAAU,QAAQ,OAAO;AAAA,IACrE;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAASA,uBACP,YAC0B;AAC1B,QAAM,SAAS,oBAAI,IAAoC;AACvD,aAAW,aAAa,YAAY;AAClC,UAAM,MAAM;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU,eAAe;AAAA,MACzB,UAAU,aAAa;AAAA,IACzB,EAAE,KAAK,GAAG;AACV,UAAM,WAAW,OAAO,IAAI,GAAG;AAC/B,QAAI,CAAC,YAAY,UAAU,QAAQ,SAAS,OAAO;AACjD,aAAO,IAAI,KAAK,SAAS;AAAA,IAC3B;AAAA,EACF;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE;AAAA,IAAK,CAAC,MAAM,UACtC,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO,MAAM;AAAA,EAChD;AACF;;;AC5JA;AAEA;AAEA,IAAAC,oBAAiB;AAwBjB,eAAsB,iBACpB,KACA,eACA,OAGI,CAAC,GACsB;AAC3B,QAAM,UAA4B,CAAC;AACnC,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,kBAAkB,KAAK;AAC7B,MAAI;AACJ,QAAM,sBAAsB,MAAwB;AAClD,yBAAqB,uBAAuB,aAAa;AACzD,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,KAAK,SAAU,MAAM,eAAe,GAAI;AAC3C,UAAM,WAAW,KAAK,YAAa,MAAM,aAAa,KAAK,GAAG;AAC9D,QAAI,YAAY,KAAK,cAAc;AACjC,YAAM,UAAU,kBAAAC,QAAK,SAAS,UAAU,KAAK,YAAY;AACzD,YAAM,OAAO,MAAM,iBAAiB,QAAQ;AAG5C,YAAM,aAAa,KAAK;AACxB,YAAM,YAAY,oBAAI,IAAwB;AAC9C,YAAM,kBAAkB,oBAAI,IAG1B;AACF,YAAM,eAAe,oBAAI,IAA4C;AACrE,YAAM,uBAAuB,oBAAI,IAAoB;AACrD,YAAM,uBAAuB,oBAAI,IAO/B;AAEF,iBAAW,WAAW,IAAI,UAAU;AAClC,cAAM,mBAAmB,cAAc,QAAQ;AAC/C,YAAI,oBAAoB,MAAM;AAC5B,gBAAM,eAAe,qBAAqB,IAAI,gBAAgB;AAC9D,gBAAM,gBAAgB,gBACjB,MAAM,cAAc,kBAAkB,QAAQ,KAC9C;AACL,cAAI,CAAC,cAAc;AACjB,iCAAqB,IAAI,kBAAkB,aAAa;AAAA,UAC1D;AACA,cAAI,kBAAkB,MAAM;AAC1B,oBAAQ;AAAA,cACN,gBAAgB,SAAS,eAAe;AAAA,gBACtC;AAAA,gBACA,eAAe;AAAA,gBACf;AAAA,gBACA;AAAA,cACF,CAAC;AAAA,YACH;AACA;AAAA,UACF;AACA,cAAI,QAAQ,UAAU,IAAI,aAAa;AACvC,cAAI,CAAC,OAAO;AACV,oBAAQ,MAAM,QAAQ,eAAe,MAAM,SAAS,QAAQ;AAC5D,sBAAU,IAAI,eAAe,KAAK;AAAA,UACpC;AACA,cAAI,qBAAqB,gBAAgB,IAAI,aAAa;AAC1D,cAAI,gBAAgB,aAAa,IAAI,aAAa;AAClD,cAAI,CAAC,gBAAgB,IAAI,aAAa,GAAG;AACvC,kBAAM,aAAa,MAAM;AAAA,cACvB;AAAA,cACA;AAAA,cACA;AAAA,YACF;AACA,iCAAqB,cAAc,OAC/B,SACA;AAAA,cACA,gBAAgB,UAAU;AAAA,cAC1B;AAAA,YACF;AACF,4BAAgB,cAAc,OAC1B,SACA;AAAA,cACA,gBAAgB,UAAU;AAAA,cAC1B;AAAA,YACF;AACF,4BAAgB,IAAI,eAAe,kBAAkB;AACrD,yBAAa,IAAI,eAAe,aAAa;AAAA,UAC/C;AACA,gBAAM,SAAS,gBAAgB,SAAS,eAAe;AAAA,YACrD,WAAW;AAAA,YACX;AAAA,YACA,eAAe;AAAA,YACf;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AACD,gBAAM,cAAc,QAAQ;AAC5B,kBAAQ,KAAK,MAAM;AACnB,cAAI,eAAe;AACjB,kBAAM,QAAQ,qBAAqB,IAAI,aAAa;AACpD,gBAAI,OAAO;AACT,oBAAM,SAAS,KAAK,OAAO;AAC3B,oBAAM,cAAc,KAAK,WAAW;AAAA,YACtC,OAAO;AACL,mCAAqB,IAAI,eAAe;AAAA,gBACtC,UAAU,CAAC,OAAO;AAAA,gBAClB,eAAe,CAAC,WAAW;AAAA,gBAC3B;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF;AACA;AAAA,QACF;AAGA,gBAAQ;AAAA,UACN,gBAAgB,SAAS,eAAe;AAAA,YACtC;AAAA,YACA,eAAe;AAAA,YACf;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,iBAAW,SAAS,qBAAqB,OAAO,GAAG;AACjD,cAAM,aAAa;AAAA,UACjB,MAAM;AAAA,UACN,MAAM,cAAc,IAAI,CAAC,UAAU,QAAQ,KAAK,CAAC;AAAA,UACjD,MAAM;AAAA,QACR;AACA,mBAAW,CAAC,QAAQ,WAAW,KAAK,MAAM,cAAc,QAAQ,GAAG;AACjE,kBAAQ,WAAW,IAAI,WAAW,MAAM;AAAA,QAC1C;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,sBAAsB,KAAK,eAAe,EAAE,WAAW,gBAAgB,CAAC;AACjF;AAKA,eAAsB,aACpB,aACA,OAAwB,CAAC,GAKxB;AACD,QAAM,MAAM,MAAM,aAAa,WAAW;AAC1C,QAAM,UAAU,kBAAkB,WAAW;AAC7C,QAAM,gBAAgB,MAAM,kBAAkB,OAAO;AAErD,QAAM,WAAW,CAAC,KAAK,QAAQ,MAAM,aAAa,KAAK,GAAG,IAAI;AAC9D,QAAM,aAAa,WAAW,MAAM,iBAAiB,QAAQ,IAAI;AAEjE,QAAM,UAAU,MAAM,iBAAiB,KAAK,eAAe;AAAA,IACzD,GAAG;AAAA,IACH,cAAc;AAAA,IACd,UAAU,YAAY;AAAA,EACxB,CAAC;AAED,MAAI,UAAU;AACd,MAAI,UAAU;AAEd,MAAI,CAAC,KAAK,QAAQ;AAChB,cAAU,qBAAqB,KAAK,SAAS;AAAA,MAC3C,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK;AAAA,MACZ,YAAY,cAAc;AAAA,IAC5B,CAAC;AACD,QAAI,UAAU,KAAK,KAAK,YAAY;AAClC,YAAM,aAAa,aAAa,GAAG;AACnC,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,SAAS,QAAQ;AACrC;;;ACvQA,kBAA6B;AAOtB,SAAS,aAAa,MAAc,QAAyB;AAClE,QAAM,cAAc,KAAK,KAAK;AAC9B,QAAM,gBAAgB,QAAQ,KAAK;AACnC,SAAO,gBAAgB,GAAG,WAAW,KAAK,aAAa,MAAM;AAC/D;AAEO,SAAS,YAAY,QAA8B;AACxD,QAAM,UAAU,OAAO,KAAK;AAC5B,QAAM,QAAQ,4BAA4B,KAAK,OAAO;AACtD,MAAI,CAAC,MAAO,QAAO,EAAE,MAAM,QAAQ;AAEnC,QAAM,OAAO,MAAM,CAAC,EAAE,KAAK;AAC3B,QAAM,SAAS,MAAM,CAAC,EAAE,KAAK;AAC7B,SAAO,SAAS,EAAE,MAAM,OAAO,IAAI,EAAE,KAAK;AAC5C;AAMO,SAAS,eAAuB;AACrC,aAAO,YAAAC,IAAO;AAChB;;;ACRA,SAAS,cAAc,OAAkD;AACvE,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,QAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,SAAO,cAAc,OAAO,aAAa,cAAc;AACzD;AAEA,SAAS,wBAAwB,OAAgD;AAC/E,MAAI,SAAS,KAAM,QAAO;AAE1B,UAAQ,OAAO,OAAO;AAAA,IACpB,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,OAAO,SAAS,KAAK;AAAA,IAC9B,KAAK,UAAU;AACb,UAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,eAAO,MAAM,MAAM,CAAC,SAAS,wBAAwB,IAAI,CAAC;AAAA,MAC5D;AAEA,UAAI,CAAC,cAAc,KAAK,GAAG;AACzB,eAAO;AAAA,MACT;AAEA,aAAO,OAAO,OAAO,KAAK,EAAE,MAAM,CAAC,SAAS,wBAAwB,IAAI,CAAC;AAAA,IAC3E;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,2BACd,YACmB;AACnB,MAAI,CAAC,WAAY,QAAO,CAAC;AAEzB,QAAM,oBAAmE,CAAC;AAE1E,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,QAAI,CAAC,IAAI,WAAW,IAAI,GAAG;AACzB,YAAM,IAAI,MAAM,0BAA0B,GAAG,yBAAyB;AAAA,IACxE;AAEA,QAAI,CAAC,wBAAwB,KAAK,GAAG;AACnC,YAAM,IAAI;AAAA,QACR,sBAAsB,GAAG;AAAA,MAC3B;AAAA,IACF;AAEA,sBAAkB,KAAK,CAAC,KAAsB,KAAK,CAAC;AAAA,EACtD;AAEA,SAAO,OAAO,YAAY,iBAAiB;AAC7C;AAMA,eAAsB,WACpB,KACA,MACA,UACkB;AAClB,QAAM,KAAK,KAAK,MAAM,aAAa;AACnC,QAAM,YAAY,KAAK,cAAa,oBAAI,KAAK,GAAE,YAAY;AAG3D,MAAI,SAAS,KAAK;AAClB,MAAI,CAAC,UAAU,YAAa,MAAM,eAAe,GAAI;AACnD,aAAU,MAAM,iBAAiB,QAAQ,KAAM;AAAA,EACjD;AAEA,QAAM,UAAmB;AAAA,IACvB;AAAA,IACA,QAAQ,KAAK;AAAA,IACb;AAAA,IACA,MAAM,KAAK;AAAA,IACX,UAAU;AAAA,EACZ;AAGA,MAAI,KAAK,QAAQ,KAAM,SAAQ,OAAO,KAAK;AAC3C,MAAI,KAAK,YAAY,KAAM,SAAQ,WAAW,KAAK;AACnD,MAAI,KAAK,gBAAgB,KAAM,SAAQ,eAAe,KAAK;AAC3D,MAAI,KAAK,cAAc,KAAM,SAAQ,aAAa,KAAK;AACvD,MAAI,KAAK,KAAM,SAAQ,OAAO,KAAK;AACnC,MAAI,KAAK,SAAU,SAAQ,WAAW,KAAK;AAC3C,MAAI,KAAK,SAAU,SAAQ,WAAW,KAAK;AAC3C,MAAI,OAAQ,SAAQ,SAAS;AAE7B,SAAO,OAAO,SAAS,2BAA2B,KAAK,UAAU,CAAC;AAElE,MAAI,SAAS,KAAK,OAAO;AACzB,SAAO;AACT;AAMO,SAAS,qBACd,SACA,eACM;AACN,MAAI,QAAQ,cAAe;AAC3B,MAAI,QAAQ,QAAQ,KAAM;AAE1B,QAAM,WAAW,QAAQ,OAAO;AAChC,QAAM,UAAU,QAAQ,YAAY,QAAQ,QAAQ;AAEpD,MAAI,WAAW,KAAK,UAAU,cAAc,OAAQ;AAEpD,MAAI,aAAa,QAAQ;AACvB,QAAI,OAAO,cAAc,QAAQ;AACjC,QAAI,QAAQ,gBAAgB,QAAQ,QAAQ,cAAc,MAAM;AAC9D,aAAO,KAAK,MAAM,QAAQ,cAAc,QAAQ,UAAU;AAAA,IAC5D;AACA,YAAQ,gBAAgB;AAAA,EAC1B,OAAO;AACL,UAAM,QAAkB,CAAC;AACzB,aAAS,IAAI,UAAU,KAAK,QAAQ,KAAK;AACvC,UAAI,IAAI,cAAc,CAAC;AACvB,UAAI,MAAM,YAAY,QAAQ,gBAAgB,MAAM;AAClD,YAAI,EAAE,MAAM,QAAQ,YAAY;AAAA,MAClC;AACA,UAAI,MAAM,UAAU,QAAQ,cAAc,MAAM;AAC9C,YAAI,EAAE,MAAM,GAAG,QAAQ,UAAU;AAAA,MACnC;AACA,YAAM,KAAK,CAAC;AAAA,IACd;AACA,YAAQ,gBAAgB,MAAM,KAAK,IAAI;AAAA,EACzC;AAGA,MAAI,QAAQ,eAAe;AACzB,YAAQ,qBAAqB,YAAY,QAAQ,aAAa;AAAA,EAChE;AACF;AAEO,SAAS,YACd,KACA,WACA,MACS;AACT,QAAM,UAAU,IAAI,SAAS,KAAK,CAAC,UAAU,MAAM,OAAO,SAAS;AACnE,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,oBAAoB,SAAS,IAAI;AAAA,EACnD;AACA,MAAI,KAAK,SAAS,QAAQ,WAAW,KAAK,OAAO;AAC/C,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,MAAI,KAAK,KAAK,KAAK,EAAE,WAAW,GAAG;AACjC,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,UAAQ,OAAO,KAAK;AACpB,SAAO;AACT;AAYO,SAAS,eACd,KACA,WACA,UAAU,OACD;AACT,QAAM,UAAU,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AAC3D,MAAI,CAAC,QAAS,QAAO;AAErB,UAAQ,WAAW;AAEnB,MAAI,SAAS;AAEX,eAAW,KAAK,IAAI,UAAU;AAC5B,UAAI,EAAE,aAAa,WAAW;AAC5B,UAAE,WAAW;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,iBACd,KACA,WACS;AACT,QAAM,UAAU,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AAC3D,MAAI,CAAC,QAAS,QAAO;AACrB,UAAQ,WAAW;AACnB,SAAO;AACT;AAOA,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAmBO,SAAS,cACd,KACA,WACA,MACS;AACT,QAAM,UAAU,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AAC3D,MAAI,CAAC,QAAS,QAAO;AAErB,MAAI,MAAM,SAAS;AAEjB,QAAI,WAAW,IAAI,SAAS;AAAA,MAC1B,CAAC,MAAM,EAAE,OAAO,aAAa,EAAE,aAAa;AAAA,IAC9C;AAAA,EACF,OAAO;AAEL,eAAW,KAAK,IAAI,UAAU;AAC5B,UAAI,EAAE,aAAa,UAAW;AAG9B,iBAAW,SAAS,eAAe;AACjC,YAAI,EAAE,KAAK,KAAK,QAAQ,QAAQ,KAAK,KAAK,MAAM;AAC9C,UAAC,EAA8B,KAAK,IAAI,QAAQ,KAAK;AAAA,QACvD;AAAA,MACF;AAGA,UAAI,QAAQ,UAAU;AACpB,UAAE,WAAW,QAAQ;AAAA,MACvB,OAAO;AACL,eAAO,EAAE;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAGA,QAAM,MAAM,IAAI,SAAS,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS;AAC5D,MAAI,QAAQ,GAAI,KAAI,SAAS,OAAO,KAAK,CAAC;AAE1C,SAAO;AACT;AASO,SAAS,eACd,UACA,QACW;AACX,SAAO,SAAS,OAAO,CAAC,MAAM;AAC5B,QAAI,OAAO,SAAS,QAAQ,EAAE,SAAU,QAAO;AAC/C,QAAI,OAAO,aAAa,QAAQ,CAAC,EAAE,SAAU,QAAO;AACpD,QAAI,OAAO,UAAU,EAAE,WAAW,OAAO,OAAQ,QAAO;AACxD,QAAI,OAAO,QAAQ,EAAE,SAAS,OAAO,KAAM,QAAO;AAClD,QAAI,OAAO,YAAY,EAAE,aAAa,OAAO,SAAU,QAAO;AAC9D,QAAI,OAAO,aAAa,QAAQ,EAAE,sBAAsB,WAAY,QAAO;AAC3E,QAAI,OAAO,aAAa,SAAS,EAAE,sBAAsB,WAAY,QAAO;AAC5E,WAAO;AAAA,EACT,CAAC;AACH;AAMO,SAAS,WACd,UACwB;AACxB,QAAM,UAAU,oBAAI,IAAuB;AAC3C,QAAM,WAAW,oBAAI,IAAoB;AAGzC,aAAW,KAAK,UAAU;AACxB,QAAI,CAAC,EAAE,UAAU;AACf,cAAQ,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAAA,IACvB,OAAO;AACL,eAAS,IAAI,EAAE,IAAI,EAAE,QAAQ;AAAA,IAC/B;AAAA,EACF;AAGA,WAAS,SAAS,IAAoB;AACpC,UAAM,SAAS,SAAS,IAAI,EAAE;AAC9B,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO,SAAS,MAAM;AAAA,EACxB;AAGA,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,UAAU;AACd,YAAM,SAAS,SAAS,EAAE,EAAE;AAC5B,UAAI,CAAC,QAAQ,IAAI,MAAM,GAAG;AACxB,gBAAQ,IAAI,QAAQ,CAAC,CAAC;AAAA,MACxB;AACA,cAAQ,IAAI,MAAM,EAAG,KAAK,CAAC;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AACT;AAmBO,SAAS,UAAU,UAAqC;AAC7D,QAAM,UAA0B;AAAA,IAC9B,OAAO,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,SAAS;AAAA,IACT,QAAQ,CAAC;AAAA,IACT,YAAY,CAAC;AAAA,EACf;AAEA,QAAM,QAAQ,oBAAI,IAAY;AAE9B,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,SAAU,SAAQ;AAAA,QACnB,SAAQ;AAEb,QAAI,EAAE,sBAAsB,WAAY,SAAQ;AAEhD,QAAI,EAAE,MAAM;AACV,cAAQ,OAAO,EAAE,IAAI,KAAK,QAAQ,OAAO,EAAE,IAAI,KAAK,KAAK;AAAA,IAC3D;AACA,QAAI,EAAE,UAAU;AACd,cAAQ,WAAW,EAAE,QAAQ,KAAK,QAAQ,WAAW,EAAE,QAAQ,KAAK,KAAK;AAAA,IAC3E;AAEA,QAAI,CAAC,EAAE,SAAU,OAAM,IAAI,EAAE,EAAE;AAAA,EACjC;AAEA,UAAQ,UAAU,MAAM;AACxB,SAAO;AACT;;;AjBzWO,IAAMC,qBAA8B;AACpC,IAAMC,cAAuB;AAC7B,IAAMC,mBAA4B;AAClC,IAAMC,qBAA8B;AACpC,IAAMC,uBAAgC;AAGtC,IAAMC,uBAAmC;AAGzC,IAAMC,gBAAsB;AAC5B,IAAMC,uBAA6B;AACnC,IAAMC,uBAA6B;AACnC,IAAMC,8BAAoC;AAC1C,IAAMC,qBAA2B;AAKjC,IAAMC,eAAqB;AAC3B,IAAMC,YAAkB;AACxB,IAAMC,UAAgB;AACtB,IAAMC,UAAgB;AACtB,IAAMC,gBAAsB;AAG5B,IAAMC,YAAqB;AAC3B,IAAMC,gBAAyB;AAC/B,IAAMC,oBAAgC;AAItC,IAAMC,cAAmB;AACzB,IAAMC,mBAAwB;AAC9B,IAAMC,eAAoB;AAC1B,IAAMC,iBAAsB;AAG5B,IAAMC,kBAAqB;AAC3B,IAAMC,gBAAmB;AACzB,IAAMC,kBAAqB;AAC3B,IAAMC,oBAAuB;AAC7B,IAAMC,iBAAoB;AAC1B,IAAMC,WAAc;AACpB,IAAMC,WAAc;AACpB,IAAMC,gBAAmB;AACzB,IAAMC,mBAAsB;AAC5B,IAAMC,kBAAqB;AAC3B,IAAMC,iBAAoB;AAC1B,IAAMC,kBAAqB;AAG3B,IAAMC,qBAA6B;AACnC,IAAMC,kBAA0B;AAChC,IAAMC,mBAA2B;AACjC,IAAMC,yBAAiC;AACvC,IAAMC,wBAAgC;AACtC,IAAMC,mBAA2B;AACjC,IAAMC,iBAAyB;AAC/B,IAAMC,oBAA4B;AAClC,IAAMC,wBAAgC;AACtC,IAAMC,gBAAwB;AAC9B,IAAMC,4BAAyC;AAC/C,IAAMC,2BACU;AAChB,IAAMC,4BACQ;AACd,IAAMC,2BACW;AAgBjB,IAAMC,cAAsB;AAC5B,IAAMC,eAAuB;AAC7B,IAAMC,8BAAsC;AAC5C,IAAMC,wBAAgC;AACtC,IAAMC,kBAA0B;AAChC,IAAMC,oBAA4B;AAClC,IAAMC,iBAAyB;AAC/B,IAAMC,kBAA0B;AAChC,IAAMC,cAAsB;AAC5B,IAAMC,aAAqB;AAI3B,IAAMC,gBAAwB;AAC9B,IAAMC,eAAuB;AAC7B,IAAMC,gBAAwB;",
  "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", "getGitUserName", "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", "getGitUserName", "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"]
}
