{"version":3,"file":"diff-B7dMUCoJ.mjs","names":["extractDeclarationName","declarationKey","path","path","path"],"sources":["../src/ir/operation-hints.ts","../src/engine/merge-adapters/url-fingerprint.ts","../src/engine/merge-adapters/dotnet.ts","../src/engine/merge-adapters/elixir.ts","../src/engine/merge-adapters/go.ts","../src/engine/merge-adapters/kotlin.ts","../src/engine/merge-adapters/node.ts","../src/engine/merge-adapters/php.ts","../src/engine/merge-adapters/python.ts","../src/engine/merge-adapters/ruby.ts","../src/engine/merge-adapters/rust.ts","../src/engine/merge-adapters/index.ts","../src/engine/merger.ts","../src/engine/json-merge.ts","../src/engine/writer.ts","../src/engine/generate-files.ts","../src/engine/scoped-services.ts","../src/engine/integrate.ts","../src/engine/formatter.ts","../src/engine/manifest.ts","../src/engine/orchestrator.ts","../src/engine/registry.ts","../src/differ/classify.ts","../src/differ/models.ts","../src/differ/operations.ts","../src/differ/services.ts","../src/differ/diff.ts"],"sourcesContent":["import type { ApiSpec, Service, Operation, HttpMethod } from './types.js';\n\n/** Minimal snake_case converter for path segments (avoids cross-layer import). */\nfunction toSnake(s: string): string {\n  return s\n    .replace(/([a-z])([A-Z])/g, '$1_$2')\n    .replace(/[-\\s.]+/g, '_')\n    .toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// Hint types — consumer-provided overrides for operation resolution\n// ---------------------------------------------------------------------------\n\n/** Per-operation override keyed by \"METHOD /path\" (e.g. \"POST /auth/token\"). */\nexport interface OperationHint {\n  /** Override the algorithm-derived method name. */\n  name?: string;\n  /** Remount this operation to a different service/namespace (PascalCase). */\n  mountOn?: string;\n  /** Split a union-body operation into N typed wrapper methods. */\n  split?: SplitHint[];\n  /** Inject constant body defaults (e.g. { grant_type: 'password' }). */\n  defaults?: Record<string, string | number | boolean>;\n  /** Fields the SDK reads from client config at runtime (e.g. ['client_id']). */\n  inferFromClient?: string[];\n  /**\n   * Marks this operation as a URL builder rather than a real HTTP call. Emitters\n   * should generate a method that returns the constructed URL (typically as a\n   * string) without performing any I/O. Used for OAuth-style redirect endpoints\n   * such as /auth/authorize and /accounts/sessions/logout.\n   */\n  urlBuilder?: boolean;\n}\n\nexport interface SplitHint {\n  /** Wrapper method name (snake_case). */\n  name: string;\n  /** The discriminated union variant model name (e.g. 'PasswordSessionAuthenticateRequest'). */\n  targetVariant: string;\n  /** Constant body fields injected by the wrapper. */\n  defaults?: Record<string, string | number | boolean>;\n  /** Fields the SDK reads from client config at runtime. */\n  inferFromClient?: string[];\n  /** Only these body fields are exposed as method params. If omitted, all non-default/non-inferred fields are exposed. */\n  exposedParams?: string[];\n  /**\n   * Subset of exposedParams that should be emitted as optional even when the\n   * variant model would otherwise mark them required (or when the variant has\n   * no addressable model, as happens for inline oneOf branches).\n   */\n  optionalParams?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Resolved output — consumed by emitters\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedOperation {\n  /** The original IR operation (preserves description, params, types, etc.). */\n  operation: Operation;\n  /** The original IR service that owns this operation. */\n  service: Service;\n  /** Resolved snake_case method name (emitters convert to their convention). */\n  methodName: string;\n  /** Resolved target service/namespace (PascalCase). */\n  mountOn: string;\n  /** For split operations: one wrapper per union variant. */\n  wrappers?: ResolvedWrapper[];\n  /** Constant defaults injected into query/body at runtime (from operation-level hint). */\n  defaults: Record<string, string | number | boolean>;\n  /** Fields the SDK reads from client config at runtime (from operation-level hint). */\n  inferFromClient: string[];\n  /** Marks this operation as a URL builder; emitters should not generate an HTTP call. */\n  urlBuilder: boolean;\n}\n\nexport interface ResolvedWrapper {\n  /** Wrapper method name (snake_case). */\n  name: string;\n  /** The discriminated union variant model name. */\n  targetVariant: string;\n  /** Constant body defaults injected by the wrapper. */\n  defaults: Record<string, string | number | boolean>;\n  /** Fields read from client config at runtime. */\n  inferFromClient: string[];\n  /** Body fields exposed as method params. */\n  exposedParams: string[];\n  /** Optional body fields (not required in the variant). */\n  optionalParams: string[];\n  /** Response model name (if any). */\n  responseModelName: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Algorithm\n// ---------------------------------------------------------------------------\n\n/**\n * Action verbs recognised at the terminal path segment.\n * When a path ends with one of these, we use it as the verb instead of\n * deriving a CRUD verb from the HTTP method.\n */\nconst ACTION_VERBS = new Set([\n  'accept',\n  'activate',\n  'authorize',\n  'challenge',\n  'check',\n  'complete',\n  'confirm',\n  'deactivate',\n  'disable',\n  'enable',\n  'enroll',\n  'generate',\n  'reactivate',\n  'resend',\n  'revoke',\n  'send',\n  'verify',\n]);\n\n/** Map HTTP method → default CRUD verb. */\nconst CRUD_VERB: Record<HttpMethod, string> = {\n  get: 'list',\n  post: 'create',\n  put: 'update',\n  patch: 'update',\n  delete: 'delete',\n  head: 'get',\n  options: 'list',\n  trace: 'list',\n};\n\n/**\n * Naive singularization: strips trailing \"s\" with common-sense exceptions.\n * Good enough for API resource nouns; not a general-purpose English stemmer.\n */\nfunction singularize(word: string): string {\n  if (word.length <= 2) return word;\n  if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\n  if (\n    word.endsWith('ses') ||\n    word.endsWith('zes') ||\n    word.endsWith('xes') ||\n    word.endsWith('ches') ||\n    word.endsWith('shes')\n  ) {\n    return word.slice(0, -2);\n  }\n  if (word.endsWith('ss') || word.endsWith('us') || word.endsWith('is')) return word;\n  if (word.endsWith('s')) return word.slice(0, -1);\n  return word;\n}\n\n/**\n * Derive a snake_case method name from an operation's HTTP method and path.\n *\n * Rules:\n * 1. Strip path-param segments (`{id}`, `{slug}`, etc.)\n * 2. If the terminal segment is an action verb, use it as the verb\n * 3. Otherwise, use the CRUD verb for the HTTP method\n * 4. For GET on a collection (no trailing {id}), use \"list\"; with {id}, use \"get\"\n * 5. For POST on a resource path, if only one path param, use \"create\" singular\n * 6. Singularize the resource noun for single-resource operations\n */\nexport function deriveMethodName(op: Operation, _service: Service): string {\n  const segments = op.path.split('/').filter(Boolean);\n\n  // Separate static segments from param segments\n  const staticSegments: string[] = [];\n  let trailingParam = false;\n  for (const seg of segments) {\n    if (seg.startsWith('{') && seg.endsWith('}')) {\n      trailingParam = true;\n    } else {\n      staticSegments.push(seg);\n      trailingParam = false;\n    }\n  }\n\n  if (staticSegments.length === 0) {\n    return `${CRUD_VERB[op.httpMethod] ?? 'get'}_root`;\n  }\n\n  const terminal = toSnake(staticSegments[staticSegments.length - 1]);\n\n  // Check if terminal is an action verb\n  if (ACTION_VERBS.has(terminal)) {\n    // Resource context from preceding segments\n    const context = staticSegments.slice(0, -1).filter((s) => !s.startsWith('{'));\n    const resource = context.length > 0 ? toSnake(singularize(context[context.length - 1])) : '';\n    if (resource) {\n      return `${terminal}_${resource}`;\n    }\n    return terminal;\n  }\n\n  // Determine verb from HTTP method\n  let verb = CRUD_VERB[op.httpMethod] ?? 'get';\n\n  // GET with trailing {id} → \"get\" instead of \"list\"\n  if (op.httpMethod === 'get' && trailingParam) {\n    verb = 'get';\n  }\n\n  // Build resource name from static segments.\n  // When path params separate static segments, include the penultimate static\n  // segment (singularized) as a parent-context prefix to disambiguate nested paths.\n  // e.g. /projects/{id}/roles → \"project_roles\"\n  let resource = toSnake(terminal);\n  if (staticSegments.length >= 2) {\n    const penultimate = staticSegments[staticSegments.length - 2];\n    // Check if a path param appears between the penultimate and terminal segments\n    // in the original path by finding both positions and looking for {…} between them.\n    const penIdx = segments.lastIndexOf(penultimate);\n    const termIdx = segments.lastIndexOf(staticSegments[staticSegments.length - 1]);\n    const hasParamBetween = segments.slice(penIdx + 1, termIdx).some((s) => s.startsWith('{'));\n    if (hasParamBetween) {\n      const prefix = toSnake(singularize(penultimate));\n      resource = `${prefix}_${resource}`;\n    }\n  }\n\n  // Singularize when:\n  //   * there's a trailing path param (single-resource read/update/delete), or\n  //   * the verb itself implies a single-resource operation (e.g. POST → create\n  //     always creates one item even when posted to a collection endpoint).\n  const isSingleResource = trailingParam || verb === 'create';\n  const noun = isSingleResource ? singularize(resource) : resource;\n\n  // For \"list\" verb, keep plural\n  const finalNoun = verb === 'list' ? resource : noun;\n\n  return `${verb}_${finalNoun}`;\n}\n\n/**\n * Resolve all operations in the spec, applying hints and mount rules.\n *\n * @param spec - The parsed API spec\n * @param hints - Per-operation overrides keyed by \"METHOD /path\"\n * @param mountRules - Service name → target service mappings\n * @returns Resolved operations ready for emitter consumption\n */\nexport function resolveOperations(\n  spec: ApiSpec,\n  hints?: Record<string, OperationHint>,\n  mountRules?: Record<string, string>,\n): ResolvedOperation[] {\n  const resolved: ResolvedOperation[] = [];\n  const hintMap = hints ?? {};\n  const mounts = mountRules ?? {};\n\n  for (const service of spec.services) {\n    for (const op of service.operations) {\n      const key = `${op.httpMethod.toUpperCase()} ${op.path}`;\n      const hint = hintMap[key];\n\n      // Resolve method name: hint > algorithm\n      const methodName = hint?.name ?? deriveMethodName(op, service);\n\n      // Resolve mount target: per-op hint > service mount rule > original service\n      const mountOn = hint?.mountOn ?? mounts[service.name] ?? service.name;\n\n      // Build wrappers for split operations\n      let wrappers: ResolvedWrapper[] | undefined;\n      if (hint?.split) {\n        wrappers = hint.split.map((sh) => ({\n          name: sh.name,\n          targetVariant: sh.targetVariant,\n          defaults: sh.defaults ?? {},\n          inferFromClient: sh.inferFromClient ?? [],\n          exposedParams: sh.exposedParams ?? [],\n          optionalParams: sh.optionalParams ?? [],\n          responseModelName: resolveResponseModelName(op),\n        }));\n      }\n\n      resolved.push({\n        operation: op,\n        service,\n        methodName,\n        mountOn,\n        wrappers,\n        defaults: hint?.defaults ?? {},\n        inferFromClient: hint?.inferFromClient ?? [],\n        urlBuilder: hint?.urlBuilder ?? false,\n      });\n    }\n  }\n\n  return resolved;\n}\n\n/** Extract the response model name from an operation (for wrapper metadata). */\nfunction resolveResponseModelName(op: Operation): string | null {\n  if (op.httpMethod === 'delete') return null;\n  const ref = op.response;\n  if (ref.kind === 'model') return ref.name;\n  if (ref.kind === 'nullable' && ref.inner.kind === 'model') return ref.inner.name;\n  return null;\n}\n","import type Parser from 'tree-sitter';\nimport type { UrlFingerprintConfig } from './types.js';\n\n/**\n * Extract a URL path fingerprint from a method body using tree-sitter AST traversal.\n *\n * Walks the AST subtree of the member node looking for the first string literal\n * that starts with '/'. Normalizes interpolation expressions to '{}' and format\n * specifiers (%s, %d, etc.) to '{}' for cross-language comparison.\n *\n * @returns A normalized URL fingerprint like \"/organizations/{}\" or undefined if none found.\n */\nexport function extractUrlFingerprint(memberNode: Parser.SyntaxNode, config: UrlFingerprintConfig): string | undefined {\n  const stringTypes = new Set(config.stringNodeTypes);\n  const contentTypes = new Set(config.contentNodeTypes);\n  const interpolationTypes = new Set(config.interpolationNodeTypes);\n  const formatFns = config.formatFunctionNames ? new Set(config.formatFunctionNames) : null;\n\n  // Iterative DFS through the method's AST subtree\n  const stack: Parser.SyntaxNode[] = [memberNode];\n\n  while (stack.length > 0) {\n    const node = stack.pop()!;\n\n    if (stringTypes.has(node.type)) {\n      const fp = resolveFingerprint(node, contentTypes, interpolationTypes);\n      if (fp?.startsWith('/')) return fp;\n    }\n\n    // For format functions (Go's Sprintf, Rust's format!): check if this call\n    // matches and extract the first string argument.\n    if (formatFns && isFormatCall(node, formatFns)) {\n      const fp = extractFromFormatCall(node, stringTypes, contentTypes, interpolationTypes);\n      if (fp?.startsWith('/')) return fp;\n    }\n\n    // Push children in reverse order so leftmost child is processed first\n    for (let i = node.childCount - 1; i >= 0; i--) {\n      const child = node.child(i);\n      if (child) stack.push(child);\n    }\n  }\n\n  return undefined;\n}\n\n/**\n * Resolve the text content of a string node, normalizing interpolations to '{}'.\n */\nfunction resolveFingerprint(\n  stringNode: Parser.SyntaxNode,\n  contentTypes: Set<string>,\n  interpolationTypes: Set<string>,\n): string | undefined {\n  // Leaf string node (no children besides quotes) — strip quotes\n  if (stringNode.namedChildCount === 0) {\n    return normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n  }\n\n  // Composite string (has content fragments + interpolation children)\n  let result = '';\n  for (let i = 0; i < stringNode.childCount; i++) {\n    const child = stringNode.child(i)!;\n    if (contentTypes.has(child.type)) {\n      result += child.text;\n    } else if (interpolationTypes.has(child.type)) {\n      result += '{}';\n    }\n    // Skip quote delimiters, interpolation markers, etc.\n  }\n\n  return result ? normalizeFormatSpecifiers(result) : normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n}\n\n/** Check if a node is a call to one of the format functions (e.g., fmt.Sprintf, format!). */\nfunction isFormatCall(node: Parser.SyntaxNode, formatFns: Set<string>): boolean {\n  // Rust macro: format!(...) — tree-sitter may parse as macro_invocation\n  if (node.type === 'macro_invocation') {\n    const macroName = node.childForFieldName('macro')?.text;\n    return !!(macroName && formatFns.has(macroName.replace(/!$/, '')));\n  }\n\n  if (node.type !== 'call_expression') return false;\n  const fnNode = node.childForFieldName('function');\n  if (!fnNode) return false;\n\n  // Direct call: Sprintf(...) or format!(...)\n  if (formatFns.has(fnNode.text)) return true;\n\n  // Member call: fmt.Sprintf(...)\n  if (fnNode.type === 'selector_expression' || fnNode.type === 'member_expression') {\n    const prop = fnNode.childForFieldName('field') ?? fnNode.childForFieldName('property');\n    if (prop && formatFns.has(prop.text)) return true;\n  }\n  return false;\n}\n\n/** Extract the first string argument from a format function call. */\nfunction extractFromFormatCall(\n  callNode: Parser.SyntaxNode,\n  stringTypes: Set<string>,\n  contentTypes: Set<string>,\n  interpolationTypes: Set<string>,\n): string | undefined {\n  const args = callNode.childForFieldName('arguments');\n  if (!args) return undefined;\n\n  for (let i = 0; i < args.childCount; i++) {\n    const arg = args.child(i)!;\n    if (stringTypes.has(arg.type)) {\n      return resolveFingerprint(arg, contentTypes, interpolationTypes);\n    }\n  }\n  return undefined;\n}\n\n/** Strip surrounding quote characters from a string literal. */\nfunction stripQuotes(text: string): string {\n  // Handle various quote styles: \"...\", '...', `...`, f\"...\", $\"...\", @\"...\"\n  const match = text.match(/^(?:f|r|b|@|\\$)?(?:\"\"\"([\\s\\S]*)\"\"\"|'''([\\s\\S]*)'''|\"(.*)\"|'(.*)'|`(.*)`)$/s);\n  if (match) return match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? text;\n  return text;\n}\n\n/** Replace printf-style format specifiers (%s, %d, %v, %f) with {}. */\nfunction normalizeFormatSpecifiers(s: string): string {\n  return s.replace(/%[sdvf]/g, '{}');\n}\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst DOTNET_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string_literal', 'interpolated_string_expression'],\n  contentNodeTypes: ['string_content', 'string_literal_content'],\n  interpolationNodeTypes: ['interpolation'],\n};\n\nconst DECLARATION_TYPES = new Set([\n  'class_declaration',\n  'struct_declaration',\n  'interface_declaration',\n  'enum_declaration',\n  'record_declaration',\n]);\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n  if (DECLARATION_TYPES.has(node.type)) {\n    const nameNode = node.childForFieldName('name') ?? node.children.find((c) => c.type === 'identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'namespace_declaration' || node.type === 'file_scoped_namespace_declaration') {\n    const nameNode =\n      node.children.find((c) => c.type === 'qualified_name') ?? node.children.find((c) => c.type === 'identifier');\n    return nameNode ? `__namespace:${nameNode.text}` : null;\n  }\n  return null;\n}\n\nfunction collectPrecedingXmlDocComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('///')) {\n        if (lastIdx === -1) lastIdx = k;\n        firstIdx = k;\n      } else {\n        break;\n      }\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\n/**\n * Collect declarations from a list of sibling nodes (root level or namespace body).\n */\nfunction collectDeclarations(\n  children: Parser.SyntaxNode[],\n  source: string,\n  statements: MergeStatement[],\n  imports: MergeImport[],\n  importAnchors: string[],\n  importInsertionAnchor: { value?: string },\n): void {\n  for (const child of children) {\n    if (child.type === 'comment') continue;\n\n    if (child.type === 'using_directive') {\n      const text = source.slice(child.startIndex, child.endIndex);\n      imports.push({ key: text.trim(), text });\n      importAnchors.push(text);\n      continue;\n    }\n\n    if (child.type === 'file_scoped_namespace_declaration') {\n      importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n      // File-scoped namespace: subsequent declarations are siblings at root\n      continue;\n    }\n\n    if (child.type === 'namespace_declaration') {\n      importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n      // Block namespace: recurse into declaration_list\n      const body = child.children.find((c) => c.type === 'declaration_list');\n      if (body) {\n        collectDeclarations(body.namedChildren, source, statements, imports, importAnchors, importInsertionAnchor);\n      }\n      continue;\n    }\n\n    const name = extractDeclarationName(child);\n    statements.push({\n      key: name,\n      kind: name ? 'declaration' : 'other',\n      text: source.slice(child.startIndex, child.endIndex),\n    });\n  }\n}\n\nexport const dotnetMergeAdapter: MergeAdapter = {\n  language: 'dotnet',\n  grammarModule: 'tree-sitter-c-sharp',\n  testFilePatterns: [/Tests?\\.cs$/],\n  urlFingerprintConfig: DOTNET_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n    const importInsertionAnchor: { value?: string } = {};\n\n    collectDeclarations(tree.rootNode.children, source, statements, imports, importAnchors, importInsertionAnchor);\n\n    return {\n      imports,\n      importAnchors,\n      importInsertionAnchor: importInsertionAnchor.value,\n      statements,\n    };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n\n    function processChildren(children: Parser.SyntaxNode[]): void {\n      for (let i = 0; i < children.length; i++) {\n        const child = children[i];\n\n        // Recurse into namespaces\n        if (child.type === 'namespace_declaration') {\n          const body = child.children.find((c) => c.type === 'declaration_list');\n          if (body) processChildren(body.children);\n          continue;\n        }\n\n        const name = extractDeclarationName(child);\n        if (!name || name.startsWith('__namespace:')) continue;\n\n        const docstring = collectPrecedingXmlDocComments(children, i, source);\n        const members = new Map<string, MemberDocstrings>();\n\n        // Extract member docstrings\n        const body = child.children.find((c) => c.type === 'declaration_list');\n        if (body) {\n          const bodyChildren = body.children;\n          for (let j = 0; j < bodyChildren.length; j++) {\n            const member = bodyChildren[j];\n            if (member.type !== 'method_declaration' && member.type !== 'property_declaration') continue;\n            // For methods, the second identifier is the name (first is return type)\n            const identifiers = member.children.filter((c) => c.type === 'identifier');\n            const memberName =\n              member.type === 'method_declaration'\n                ? identifiers.length >= 2\n                  ? identifiers[1]!.text\n                  : identifiers[0]?.text\n                : identifiers[0]?.text;\n            if (!memberName) continue;\n            const memberDoc = collectPrecedingXmlDocComments(bodyChildren, j, source);\n            members.set(memberName, {\n              docstring: memberDoc,\n              declStartIndex: member.startIndex,\n              declColumn: member.startPosition.column,\n              urlFingerprint: extractUrlFingerprint(member, DOTNET_URL_FINGERPRINT_CONFIG),\n            });\n          }\n        }\n\n        result.set(name, {\n          docstring,\n          declStartIndex: child.startIndex,\n          declColumn: child.startPosition.column,\n          members,\n        });\n      }\n    }\n\n    processChildren(tree.rootNode.children);\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst ELIXIR_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string'],\n  contentNodeTypes: ['quoted_content'],\n  interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isDefmodule(node: Parser.SyntaxNode): boolean {\n  return node.type === 'call' && node.children[0]?.text === 'defmodule';\n}\n\nfunction getModuleName(node: Parser.SyntaxNode): string | null {\n  if (!isDefmodule(node)) return null;\n  const args = node.children.find((c) => c.type === 'arguments');\n  if (!args) return null;\n  const alias = args.children.find((c) => c.type === 'alias');\n  return alias?.text ?? null;\n}\n\nfunction getDoBlock(node: Parser.SyntaxNode): Parser.SyntaxNode | null {\n  return node.children.find((c) => c.type === 'do_block') ?? null;\n}\n\n/** Check if a node is an @moduledoc or @doc attribute. */\nfunction isDocAttribute(node: Parser.SyntaxNode): string | null {\n  if (node.type !== 'unary_operator') return null;\n  const call = node.children.find((c) => c.type === 'call');\n  if (!call) return null;\n  const id = call.children.find((c) => c.type === 'identifier');\n  if (id?.text === 'moduledoc' || id?.text === 'doc') return id.text;\n  return null;\n}\n\n/** Check if a node is a def/defp call. */\nfunction getDefName(node: Parser.SyntaxNode): string | null {\n  if (node.type !== 'call') return null;\n  const id = node.children[0];\n  if (!id || (id.text !== 'def' && id.text !== 'defp')) return null;\n  const args = node.children.find((c) => c.type === 'arguments');\n  if (!args) return null;\n  // The function name is either a simple identifier or a call (for functions with params)\n  for (const arg of args.namedChildren) {\n    if (arg.type === 'identifier') return arg.text;\n    if (arg.type === 'call') {\n      const nameNode = arg.children.find((c) => c.type === 'identifier');\n      return nameNode?.text ?? null;\n    }\n  }\n  return null;\n}\n\n/** Check if a node is an alias/import/require/use call. */\nfunction isImportLike(node: Parser.SyntaxNode): boolean {\n  if (node.type !== 'call') return false;\n  const id = node.children[0];\n  return id?.type === 'identifier' && ['alias', 'import', 'require', 'use'].includes(id.text);\n}\n\nexport const elixirMergeAdapter: MergeAdapter = {\n  language: 'elixir',\n  grammarModule: 'tree-sitter-elixir',\n  testFilePatterns: [/_test\\.exs$/],\n  urlFingerprintConfig: ELIXIR_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      // Top-level alias/import/require/use (rare but possible outside modules)\n      if (isImportLike(child)) {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const moduleName = getModuleName(child);\n      statements.push({\n        key: moduleName,\n        kind: moduleName ? 'declaration' : 'other',\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const moduleName = getModuleName(child);\n      if (!moduleName) continue;\n\n      // Look for @moduledoc inside the do_block\n      let docstring: DocstringInfo | null = null;\n      const doBlock = getDoBlock(child);\n      const members = new Map<string, MemberDocstrings>();\n\n      if (doBlock) {\n        const bodyChildren = doBlock.children;\n\n        // Find @moduledoc\n        for (const bodyChild of bodyChildren) {\n          if (isDocAttribute(bodyChild) === 'moduledoc') {\n            docstring = {\n              text: source.slice(bodyChild.startIndex, bodyChild.endIndex),\n              startIndex: bodyChild.startIndex,\n              endIndex: bodyChild.endIndex,\n            };\n            break;\n          }\n        }\n\n        // Find @doc + def pairs for member docstrings\n        for (let j = 0; j < bodyChildren.length; j++) {\n          const bodyChild = bodyChildren[j];\n          const defName = getDefName(bodyChild);\n          if (!defName) continue;\n\n          // Look for preceding @doc attribute\n          let memberDoc: DocstringInfo | null = null;\n          for (let k = j - 1; k >= 0; k--) {\n            const prev = bodyChildren[k];\n            if (isDocAttribute(prev) === 'doc') {\n              memberDoc = {\n                text: source.slice(prev.startIndex, prev.endIndex),\n                startIndex: prev.startIndex,\n                endIndex: prev.endIndex,\n              };\n              break;\n            }\n            if (prev.type === 'comment') continue;\n            break;\n          }\n\n          members.set(defName, {\n            docstring: memberDoc,\n            declStartIndex: bodyChild.startIndex,\n            declColumn: bodyChild.startPosition.column,\n            urlFingerprint: extractUrlFingerprint(bodyChild, ELIXIR_URL_FINGERPRINT_CONFIG),\n          });\n        }\n      }\n\n      result.set(moduleName, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst GO_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['interpreted_string_literal'],\n  contentNodeTypes: ['interpreted_string_literal_content'],\n  interpolationNodeTypes: [],\n  formatFunctionNames: ['Sprintf'],\n};\n\nfunction lastIdentifier(text: string): string | null {\n  const matches = [...text.matchAll(/[A-Za-z_][A-Za-z0-9_]*/g)];\n  return matches.length > 0 ? matches[matches.length - 1]![0] : null;\n}\n\nfunction receiverKey(node: Parser.SyntaxNode): string | null {\n  const receiver = node.childForFieldName('receiver');\n  if (!receiver) return null;\n  return lastIdentifier(receiver.text);\n}\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n  switch (node.type) {\n    case 'package_clause': {\n      const pkg = lastIdentifier(node.text);\n      return pkg ? `__package:${pkg}` : '__package:';\n    }\n    case 'type_declaration': {\n      const spec = node.firstNamedChild?.type === 'type_spec' ? node.firstNamedChild : node.namedChildren[0];\n      const nameNode = spec?.childForFieldName('name');\n      return nameNode?.text ?? null;\n    }\n    case 'function_declaration': {\n      return node.childForFieldName('name')?.text ?? null;\n    }\n    case 'method_declaration': {\n      const name = node.childForFieldName('name')?.text ?? null;\n      const receiver = receiverKey(node);\n      return name && receiver ? `method:${receiver}.${name}` : name;\n    }\n    case 'const_declaration':\n    case 'var_declaration': {\n      return node.text.split(/\\s+/).slice(0, 3).join(' ');\n    }\n    default:\n      return null;\n  }\n}\n\nfunction importEntries(node: Parser.SyntaxNode, source: string): MergeImport[] {\n  const entries: MergeImport[] = [];\n\n  const collect = (spec: Parser.SyntaxNode): void => {\n    const path = spec.childForFieldName('path')?.text ?? spec.text;\n    const name = spec.childForFieldName('name')?.text ?? '';\n    const text = source.slice(spec.startIndex, spec.endIndex);\n    entries.push({\n      key: `${name}:${path.replace(/^\"|\"$/g, '')}`,\n      text,\n    });\n  };\n\n  for (const child of node.namedChildren) {\n    if (child.type === 'import_spec') {\n      collect(child);\n      continue;\n    }\n    if (child.type === 'import_spec_list') {\n      for (const spec of child.namedChildren) {\n        if (spec.type === 'import_spec') collect(spec);\n      }\n    }\n  }\n\n  return entries;\n}\n\nfunction collectPrecedingGoComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('//')) {\n        if (lastIdx === -1) lastIdx = k;\n        firstIdx = k;\n      } else {\n        break;\n      }\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const goMergeAdapter: MergeAdapter = {\n  language: 'go',\n  grammarModule: 'tree-sitter-go',\n  testFilePatterns: [/_test\\.go$/],\n  urlFingerprintConfig: GO_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    let importInsertionAnchor: string | undefined;\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'package_clause') {\n        importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n      }\n\n      if (child.type === 'import_declaration') {\n        imports.push(...importEntries(child, source));\n        importAnchors.push(source.slice(child.startIndex, child.endIndex));\n        continue;\n      }\n\n      const key = declarationKey(child);\n      statements.push({\n        key,\n        kind: key ? 'declaration' : 'other',\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, importInsertionAnchor, statements };\n  },\n  renderImports(imports) {\n    if (imports.length === 0) return [];\n    if (imports.length === 1) return [`import ${imports[0]!.text}`];\n    return [`import (\\n${imports.map((entry) => `  ${entry.text}`).join('\\n')}\\n)`];\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const key = declarationKey(child);\n      if (!key || key.startsWith('__package:')) continue;\n\n      const docstring = collectPrecedingGoComments(rootChildren, i, source);\n      result.set(key, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members: new Map(),\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  MergeMember,\n  DeepMergeSymbol,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst KOTLIN_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string_literal'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: ['interpolated_expression'],\n};\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n  if (node.type === 'class_declaration') {\n    // Handles class, data class, enum class, etc.\n    const nameNode = node.children.find((c) => c.type === 'type_identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'function_declaration') {\n    const nameNode = node.children.find((c) => c.type === 'simple_identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'object_declaration') {\n    const nameNode = node.children.find((c) => c.type === 'type_identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'type_alias') {\n    const nameNode = node.children.find((c) => c.type === 'type_identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'property_declaration') {\n    const nameNode = node.children.find((c) => c.type === 'variable_declaration');\n    if (nameNode) {\n      const id = nameNode.children.find((c) => c.type === 'simple_identifier');\n      return id?.text ?? null;\n    }\n  }\n  return null;\n}\n\nfunction findPrecedingKdoc(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'multiline_comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('/**')) {\n        return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n      }\n      return null;\n    }\n    if (prev.type === 'line_comment') continue;\n    return null;\n  }\n  return null;\n}\n\nfunction extractKotlinClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n  const members: MergeMember[] = [];\n  const children = classBody.namedChildren;\n\n  for (let i = 0; i < children.length; i++) {\n    const child = children[i];\n    let memberName: string | null = null;\n\n    if (child.type === 'property_declaration') {\n      const varDecl = child.children.find((c) => c.type === 'variable_declaration');\n      memberName = varDecl?.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n    } else if (child.type === 'function_declaration') {\n      memberName = child.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n    } else if (child.type === 'companion_object') {\n      memberName = 'companion';\n    }\n\n    if (!memberName) continue;\n\n    // Fold trailing getter/setter into the property's text span\n    let endIdx = child.endIndex;\n    if (child.type === 'property_declaration') {\n      while (i + 1 < children.length) {\n        const next = children[i + 1];\n        if (next.type === 'getter' || next.type === 'setter') {\n          endIdx = next.endIndex;\n          i++;\n        } else {\n          break;\n        }\n      }\n    }\n\n    // Include preceding KDoc comment in the text span so deep merge\n    // inserts the member with its documentation intact.\n    let startIdx = child.startIndex;\n    for (let k = i - 1; k >= 0; k--) {\n      const prev = children[k];\n      if (prev.type === 'multiline_comment') {\n        const text = source.slice(prev.startIndex, prev.endIndex);\n        if (text.startsWith('/**')) startIdx = prev.startIndex;\n        break;\n      }\n      if (prev.type === 'line_comment') continue;\n      break;\n    }\n\n    members.push({ key: memberName, text: source.slice(startIdx, endIdx), startIndex: startIdx, endIndex: endIdx });\n  }\n\n  return members;\n}\n\n/**\n * KDoc signature that identifies a generator-emitted service accessor inside\n * a Kotlin client class. The Kotlin client emitter writes every accessor with this\n * exact doc preamble — when the existing file carries a member with this doc\n * but the regenerated content omits it, the member is stale (its mount target\n * was remapped or removed) and gets pruned.\n */\nconst KOTLIN_MANAGED_ACCESSOR_DOC =\n  /\\/\\*\\*[\\s\\S]*?Lazily-constructed \\[[^\\]]+\\] accessor for this \\[[^\\]]+\\] client\\.[\\s\\S]*?\\*\\//;\n\nexport const kotlinMergeAdapter: MergeAdapter = {\n  language: 'kotlin',\n  grammarModule: 'tree-sitter-kotlin',\n  testFilePatterns: [/Test\\.kt$/],\n  urlFingerprintConfig: KOTLIN_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'multiline_comment' || child.type === 'line_comment') continue;\n\n      if (child.type === 'import_list') {\n        const fullText = source.slice(child.startIndex, child.endIndex);\n        importAnchors.push(fullText);\n        for (const imp of child.namedChildren) {\n          if (imp.type === 'import_header') {\n            const text = source.slice(imp.startIndex, imp.endIndex).trim();\n            // Key on the full import path\n            const idNode = imp.children.find((c) => c.type === 'identifier');\n            const key = idNode?.text ?? text;\n            imports.push({ key, text });\n          }\n        }\n        continue;\n      }\n\n      const name = extractDeclarationName(child);\n      statements.push({\n        key: name,\n        kind: name ? 'declaration' : 'other',\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  isManagedMember(member) {\n    return KOTLIN_MANAGED_ACCESSOR_DOC.test(member.text);\n  },\n  shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n    // Skip if new members reference instance properties that don't exist in the target\n    const newText = newMembers.map((m) => m.text).join('\\n');\n    for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n      const propName = match[1];\n      if (propName && !existingMemberKeys.has(propName)) return true;\n    }\n    return false;\n  },\n  extractMembers(tree, source) {\n    const result = new Map<string, DeepMergeSymbol>();\n\n    for (const child of tree.rootNode.children) {\n      if (child.type !== 'class_declaration') continue;\n      const nameNode = child.children.find((c) => c.type === 'type_identifier');\n      if (!nameNode) continue;\n      const body = child.children.find((c) => c.type === 'class_body');\n      if (!body) continue;\n\n      const members = extractKotlinClassMembers(body, source);\n      const firstMember = body.firstNamedChild;\n      const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n      result.set(nameNode.text, { members, bodyEndLine: body.endPosition.row, memberIndent });\n    }\n\n    return result;\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const name = extractDeclarationName(child);\n      if (!name) continue;\n\n      const docstring = findPrecedingKdoc(rootChildren, i, source);\n      const members = new Map<string, MemberDocstrings>();\n\n      // Extract member docstrings for classes\n      if (child.type === 'class_declaration') {\n        const body = child.children.find((c) => c.type === 'class_body' || c.type === 'enum_class_body');\n        if (body) {\n          const bodyChildren = body.children;\n          for (let j = 0; j < bodyChildren.length; j++) {\n            const member = bodyChildren[j];\n            const memberName = extractDeclarationName(member);\n            if (!memberName) continue;\n            const memberDoc = findPrecedingKdoc(bodyChildren, j, source);\n            members.set(memberName, {\n              docstring: memberDoc,\n              declStartIndex: member.startIndex,\n              declColumn: member.startPosition.column,\n              urlFingerprint: extractUrlFingerprint(member, KOTLIN_URL_FINGERPRINT_CONFIG),\n            });\n          }\n        }\n      }\n\n      result.set(name, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport { normalizeJsExtension } from '../../utils/naming.js';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DeepMergeSymbol,\n  MergeMember,\n  DocstringInfo,\n  SymbolDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst REEXPORT_PREFIX = '__export:';\n\nfunction extractDeclName(node: Parser.SyntaxNode): string | null {\n  const nameNode = node.childForFieldName('name');\n  if (nameNode) return nameNode.text;\n\n  if (node.type === 'lexical_declaration') {\n    const declarator = node.firstNamedChild;\n    if (declarator?.type === 'variable_declarator') {\n      const name = declarator.childForFieldName('name');\n      if (name) return name.text;\n    }\n  }\n\n  return null;\n}\n\nfunction extractNodeKey(node: Parser.SyntaxNode): { key: string | null; kind: MergeStatement['kind'] } {\n  if (node.type === 'export_statement') {\n    const decl = node.childForFieldName('declaration');\n    if (decl) {\n      return { key: extractDeclName(decl), kind: 'declaration' };\n    }\n\n    const source = node.childForFieldName('source');\n    if (source) {\n      return { key: `${REEXPORT_PREFIX}${normalizeJsExtension(source.text)}`, kind: 'reexport' };\n    }\n\n    return { key: null, kind: 'other' };\n  }\n  return { key: extractDeclName(node), kind: extractDeclName(node) ? 'declaration' : 'other' };\n}\n\nfunction extractClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n  const members: MergeMember[] = [];\n  for (const child of classBody.namedChildren) {\n    if (child.type === 'method_definition') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode && nameNode.text !== 'constructor') {\n        members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n      }\n    } else if (child.type === 'public_field_definition') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) {\n        // tree-sitter may exclude the trailing semicolon from\n        // public_field_definition nodes — include it if present\n        let endIdx = child.endIndex;\n        if (source[endIdx] === ';') {\n          endIdx += 1;\n        }\n        members.push({ key: nameNode.text, text: source.slice(child.startIndex, endIdx) });\n      }\n    }\n  }\n  return members;\n}\n\nfunction extractInterfaceMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n  const members: MergeMember[] = [];\n  for (const child of body.namedChildren) {\n    if (child.type === 'property_signature' || child.type === 'method_signature') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) {\n        members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n      }\n    }\n  }\n  return members;\n}\n\nfunction extractEnumMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n  const members: MergeMember[] = [];\n  for (const child of body.namedChildren) {\n    if (child.type === 'enum_assignment') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) {\n        members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n      }\n    } else if (child.type === 'property_identifier') {\n      members.push({ key: child.text, text: source.slice(child.startIndex, child.endIndex) });\n    }\n  }\n  return members;\n}\n\nfunction isCommentNode(node: Parser.SyntaxNode): boolean {\n  // tree-sitter extras (comments) may report the parent node's type\n  // instead of 'comment' — check grammarType as fallback\n  return node.type === 'comment' || (node as any).grammarType === 'comment';\n}\n\nfunction findPrecedingDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (isCommentNode(prev)) {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('/**')) {\n        return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n      }\n      return null;\n    }\n    if (prev.type === ',' || prev.type === ';' || prev.type === '{') continue;\n    return null;\n  }\n  return null;\n}\n\nconst CLASS_MEMBER_TYPES = new Set(['method_definition', 'public_field_definition']);\nconst INTERFACE_MEMBER_TYPES = new Set(['property_signature', 'method_signature']);\nconst ENUM_MEMBER_TYPES = new Set(['enum_assignment', 'property_identifier']);\n\nconst NODE_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string', 'template_string'],\n  contentNodeTypes: ['string_fragment'],\n  interpolationNodeTypes: ['template_substitution'],\n};\n\nfunction extractBodyMemberDocstrings(\n  body: Parser.SyntaxNode,\n  source: string,\n  memberTypes: Set<string>,\n): Map<\n  string,\n  { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n> {\n  const result = new Map<\n    string,\n    { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n  >();\n  const allChildren = body.children;\n  for (let i = 0; i < allChildren.length; i++) {\n    const child = allChildren[i];\n    if (!memberTypes.has(child.type)) continue;\n    let memberName: string | null = null;\n    if (child.type === 'property_identifier') {\n      memberName = child.text;\n    } else {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) memberName = nameNode.text;\n    }\n    if (!memberName || memberName === 'constructor') continue;\n    const docstring = findPrecedingDocstring(allChildren, i, source);\n    const fp = extractUrlFingerprint(child, NODE_URL_FINGERPRINT_CONFIG);\n    result.set(memberName, {\n      docstring,\n      declStartIndex: child.startIndex,\n      declColumn: child.startPosition.column,\n      urlFingerprint: fp,\n    });\n  }\n  return result;\n}\n\nexport const nodeMergeAdapter: MergeAdapter = {\n  language: 'node',\n  grammarModule: 'tree-sitter-typescript/bindings/node/typescript.js',\n  normalizeReexport: normalizeJsExtension,\n  testFilePatterns: [/\\.(spec|test)\\.[jt]sx?$/],\n  urlFingerprintConfig: NODE_URL_FINGERPRINT_CONFIG,\n  shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n    // If new members reference instance properties (this.X) that don't exist\n    // in the target class, the merged code would be broken.\n    const newText = newMembers.map((m) => m.text).join('\\n');\n    for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n      const propName = match[1];\n      if (propName && !existingMemberKeys.has(propName)) {\n        return true;\n      }\n    }\n    return false;\n  },\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'import_statement') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        // Key on module path so `import { X }` and `import type { X }` from\n        // the same module are treated as duplicates\n        const sourceNode = child.childForFieldName('source');\n        const modulePath = sourceNode ? normalizeJsExtension(sourceNode.text) : normalizeJsExtension(text.trim());\n        imports.push({ key: modulePath, text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const { key, kind } = extractNodeKey(child);\n      statements.push({\n        key,\n        kind,\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractMembers(tree, source) {\n    const result = new Map<string, DeepMergeSymbol>();\n\n    for (const child of tree.rootNode.children) {\n      if (child.type !== 'export_statement') continue;\n      const decl = child.childForFieldName('declaration');\n      if (!decl) continue;\n\n      const nameNode = decl.childForFieldName('name');\n      if (!nameNode) continue;\n      const symbolName = nameNode.text;\n\n      if (decl.type === 'class_declaration') {\n        const body = decl.childForFieldName('body');\n        if (!body) continue;\n        const members = extractClassMembers(body, source);\n        const firstMember = body.firstNamedChild;\n        const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n        result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n      } else if (decl.type === 'interface_declaration') {\n        const body = decl.childForFieldName('body');\n        if (!body) continue;\n        const members = extractInterfaceMembers(body, source);\n        const firstMember = body.firstNamedChild;\n        const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n        result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n      } else if (decl.type === 'enum_declaration') {\n        const body = decl.childForFieldName('body');\n        if (!body) continue;\n        const members = extractEnumMembers(body, source);\n        const firstMember = body.firstNamedChild;\n        const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n        result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n      }\n    }\n\n    return result;\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      if (child.type !== 'export_statement') continue;\n      const decl = child.childForFieldName('declaration');\n      if (!decl) continue;\n      const nameNode = decl.childForFieldName('name');\n      if (!nameNode) continue;\n\n      // Find preceding JSDoc for this top-level symbol\n      const docstring = findPrecedingDocstring(rootChildren, i, source);\n\n      // Extract member-level docstrings\n      let members = new Map<string, { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number }>();\n      const body = decl.childForFieldName('body');\n      if (body) {\n        if (decl.type === 'class_declaration') {\n          members = extractBodyMemberDocstrings(body, source, CLASS_MEMBER_TYPES);\n        } else if (decl.type === 'interface_declaration') {\n          members = extractBodyMemberDocstrings(body, source, INTERFACE_MEMBER_TYPES);\n        } else if (decl.type === 'enum_declaration') {\n          members = extractBodyMemberDocstrings(body, source, ENUM_MEMBER_TYPES);\n        }\n      }\n\n      result.set(nameNode.text, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PHP_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['encapsed_string', 'string'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: ['variable_name'],\n};\n\nfunction extractPhpDeclarationName(node: Parser.SyntaxNode): string | null {\n  switch (node.type) {\n    case 'class_declaration':\n    case 'interface_declaration':\n    case 'trait_declaration':\n    case 'enum_declaration':\n    case 'function_definition': {\n      const nameNode = node.childForFieldName('name');\n      return nameNode?.text ?? null;\n    }\n    case 'namespace_definition': {\n      const nameNode = node.childForFieldName('name');\n      return nameNode ? `__namespace:${nameNode.text}` : '__namespace:';\n    }\n    default:\n      return null;\n  }\n}\n\nfunction findPhpDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('/**')) {\n        return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n      }\n      return null;\n    }\n    if (prev.type === ';' || prev.type === '{') continue;\n    return null;\n  }\n  return null;\n}\n\nexport const phpMergeAdapter: MergeAdapter = {\n  language: 'php',\n  grammarModule: 'tree-sitter-php',\n  testFilePatterns: [/Test\\.php$/],\n  urlFingerprintConfig: PHP_URL_FINGERPRINT_CONFIG,\n  resolveGrammar: (mod) => {\n    // ESM import wraps in { default: { php, php_only } }\n    const m = (mod as Record<string, unknown>)?.default ?? mod;\n    if (typeof m === 'object' && m !== null && 'php' in (m as Record<string, unknown>))\n      return (m as { php: unknown }).php;\n    return m;\n  },\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    let importInsertionAnchor: string | undefined;\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'namespace_definition') {\n        importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n      }\n\n      if (child.type === 'namespace_use_declaration') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const declarationName = extractPhpDeclarationName(child);\n      const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n      statements.push({\n        key: declarationName,\n        kind,\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, importInsertionAnchor, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const name = extractPhpDeclarationName(child);\n      if (!name || name.startsWith('__namespace:')) continue;\n\n      const docstring = findPhpDocstring(rootChildren, i, source);\n      const members = new Map<string, MemberDocstrings>();\n\n      const body = child.childForFieldName('body');\n      if (body) {\n        const bodyChildren = body.children;\n        for (let j = 0; j < bodyChildren.length; j++) {\n          const member = bodyChildren[j];\n          if (member.type !== 'method_declaration') continue;\n          const memberName = member.childForFieldName('name')?.text;\n          if (!memberName) continue;\n          const memberDoc = findPhpDocstring(bodyChildren, j, source);\n          members.set(memberName, {\n            docstring: memberDoc,\n            declStartIndex: member.startIndex,\n            declColumn: member.startPosition.column,\n            urlFingerprint: extractUrlFingerprint(member, PHP_URL_FINGERPRINT_CONFIG),\n          });\n        }\n      }\n\n      result.set(name, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PYTHON_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: ['interpolation'],\n};\n\nfunction extractPythonDeclarationName(node: Parser.SyntaxNode): string | null {\n  if (node.type === 'class_definition' || node.type === 'function_definition') {\n    const nameNode = node.childForFieldName('name');\n    return nameNode?.text ?? null;\n  }\n\n  // Detect `__all__ = [...]` assignments so they get a key and can be deduplicated\n  if (node.type === 'expression_statement') {\n    const firstChild = node.firstNamedChild;\n    if (firstChild?.type === 'assignment') {\n      const left = firstChild.childForFieldName('left');\n      if (left?.type === 'identifier' && left.text === '__all__') {\n        return '__all__';\n      }\n    }\n  }\n\n  return null;\n}\n\nfunction extractPythonDocstring(bodyNode: Parser.SyntaxNode, source: string): DocstringInfo | null {\n  // Python docstrings are the first expression_statement in a body block\n  // where the expression is a string literal\n  for (const child of bodyNode.namedChildren) {\n    if (child.type === 'expression_statement') {\n      const expr = child.firstNamedChild;\n      if (expr?.type === 'string') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        return { text, startIndex: child.startIndex, endIndex: child.endIndex };\n      }\n    }\n    // Only the FIRST statement can be a docstring\n    break;\n  }\n  return null;\n}\n\nfunction collectPrecedingPythonComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'comment') {\n      if (lastIdx === -1) lastIdx = k;\n      firstIdx = k;\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const pythonMergeAdapter: MergeAdapter = {\n  language: 'python',\n  grammarModule: 'tree-sitter-python',\n  testFilePatterns: [/(?:^|\\/)test_.*\\.py$/, /_test\\.py$/],\n  urlFingerprintConfig: PYTHON_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'import_statement' || child.type === 'import_from_statement') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const declarationName = extractPythonDeclarationName(child);\n      const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n      statements.push({\n        key: declarationName,\n        kind,\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const name = extractPythonDeclarationName(child);\n      if (!name) continue;\n\n      // Python: class/function docstrings are inside the body, OR use # comments before\n      let docstring: DocstringInfo | null = null;\n      const body = child.childForFieldName('body');\n      if (body) {\n        docstring = extractPythonDocstring(body, source);\n      }\n      // Fallback: check for # comments before the declaration\n      if (!docstring) {\n        docstring = collectPrecedingPythonComments(rootChildren, i, source);\n      }\n\n      const members = new Map<string, MemberDocstrings>();\n\n      // Extract method docstrings for classes\n      if (child.type === 'class_definition' && body) {\n        for (const member of body.namedChildren) {\n          if (member.type !== 'function_definition') continue;\n          const memberName = member.childForFieldName('name')?.text;\n          if (!memberName) continue;\n\n          let memberDoc: DocstringInfo | null = null;\n          const memberBody = member.childForFieldName('body');\n          if (memberBody) {\n            memberDoc = extractPythonDocstring(memberBody, source);\n          }\n\n          members.set(memberName, {\n            docstring: memberDoc,\n            declStartIndex: member.startIndex,\n            declColumn: member.startPosition.column,\n            urlFingerprint: extractUrlFingerprint(member, PYTHON_URL_FINGERPRINT_CONFIG),\n          });\n        }\n      }\n\n      result.set(name, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst RUBY_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isRequireCall(node: Parser.SyntaxNode): boolean {\n  if (node.type !== 'call') return false;\n  const method = node.childForFieldName('method');\n  if (!method) return false;\n  return method.text === 'require' || method.text === 'require_relative';\n}\n\nfunction extractRubyDeclarationName(node: Parser.SyntaxNode): string | null {\n  if (node.type !== 'class' && node.type !== 'module') return null;\n  const nameNode = node.childForFieldName('name');\n  return nameNode?.text ?? null;\n}\n\nfunction collectPrecedingRubyComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    const nodeType = (prev as any).grammarType ?? prev.type;\n    if (nodeType === 'comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('#')) {\n        if (lastIdx === -1) lastIdx = k;\n        firstIdx = k;\n      } else {\n        break;\n      }\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rubyMergeAdapter: MergeAdapter = {\n  language: 'ruby',\n  grammarModule: 'tree-sitter-ruby',\n  testFilePatterns: [/_test\\.rb$/, /_spec\\.rb$/],\n  urlFingerprintConfig: RUBY_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      const declarationName = extractRubyDeclarationName(child);\n      if (isRequireCall(child)) {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n      statements.push({\n        key: declarationName,\n        kind,\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const name = extractRubyDeclarationName(child);\n      if (!name) continue;\n\n      const docstring = collectPrecedingRubyComments(rootChildren, i, source);\n      const members = new Map<string, MemberDocstrings>();\n\n      // Ruby class/module bodies: comments may appear in class children\n      // (before body_statement) or in body_statement children (between methods)\n      if (child.type === 'class' || child.type === 'module') {\n        const allClassChildren = child.children;\n        const body = child.childForFieldName('body');\n\n        // Check for comment before body_statement in class children\n        // (docstring for the first method)\n        let firstMethodDocFromClass: DocstringInfo | null = null;\n        for (let j = 0; j < allClassChildren.length; j++) {\n          if (allClassChildren[j] === body || allClassChildren[j].type === 'body_statement') {\n            firstMethodDocFromClass = collectPrecedingRubyComments(allClassChildren, j, source);\n            break;\n          }\n        }\n\n        if (body) {\n          const bodyChildren = body.children;\n          let firstMethodHandled = false;\n          for (let j = 0; j < bodyChildren.length; j++) {\n            const member = bodyChildren[j];\n            if (member.type !== 'method') continue;\n            const memberName = member.childForFieldName('name')?.text;\n            if (!memberName) continue;\n\n            let memberDoc: DocstringInfo | null;\n            if (!firstMethodHandled && firstMethodDocFromClass) {\n              memberDoc = firstMethodDocFromClass;\n              firstMethodHandled = true;\n            } else {\n              memberDoc = collectPrecedingRubyComments(bodyChildren, j, source);\n              firstMethodHandled = true;\n            }\n\n            members.set(memberName, {\n              docstring: memberDoc,\n              declStartIndex: member.startIndex,\n              declColumn: member.startPosition.column,\n              urlFingerprint: extractUrlFingerprint(member, RUBY_URL_FINGERPRINT_CONFIG),\n            });\n          }\n        }\n      }\n\n      result.set(name, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst RUST_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string_literal'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: [],\n};\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n  switch (node.type) {\n    case 'struct_item':\n    case 'enum_item':\n    case 'function_item':\n    case 'trait_item':\n    case 'type_item':\n    case 'const_item': {\n      return node.childForFieldName('name')?.text ?? null;\n    }\n    case 'impl_item': {\n      const typeName = node.childForFieldName('type')?.text ?? 'unknown';\n      const traitName = node.childForFieldName('trait')?.text;\n      return traitName ? `impl:${traitName}->${typeName}` : `impl:${typeName}`;\n    }\n    default:\n      return null;\n  }\n}\n\nfunction collectPrecedingRustDocComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'line_comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('///')) {\n        if (lastIdx === -1) lastIdx = k;\n        firstIdx = k;\n      } else {\n        break;\n      }\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rustMergeAdapter: MergeAdapter = {\n  language: 'rust',\n  grammarModule: 'tree-sitter-rust',\n  testFilePatterns: [/_test\\.rs$/, /(?:^|\\/)tests\\/.*\\.rs$/],\n  urlFingerprintConfig: RUST_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'use_declaration') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const key = declarationKey(child);\n      statements.push({\n        key,\n        kind: key ? 'declaration' : 'other',\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const key = declarationKey(child);\n      if (!key) continue;\n\n      const docstring = collectPrecedingRustDocComments(rootChildren, i, source);\n      result.set(key, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members: new Map(),\n      });\n    }\n\n    return result;\n  },\n};\n","import type { MergeAdapter } from './types.js';\nimport { dotnetMergeAdapter } from './dotnet.js';\nimport { elixirMergeAdapter } from './elixir.js';\nimport { goMergeAdapter } from './go.js';\nimport { kotlinMergeAdapter } from './kotlin.js';\nimport { nodeMergeAdapter } from './node.js';\nimport { phpMergeAdapter } from './php.js';\nimport { pythonMergeAdapter } from './python.js';\nimport { rubyMergeAdapter } from './ruby.js';\nimport { rustMergeAdapter } from './rust.js';\n\nconst adapters = new Map<string, MergeAdapter>([\n  ['dotnet', dotnetMergeAdapter],\n  ['elixir', elixirMergeAdapter],\n  ['go', goMergeAdapter],\n  ['kotlin', kotlinMergeAdapter],\n  ['node', nodeMergeAdapter],\n  ['php', phpMergeAdapter],\n  ['python', pythonMergeAdapter],\n  ['ruby', rubyMergeAdapter],\n  ['rust', rustMergeAdapter],\n]);\n\nexport function getMergeAdapter(language: string): MergeAdapter | undefined {\n  return adapters.get(language);\n}\n","/**\n * AST-level file merger using tree-sitter.\n *\n * When generating into a directory that already contains files, the merger\n * parses both the existing and generated content, detects top-level symbols,\n * and only appends symbols that don't already exist. Hand-written code is\n * never modified or removed.\n *\n * Supports any language with a tree-sitter grammar package.\n */\n\nimport Parser from 'tree-sitter';\nimport { getMergeAdapter } from './merge-adapters/index.js';\nimport type { MergeImport, ParsedMergeFile, SymbolDocstrings } from './merge-adapters/types.js';\n\n// Cache parser instances per language\nconst parserCache = new Map<string, Parser>();\n\nimport { safeParse } from '../utils/tree-sitter.js';\n\n// --- @deprecated preservation ---\n\n/**\n * When replacing an existing docstring with a generated one, carry over any\n * `@deprecated` lines from the existing doc that aren't present in the\n * generated doc.  This prevents hand-written deprecation notices from being\n * silently dropped during docstring refresh.\n */\nfunction preserveDeprecatedTags(existingDoc: string, generatedDoc: string): string {\n  // Check if the existing docstring contains @deprecated anywhere\n  if (!existingDoc.includes('@deprecated')) return generatedDoc;\n\n  // If generated doc already has @deprecated, no need to merge\n  if (generatedDoc.includes('@deprecated')) return generatedDoc;\n\n  // Extract the @deprecated content from the existing doc.\n  // Handle both multi-line (`* @deprecated ...`) and one-liner (`/** @deprecated ... */`) formats.\n  const deprecatedParts: string[] = [];\n  for (const line of existingDoc.split('\\n')) {\n    if (/@deprecated\\b/.test(line)) {\n      // Normalize to JSDoc member format: `   * @deprecated ...`\n      const match = line.match(/@deprecated\\b.*/);\n      if (match) {\n        // Strip trailing */ and whitespace (from one-liner JSDoc like `/** @deprecated ... */`)\n        const cleaned = match[0].replace(/\\s*\\*\\/\\s*$/, '');\n        deprecatedParts.push(`   * ${cleaned}`);\n      }\n    }\n  }\n  if (deprecatedParts.length === 0) return generatedDoc;\n\n  // Insert @deprecated lines before the closing */ of the generated doc\n  const closingIdx = generatedDoc.lastIndexOf('*/');\n  if (closingIdx === -1) return generatedDoc;\n  const before = generatedDoc.slice(0, closingIdx);\n  const after = generatedDoc.slice(closingIdx);\n  return before + deprecatedParts.join('\\n') + '\\n ' + after;\n}\n\n// --- @oagen-ignore region helpers ---\n\ninterface IgnoredRegion {\n  startIndex: number;\n  endIndex: number;\n}\n\nfunction findIgnoredRegions(source: string): IgnoredRegion[] {\n  const regions: IgnoredRegion[] = [];\n  const startTag = '@oagen-ignore-start';\n  const endTag = '@oagen-ignore-end';\n  let searchFrom = 0;\n\n  while (true) {\n    const startIdx = source.indexOf(startTag, searchFrom);\n    if (startIdx === -1) break;\n    const endIdx = source.indexOf(endTag, startIdx + startTag.length);\n    if (endIdx === -1) break; // Unclosed — silently ignore\n    regions.push({ startIndex: startIdx, endIndex: endIdx + endTag.length });\n    searchFrom = endIdx + endTag.length;\n  }\n\n  return regions;\n}\n\nfunction buildIgnoredSymbolNames(docstrings: Map<string, SymbolDocstrings>, regions: IgnoredRegion[]): Set<string> {\n  if (regions.length === 0) return new Set();\n  const ignored = new Set<string>();\n  for (const [name, info] of docstrings) {\n    if (regions.some((r) => info.declStartIndex >= r.startIndex && info.declStartIndex <= r.endIndex)) {\n      ignored.add(name);\n    }\n  }\n  return ignored;\n}\n\nfunction clampIndex(value: number, contentLength: number): number {\n  if (!Number.isFinite(value)) return 0;\n  if (value < 0) return 0;\n  if (value > contentLength) return contentLength;\n  return value;\n}\n\n/**\n * Resolve the declaration line start for insertion using the current content,\n * instead of relying on parser column arithmetic. This avoids misplaced inserts\n * when parser columns/offsets drift.\n */\nfunction declarationLineStart(content: string, declStartIndex: number): number {\n  const idx = clampIndex(declStartIndex, content.length);\n  const prevNewline = content.lastIndexOf('\\n', Math.max(0, idx - 1));\n  return prevNewline === -1 ? 0 : prevNewline + 1;\n}\n\n/**\n * Resolve a docstring range by searching for the nearest matching text before\n * the declaration start. Falls back to parser-provided offsets when search fails.\n */\nfunction resolveDocRange(\n  content: string,\n  docText: string,\n  declStartIndex: number,\n  fallbackStart: number,\n  fallbackEnd: number,\n): { start: number; end: number } {\n  const safeDecl = clampIndex(declStartIndex, content.length);\n  const safeFallbackStart = clampIndex(fallbackStart, content.length);\n  const safeFallbackEnd = clampIndex(fallbackEnd, content.length);\n  const found = content.lastIndexOf(docText, safeDecl);\n  if (found !== -1) {\n    return { start: found, end: found + docText.length };\n  }\n  return { start: safeFallbackStart, end: safeFallbackEnd };\n}\n\n/**\n * Check if a tree-sitter grammar is configured for the given language.\n */\nexport function hasGrammar(language: string): boolean {\n  return getMergeAdapter(language) !== undefined;\n}\n\nasync function getParser(language: string): Promise<Parser> {\n  const cached = parserCache.get(language);\n  if (cached) return cached;\n\n  const adapter = getMergeAdapter(language);\n  if (!adapter) {\n    throw new Error(\n      `No tree-sitter grammar configured for language \"${language}\". ` +\n        `Add a merge adapter and install the corresponding tree-sitter grammar package.`,\n    );\n  }\n\n  const mod = await import(adapter.grammarModule);\n  const exported = adapter.resolveGrammar ? adapter.resolveGrammar(mod) : mod;\n  const grammar = (exported as { default?: unknown }).default ?? exported;\n  const parser = new Parser();\n  parser.setLanguage(grammar);\n  parserCache.set(language, parser);\n  return parser;\n}\n\ninterface ParsedSymbols {\n  names: Set<string>;\n  /** Trimmed text of unnamed top-level statements (for text-based dedup) */\n  unnamedTexts: Set<string>;\n}\n\n/**\n * Extract all top-level symbol names (and unnamed statement texts) from source code.\n */\nexport async function extractTopLevelSymbols(source: string, language: string): Promise<ParsedSymbols> {\n  const parser = await getParser(language);\n  const adapter = getMergeAdapter(language);\n  if (!adapter) {\n    throw new Error(`No merge adapter configured for language \"${language}\"`);\n  }\n  if (typeof source !== 'string') {\n    throw new Error(`extractTopLevelSymbols: expected string source, got ${typeof source}`);\n  }\n  const tree = safeParse(parser, source);\n  const names = new Set<string>();\n  const unnamedTexts = new Set<string>();\n  const parsed = adapter.parseStatements(tree, source);\n\n  for (const imp of parsed.imports) {\n    names.add(imp.key);\n  }\n  for (const statement of parsed.statements) {\n    if (statement.key) {\n      names.add(statement.key);\n    } else {\n      unnamedTexts.add(statement.text.trim());\n    }\n  }\n\n  return { names, unnamedTexts };\n}\n\n/** Convenience wrapper that returns only the name set. */\nexport async function extractTopLevelNames(source: string, language: string): Promise<Set<string>> {\n  return (await extractTopLevelSymbols(source, language)).names;\n}\n\n/**\n * Extract top-level statements from generated source with their names\n * and exact text span.\n */\nexport async function extractStatements(source: string, language: string): Promise<ParsedMergeFile> {\n  const parser = await getParser(language);\n  const adapter = getMergeAdapter(language);\n  if (!adapter) {\n    throw new Error(`No merge adapter configured for language \"${language}\"`);\n  }\n  const tree = safeParse(parser, source);\n  return adapter.parseStatements(tree, source);\n}\n\n/**\n * Return a map of top-level class name → { bodyEndLine, bodyEndCol } using\n * tree-sitter.  `bodyEndLine` is 0-based.  For brace-delimited classes the\n * end points at the closing brace line; for indentation-delimited classes\n * it points one past the last line of the class body.\n */\nexport async function extractClassEndLines(\n  source: string,\n  language: string,\n): Promise<Map<string, { bodyEndLine: number }>> {\n  const parser = await getParser(language);\n  const tree = safeParse(parser, source);\n  const map = new Map<string, { bodyEndLine: number }>();\n\n  function processClassNode(node: Parser.SyntaxNode): void {\n    const nameNode =\n      node.childForFieldName('name') ??\n      node.children.find((c) => c.type === 'type_identifier' || c.type === 'identifier');\n    if (!nameNode) return;\n    const name = nameNode.text;\n\n    const body =\n      node.childForFieldName('body') ?? node.children.find((c) => c.type === 'class_body' || c.type === 'body');\n    const endRow = body ? body.endPosition.row : node.endPosition.row;\n    const lastChar = source[body ? body.endIndex - 1 : node.endIndex - 1];\n\n    if (lastChar === '}') {\n      map.set(name, { bodyEndLine: endRow });\n    } else {\n      map.set(name, { bodyEndLine: endRow + 1 });\n    }\n  }\n\n  // Walk the tree recursively. Ruby (and Python) often nest target classes\n  // inside `module Foo` / `class Outer:` containers, so a flat iteration over\n  // root children would miss them.\n  function walk(node: Parser.SyntaxNode): void {\n    if (node.type === 'class' || node.type === 'class_definition' || node.type === 'class_declaration') {\n      processClassNode(node);\n    }\n    if (node.type === 'decorated_definition') {\n      for (const inner of node.namedChildren) {\n        if (inner.type === 'class_definition') processClassNode(inner);\n      }\n    }\n    if (node.type === 'export_statement') {\n      for (const inner of node.namedChildren) {\n        if (inner.type === 'class_declaration') processClassNode(inner);\n      }\n    }\n    for (const child of node.namedChildren) walk(child);\n  }\n  for (const child of tree.rootNode.children) {\n    walk(child);\n  }\n\n  return map;\n}\n\nexport interface MergeResult {\n  content: string;\n  added: number;\n  preserved: number;\n  changed: boolean;\n}\n\n/**\n * Merge generated content into an existing file.\n *\n * - Parses both files with tree-sitter\n * - Detects which top-level symbols already exist\n * - Appends only new symbols\n * - Never modifies or removes existing code\n * - Adds auto-generated header if not present\n */\nexport async function mergeIntoExisting(\n  existingContent: string,\n  generatedContent: string,\n  language: string,\n  header: string,\n): Promise<MergeResult> {\n  const adapter = getMergeAdapter(language);\n  if (!adapter) {\n    throw new Error(`No merge adapter configured for language \"${language}\"`);\n  }\n\n  // Parse existing file once — extract both symbols and statements from the same AST pass\n  const existingStatements = await extractStatements(existingContent, language);\n  const generatedStatements = await extractStatements(generatedContent, language);\n\n  const existingKeys = new Set<string>();\n  const existingUnnamedTexts = new Set<string>();\n  const existingImportKeys = new Set<string>();\n  const existingReexports = new Set<string>();\n  let lastImportEndIndex = -1;\n\n  // Collect import keys AND imported identifiers (to prevent adding declarations\n  // that clash with already-imported names)\n  const existingImportedNames = new Set<string>();\n  for (const imp of existingStatements.imports) {\n    existingImportKeys.add(imp.key);\n    // Extract identifiers from import text: import { Foo, Bar } from '...'\n    const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n    if (braceMatch) {\n      for (const name of braceMatch[1].split(',')) {\n        const trimmed = name.replace(/\\btype\\b/, '').trim();\n        if (trimmed) existingImportedNames.add(trimmed);\n      }\n    }\n  }\n  for (const anchor of existingStatements.importAnchors) {\n    const linesBefore = existingContent.slice(0, existingContent.indexOf(anchor)).split('\\n').length - 1;\n    const stmtLines = anchor.split('\\n').length;\n    lastImportEndIndex = linesBefore + stmtLines - 1;\n  }\n  if (lastImportEndIndex === -1 && existingStatements.importInsertionAnchor) {\n    const linesBefore =\n      existingContent.slice(0, existingContent.indexOf(existingStatements.importInsertionAnchor)).split('\\n').length -\n      1;\n    const stmtLines = existingStatements.importInsertionAnchor.split('\\n').length;\n    lastImportEndIndex = linesBefore + stmtLines - 1;\n  }\n\n  // Track all names exported by existing statements (both direct exports and\n  // re-export aliases like `export { X as Y }`).  Used to prevent the merger\n  // from appending a re-export that introduces a duplicate exported name.\n  const existingExportedNames = new Set<string>();\n\n  for (const stmt of existingStatements.statements) {\n    if (stmt.kind === 'reexport') {\n      existingReexports.add(adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim());\n      // Collect aliased export names from re-exports\n      const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n      if (braceMatch) {\n        for (const part of braceMatch[1].split(',')) {\n          const segments = part.trim().split(/\\s+as\\s+/);\n          const exportedName = (segments[1] ?? segments[0]).trim();\n          if (exportedName) existingExportedNames.add(exportedName);\n        }\n      }\n    }\n    if (stmt.key) {\n      existingKeys.add(stmt.key);\n      existingExportedNames.add(stmt.key);\n    } else {\n      existingUnnamedTexts.add(stmt.text.trim());\n    }\n  }\n\n  const headerLine = header.trim();\n\n  const newImports: MergeImport[] = [];\n  const toAppend: string[] = [];\n  let preserved = 0;\n\n  for (const imp of generatedStatements.imports) {\n    if (imp.text.trim() === headerLine) continue;\n    if (existingImportKeys.has(imp.key)) {\n      // The existing file already imports from this module path.\n      // Check if the generated import adds identifiers not present in\n      // the existing import — if so, create a supplemental import with\n      // only the new identifiers.  The supplemental participates in the\n      // usage-based filter (below) so unused identifiers are dropped.\n      const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n      if (braceMatch) {\n        const names = braceMatch[1]\n          .split(',')\n          .map((n) => n.replace(/\\btype\\b/, '').trim())\n          .filter(Boolean);\n        const newNames = names.filter((n) => !existingImportedNames.has(n) && !existingKeys.has(n));\n        if (newNames.length > 0) {\n          const isTypeImport = imp.text.trimStart().startsWith('import type');\n          const prefix = isTypeImport ? 'import type' : 'import';\n          const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n          if (sourceMatch) {\n            newImports.push({\n              key: imp.key + '#supplemental',\n              text: `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`,\n            });\n          }\n        }\n      }\n      preserved++;\n      continue;\n    }\n    // Strip out identifiers that are already imported from another path.\n    // This prevents duplicates when the generated file uses a specific path\n    // (e.g., '../interfaces/organization.interface') while the existing file\n    // imports the same names from a barrel (e.g., '../interfaces').\n    const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n    if (braceMatch) {\n      const names = braceMatch[1]\n        .split(',')\n        .map((n) => n.replace(/\\btype\\b/, '').trim())\n        .filter(Boolean);\n      // Check against both existing imports AND existing top-level declarations\n      const isAlreadyDefined = (n: string) => existingImportedNames.has(n) || existingKeys.has(n);\n      if (names.length > 0 && names.every(isAlreadyDefined)) {\n        preserved++;\n        continue;\n      }\n      // If only SOME identifiers are already defined, strip them out and keep only new ones\n      if (names.some(isAlreadyDefined)) {\n        const newNames = names.filter((n) => !isAlreadyDefined(n));\n        if (newNames.length === 0) {\n          preserved++;\n          continue;\n        }\n        // Rebuild the import with only new identifiers\n        const isTypeImport = imp.text.trimStart().startsWith('import type');\n        const prefix = isTypeImport ? 'import type' : 'import';\n        const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n        if (sourceMatch) {\n          const newText = `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`;\n          newImports.push({ key: imp.key, text: newText });\n          continue;\n        }\n      }\n    }\n    newImports.push(imp);\n  }\n\n  for (const stmt of generatedStatements.statements) {\n    // Skip the header comment\n    if (stmt.text.trim() === headerLine) continue;\n\n    // Skip re-export statements that duplicate existing re-exports\n    // (e.g., generated uses .js extension but existing doesn't).\n    // Allow genuinely new re-exports through.\n    if (stmt.kind === 'reexport') {\n      const normalizedText = adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim();\n      if (existingReexports.has(normalizedText) || (stmt.key !== null && existingKeys.has(stmt.key))) {\n        preserved++;\n        continue;\n      }\n      // Also skip re-exports whose aliased names are already defined as\n      // top-level exports in the existing file (e.g., generated file has\n      // `export { X as deserializeFoo } from '...'` but existing file\n      // already has `export const deserializeFoo = ...`).\n      const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n      if (braceMatch) {\n        const exportedNames = braceMatch[1]\n          .split(',')\n          .map((n) => {\n            const parts = n.trim().split(/\\s+as\\s+/);\n            return (parts[1] ?? parts[0]).trim();\n          })\n          .filter(Boolean);\n        if (exportedNames.length > 0 && exportedNames.every((n) => existingExportedNames.has(n))) {\n          preserved++;\n          continue;\n        }\n      }\n    }\n\n    if (stmt.key && (existingKeys.has(stmt.key) || existingImportedNames.has(stmt.key))) {\n      preserved++;\n      continue;\n    }\n\n    if (!stmt.key) {\n      if (existingUnnamedTexts.has(stmt.text.trim())) {\n        preserved++;\n        continue;\n      }\n    }\n\n    toAppend.push(stmt.text);\n  }\n\n  if (newImports.length === 0 && toAppend.length === 0) {\n    // No top-level changes — check for deep merge before returning\n    if (!adapter.extractMembers) {\n      // Still need to check docstring refresh below\n    }\n  }\n\n  let result = existingContent;\n\n  // Append new top-level symbols first (so deep merge can see them)\n  if (toAppend.length > 0) {\n    result = result.trimEnd() + '\\n\\n' + toAppend.join('\\n\\n') + '\\n';\n  }\n\n  // Deep merge pass: add new members to existing symbols\n  // Runs after import/symbol merge so line numbers are based on the updated content\n  let deepAdded = 0;\n  let deepPruned = 0;\n  const insertions: { line: number; text: string }[] = [];\n  if (adapter.extractMembers) {\n    const parser = await getParser(language);\n    const resultTree = safeParse(parser, result);\n    const generatedTree = safeParse(parser, generatedContent);\n    const resultSymbols = adapter.extractMembers(resultTree, result);\n    const generatedSymbols = adapter.extractMembers(generatedTree, generatedContent);\n\n    // Build ignored symbol set from @oagen-ignore-start/@oagen-ignore-end regions\n    const existingTree = safeParse(parser, existingContent);\n    const existingDocs = adapter.extractDocstrings(existingTree, existingContent);\n    const deepIgnoredRegions = findIgnoredRegions(existingContent);\n    const deepIgnoredSymbols = buildIgnoredSymbolNames(existingDocs, deepIgnoredRegions);\n\n    // Pass 1: prune stale \"managed\" members (existing members the adapter\n    // recognizes as generator-owned but that no longer appear in the\n    // regenerated content — e.g. accessors whose mount target was remapped).\n    // Done as byte-range deletes before line-based insertions so insertion\n    // line numbers stay valid for the post-prune result.\n    if (adapter.isManagedMember) {\n      const pruneEdits: { start: number; end: number }[] = [];\n      for (const [symbolName, genSymbol] of generatedSymbols) {\n        if (deepIgnoredSymbols.has(symbolName)) continue;\n        const existSymbol = resultSymbols.get(symbolName);\n        if (!existSymbol) continue;\n        const genMemberKeys = new Set(genSymbol.members.map((m) => m.key));\n        for (const existMember of existSymbol.members) {\n          if (genMemberKeys.has(existMember.key)) continue;\n          if (existMember.startIndex === undefined || existMember.endIndex === undefined) continue;\n          if (!adapter.isManagedMember(existMember)) continue;\n          pruneEdits.push({ start: existMember.startIndex, end: existMember.endIndex });\n        }\n      }\n      if (pruneEdits.length > 0) {\n        pruneEdits.sort((a, b) => b.start - a.start);\n        for (const edit of pruneEdits) {\n          let end = edit.end;\n          while (end < result.length && (result[end] === ' ' || result[end] === '\\t')) end++;\n          if (result[end] === '\\n') end++;\n          result = result.slice(0, edit.start) + result.slice(end);\n        }\n        deepPruned = pruneEdits.length;\n        // Re-extract since byte offsets and line numbers shifted.\n        const reTree = safeParse(parser, result);\n        resultSymbols.clear();\n        for (const [k, v] of adapter.extractMembers(reTree, result)) resultSymbols.set(k, v);\n      }\n    }\n\n    // Pass 2: append new members the regenerated content adds.\n    for (const [symbolName, genSymbol] of generatedSymbols) {\n      if (deepIgnoredSymbols.has(symbolName)) continue;\n      const existSymbol = resultSymbols.get(symbolName);\n      if (!existSymbol) continue; // New symbol — handled by top-level append\n\n      const existingMemberKeys = new Set(existSymbol.members.map((m) => m.key));\n      const newMembers = genSymbol.members.filter((m) => !existingMemberKeys.has(m.key));\n\n      if (newMembers.length > 0) {\n        // Let the adapter decide whether to skip deep merge (e.g., when new members\n        // reference dependencies the existing symbol doesn't provide)\n        if (adapter.shouldSkipDeepMerge?.(symbolName, existingMemberKeys, newMembers)) {\n          continue;\n        }\n\n        const indent = existSymbol.memberIndent ?? '  ';\n        const insertText = newMembers.map((m) => indent + m.text).join('\\n\\n');\n        // Leading blank line separates inserted members from existing ones.\n        insertions.push({ line: existSymbol.bodyEndLine, text: '\\n' + insertText });\n        deepAdded += newMembers.length;\n      }\n    }\n\n    if (insertions.length > 0) {\n      // Apply bottom-up to avoid offset shifting\n      insertions.sort((a, b) => b.line - a.line);\n      const resultLines = result.split('\\n');\n      for (const ins of insertions) {\n        resultLines.splice(ins.line, 0, ins.text);\n      }\n      result = resultLines.join('\\n');\n    }\n  }\n\n  // Insert new imports only when new symbols or members were actually added.\n  // This prevents orphaned imports for generated code that wasn't merged in.\n  // Additionally, filter imports to only include identifiers actually used in the\n  // appended/inserted code — prevents orphaned imports for generated code that\n  // referenced types used in other (non-appended) generated functions.\n  if (newImports.length > 0 && (toAppend.length > 0 || deepAdded > 0)) {\n    // Build text of all new code that was actually added (appended + deep-merged members)\n    const addedParts: string[] = [...toAppend];\n    if (insertions) {\n      for (const ins of insertions) {\n        addedParts.push(ins.text);\n      }\n    }\n    const addedCodeText = addedParts.join('\\n');\n\n    // Filter imports to only identifiers that appear in the added code.\n    // Strip individual unused identifiers from each import rather than\n    // keeping/dropping the entire import — prevents orphaned imports when\n    // a generated import line contains both used and unused identifiers\n    // (e.g., `import { deserializeFoo, serializeFoo }` where only\n    // serializeFoo is used in the appended code).\n    const filteredImports: MergeImport[] = [];\n    for (const imp of newImports) {\n      const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n      if (!braceMatch) {\n        // Non-destructured import (e.g., default import) — keep as-is\n        filteredImports.push(imp);\n        continue;\n      }\n      const names = braceMatch[1]\n        .split(',')\n        .map((n) => n.replace(/\\btype\\b/, '').trim())\n        .filter(Boolean);\n      const usedNames = names.filter((name) => addedCodeText.includes(name));\n      if (usedNames.length === 0) continue; // Drop entirely\n      if (usedNames.length === names.length) {\n        // All identifiers used — keep original import\n        filteredImports.push(imp);\n      } else {\n        // Rebuild import with only used identifiers\n        const isTypeImport = imp.text.trimStart().startsWith('import type');\n        const prefix = isTypeImport ? 'import type' : 'import';\n        const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n        if (sourceMatch) {\n          filteredImports.push({\n            key: imp.key,\n            text: `${prefix} { ${usedNames.join(', ')} } from ${sourceMatch[1]};`,\n          });\n        } else {\n          filteredImports.push(imp);\n        }\n      }\n    }\n\n    if (filteredImports.length > 0) {\n      const renderedImports = adapter.renderImports\n        ? adapter.renderImports(filteredImports)\n        : filteredImports.map((entry) => entry.text);\n      const lines = result.split('\\n');\n      const insertIdx = lastImportEndIndex + 1;\n      lines.splice(insertIdx, 0, ...renderedImports);\n      result = lines.join('\\n');\n    }\n  }\n\n  // Docstring refresh pass: update existing docstrings to match generated content\n  let docstringUpdates = 0;\n  {\n    const parser = await getParser(language);\n    const resultTree = safeParse(parser, result);\n    const generatedTree = safeParse(parser, generatedContent);\n    const resultDocs = adapter.extractDocstrings(resultTree, result);\n    const generatedDocs = adapter.extractDocstrings(generatedTree, generatedContent);\n    const docIgnoredRegions = findIgnoredRegions(result);\n    const docIgnoredSymbols = buildIgnoredSymbolNames(resultDocs, docIgnoredRegions);\n\n    const edits: { start: number; end: number; newText: string }[] = [];\n\n    for (const [symbolName, genInfo] of generatedDocs) {\n      const existInfo = resultDocs.get(symbolName);\n      if (!existInfo) continue;\n      if (docIgnoredSymbols.has(symbolName)) continue;\n\n      // Skip header comments being treated as docstrings\n      const genDoc = genInfo.docstring && genInfo.docstring.text.trim() !== headerLine ? genInfo.docstring : null;\n\n      // Top-level docstring\n      if (genDoc) {\n        if (existInfo.docstring) {\n          const isPreserved = existInfo.docstring.text.includes('@oagen-ignore');\n          if (!isPreserved && existInfo.docstring.text !== genDoc.text) {\n            const newText = preserveDeprecatedTags(existInfo.docstring.text, genDoc.text);\n            const range = resolveDocRange(\n              result,\n              existInfo.docstring.text,\n              existInfo.declStartIndex,\n              existInfo.docstring.startIndex,\n              existInfo.docstring.endIndex,\n            );\n            edits.push({\n              start: range.start,\n              end: range.end,\n              newText,\n            });\n            docstringUpdates++;\n          }\n        } else {\n          const lineStart = declarationLineStart(result, existInfo.declStartIndex);\n          const indent = ' '.repeat(existInfo.declColumn);\n          edits.push({\n            start: lineStart,\n            end: lineStart,\n            newText: indent + genDoc.text + '\\n',\n          });\n          docstringUpdates++;\n        }\n      }\n\n      // Member-level docstrings — first pass: match by name\n      const matchedExistMembers = new Set<string>();\n      for (const [memberName, genMember] of genInfo.members) {\n        const existMember = existInfo.members.get(memberName);\n        if (!existMember) continue;\n        matchedExistMembers.add(memberName);\n        if (!genMember.docstring) continue;\n\n        if (existMember.docstring) {\n          const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n          if (!isPreserved && existMember.docstring.text !== genMember.docstring.text) {\n            const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n            const range = resolveDocRange(\n              result,\n              existMember.docstring.text,\n              existMember.declStartIndex,\n              existMember.docstring.startIndex,\n              existMember.docstring.endIndex,\n            );\n            edits.push({\n              start: range.start,\n              end: range.end,\n              newText,\n            });\n            docstringUpdates++;\n          }\n        } else {\n          const lineStart = declarationLineStart(result, existMember.declStartIndex);\n          const indent = ' '.repeat(existMember.declColumn);\n          edits.push({\n            start: lineStart,\n            end: lineStart,\n            newText: indent + genMember.docstring.text + '\\n',\n          });\n          docstringUpdates++;\n        }\n      }\n\n      // Member-level docstrings — second pass: URL fingerprint fallback\n      // Match generated members to existing members by URL pattern when\n      // name-based matching fails (e.g., generated \"find\" vs existing \"getWidget\"\n      // both call this.client.get('/widgets/${id}')).\n      //\n      // Safety: only attempt fingerprint matching when there is exactly ONE\n      // unmatched generated member and ONE unmatched existing member for a\n      // given fingerprint.  When multiple members share the same URL path\n      // (e.g., POST and GET on /authorization/roles), fingerprint matching\n      // is ambiguous and would swap docstrings between methods.\n      const unmatchedGenByFp = new Map<\n        string,\n        { name: string; member: typeof genInfo.members extends Map<string, infer V> ? V : never }[]\n      >();\n      for (const [genName, genMember] of genInfo.members) {\n        if (matchedExistMembers.has(genName)) continue; // name-matched in pass 1 (as an exist member) — skip\n        if (!genMember.docstring || !genMember.urlFingerprint) continue;\n        // Skip if this generated member was already name-matched\n        if (existInfo.members.has(genName)) continue;\n        const bucket = unmatchedGenByFp.get(genMember.urlFingerprint) ?? [];\n        bucket.push({ name: genName, member: genMember });\n        unmatchedGenByFp.set(genMember.urlFingerprint, bucket);\n      }\n      const unmatchedExistByFp = new Map<\n        string,\n        { name: string; member: typeof existInfo.members extends Map<string, infer V> ? V : never }[]\n      >();\n      for (const [existName, existMember] of existInfo.members) {\n        if (matchedExistMembers.has(existName)) continue;\n        if (!existMember.urlFingerprint) continue;\n        const bucket = unmatchedExistByFp.get(existMember.urlFingerprint) ?? [];\n        bucket.push({ name: existName, member: existMember });\n        unmatchedExistByFp.set(existMember.urlFingerprint, bucket);\n      }\n      for (const [fp, genBucket] of unmatchedGenByFp) {\n        if (genBucket.length !== 1) continue; // ambiguous — skip\n        const existBucket = unmatchedExistByFp.get(fp);\n        if (!existBucket || existBucket.length !== 1) continue; // ambiguous — skip\n        const genMember = genBucket[0].member;\n        const existEntry = existBucket[0];\n        const existMember = existEntry.member;\n        if (!genMember.docstring) continue;\n\n        if (existMember.docstring) {\n          const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n          if (isPreserved) continue;\n          if (existMember.docstring.text !== genMember.docstring.text) {\n            const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n            const range = resolveDocRange(\n              result,\n              existMember.docstring.text,\n              existMember.declStartIndex,\n              existMember.docstring.startIndex,\n              existMember.docstring.endIndex,\n            );\n            edits.push({\n              start: range.start,\n              end: range.end,\n              newText,\n            });\n            docstringUpdates++;\n          }\n        } else {\n          const lineStart = declarationLineStart(result, existMember.declStartIndex);\n          const indent = ' '.repeat(existMember.declColumn);\n          edits.push({\n            start: lineStart,\n            end: lineStart,\n            newText: indent + genMember.docstring.text + '\\n',\n          });\n          docstringUpdates++;\n        }\n        matchedExistMembers.add(existEntry.name);\n      }\n    }\n\n    if (edits.length > 0) {\n      edits.sort((a, b) => b.start - a.start);\n      for (const edit of edits) {\n        result = result.slice(0, edit.start) + edit.newText + result.slice(edit.end);\n      }\n    }\n  }\n\n  const importsActuallyAdded =\n    toAppend.length > 0 || deepAdded > 0\n      ? adapter.renderImports\n        ? adapter.renderImports(newImports).length\n        : newImports.length\n      : 0;\n  const topLevelAdded = importsActuallyAdded + toAppend.length;\n  const totalAdded = topLevelAdded + deepAdded;\n\n  if (totalAdded === 0 && docstringUpdates === 0 && deepPruned === 0) {\n    return { content: existingContent, added: 0, preserved, changed: false };\n  }\n\n  return {\n    content: result,\n    added: totalAdded,\n    preserved,\n    changed: true,\n  };\n}\n","/**\n * Deep merge two parsed JSON values.\n *\n * - Objects: recursively merge, preserving existing keys not in generated\n * - Arrays: generated replaces existing entirely (generated owns array contents)\n * - Primitives: generated wins\n */\nexport function deepMergeJson(existing: unknown, generated: unknown): unknown {\n  if (\n    typeof existing === 'object' &&\n    existing !== null &&\n    !Array.isArray(existing) &&\n    typeof generated === 'object' &&\n    generated !== null &&\n    !Array.isArray(generated)\n  ) {\n    const merged: Record<string, unknown> = { ...(existing as Record<string, unknown>) };\n    for (const [key, value] of Object.entries(generated as Record<string, unknown>)) {\n      if (key in merged) {\n        merged[key] = deepMergeJson(merged[key], value);\n      } else {\n        merged[key] = value;\n      }\n    }\n    return merged;\n  }\n\n  // Arrays and primitives: generated wins\n  return generated;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { mergeIntoExisting, hasGrammar, extractClassEndLines, extractStatements } from './merger.js';\nimport { deepMergeJson } from './json-merge.js';\nimport { getMergeAdapter } from './merge-adapters/index.js';\n\nexport interface WriteOptions {\n  /** The emitter language (e.g., \"node\", \"ruby\"). Used to select the\n   *  tree-sitter grammar for AST-level merging. */\n  language?: string;\n  /** The auto-generated file header string. */\n  header?: string;\n}\n\nexport interface WriteResult {\n  written: string[];\n  merged: string[];\n  skipped: string[];\n  identical: string[];\n  ignored: string[];\n}\n\n/**\n * Write generated files to disk with AST-level merging.\n *\n * When a file already exists:\n * - skipIfExists → leave it alone entirely\n * - AST merge available → parse both, append only new symbols\n * - No grammar → skip (never clobber hand-written code)\n *\n * New files are always written in full.\n */\nexport async function writeFiles(\n  files: GeneratedFile[],\n  outputDir: string,\n  options?: WriteOptions,\n): Promise<WriteResult> {\n  const result: WriteResult = {\n    written: [],\n    merged: [],\n    skipped: [],\n    identical: [],\n    ignored: [],\n  };\n  const sorted = [...files].sort((a, b) => a.path.localeCompare(b.path));\n  const language = options?.language;\n  const header = options?.header ?? '';\n\n  for (const file of sorted) {\n    const fullPath = path.join(outputDir, file.path);\n\n    // Repair on-disk casing when an emitter renames a generated file in a\n    // case-only way (e.g. `AuthenticationMfaFailed.kt` → `AuthenticationMFAFailed.kt`\n    // after adding `MFA` to an acronym list). On case-insensitive filesystems\n    // (APFS, NTFS) `writeFile` would otherwise reuse the existing inode and\n    // preserve the stale casing — surfacing later as ktlint/eslint errors.\n    await renameMismatchedCasing(fullPath);\n\n    // Check if file already exists\n    let existingContent: string | null = null;\n    try {\n      existingContent = await fs.readFile(fullPath, 'utf-8');\n    } catch {\n      // File doesn't exist\n    }\n\n    // New file → write in full\n    if (existingContent === null) {\n      await fs.mkdir(path.dirname(fullPath), { recursive: true });\n      await fs.writeFile(fullPath, file.content, 'utf-8');\n      result.written.push(file.path);\n      continue;\n    }\n\n    // skipIfExists → hard skip, no merge (but ensure header is present).\n    // JSON files are skipped from header injection because a leading `//`\n    // comment makes the file invalid JSON.\n    if (file.skipIfExists) {\n      if (header && !existingContent.startsWith(header) && !file.path.endsWith('.json')) {\n        await fs.writeFile(fullPath, header + '\\n\\n' + existingContent, 'utf-8');\n      }\n      result.skipped.push(file.path);\n      continue;\n    }\n\n    // @oagen-ignore-file → skip entirely (existing file opts out of all generation)\n    if (existingContent.includes('@oagen-ignore-file')) {\n      result.ignored.push(file.path);\n      continue;\n    }\n\n    // Don't merge test files into hand-written test files — generated tests are\n    // designed for the standalone generated SDK and will have wrong\n    // signatures/fixtures when merged into hand-written tests.\n    // However, if the existing test file is itself auto-generated (has the oagen\n    // header), allow overwriteExisting to take effect so new methods get coverage.\n    const adapter = language ? getMergeAdapter(language) : undefined;\n    const isTestFile = adapter?.testFilePatterns\n      ? adapter.testFilePatterns.some((p) => p.test(file.path))\n      : isDefaultTestFile(file.path);\n    if (isTestFile) {\n      const isExistingAutoGenerated = header && existingContent.startsWith(header);\n      if (!isExistingAutoGenerated && !file.overwriteExisting) {\n        result.skipped.push(file.path);\n        continue;\n      }\n      // Auto-generated test file or overwriteExisting — fall through to overwriteExisting / identical checks\n    }\n\n    // Identical content → no-op\n    if (existingContent === file.content) {\n      result.identical.push(file.path);\n      continue;\n    }\n\n    // Force overwrite — but preserve any @oagen-ignore regions from existing content\n    if (file.overwriteExisting) {\n      const content =\n        existingContent.includes('@oagen-ignore-start') && language && hasGrammar(language)\n          ? await overwriteWithPreservedRegions(existingContent, file.content, language)\n          : file.content;\n      await fs.writeFile(fullPath, content, 'utf-8');\n      result.written.push(file.path);\n      continue;\n    }\n\n    // JSON files → deep merge preserving existing keys\n    if (file.path.endsWith('.json')) {\n      try {\n        const existingJson = JSON.parse(existingContent);\n        const generatedJson = JSON.parse(file.content);\n        const merged = deepMergeJson(existingJson, generatedJson);\n        const mergedContent = JSON.stringify(merged, null, 2) + '\\n';\n        if (mergedContent === existingContent) {\n          result.identical.push(file.path);\n        } else {\n          await fs.writeFile(fullPath, mergedContent, 'utf-8');\n          result.merged.push(file.path);\n        }\n      } catch {\n        // Parse failed — fall back to overwrite\n        await fs.writeFile(fullPath, file.content, 'utf-8');\n        result.written.push(file.path);\n      }\n      continue;\n    }\n\n    // Source files with grammar → AST-level merge\n    if (language && hasGrammar(language)) {\n      try {\n        const mergeResult = await mergeIntoExisting(existingContent, file.content, language, header);\n\n        // Ensure header is present on merged content\n        let finalContent = mergeResult.content;\n        if (header && !finalContent.startsWith(header)) {\n          finalContent = header + '\\n\\n' + finalContent;\n        }\n\n        if (!mergeResult.changed && finalContent === existingContent) {\n          result.identical.push(file.path);\n          continue;\n        }\n\n        await fs.writeFile(fullPath, finalContent, 'utf-8');\n        result.merged.push(file.path);\n        continue;\n      } catch (err) {\n        // AST merge failed (e.g. tree-sitter grammar ABI issue) — fall back to overwrite\n        console.warn(\n          `[oagen] AST merge failed for ${file.path}, falling back to overwrite.${err instanceof Error ? ` ${err.message}` : ''}`,\n        );\n        await fs.writeFile(fullPath, file.content, 'utf-8');\n        result.written.push(file.path);\n        continue;\n      }\n    }\n\n    // No grammar available → skip to avoid clobbering\n    result.skipped.push(file.path);\n  }\n\n  return result;\n}\n\n/**\n * If a sibling exists with the same name except for letter case, rename it to\n * the requested casing. Uses a two-step rename via a temporary unique name so\n * case-insensitive filesystems (APFS on macOS, NTFS on Windows) actually\n * update the entry — `rename('Foo', 'FOO')` is a no-op on those systems.\n */\nasync function renameMismatchedCasing(fullPath: string): Promise<void> {\n  const dir = path.dirname(fullPath);\n  const target = path.basename(fullPath);\n  let entries: string[];\n  try {\n    entries = await fs.readdir(dir);\n  } catch {\n    return;\n  }\n  if (entries.includes(target)) return;\n  const targetLower = target.toLowerCase();\n  const mismatch = entries.find((e) => e.toLowerCase() === targetLower);\n  if (!mismatch) return;\n  const oldPath = path.join(dir, mismatch);\n  const tempPath = path.join(dir, `.oagen-case-${process.pid}-${Date.now()}-${target}`);\n  await fs.rename(oldPath, tempPath);\n  await fs.rename(tempPath, fullPath);\n}\n\n/** Comprehensive fallback when no adapter is available. */\nfunction isDefaultTestFile(filePath: string): boolean {\n  return (\n    /\\.(spec|test)\\.[jt]sx?$/.test(filePath) ||\n    filePath.endsWith('_test.go') ||\n    filePath.endsWith('_test.rb') ||\n    filePath.endsWith('_spec.rb') ||\n    /(?:^|\\/)test_.*\\.py$/.test(filePath) ||\n    filePath.endsWith('_test.py') ||\n    filePath.endsWith('Test.php') ||\n    filePath.endsWith('_test.rs') ||\n    /(?:^|\\/)tests\\/.*\\.rs$/.test(filePath)\n  );\n}\n\n// --- @oagen-ignore region preservation for overwriteExisting ---\n\n/**\n * Overwrite a file with generated content while preserving\n * `@oagen-ignore-start` / `@oagen-ignore-end` regions (and their\n * required imports) from the existing file.\n *\n * Uses tree-sitter via `extractClassEndLines` to find accurate class\n * boundaries so ignore blocks are inserted at the correct position even\n * when docstrings contain unindented text.\n */\nexport async function overwriteWithPreservedRegions(\n  existingContent: string,\n  generatedContent: string,\n  language: string,\n): Promise<string> {\n  const existingLines = existingContent.split('\\n');\n  const generatedLines = generatedContent.split('\\n');\n\n  // 1. Extract ignore blocks, their containing class, and the anchor line\n  //    (first non-blank line after the block in the existing file).\n  const blocks: { containingClass: string; containingScope: string; lines: string[]; anchor: string }[] = [];\n  for (let i = 0; i < existingLines.length; i++) {\n    if (!existingLines[i].includes('@oagen-ignore-start')) continue;\n    const startIdx = i;\n    while (i < existingLines.length && !existingLines[i].includes('@oagen-ignore-end')) i++;\n    let anchor = '';\n    for (let a = i + 1; a < existingLines.length; a++) {\n      if (existingLines[a].trim()) {\n        anchor = existingLines[a].trimStart();\n        break;\n      }\n    }\n    blocks.push({\n      containingClass: findContainingClass(existingLines, startIdx),\n      containingScope: findContainingDescribeScope(existingLines, startIdx),\n      lines: existingLines.slice(startIdx, i + 1),\n      anchor,\n    });\n  }\n  if (blocks.length === 0) return generatedContent;\n\n  // 2. Splice extra imports from existing into generated.\n  // First strip any `@oagen-ignore-start`..`@oagen-ignore-end` regions the\n  // generator itself emitted: we are about to re-insert the on-disk versions,\n  // and if we left the generator's seed blocks in place we'd end up with two\n  // copies of every ignore block per regeneration (monotonically growing).\n  const result = stripIgnoreRegions(generatedLines);\n  spliceExtraImports(existingLines, result);\n\n  // 3. Build class-end map from the generated content (after import splicing)\n  //    via tree-sitter for accurate boundary detection.\n  const genSource = result.join('\\n');\n  const classEndLines = await extractClassEndLines(genSource, language);\n\n  // 4. Group ignore blocks by class and determine insertion points\n  const blocksByClass = new Map<string, Array<{ containingScope: string; lines: string[]; anchor: string }>>();\n  for (const b of blocks) {\n    if (!blocksByClass.has(b.containingClass)) blocksByClass.set(b.containingClass, []);\n    blocksByClass.get(b.containingClass)!.push({\n      containingScope: b.containingScope,\n      lines: b.lines,\n      anchor: b.anchor,\n    });\n  }\n\n  // 4a. Handle replacement blocks: ignore blocks that redefine their\n  //     containing class replace the generated class entirely.\n  //     Also handles top-level blocks (no containing class) that define\n  //     a class matching one in the generated content.\n  const replacedClasses = new Set<string>();\n  const handledBlockKeys = new Set<string>();\n  const replacements: {\n    startLine: number;\n    endLine: number;\n    content: string[];\n  }[] = [];\n  for (const [className, classBlocks] of blocksByClass) {\n    // Determine the target class for replacement.  When the block has a\n    // containing class, we check if the block redefines that class.  When\n    // there is no containing class (top-level ignore block), we look for a\n    // class definition inside the block that matches a generated class.\n    let targetClass = className;\n    if (!targetClass) {\n      for (const entry of classBlocks) {\n        for (const l of entry.lines) {\n          const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n          if (m && classEndLines.has(m[1])) {\n            targetClass = m[1];\n            break;\n          }\n        }\n        if (targetClass) break;\n      }\n    }\n    if (!targetClass) continue;\n    const isReplacement = classBlocks.some((entry) =>\n      entry.lines.some((l) => {\n        const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n        return m?.[1] === targetClass;\n      }),\n    );\n    if (!isReplacement) continue;\n    const info = classEndLines.get(targetClass);\n    if (!info) continue;\n    const startLine = findClassDeclarationStart(result, targetClass, info.bodyEndLine);\n    if (startLine < 0) continue;\n    const content: string[] = [];\n    for (const entry of classBlocks) {\n      content.push('');\n      content.push(...entry.lines);\n    }\n    replacements.push({ startLine, endLine: info.bodyEndLine, content });\n    replacedClasses.add(targetClass);\n    handledBlockKeys.add(className);\n  }\n  // Apply replacements bottom-up to preserve line indices\n  replacements.sort((a, b) => b.startLine - a.startLine);\n  for (const rep of replacements) {\n    result.splice(rep.startLine, rep.endLine - rep.startLine, ...rep.content);\n  }\n\n  // 4a-bis. Top-level declarations protected by ignore regions win over their\n  //         generated counterparts. For each top-level block, drop generated\n  //         declarations (interface/type/const/function/…) whose names are\n  //         declared inside the block; the block content replaces the first\n  //         such declaration in place. Without this, every regeneration\n  //         re-emits a duplicate of each region-protected declaration.\n  let regionDeclarationEdits = 0;\n  {\n    const topLevelEntries = blocksByClass.get('');\n    if (topLevelEntries) {\n      // When 4a already placed the top-level blocks (as part of a class\n      // replacement), only delete generated duplicates — never re-insert.\n      const alreadyPlaced = handledBlockKeys.has('');\n      const remaining: typeof topLevelEntries = [];\n      for (const entry of topLevelEntries) {\n        const outcome = await applyRegionDeclarationOverride(result, entry.lines, language, !alreadyPlaced);\n        if (outcome.edited) regionDeclarationEdits++;\n        if (!alreadyPlaced && !outcome.placed) remaining.push(entry);\n      }\n      if (!alreadyPlaced) {\n        if (remaining.length === 0) {\n          blocksByClass.delete('');\n        } else {\n          blocksByClass.set('', remaining);\n        }\n      }\n    }\n  }\n\n  // 4b. Standard insertions for non-replacement blocks\n  // Rebuild class end lines if replacements shifted line numbers.\n  let effectiveClassEndLines = classEndLines;\n  if (replacedClasses.size > 0 || regionDeclarationEdits > 0) {\n    effectiveClassEndLines = await extractClassEndLines(result.join('\\n'), language);\n  }\n\n  const insertions: { line: number; order: number; content: string[] }[] = [];\n  let insertionOrder = 0;\n  for (const [className, classBlocks] of blocksByClass) {\n    if (handledBlockKeys.has(className) || replacedClasses.has(className)) continue;\n    const info = className ? effectiveClassEndLines.get(className) : undefined;\n\n    // Insert each block individually so each can use its own anchor.\n    for (const entry of classBlocks) {\n      let insertLine: number | undefined;\n\n      // Try anchor-based positioning: find the first line in the generated\n      // file whose trimmed-start content matches the anchor (the first\n      // non-blank line that followed this block in the existing file).\n      // Skip anchors that are just punctuation (braces, etc.) since they\n      // match too many locations. Accept doc comment starters (/** /// #)\n      // as valid anchors since they're structurally meaningful.\n      // Also skip bare language keywords (`end`, `end;`, `end)`) that appear\n      // on many lines and would match the wrong location (e.g. nesting the\n      // block inside a Ruby method body instead of at class level).\n      const isAmbiguousAnchor = /^end[;)\\s]*$/.test(entry.anchor);\n      if (\n        entry.anchor &&\n        !entry.anchor.includes('@oagen-ignore') &&\n        !isAmbiguousAnchor &&\n        /[a-zA-Z]|^\\/\\*|^\\/\\//.test(entry.anchor)\n      ) {\n        for (let li = 0; li < result.length; li++) {\n          if (result[li].trimStart() === entry.anchor) {\n            insertLine = li;\n            break;\n          }\n        }\n      }\n\n      // Fallback: class body end, or for top-level import blocks, after the\n      // last import line (so they stay near the top of the file, not at the\n      // bottom where they'd trigger E402 lint errors).\n      if (insertLine === undefined) {\n        if (info) {\n          insertLine = info.bodyEndLine;\n        } else {\n          const scopeEndLine = entry.containingScope\n            ? findDescribeScopeEndLine(result, entry.containingScope)\n            : undefined;\n          const blockHasImportsFallback = entry.lines.some((l: string) => /^\\s*(import|from)\\s/.test(l));\n          if (scopeEndLine !== undefined) {\n            insertLine = scopeEndLine;\n          } else if (blockHasImportsFallback || hasTopLevelDeclaration(entry.lines)) {\n            let lastImportLine = 0;\n            for (let li = 0; li < result.length; li++) {\n              const trimmed = result[li].trimStart();\n              if (/^(import|from)\\s/.test(trimmed)) lastImportLine = li + 1;\n            }\n            insertLine = lastImportLine;\n          } else {\n            insertLine = result.length;\n          }\n        }\n      }\n\n      // When inserting an import-containing ignore block, move up past\n      // blank separator lines so the block sits flush with surrounding\n      // imports (e.g., Kotlin's ktlint forbids blank lines within import\n      // blocks).\n      const blockHasImports = entry.lines.some((l: string) => /^\\s*import\\s/.test(l));\n      if (blockHasImports) {\n        while (\n          insertLine >= 2 &&\n          result[insertLine - 1]?.trim() === '' &&\n          /^\\s*(import|using|from)\\s/.test(result[insertLine - 2] ?? '')\n        ) {\n          insertLine--;\n        }\n      }\n\n      // Skip the leading blank line when the block is adjacent to imports\n      // or already preceded by a blank line (avoids double-blank-line gaps).\n      // Exclude C# `using` directives — StyleCop SA1515 requires a blank\n      // line before comments, so collapsing breaks the build.\n      const prevLine = insertLine > 0 ? (result[insertLine - 1]?.trimStart() ?? '') : '';\n      const prevIsImport = /^import\\s/.test(prevLine) || /^from\\s/.test(prevLine);\n      const prevIsBlank = insertLine > 0 && prevLine === '';\n      const blockContent = prevIsImport || prevIsBlank ? [...entry.lines] : ['', ...entry.lines];\n      // Add a trailing blank line when the next line is a doc comment\n      // (C# SA1514 requires a blank line before `///` doc headers).\n      const nextLine = result[insertLine]?.trimStart() ?? '';\n      if (nextLine.startsWith('///')) {\n        blockContent.push('');\n      }\n      insertions.push({ line: insertLine, order: insertionOrder++, content: blockContent });\n    }\n  }\n\n  // Apply bottom-up to preserve line indices. Blocks with the same insertion\n  // line must be applied in reverse discovery order because each splice inserts\n  // at the same index; otherwise repeated generation flips their order.\n  insertions.sort((a, b) => b.line - a.line || b.order - a.order);\n  for (const ins of insertions) {\n    result.splice(ins.line, 0, ...ins.content);\n  }\n\n  removeDuplicateImportsCoveredByIgnoreBlocks(result);\n\n  return result.join('\\n');\n}\n\n/**\n * Remove every `@oagen-ignore-start`..`@oagen-ignore-end` region from the\n * supplied lines, collapsing stretches of blank lines that get left behind.\n * Used to drop generator-emitted seed blocks before splicing the on-disk\n * versions back in — otherwise every regen doubles up.\n */\nfunction stripIgnoreRegions(lines: string[]): string[] {\n  const out: string[] = [];\n  let skipping = false;\n  for (const line of lines) {\n    if (!skipping && line.includes('@oagen-ignore-start')) {\n      skipping = true;\n      // Drop a preceding blank line if we have one queued up — otherwise\n      // regen leaves a stray blank line above the spliced-in block.\n      while (out.length > 0 && out[out.length - 1].trim() === '') out.pop();\n      continue;\n    }\n    if (skipping) {\n      if (line.includes('@oagen-ignore-end')) skipping = false;\n      continue;\n    }\n    out.push(line);\n  }\n  return out;\n}\n\n/** Scan backwards from `lineIdx` to find the nearest class declaration name. */\nfunction findContainingClass(lines: string[], lineIdx: number): string {\n  if (/^\\S/.test(lines[lineIdx] ?? '')) return '';\n  // Allow leading whitespace and language-specific modifiers before `class`.\n  // Covers: `public class Foo` (C#/Java), `export class Foo` (TS),\n  // `class Foo` (Python/Ruby), `internal sealed class Foo` (C#), etc.\n  for (let j = lineIdx - 1; j >= 0; j--) {\n    const m = lines[j].match(\n      /^\\s*(?:(?:export|public|private|protected|internal|abstract|sealed|static|partial)\\s+)*class\\s+(\\w+)/,\n    );\n    if (m) return m[1];\n  }\n  return '';\n}\n\nfunction findContainingDescribeScope(lines: string[], lineIdx: number): string {\n  const markerLine = lines[lineIdx] ?? '';\n  if (/^\\S/.test(markerLine)) return '';\n  const markerIndent = leadingSpaces(markerLine);\n  for (let j = lineIdx - 1; j >= 0; j--) {\n    const line = lines[j];\n    const indent = leadingSpaces(line);\n    if (indent >= markerIndent) continue;\n    const match = line.match(/^\\s*describe\\((['\"`])(.+?)\\1\\s*,/);\n    if (match) return match[2];\n    if (/^\\s*(?:export\\s+)?class\\s+\\w+/.test(line)) return '';\n  }\n  return '';\n}\n\nfunction findDescribeScopeEndLine(lines: string[], scopeName: string): number | undefined {\n  for (let i = 0; i < lines.length; i++) {\n    const match = lines[i].match(/^\\s*describe\\((['\"`])(.+?)\\1\\s*,/);\n    if (!match || match[2] !== scopeName) continue;\n\n    let depth = 0;\n    for (let j = i; j < lines.length; j++) {\n      depth += countChar(lines[j], '{');\n      depth -= countChar(lines[j], '}');\n      if (j > i && depth <= 0) return j;\n    }\n  }\n  return undefined;\n}\n\nfunction leadingSpaces(line: string): number {\n  return line.match(/^\\s*/)?.[0].length ?? 0;\n}\n\nfunction countChar(line: string, char: string): number {\n  return [...line].filter((c) => c === char).length;\n}\n\nfunction hasTopLevelDeclaration(lines: string[]): boolean {\n  return lines.some((line) =>\n    /^(?:export\\s+)?(?:interface|type|class|function|const|let|var|enum)\\s+\\w+/.test(line.trim()),\n  );\n}\n\n/**\n * Find the start line of a class declaration (including decorators above it)\n * by scanning backwards from `beforeLine`.\n */\nfunction findClassDeclarationStart(lines: string[], className: string, beforeLine: number): number {\n  // Match optional indentation so Ruby/Python nested classes are found.\n  const classPattern = new RegExp(`^\\\\s*(?:export\\\\s+)?class\\\\s+${className}\\\\b`);\n  for (let i = beforeLine - 1; i >= 0; i--) {\n    if (!classPattern.test(lines[i])) continue;\n    // Scan backward past decorators\n    let start = i;\n    while (start > 0 && /^\\s*@\\w+/.test(lines[start - 1])) {\n      start--;\n    }\n    return start;\n  }\n  return -1;\n}\n\n// --- region-protected top-level declaration overrides ---\n\n/**\n * Conservative top-level declaration matcher for ignore-block content.\n * Matches column-0 declarations like `export interface X`, `type X = …`,\n * `const X = …`, `function X(…)`, `class X` (export optional). Names found\n * here are only acted on when the language's merge adapter also reports a\n * generated top-level statement with the same key, so false positives are\n * filtered by the real parser.\n */\nconst REGION_DECLARATION_PATTERN =\n  /^(?:export\\s+)?(?:declare\\s+)?(?:interface|type|enum|class|const|let|var|async\\s+function|function)\\s+([A-Za-z_$][\\w$]*)/;\n\n/** Extract top-level symbol names declared inside an ignore block's lines. */\nfunction collectRegionDeclaredNames(blockLines: string[]): Set<string> {\n  const names = new Set<string>();\n  for (const line of blockLines) {\n    if (line.includes('@oagen-ignore')) continue;\n    const m = line.match(REGION_DECLARATION_PATTERN);\n    if (m) names.add(m[1]);\n  }\n  return names;\n}\n\n/** Inclusive line ranges of `@oagen-ignore-start`..`@oagen-ignore-end` regions. */\nfunction collectIgnoreRegionLineRanges(lines: string[]): Array<{ start: number; end: number }> {\n  const ranges: Array<{ start: number; end: number }> = [];\n  let start = -1;\n  for (let i = 0; i < lines.length; i++) {\n    if (start === -1 && lines[i].includes('@oagen-ignore-start')) {\n      start = i;\n      continue;\n    }\n    if (start !== -1 && lines[i].includes('@oagen-ignore-end')) {\n      ranges.push({ start, end: i });\n      start = -1;\n    }\n  }\n  return ranges;\n}\n\n/**\n * Walk upward from a declaration's first line over its contiguous comment\n * block (doc comment), so the comment is dropped together with the\n * declaration. Stops at blank lines, region markers, and line 0 (a comment\n * on line 0 is the file header, not a docstring).\n */\nfunction extendOverPrecedingComments(lines: string[], startLine: number): number {\n  let s = startLine;\n  while (s > 1) {\n    const prev = lines[s - 1].trim();\n    if (prev === '' || prev.includes('@oagen-ignore')) break;\n    const isComment = prev.startsWith('//') || prev.startsWith('/*') || prev.startsWith('*') || prev.startsWith('#');\n    if (!isComment) break;\n    s--;\n  }\n  return s;\n}\n\n/**\n * Drop generated top-level declarations that are redeclared inside an ignore\n * block (\"region wins\"). When `placeBlock` is set and at least one generated\n * declaration matches, the block's lines replace the first match in place\n * (mirroring the class-replacement behavior above); any further matches are\n * deleted. Mutates `result` in place.\n *\n * Returns `placed` (the block content now lives in `result` and must not be\n * inserted again) and `edited` (line numbers shifted).\n */\nasync function applyRegionDeclarationOverride(\n  result: string[],\n  blockLines: string[],\n  language: string,\n  placeBlock: boolean,\n): Promise<{ placed: boolean; edited: boolean }> {\n  const names = collectRegionDeclaredNames(blockLines);\n  if (names.size === 0) return { placed: false, edited: false };\n\n  const source = result.join('\\n');\n  let parsed;\n  try {\n    parsed = await extractStatements(source, language);\n  } catch {\n    return { placed: false, edited: false };\n  }\n\n  const regionRanges = collectIgnoreRegionLineRanges(result);\n  const inRegion = (line: number) => regionRanges.some((r) => line >= r.start && line <= r.end);\n\n  const spans: Array<{ start: number; end: number }> = [];\n  for (const stmt of parsed.statements) {\n    if (stmt.kind !== 'declaration' || !stmt.key || !names.has(stmt.key)) continue;\n    // Locate the statement's line span; skip occurrences inside ignore\n    // regions (those ARE the protected content).\n    let idx = source.indexOf(stmt.text);\n    let startLine = -1;\n    while (idx !== -1) {\n      const line = source.slice(0, idx).split('\\n').length - 1;\n      if (!inRegion(line)) {\n        startLine = line;\n        break;\n      }\n      idx = source.indexOf(stmt.text, idx + 1);\n    }\n    if (startLine === -1) continue;\n    const endLine = startLine + stmt.text.split('\\n').length - 1;\n    spans.push({ start: extendOverPrecedingComments(result, startLine), end: endLine });\n  }\n  if (spans.length === 0) return { placed: false, edited: false };\n\n  spans.sort((a, b) => a.start - b.start);\n\n  // Delete all matches after the first, bottom-up to preserve indices.\n  for (let i = spans.length - 1; i >= 1; i--) {\n    const span = spans[i];\n    let deleteCount = span.end - span.start + 1;\n    // Collapse the blank separator the deletion leaves behind.\n    const prevBlank = span.start === 0 || (result[span.start - 1] ?? '').trim() === '';\n    const nextBlank = (result[span.end + 1] ?? '').trim() === '';\n    if (prevBlank && nextBlank && span.end + 1 < result.length) deleteCount++;\n    result.splice(span.start, deleteCount);\n  }\n\n  const first = spans[0];\n  if (placeBlock) {\n    result.splice(first.start, first.end - first.start + 1, ...blockLines);\n    return { placed: true, edited: true };\n  }\n\n  let deleteCount = first.end - first.start + 1;\n  const prevBlank = first.start === 0 || (result[first.start - 1] ?? '').trim() === '';\n  const nextBlank = (result[first.end + 1] ?? '').trim() === '';\n  if (prevBlank && nextBlank && first.end + 1 < result.length) deleteCount++;\n  result.splice(first.start, deleteCount);\n  return { placed: false, edited: true };\n}\n\n/**\n * Collect `from X import Y, Z` identifiers grouped by module, handling\n * both single-line and multiline (parenthesized) forms.\n */\nfunction collectFromImports(lines: string[]): Map<string, Set<string>> {\n  const byModule = new Map<string, Set<string>>();\n  for (let i = 0; i < lines.length; i++) {\n    if (!/^from\\s+/.test(lines[i])) continue;\n\n    let fullText = lines[i];\n    if (fullText.includes('(') && !fullText.includes(')')) {\n      while (i + 1 < lines.length) {\n        i++;\n        fullText += ' ' + lines[i].trim();\n        if (lines[i].includes(')')) break;\n      }\n    }\n\n    const normalized = fullText.replace(/[()]/g, '').replace(/\\s+/g, ' ').trim();\n    const match = normalized.match(/^from\\s+(\\S+)\\s+import\\s+(.+)$/);\n    if (!match) continue;\n\n    const mod = match[1];\n    if (!byModule.has(mod)) byModule.set(mod, new Set());\n    for (const id of match[2]\n      .split(',')\n      .map((s) => s.trim())\n      .filter(Boolean)) {\n      byModule.get(mod)!.add(id);\n    }\n  }\n  return byModule;\n}\n\n/**\n * Collected TypeScript imports grouped by form. Each map keys on the module\n * specifier (e.g. `./foo`, `node:fs`).\n */\ninterface TsImports {\n  /** `import { X, Y } from 'module'` — module → identifier names. */\n  named: Map<string, Set<string>>;\n  /** `import type { X } from 'module'` — module → identifier names. */\n  typeOnly: Map<string, Set<string>>;\n  /** `import X from 'module'` or `import type X from 'module'` — module → name. */\n  defaults: Map<string, string>;\n  /** `import * as X from 'module'` — module → namespace alias name. */\n  namespaces: Map<string, string>;\n  /** `import 'module'` — modules imported for side effects only. */\n  sideEffects: Set<string>;\n}\n\n/**\n * Collect TypeScript imports, grouped by form. Handles single-line and\n * multi-line `{ … }` named imports. Disjoint from Python's `from X import Y`\n * syntax so this can be called in parallel with `collectFromImports`.\n */\nfunction collectTsImports(lines: string[]): TsImports {\n  const out: TsImports = {\n    named: new Map(),\n    typeOnly: new Map(),\n    defaults: new Map(),\n    namespaces: new Map(),\n    sideEffects: new Set(),\n  };\n\n  for (let i = 0; i < lines.length; i++) {\n    const trimmed = lines[i].trim();\n    if (!/^import(\\s|$)/.test(trimmed)) continue;\n\n    // Accumulate multi-line `{ … }` imports.\n    let fullText = lines[i];\n    if (fullText.includes('{') && !fullText.includes('}')) {\n      while (i + 1 < lines.length) {\n        i++;\n        fullText += ' ' + lines[i].trim();\n        if (lines[i].includes('}')) break;\n      }\n    }\n\n    const normalized = fullText.replace(/\\s+/g, ' ').trim().replace(/;\\s*$/, '');\n\n    // `import 'module'`\n    let m = normalized.match(/^import\\s+['\"]([^'\"]+)['\"]$/);\n    if (m) {\n      out.sideEffects.add(m[1]);\n      continue;\n    }\n\n    // `import * as X from 'module'`\n    m = normalized.match(/^import\\s+\\*\\s+as\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n    if (m) {\n      out.namespaces.set(m[2], m[1]);\n      continue;\n    }\n\n    // `import [Default,] { X, Y as Z } from 'module'` or `import type { X } from 'module'`\n    m = normalized.match(/^import\\s+(type\\s+)?(?:(\\w+)\\s*,\\s*)?\\{\\s*([^}]*)\\s*\\}\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n    if (m) {\n      const isTypeOnly = !!m[1];\n      const defaultName = m[2];\n      const namesRaw = m[3];\n      const mod = m[4];\n      if (defaultName) out.defaults.set(mod, defaultName);\n      const names = namesRaw\n        .split(',')\n        .map((s) => s.trim().replace(/\\s+as\\s+\\w+$/, ''))\n        .filter(Boolean);\n      for (const rawName of names) {\n        const isInlineTypeOnly = rawName.startsWith('type ');\n        const name = rawName.replace(/^type\\s+/, '');\n        const target = isTypeOnly || isInlineTypeOnly ? out.typeOnly : out.named;\n        if (!target.has(mod)) target.set(mod, new Set());\n        target.get(mod)!.add(name);\n      }\n      continue;\n    }\n\n    // `import X from 'module'` or `import type X from 'module'`\n    m = normalized.match(/^import\\s+(?:type\\s+)?(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n    if (m) {\n      out.defaults.set(m[2], m[1]);\n      continue;\n    }\n  }\n\n  return out;\n}\n\n/**\n * Remove the given symbols from generated `import type` bindings, in place.\n *\n * Called when an existing *value* import for the same symbol is being spliced\n * back into the file. A value import satisfies both runtime and type uses, so\n * leaving the generated `import type { X }` would re-declare `X` (TS2300\n * duplicate identifier). Callers guarantee every symbol here is absent from\n * generated *value* imports, so each occurrence is type-only and safe to drop.\n *\n * Handles whole-line `import type { … }` and inline `import { …, type X }`,\n * single- or multi-line. A statement whose bindings all get stripped is\n * removed entirely.\n */\nfunction dropGeneratedTypeOnlyBindings(resultLines: string[], symbols: Set<string>): void {\n  if (symbols.size === 0) return;\n  const out: string[] = [];\n  for (let i = 0; i < resultLines.length; i++) {\n    const line = resultLines[i];\n    const trimmed = line.trim();\n    // Only named imports (with a brace) can carry the symbols we strip.\n    if (!/^import\\b/.test(trimmed) || !trimmed.includes('{')) {\n      out.push(line);\n      continue;\n    }\n    // Gather the full (possibly multi-line) `{ … }` statement.\n    const span = [line];\n    while (!span.join(' ').includes('}') && i + 1 < resultLines.length) {\n      i++;\n      span.push(resultLines[i]);\n    }\n    const normalized = span.join(' ').replace(/\\s+/g, ' ').trim().replace(/;\\s*$/, '');\n    const m = normalized.match(/^import\\s+(type\\s+)?(?:(\\w+)\\s*,\\s*)?\\{\\s*([^}]*)\\s*\\}\\s+from\\s+(['\"][^'\"]+['\"])$/);\n    if (!m) {\n      for (const s of span) out.push(s);\n      continue;\n    }\n    const isTypeOnly = !!m[1];\n    const defaultName = m[2];\n    const items = m[3]\n      .split(',')\n      .map((s) => s.trim())\n      .filter(Boolean);\n    const modQuoted = m[4];\n    const kept = items.filter((raw) => {\n      const isTypeBinding = isTypeOnly || raw.startsWith('type ');\n      const bare = raw.replace(/^type\\s+/, '');\n      return !(isTypeBinding && symbols.has(bare));\n    });\n    if (kept.length === items.length) {\n      // Nothing stripped — preserve the original lines verbatim.\n      for (const s of span) out.push(s);\n      continue;\n    }\n    if (kept.length === 0 && !defaultName) continue; // statement fully emptied\n    const lead = line.match(/^(\\s*)/)?.[1] ?? '';\n    const prefix = isTypeOnly ? 'import type ' : 'import ';\n    const defaultPart = defaultName ? `${defaultName}, ` : '';\n    out.push(`${lead}${prefix}${defaultPart}{ ${kept.join(', ')} } from ${modQuoted};`);\n  }\n  resultLines.splice(0, resultLines.length, ...out);\n}\n\n/**\n * Add imports from the existing file that are absent from the generated\n * result. Handles:\n *\n * - Python: `import X` and `from X import Y`\n * - TypeScript: `import { X } from 'module'`, `import type { X } from 'module'`,\n *   `import X from 'module'`, `import * as X from 'module'`, `import 'module'`\n * - PHP: `use Foo\\Bar;` and `use Foo\\Bar as Baz;` (namespace-qualified only)\n * - Ruby: `require '…'` and `require_relative '…'`\n *\n * Mutates `resultLines` in place.\n */\nfunction filterOutIgnoreRegions(lines: string[]): string[] {\n  const out: string[] = [];\n  let skipping = false;\n  for (const line of lines) {\n    if (!skipping && line.includes('@oagen-ignore-start')) {\n      skipping = true;\n      continue;\n    }\n    if (skipping) {\n      if (line.includes('@oagen-ignore-end')) skipping = false;\n      continue;\n    }\n    out.push(line);\n  }\n  return out;\n}\n\nfunction collectIgnoreRegionUsageText(lines: string[]): string {\n  const out: string[] = [];\n  let skipping = false;\n  for (const line of lines) {\n    if (!skipping && line.includes('@oagen-ignore-start')) {\n      skipping = true;\n      continue;\n    }\n    if (!skipping) continue;\n    if (/^\\s*(import|from)\\s/.test(line)) continue;\n    out.push(line);\n    if (line.includes('@oagen-ignore-end')) skipping = false;\n  }\n  return out.join('\\n');\n}\n\nfunction removeDuplicateImportsCoveredByIgnoreBlocks(lines: string[]): void {\n  const ignoredImports = new Set<string>();\n  const importStatements = collectImportStatements(lines);\n  for (const stmt of importStatements) {\n    if (stmt.inIgnore) ignoredImports.add(normalizeImportStatement(stmt.lines));\n  }\n  if (ignoredImports.size === 0) return;\n\n  for (const stmt of [...importStatements].reverse()) {\n    if (stmt.inIgnore) continue;\n    if (ignoredImports.has(normalizeImportStatement(stmt.lines))) {\n      lines.splice(stmt.start, stmt.end - stmt.start + 1);\n    }\n  }\n}\n\nfunction collectImportStatements(\n  lines: string[],\n): Array<{ start: number; end: number; lines: string[]; inIgnore: boolean }> {\n  const statements: Array<{ start: number; end: number; lines: string[]; inIgnore: boolean }> = [];\n  let inIgnore = false;\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i];\n    if (!inIgnore && line.includes('@oagen-ignore-start')) {\n      inIgnore = true;\n      continue;\n    }\n    if (inIgnore && line.includes('@oagen-ignore-end')) {\n      inIgnore = false;\n      continue;\n    }\n    if (!isImportLine(line)) continue;\n\n    const start = i;\n    let end = i;\n    const statementLines = [line];\n    const opens = (line.match(/[({]/g) ?? []).length;\n    const closes = (line.match(/[)}]/g) ?? []).length;\n    if (opens > closes) {\n      while (end + 1 < lines.length) {\n        end++;\n        statementLines.push(lines[end]);\n        if ((lines[end].match(/[)}]/g) ?? []).length > 0 && /\\bfrom\\b/.test(lines[end])) break;\n      }\n      i = end;\n    }\n    statements.push({ start, end, lines: statementLines, inIgnore });\n  }\n  return statements;\n}\n\nfunction normalizeImportStatement(lines: string[]): string {\n  return lines.join('\\n').replace(/,\\s*}/g, ' }').replace(/\\s+/g, ' ').trim();\n}\n\nfunction isImportLine(line: string): boolean {\n  const trimmed = line.trim();\n  return (\n    /^import(\\s|$)/.test(trimmed) ||\n    /^from\\s+/.test(trimmed) ||\n    /^use\\s+[\\w\\\\]/.test(trimmed) ||\n    /^require(_relative)?\\s+['\"]/.test(trimmed)\n  );\n}\n\nfunction identifierUsed(source: string, identifier: string): boolean {\n  return new RegExp(`\\\\b${identifier.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`).test(source);\n}\n\nfunction spliceExtraImports(existingLines: string[], resultLines: string[]): void {\n  // Imports inside @oagen-ignore regions are converted into normal imports\n  // only when non-import ignore content still references them. This prevents\n  // stale import-only ignore blocks from creating duplicate or unused imports.\n  const existingOutsideIgnore = filterOutIgnoreRegions(existingLines);\n  const ignoreRegionText = collectIgnoreRegionUsageText(existingLines);\n\n  // Python-style `import hashlib`. Excludes TS forms like `import X from '…'`\n  // (have a `from` clause) and TS multi-line type imports whose first line is\n  // `import type {` (have a brace) — both are handled by the TS collector\n  // below.\n  const isPythonSimpleImport = (l: string) => /^import\\s+\\w/.test(l) && !/\\sfrom\\s/.test(l) && !/[{}]/.test(l);\n\n  // Simple imports (import hashlib, import json, …)\n  const existingSimple = new Set(existingOutsideIgnore.filter(isPythonSimpleImport).map((l) => l.trim()));\n  const generatedSimple = new Set(resultLines.filter(isPythonSimpleImport).map((l) => l.trim()));\n  const extraSimple = [...existingSimple].filter((l) => !generatedSimple.has(l));\n\n  // From-imports — compare by module and find extra identifiers\n  const existingFrom = collectFromImports(existingOutsideIgnore);\n  const generatedFrom = collectFromImports(resultLines);\n\n  // Build a set of all identifiers imported by the generated file (across all modules)\n  // so we can detect when an existing barrel import's identifiers are covered by\n  // more-specific generated imports (e.g., `from x.y import Z` covers `from x import Z`).\n  const allGeneratedIds = new Set<string>();\n  for (const ids of generatedFrom.values()) {\n    for (const id of ids) allGeneratedIds.add(id);\n  }\n\n  const extraFromLines: string[] = [];\n  for (const [mod, existIds] of existingFrom) {\n    const genIds = generatedFrom.get(mod);\n    if (!genIds) {\n      // The exact module isn't in the generated file — but check whether every\n      // identifier is already imported from a different (e.g., more-specific) module.\n      const extra = [...existIds].filter((id) => !allGeneratedIds.has(id));\n      if (extra.length > 0) {\n        extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n      }\n    } else {\n      const extra = [...existIds].filter((id) => !genIds.has(id) && !allGeneratedIds.has(id));\n      if (extra.length > 0) {\n        extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n      }\n    }\n  }\n\n  // TypeScript imports.\n  const existingTs = collectTsImports(existingOutsideIgnore);\n  const generatedTs = collectTsImports(resultLines);\n  const extraTsLines: string[] = [];\n\n  // Bindings the generated file imports anywhere, split by capability.\n  //\n  // `allGeneratedTsIds` — every binding regardless of module. The generator\n  // frequently imports a symbol from a concrete file\n  // (`./interfaces/connection.interface`) while the existing hand-written file\n  // imported the same symbol from a barrel (`./interfaces`). Splicing the\n  // barrel form back in would re-declare the binding (TS2300 duplicate\n  // identifier), so a symbol already in scope satisfies a *type* use and is\n  // never re-imported as a type even from a different specifier.\n  //\n  // `generatedValueIds` — only runtime-capable bindings (named / default /\n  // namespace, never `import type`). A *value* use is satisfied only by one of\n  // these: an `import type` binding is erased at compile time and cannot back a\n  // runtime reference inside a preserved region. So a generated `import type`\n  // must NOT suppress an existing value import of the same symbol.\n  const allGeneratedTsIds = new Set<string>();\n  const generatedValueIds = new Set<string>();\n  for (const ids of generatedTs.named.values())\n    for (const id of ids) {\n      allGeneratedTsIds.add(id);\n      generatedValueIds.add(id);\n    }\n  for (const ids of generatedTs.typeOnly.values()) for (const id of ids) allGeneratedTsIds.add(id);\n  for (const name of generatedTs.defaults.values()) {\n    allGeneratedTsIds.add(name);\n    generatedValueIds.add(name);\n  }\n  for (const name of generatedTs.namespaces.values()) {\n    allGeneratedTsIds.add(name);\n    generatedValueIds.add(name);\n  }\n\n  // Symbols the generated file imports type-only that we are nonetheless\n  // re-splicing as value imports (because a preserved region needs the runtime\n  // binding). The spliced value import also covers the type use, so the\n  // generated `import type` for the symbol must be dropped or the two collide\n  // (TS2300). Collected during the loops below, applied just before splicing.\n  const reclaimedValueIds = new Set<string>();\n  const generatedHasValue = (id: string): boolean => generatedValueIds.has(id);\n  const generatedHasTypeOnly = (id: string): boolean => allGeneratedTsIds.has(id) && !generatedValueIds.has(id);\n\n  for (const mod of existingTs.sideEffects) {\n    if (!generatedTs.sideEffects.has(mod)) extraTsLines.push(`import '${mod}';`);\n  }\n  for (const [mod, name] of existingTs.defaults) {\n    if (generatedTs.defaults.has(mod)) continue;\n    if (!identifierUsed(ignoreRegionText, name)) continue;\n    if (generatedHasValue(name)) continue;\n    if (generatedHasTypeOnly(name)) reclaimedValueIds.add(name);\n    extraTsLines.push(`import ${name} from '${mod}';`);\n  }\n  for (const [mod, name] of existingTs.namespaces) {\n    if (!identifierUsed(ignoreRegionText, name)) continue;\n    if (generatedHasValue(name)) continue;\n    if (generatedTs.namespaces.has(mod)) continue;\n    if (generatedHasTypeOnly(name)) reclaimedValueIds.add(name);\n    extraTsLines.push(`import * as ${name} from '${mod}';`);\n  }\n  for (const [mod, existIds] of existingTs.named) {\n    const extra = [...existIds].filter((id) => !generatedHasValue(id) && identifierUsed(ignoreRegionText, id));\n    for (const id of extra) if (generatedHasTypeOnly(id)) reclaimedValueIds.add(id);\n    if (extra.length > 0) extraTsLines.push(`import { ${extra.join(', ')} } from '${mod}';`);\n  }\n  for (const [mod, existIds] of existingTs.typeOnly) {\n    const extra = [...existIds].filter((id) => !allGeneratedTsIds.has(id) && identifierUsed(ignoreRegionText, id));\n    if (extra.length > 0) extraTsLines.push(`import type { ${extra.join(', ')} } from '${mod}';`);\n  }\n\n  // Drop reclaimed symbols from generated `import type` lines so the value\n  // imports spliced above do not duplicate them.\n  dropGeneratedTypeOnlyBindings(resultLines, reclaimedValueIds);\n\n  // PHP `use Foo\\Bar;` and `use Foo\\Bar as Baz;` — namespace-qualified only\n  // (a backslash anywhere in the path) so this doesn't mistakenly hoist\n  // single-segment in-class trait references like `use TraitName;`.\n  const isPhpUseImport = (l: string) => /^use\\s+[\\w\\\\]+\\\\[\\w\\\\]*(\\s+as\\s+\\w+)?\\s*;?$/.test(l);\n  const existingPhpUse = new Set(existingOutsideIgnore.filter(isPhpUseImport).map((l) => l.trim()));\n  const generatedPhpUse = new Set(resultLines.filter(isPhpUseImport).map((l) => l.trim()));\n  const extraPhpUse = [...existingPhpUse].filter((l) => !generatedPhpUse.has(l));\n\n  // Ruby `require '...'` and `require_relative '...'`. Dedupe by (kind, path)\n  // so quote style differs without producing duplicates — e.g. when the\n  // emitter writes `require 'json'` but a Ruby formatter has rewritten the\n  // on-disk copy to `require \"json\"`.\n  const rubyRequireRe = /^(require(?:_relative)?)\\s+['\"]([^'\"]+)['\"]\\s*$/;\n  const rubyRequireKey = (l: string): string | undefined => {\n    const m = l.trim().match(rubyRequireRe);\n    return m ? `${m[1]}\\t${m[2]}` : undefined;\n  };\n  const generatedRubyRequireKeys = new Set<string>();\n  for (const l of resultLines) {\n    const key = rubyRequireKey(l);\n    if (key) generatedRubyRequireKeys.add(key);\n  }\n  const seenExistingKeys = new Set<string>();\n  const extraRubyRequire: string[] = [];\n  for (const l of existingOutsideIgnore) {\n    const key = rubyRequireKey(l);\n    if (!key) continue;\n    if (generatedRubyRequireKeys.has(key)) continue;\n    if (seenExistingKeys.has(key)) continue;\n    seenExistingKeys.add(key);\n    extraRubyRequire.push(l.trim());\n  }\n\n  const allExtra = [...extraSimple, ...extraFromLines, ...extraTsLines, ...extraPhpUse, ...extraRubyRequire];\n  if (allExtra.length === 0) return;\n\n  // Find last import line in resultLines (accounting for multiline imports).\n  // Recognizes Python (`from X import Y`, `import X`), TS (`import …`), PHP\n  // (`use …`), and Ruby (`require`, `require_relative`).\n  const isImportStart = (l: string) =>\n    /^\\s*import(\\s|$)/.test(l) ||\n    /^from\\s+/.test(l) ||\n    /^\\s*use\\s+[\\w\\\\]/.test(l) ||\n    /^\\s*require(_relative)?\\s+['\"]/.test(l);\n  let lastImportIdx = -1;\n  for (let i = 0; i < resultLines.length; i++) {\n    if (!isImportStart(resultLines[i])) continue;\n    lastImportIdx = i;\n    const opens = (resultLines[i].match(/[({]/g) ?? []).length;\n    const closes = (resultLines[i].match(/[)}]/g) ?? []).length;\n    if (opens > closes) {\n      while (i + 1 < resultLines.length) {\n        i++;\n        lastImportIdx = i;\n        if ((resultLines[i].match(/[)}]/g) ?? []).length > 0) break;\n      }\n    }\n  }\n\n  if (lastImportIdx >= 0) {\n    resultLines.splice(lastImportIdx + 1, 0, ...allExtra);\n    return;\n  }\n\n  // No import survived in the generated file (e.g. its only import was a\n  // type-only line reclaimed above). Insert after any leading comment header\n  // so the spliced imports still land at the top of the file.\n  let insertAt = 0;\n  let inBlockComment = false;\n  for (let i = 0; i < resultLines.length; i++) {\n    const t = resultLines[i].trim();\n    if (inBlockComment) {\n      insertAt = i + 1;\n      if (t.includes('*/')) inBlockComment = false;\n      continue;\n    }\n    if (t.startsWith('//')) {\n      insertAt = i + 1;\n      continue;\n    }\n    if (t.startsWith('/*')) {\n      insertAt = i + 1;\n      inBlockComment = !t.includes('*/');\n      continue;\n    }\n    break; // first blank or code line — stop here\n  }\n  resultLines.splice(insertAt, 0, ...allExtra);\n}\n","import type { ApiSpec, Model, TypeRef, Service } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport type { Emitter, EmitterContext, GeneratedFile, OperationsMap } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { toSnakeCase } from '../utils/naming.js';\n\nexport function buildEmitterContext(\n  spec: ApiSpec,\n  options: {\n    namespace: string;\n    outputDir: string;\n    apiSurface?: ApiSurface;\n    overlayLookup?: OverlayLookup;\n    operationHints?: Record<string, OperationHint>;\n    mountRules?: Record<string, string>;\n    modelHints?: Record<string, string>;\n    emitterOptions?: Record<string, unknown>;\n    target?: string;\n    priorTargetManifestPaths?: Set<string>;\n    scopedServices?: Set<string>;\n  },\n): EmitterContext {\n  const resolvedOperations = resolveOperations(spec, options.operationHints, options.mountRules);\n\n  // In a scoped run, derive the model/enum allow-lists = names reachable\n  // from the SELECTED source services (those whose post-mount target is selected).\n  // Emitters write a model/enum FILE only when it is in these sets, so a\n  // non-selected service's exclusive models are left untouched (no leak) while\n  // shared models reachable from the selection still emit. Barrels stay full.\n  let scopedModelNames: Set<string> | undefined;\n  let scopedEnumNames: Set<string> | undefined;\n  if (options.scopedServices && options.scopedServices.size > 0) {\n    const selected = options.scopedServices;\n    const selectedSourceServices = spec.services.filter((s) =>\n      resolvedOperations.some((r) => r.service.name === s.name && selected.has(r.mountOn)),\n    );\n    const reachable = collectReferencedNames(selectedSourceServices, spec.models, { preserveAllDiscriminated: false });\n    scopedModelNames = reachable.models;\n    scopedEnumNames = reachable.enums;\n  }\n\n  return {\n    namespace: toSnakeCase(options.namespace),\n    namespacePascal: options.namespace,\n    spec,\n    outputDir: options.outputDir,\n    apiSurface: options.apiSurface,\n    overlayLookup: options.overlayLookup,\n    resolvedOperations,\n    modelHints: options.modelHints,\n    emitterOptions: options.emitterOptions,\n    targetDir: options.target,\n    priorTargetManifestPaths: options.priorTargetManifestPaths,\n    scopedServices: options.scopedServices,\n    scopedModelNames,\n    scopedEnumNames,\n  };\n}\n\n/**\n * Collect model and enum names transitively referenced by service operations.\n * Walks operation parameters, request bodies, responses, and pagination item\n * types, then chases model field references until the set stabilizes.\n */\nexport function collectReferencedNames(\n  services: Service[],\n  models: Model[],\n  opts: { preserveAllDiscriminated?: boolean } = {},\n): { models: Set<string>; enums: Set<string> } {\n  // Default: preserve EVERY discriminated/event model as public surface (full\n  // emission). Strict mode (`preserveAllDiscriminated: false`, used to compute a\n  // scoped run's reachable set) skips that blanket and instead chases the mapping\n  // variants of discriminated models that are actually reached — so a scoped\n  // service doesn't pull in the entire unrelated event tree.\n  const preserveAllDiscriminated = opts.preserveAllDiscriminated !== false;\n  const referencedModels = new Set<string>();\n  const referencedEnums = new Set<string>();\n\n  const collectFromTypeRef = (ref: TypeRef): void => {\n    walkTypeRef(ref, {\n      model: (r) => referencedModels.add(r.name),\n      enum: (r) => referencedEnums.add(r.name),\n    });\n  };\n\n  // Seed: walk every operation's params, request body, response, errors, and pagination\n  for (const service of services) {\n    for (const op of service.operations) {\n      for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n        collectFromTypeRef(p.type);\n      }\n      if (op.requestBody) collectFromTypeRef(op.requestBody);\n      collectFromTypeRef(op.response);\n      if (op.pagination) collectFromTypeRef(op.pagination.itemType);\n      for (const err of op.errors) {\n        if (err.type) collectFromTypeRef(err.type);\n      }\n      if (op.successResponses) {\n        for (const sr of op.successResponses) {\n          collectFromTypeRef(sr.type);\n        }\n      }\n    }\n  }\n\n  // Preserve discriminated models as public SDK types even when no operation\n  // returns them directly. This matters for event/webhook unions where the base\n  // operation references a generic envelope but the variant structs are still\n  // useful public surface.\n  //\n  // Also preserve the variants mapped from an `allOf [base, oneOf […]]` base\n  // (carried as `Model.discriminator.mapping`). The base model is reached\n  // through the operation; without explicitly chasing its mapping, the\n  // variant structs would be unreachable and the dispatcher would dangle\n  // imports.\n  if (preserveAllDiscriminated) {\n    for (const model of models) {\n      if (isDiscriminatedModel(model)) {\n        referencedModels.add(model.name);\n      }\n      const disc = model.discriminator;\n      if (disc?.mapping) {\n        for (const variantName of Object.values(disc.mapping)) {\n          referencedModels.add(variantName);\n        }\n      }\n    }\n  }\n\n  // Chase: transitively resolve model field references until stable\n  const modelsByName = new Map(models.map((m) => [m.name, m]));\n  const visited = new Set<string>();\n  const queue = [...referencedModels];\n  while (queue.length > 0) {\n    const name = queue.pop()!;\n    if (visited.has(name)) continue;\n    visited.add(name);\n    const model = modelsByName.get(name);\n    if (!model) continue;\n    // A reached discriminated base pulls in its mapping variants (the dispatcher\n    // would otherwise dangle). In full mode this is redundant with the blanket\n    // pass above; in strict mode it is the only path that includes variants.\n    const disc = model.discriminator;\n    if (disc?.mapping) {\n      for (const variantName of Object.values(disc.mapping)) {\n        if (!referencedModels.has(variantName)) {\n          referencedModels.add(variantName);\n          queue.push(variantName);\n        }\n      }\n    }\n    for (const field of model.fields) {\n      collectFromTypeRef(field.type);\n      // If new models were discovered, enqueue them\n      for (const m of referencedModels) {\n        if (!visited.has(m)) queue.push(m);\n      }\n    }\n  }\n\n  return { models: referencedModels, enums: referencedEnums };\n}\n\nfunction isDiscriminatedModel(model: Model): boolean {\n  return model.fields.some(\n    (field) =>\n      (field.name === 'event' || field.name === 'type' || field.name === 'object') && field.type.kind === 'literal',\n  );\n}\n\n/**\n * Collect all generated files from an emitter (no headers, no path prefixes).\n *\n * In a scoped (`--services`) run the spec is NOT filtered: every generator runs\n * over the full spec so model placement, dedup, the root client, and all\n * aggregate/barrel files are byte-identical to a full run (and a brand-new\n * selected service is wired into the client automatically). The emitters\n * themselves consult `ctx.scopedServices` to emit only the selected services'\n * per-service resource/test files.\n */\nexport function generateAllFiles(spec: ApiSpec, emitter: Emitter, ctx: EmitterContext): GeneratedFile[] {\n  const referenced = collectReferencedNames(spec.services, spec.models);\n  const reachableModels = spec.models.filter((m) => referenced.models.has(m.name));\n  const reachableEnums = spec.enums.filter((e) => referenced.enums.has(e.name));\n  const reachableSpec: ApiSpec = { ...spec, models: reachableModels, enums: reachableEnums };\n\n  return [\n    ...emitter.generateModels(reachableModels, ctx),\n    ...emitter.generateEnums(reachableEnums, ctx),\n    ...emitter.generateResources(spec.services, ctx),\n    ...emitter.generateClient(spec, ctx),\n    ...emitter.generateErrors(ctx),\n    ...(emitter.generateTypeSignatures?.(reachableSpec, ctx) ?? []),\n    ...emitter.generateTests(reachableSpec, ctx),\n  ];\n}\n\n/** Apply file header to generated files, respecting headerPlacement and JSON files. */\nexport function applyFileHeaders(files: GeneratedFile[], header: string): GeneratedFile[] {\n  return files.map((f) => ({\n    ...f,\n    content:\n      !header || f.path.endsWith('.json') || f.headerPlacement === 'skip' ? f.content : header + '\\n\\n' + f.content,\n    skipIfExists: f.skipIfExists ?? false,\n  }));\n}\n\nexport function generateFiles(\n  spec: ApiSpec,\n  emitter: Emitter,\n  options: {\n    namespace: string;\n    outputDir: string;\n    apiSurface?: ApiSurface;\n    overlayLookup?: OverlayLookup;\n    operationHints?: Record<string, OperationHint>;\n    mountRules?: Record<string, string>;\n    modelHints?: Record<string, string>;\n    emitterOptions?: Record<string, unknown>;\n    target?: string;\n    priorTargetManifestPaths?: Set<string>;\n    /** Scoped-generation signal (POST-MOUNT names); set on ctx for emitters to gate per-service emission. */\n    scopedServices?: Set<string>;\n  },\n): { files: GeneratedFile[]; ctx: EmitterContext; header: string; operations?: OperationsMap } {\n  const ctx = buildEmitterContext(spec, options);\n  const files = generateAllFiles(spec, emitter, ctx);\n  const operations = emitter.buildOperationsMap?.(spec, ctx);\n  const header = emitter.fileHeader();\n  return { files: applyFileHeaders(files, header), ctx, header, operations };\n}\n","import type { ApiSpec } from '../ir/types.js';\n\n/**\n * Validate a `--services` selection and return it as a set of POST-MOUNT service\n * names for emitters to scope on.\n *\n * Scoped generation does NOT filter the IR: model placement, dedup/aliasing, and\n * shared-schema decisions are global computations over the full service/model set\n * (filtering them churns shared `common/` files). Instead the full spec flows to\n * the emitters unchanged and this set is passed as `ctx.scopedServices`; each\n * emitter gates only its per-service resource/test emission on it.\n *\n * Matching is on the POST-MOUNT name. Mount resolution never mutates\n * `spec.services` — the post-mount target lives on `ResolvedOperation.mountOn`\n * (`mountOn = hint?.mountOn ?? mountRules[service.name] ?? service.name`) — so the\n * post-mount name of a source service is derived here as\n * `mountRules[service.name] ?? service.name`. Selecting a target (e.g.\n * `DirectorySync`) is valid because every source tag that mounts into it\n * (`DirectoryUsers`, `DirectoryGroups`, …) shares that post-mount name, and the\n * emitters group resources by mount, so all siblings emit together.\n *\n * @param spec - The parsed API spec (never mutated; never filtered).\n * @param selected - Post-mount service names from `--services` (normalized/trimmed).\n * @param mountRules - Source-service-name → post-mount-target mappings.\n * @returns The validated selection as a `Set` of post-mount names.\n * @throws A `ConfigError` listing valid post-mount names when a selection is\n *   unknown — scoped generation never silently emits the wrong set.\n */\nexport function resolveScopedServices(\n  spec: ApiSpec,\n  selected: string[],\n  mountRules?: Record<string, string>,\n): Set<string> {\n  const mounts = mountRules ?? {};\n  const postMountName = (name: string): string => mounts[name] ?? name;\n  const validPostMount = new Set(spec.services.map((s) => postMountName(s.name)));\n  const selectedSet = new Set(selected);\n\n  const unknown = [...selectedSet].filter((s) => !validPostMount.has(s));\n  if (unknown.length > 0) {\n    const err = new Error(\n      `Unknown --services: ${unknown.sort().join(', ')}. ` +\n        `Valid post-mount services: ${[...validPostMount].sort().join(', ')}`,\n    );\n    err.name = 'ConfigError';\n    throw err;\n  }\n\n  return selectedSet;\n}\n","import * as fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { writeFiles, type WriteResult } from './writer.js';\nimport { extractStatements } from './merger.js';\nimport { hasGrammar } from './merger.js';\n\n/**\n * Resolve a relative import path against a source file path to get the\n * target file path.  Handles implicit .ts extensions and /index.ts.\n */\nfunction resolveImportPath(\n  fromFilePath: string,\n  importModulePath: string,\n  knownPaths: Set<string>,\n): string | undefined {\n  // Strip quotes from module path key (tree-sitter keeps them)\n  const cleaned = importModulePath.replace(/^['\"]|['\"]$/g, '');\n  // Skip non-relative imports (node_modules, bare specifiers)\n  if (!cleaned.startsWith('.')) return undefined;\n\n  const dir = path.dirname(fromFilePath);\n  const resolved = path.normalize(path.join(dir, cleaned));\n\n  // Try exact match, .ts, /index.ts\n  for (const candidate of [resolved, `${resolved}.ts`, `${resolved}/index.ts`]) {\n    if (knownPaths.has(candidate)) return candidate;\n  }\n  return undefined;\n}\n\n/**\n * Determine whether a generated file is a \"root\" — a file that should always\n * be integrated into the target.  Roots are entry points from which we trace\n * the import graph.  Everything else must be reachable from a root.\n *\n * Roots: resource classes, client, config, errors, enums, barrel index files.\n * Non-roots: serializers, fixtures, standalone interfaces, test files.\n */\nfunction isRootFile(filePath: string): boolean {\n  // Fixtures are never roots (and should be filtered by integrateTarget already)\n  if (filePath.includes('/fixtures/')) return false;\n  // Test files are roots — they are standalone entry points that belong in the\n  // target repo even though nothing imports them.\n  if (filePath.endsWith('.spec.ts') || filePath.endsWith('.test.ts')) return true;\n  // Serializer files\n  if (filePath.includes('/serializers/')) return false;\n  // Standalone interface files (not barrel/index)\n  if (filePath.includes('/interfaces/') && !filePath.endsWith('/index.ts')) return false;\n  // Everything else is a root: resource classes, client, config, errors, enums, barrel files\n  return true;\n}\n\n/**\n * Build a file-level dependency graph from generated files and return only\n * files reachable from root entry points.  Uses tree-sitter to parse imports.\n */\nexport async function treeShakeFiles(files: GeneratedFile[], language: string): Promise<GeneratedFile[]> {\n  if (!hasGrammar(language)) return files;\n\n  const knownPaths = new Set(files.map((f) => f.path));\n\n  // Build dependency graph: file → set of files it imports\n  const deps = new Map<string, Set<string>>();\n  for (const file of files) {\n    // Only parse .ts/.js files (skip JSON, etc.)\n    if (!file.path.endsWith('.ts') && !file.path.endsWith('.js')) {\n      deps.set(file.path, new Set());\n      continue;\n    }\n    const parsed = await extractStatements(file.content, language);\n    const fileDeps = new Set<string>();\n    for (const imp of parsed.imports) {\n      const resolved = resolveImportPath(file.path, imp.key, knownPaths);\n      if (resolved) fileDeps.add(resolved);\n    }\n    // Also check re-export statements (export * from './foo')\n    for (const stmt of parsed.statements) {\n      if (stmt.kind === 'reexport') {\n        // Extract module path from \"export * from './foo'\" or \"export { X } from './foo'\"\n        const match = stmt.text.match(/from\\s+['\"]([^'\"]+)['\"]/);\n        if (match) {\n          const resolved = resolveImportPath(file.path, match[1], knownPaths);\n          if (resolved) fileDeps.add(resolved);\n        }\n      }\n    }\n    deps.set(file.path, fileDeps);\n  }\n\n  // Determine which file extensions are source code for this language\n  const codeExtensions = new Set([\n    '.ts',\n    '.js',\n    '.tsx',\n    '.jsx',\n    '.py',\n    '.rb',\n    '.go',\n    '.rs',\n    '.kt',\n    '.cs',\n    '.ex',\n    '.exs',\n    '.php',\n  ]);\n\n  // BFS from roots\n  const reachable = new Set<string>();\n  const queue: string[] = [];\n  for (const file of files) {\n    const ext = file.path.slice(file.path.lastIndexOf('.'));\n    // Non-code files (JSON, etc.) are always reachable — they can't participate\n    // in the import graph and are loaded at runtime (e.g. test fixtures).\n    if (!codeExtensions.has(ext)) {\n      reachable.add(file.path);\n      continue;\n    }\n    if (isRootFile(file.path)) {\n      reachable.add(file.path);\n      queue.push(file.path);\n    }\n  }\n  while (queue.length > 0) {\n    const current = queue.pop()!;\n    const fileDeps = deps.get(current);\n    if (!fileDeps) continue;\n    for (const dep of fileDeps) {\n      if (!reachable.has(dep)) {\n        reachable.add(dep);\n        queue.push(dep);\n      }\n    }\n  }\n\n  return files.filter((f) => reachable.has(f.path));\n}\n\nexport function mapFilesForTargetIntegration(files: GeneratedFile[], language: string): GeneratedFile[] {\n  const langPrefix = `${language}/`;\n  return files\n    .filter((f) => f.integrateTarget !== false) // integrateTarget: false files are standalone-only\n    .map((f) => {\n      const stripped = f.path.startsWith(langPrefix) ? f.path.replace(langPrefix, '') : f.path;\n      return {\n        ...f,\n        skipIfExists: false, // Always merge in target — never hard-skip\n        path: stripped,\n      };\n    });\n}\n\n/**\n * Resolve file-to-directory conflicts in the target.\n *\n * When a generated file creates a package directory (e.g., `api_keys/__init__.py`)\n * that would shadow an existing module file (e.g., `api_keys.py`), move the\n * module file's content into `_compat.py` inside the package and add a\n * re-export from `__init__.py`.  This preserves backward-compatible imports\n * (e.g., `from acme.api_keys import ApiKeysModule`) while the package directory\n * provides the generated models and resource classes.\n */\nasync function resolveFileToDirectoryConflicts(\n  files: GeneratedFile[],\n  targetDir: string,\n): Promise<{ files: GeneratedFile[]; removals: string[] }> {\n  const result = [...files];\n  const removals: string[] = [];\n\n  for (let i = 0; i < result.length; i++) {\n    const file = result[i];\n    // Match package init files: e.g., src/acme/api_keys/__init__.py\n    const match = file.path.match(/^(.+)\\/__init__\\.py$/);\n    if (!match) continue;\n\n    const dirPath = match[1]; // e.g., src/acme/api_keys\n    const moduleFilePath = `${dirPath}.py`; // e.g., src/acme/api_keys.py\n    const fullModulePath = path.join(targetDir, moduleFilePath);\n\n    let moduleContent: string;\n    try {\n      moduleContent = await fs.readFile(fullModulePath, 'utf-8');\n    } catch {\n      continue; // Module file doesn't exist — no conflict\n    }\n\n    // Create a compat shim inside the package with the old module's content\n    const compatPath = `${dirPath}/_compat.py`;\n    result.push({\n      path: compatPath,\n      content: moduleContent,\n      overwriteExisting: true,\n    });\n\n    // Append re-export from _compat to __init__.py so existing imports work.\n    // Compat must come AFTER generated models so hand-written types take\n    // precedence over generated types with the same name.\n    const compatImport = 'from ._compat import *  # noqa: F401,F403  # pyright: ignore[reportUnusedImport]';\n    const existingContent = file.content.endsWith('\\n') ? file.content : file.content + '\\n';\n    result[i] = {\n      ...file,\n      content: existingContent + compatImport + '\\n',\n    };\n\n    // Schedule the shadowed module file for removal\n    removals.push(fullModulePath);\n  }\n\n  return { files: result, removals };\n}\n\nexport interface IntegrateResult extends WriteResult {\n  /** Final set of paths this run claims ownership of in the target (post tree-shake + conflict resolution). */\n  emittedPaths: string[];\n}\n\nexport async function integrateGeneratedFiles(opts: {\n  files: GeneratedFile[];\n  language: string;\n  targetDir: string;\n  header: string;\n}): Promise<IntegrateResult> {\n  const mapped = mapFilesForTargetIntegration(opts.files, opts.language);\n  const shaken = await treeShakeFiles(mapped, opts.language);\n\n  // Handle file-to-directory conflicts before writing\n  const { files: resolved, removals } = await resolveFileToDirectoryConflicts(shaken, opts.targetDir);\n\n  const result = await writeFiles(resolved, opts.targetDir, {\n    language: opts.language,\n    header: opts.header,\n  });\n\n  // Remove shadowed module files after integration\n  for (const filePath of removals) {\n    try {\n      await fs.unlink(filePath);\n    } catch {\n      // File may already be gone\n    }\n  }\n\n  // The manifest tracks ALL files oagen owns, including tree-shaken ones.\n  // Tree-shaking decides what to write, but shaken files are still oagen-managed\n  // and must not be pruned from the target on subsequent runs.\n  return { ...result, emittedPaths: mapped.map((f) => f.path) };\n}\n","/**\n * Post-integration formatter.\n *\n * After generating and merging files into a target directory, runs the\n * emitter-provided format command on all written/merged files so that\n * generated code matches the target project's style conventions.\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport * as path from 'node:path';\nimport type { Emitter } from './types.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Run the emitter's format command on the given target files.\n * Silently skips if the emitter has no formatCommand or returns null.\n */\nexport async function formatTargetFiles(emitter: Emitter, targetDir: string, filePaths: string[]): Promise<void> {\n  if (filePaths.length === 0) return;\n  if (!emitter.formatCommand) return;\n\n  const formatCmd = emitter.formatCommand(targetDir);\n  if (!formatCmd) return;\n\n  const absolutePaths = filePaths.map((f) => path.resolve(targetDir, f));\n  const batchSize = formatCmd.batchSize ?? 100;\n\n  process.stderr.write(\n    `[oagen] formatting ${absolutePaths.length} file(s) with ${formatCmd.cmd} (batch ${batchSize})\\n`,\n  );\n\n  for (let i = 0; i < absolutePaths.length; i += batchSize) {\n    const batch = absolutePaths.slice(i, i + batchSize);\n    try {\n      await execFileAsync(formatCmd.cmd, [...formatCmd.args, ...batch], {\n        cwd: targetDir,\n        maxBuffer: 10 * 1024 * 1024,\n        timeout: 120_000,\n      });\n    } catch (err) {\n      // Formatter failed on this batch — continue with remaining batches.\n      // Surface the failure on stderr so misconfigured commands don't silently\n      // leave generated code unformatted every regen.\n      const msg = err instanceof Error ? err.message : String(err);\n      process.stderr.write(`[oagen] formatter batch failed: ${msg}\\n`);\n    }\n  }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n/**\n * Prune-manifest support for `oagen generate`.\n *\n * The manifest records every auto-generated file emitted on the previous run,\n * relative to the directory it lives in (either the `--output` standalone dir\n * or the `--target` integration dir).  On the next run we diff the previous\n * list against the current emission set and delete anything that's no longer\n * produced — preventing stale-file accumulation across regens.\n *\n * Design notes:\n *  - The manifest is versioned so future format changes can be handled safely.\n *  - Paths are stored sorted for deterministic diffs in git.\n *  - Deletion is gated on a header guard when one is available: we only remove\n *    files whose contents start with the auto-generated header.  This protects\n *    a hand-maintained file that happens to share a name with a previously\n *    generated one (extremely rare, but worth catching).\n *  - On first adoption (no previous manifest), pruning is skipped and a\n *    one-line notice is printed — no surprise deletions.\n */\n\nexport const MANIFEST_FILENAME = '.oagen-manifest.json';\nconst MANIFEST_VERSION = 2;\n\nexport interface Manifest {\n  /** Schema version.  Bump when the format changes incompatibly. */\n  version: number;\n  /** Emitter language (e.g. \"python\").  Used only as a consistency hint. */\n  language: string;\n  /** Human-readable or package-level SDK identity (e.g. \"acme-php\"). */\n  sdkName?: string;\n  /** ISO-8601 timestamp of the run that produced the current manifest contents. */\n  generatedAt: string;\n  /** SHA-256 hash of the source OpenAPI spec used for generation. */\n  specSha?: string;\n  /** Path or reference to the source spec. */\n  specPath?: string;\n  /** Git SHA or version of the emitter code used. */\n  emitterSha?: string;\n  /** Emitter version string if available. */\n  emitterVersion?: string;\n  /** SHA-256 hash of the effective oagen.config.ts after resolution. */\n  configSha?: string;\n  /** Version of the compat snapshot/report schema expected by this generation. */\n  compatSchemaVersion?: string;\n  /** Sorted list of paths, relative to the manifest's containing directory. */\n  files: string[];\n  /** Maps \"METHOD /path\" to SDK method + service property name. */\n  operations?: Record<string, unknown>;\n}\n\nexport interface PruneResult {\n  /** Paths actually deleted. */\n  pruned: string[];\n  /** Paths skipped because the header guard didn't match (preserved). */\n  preserved: string[];\n  /** Paths already absent on disk (nothing to do). */\n  missing: string[];\n}\n\n/** Read `.oagen-manifest.json` from a directory.  Returns null if absent or malformed. */\nexport async function readManifest(dir: string): Promise<Manifest | null> {\n  const manifestPath = path.join(dir, MANIFEST_FILENAME);\n  let raw: string;\n  try {\n    raw = await fs.readFile(manifestPath, 'utf-8');\n  } catch {\n    return null;\n  }\n  try {\n    const parsed = JSON.parse(raw) as Partial<Manifest>;\n    if (\n      typeof parsed.version !== 'number' ||\n      typeof parsed.language !== 'string' ||\n      typeof parsed.generatedAt !== 'string' ||\n      !Array.isArray(parsed.files) ||\n      !parsed.files.every((p): p is string => typeof p === 'string')\n    ) {\n      return null;\n    }\n    if (parsed.version > MANIFEST_VERSION) {\n      console.warn(\n        `[oagen] ${MANIFEST_FILENAME} schema version ${parsed.version} is newer than supported (${MANIFEST_VERSION}); ignoring for pruning.`,\n      );\n      return null;\n    }\n    // v1 manifests are forward-compatible — new fields are simply absent\n    return parsed as Manifest;\n  } catch {\n    return null;\n  }\n}\n\n/** Options for writing a manifest. */\nexport interface WriteManifestOpts {\n  language: string;\n  files: Iterable<string>;\n  sdkName?: string;\n  specSha?: string;\n  specPath?: string;\n  emitterSha?: string;\n  emitterVersion?: string;\n  configSha?: string;\n  compatSchemaVersion?: string;\n  operations?: Record<string, unknown>;\n}\n\n/** Write `.oagen-manifest.json` to a directory with sorted paths. */\nexport async function writeManifest(dir: string, opts: WriteManifestOpts): Promise<void> {\n  const manifestPath = path.join(dir, MANIFEST_FILENAME);\n  const manifest: Manifest = {\n    version: MANIFEST_VERSION,\n    language: opts.language,\n    ...(opts.sdkName !== undefined ? { sdkName: opts.sdkName } : {}),\n    generatedAt: new Date().toISOString(),\n    ...(opts.specSha !== undefined ? { specSha: opts.specSha } : {}),\n    ...(opts.specPath !== undefined ? { specPath: opts.specPath } : {}),\n    ...(opts.emitterSha !== undefined ? { emitterSha: opts.emitterSha } : {}),\n    ...(opts.emitterVersion !== undefined ? { emitterVersion: opts.emitterVersion } : {}),\n    ...(opts.configSha !== undefined ? { configSha: opts.configSha } : {}),\n    ...(opts.compatSchemaVersion !== undefined ? { compatSchemaVersion: opts.compatSchemaVersion } : {}),\n    files: [...new Set(opts.files)].sort(),\n    ...(opts.operations !== undefined ? { operations: opts.operations } : {}),\n  };\n  const previous = await readManifest(dir);\n  if (previous && sameManifestExceptGeneratedAt(previous, manifest)) {\n    manifest.generatedAt = previous.generatedAt;\n  }\n  await fs.mkdir(dir, { recursive: true });\n  await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8');\n}\n\nfunction sameManifestExceptGeneratedAt(a: Manifest, b: Manifest): boolean {\n  const { generatedAt: _aGeneratedAt, ...aComparable } = a;\n  const { generatedAt: _bGeneratedAt, ...bComparable } = b;\n  return JSON.stringify(aComparable) === JSON.stringify(bComparable);\n}\n\n/** Return the set of previous paths no longer present in the current emission. */\nexport function computeStalePaths(prev: Manifest, currentPaths: Iterable<string>): string[] {\n  const current = new Set(currentPaths);\n  return prev.files.filter((p) => !current.has(p)).sort();\n}\n\n/**\n * Merge a scoped run's emitted records into the prior manifest's records.\n *\n * A scoped (`--services`) run only emits files for the selected services, but it\n * must NOT discard the prior manifest's record of unselected services' files\n * records. The result unions prior + scoped file paths and shallow-merges the\n * operations maps, with scoped operations overriding prior entries for the same\n * \"METHOD /path\" key (a re-emission updates that operation's record).\n *\n * When `prev` is null (the first-ever run is scoped) there is nothing to\n * preserve, so the scoped subset is returned unchanged — matching the\n * first-adoption behavior of a full run.\n */\nexport function mergeScopedManifestRecords(\n  prev: Manifest | null,\n  scopedFiles: Iterable<string>,\n  scopedOperations?: Record<string, unknown>,\n): { files: string[]; operations?: Record<string, unknown> } {\n  const scopedFileList = [...scopedFiles];\n  if (!prev) {\n    return { files: scopedFileList, operations: scopedOperations };\n  }\n  const files = [...new Set([...prev.files, ...scopedFileList])].sort();\n  const priorOps = prev.operations;\n  const operations = priorOps || scopedOperations ? { ...priorOps, ...scopedOperations } : undefined;\n  return { files, operations };\n}\n\n/**\n * Delete stale files from `dir`.\n *\n * When `header` is provided, a file is only deleted if its contents start with\n * that header — so hand-maintained files that somehow collide with a previously\n * generated path can't be clobbered.  When `header` is omitted, the guard is\n * skipped (useful for non-source artifacts like fixture JSON).\n *\n * Returns lists for reporting.  Empty parent directories are removed after\n * deletion, up to (but not including) `dir` itself.\n */\nexport async function pruneStaleFiles(\n  dir: string,\n  paths: string[],\n  opts: { header?: string } = {},\n): Promise<PruneResult> {\n  const pruned: string[] = [];\n  const preserved: string[] = [];\n  const missing: string[] = [];\n\n  for (const relPath of paths) {\n    const fullPath = path.join(dir, relPath);\n    let content: string;\n    try {\n      content = await fs.readFile(fullPath, 'utf-8');\n    } catch {\n      missing.push(relPath);\n      continue;\n    }\n    if (opts.header && !content.startsWith(opts.header)) {\n      preserved.push(relPath);\n      continue;\n    }\n    try {\n      await fs.unlink(fullPath);\n      pruned.push(relPath);\n    } catch {\n      // Racing deletion or permission issue — treat as missing rather than fatal.\n      missing.push(relPath);\n      continue;\n    }\n    await removeEmptyParents(path.dirname(fullPath), dir);\n  }\n\n  return { pruned, preserved, missing };\n}\n\n/**\n * Walk up from `startDir` removing empty directories until we hit `stopDir`\n * (exclusive) or a non-empty directory.  Silently ignores errors.\n */\nasync function removeEmptyParents(startDir: string, stopDir: string): Promise<void> {\n  let current = path.resolve(startDir);\n  const stop = path.resolve(stopDir);\n  while (current.startsWith(stop + path.sep) && current !== stop) {\n    let entries: string[];\n    try {\n      entries = await fs.readdir(current);\n    } catch {\n      return;\n    }\n    if (entries.length > 0) return;\n    try {\n      await fs.rmdir(current);\n    } catch {\n      return;\n    }\n    current = path.dirname(current);\n  }\n}\n","import type { ApiSpec } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Emitter, GeneratedFile } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { writeFiles } from './writer.js';\nimport { generateFiles } from './generate-files.js';\nimport { resolveScopedServices } from './scoped-services.js';\nimport { integrateGeneratedFiles } from './integrate.js';\nimport { formatTargetFiles } from './formatter.js';\nimport {\n  computeStalePaths,\n  MANIFEST_FILENAME,\n  mergeScopedManifestRecords,\n  pruneStaleFiles,\n  readManifest,\n  writeManifest,\n} from './manifest.js';\n\nexport async function generate(\n  spec: ApiSpec,\n  emitter: Emitter,\n  options: {\n    namespace: string;\n    dryRun?: boolean;\n    outputDir: string;\n    target?: string;\n    apiSurface?: ApiSurface;\n    overlayLookup?: OverlayLookup;\n    operationHints?: Record<string, OperationHint>;\n    mountRules?: Record<string, string>;\n    modelHints?: Record<string, string>;\n    emitterOptions?: Record<string, unknown>;\n    /** When true, skip deletion of files recorded in the previous manifest but not in the current emission. */\n    noPrune?: boolean;\n    /**\n     * Post-mount service names to generate (a `--services` run). When non-empty,\n     * the FULL spec is still emitted for models/enums/client/barrels (so shared\n     * files stay byte-identical and a brand-new selected service is wired into the\n     * client automatically); only per-service resource/test emission is gated to\n     * the selection (via `ctx.scopedServices`). Pruning is disabled and the\n     * manifest is merged so unselected services' records survive.\n     */\n    services?: string[];\n  },\n): Promise<GeneratedFile[]> {\n  // Scoped generation: validate + expand the selection to POST-MOUNT names. The\n  // spec is NOT filtered — placement/dedup/shared-schemas are computed over the\n  // full spec so shared files stay byte-identical; emitters gate only per-service\n  // resource/test emission on this set.\n  const scopedServices =\n    options.services && options.services.length > 0\n      ? resolveScopedServices(spec, options.services, options.mountRules)\n      : undefined;\n  const scoped = scopedServices !== undefined;\n  // Scoped mode implies no-prune so unselected services' files survive.\n  const noPrune = options.noPrune === true || scoped;\n\n  // Read previous manifests up front so emitters can mark files the prior run\n  // wrote as safe-to-overwrite (vs files a human hand-maintains), and so scoped\n  // runs can merge prior records. Skipped only when --no-prune is set on a\n  // non-scoped run (opting out of lifecycle tracking). Scoped runs always read,\n  // even though they force no-prune, because the merge needs the prior records.\n  const skipManifestRead = options.noPrune === true && !scoped;\n  const outputPrevManifestForCtx = skipManifestRead ? null : await readManifest(options.outputDir);\n  const targetManifestForCtx = options.target && !skipManifestRead ? await readManifest(options.target) : null;\n  const priorTargetManifestPaths = targetManifestForCtx\n    ? new Set(targetManifestForCtx.files)\n    : outputPrevManifestForCtx\n      ? new Set(outputPrevManifestForCtx.files)\n      : undefined;\n\n  const {\n    files: withHeaders,\n    header,\n    operations,\n  } = generateFiles(spec, emitter, {\n    ...options,\n    priorTargetManifestPaths,\n    scopedServices,\n  });\n\n  if (options.dryRun) {\n    if (options.target) {\n      console.log(`\\nTarget integration (${options.target}):`);\n      for (const f of withHeaders) {\n        console.log(`  ${f.path}`);\n      }\n    }\n    return withHeaders;\n  }\n\n  // Reuse the manifest read before generation; nothing above writes it.\n  const outputPrevManifest = outputPrevManifestForCtx;\n\n  const writeResult = await writeFiles(withHeaders, options.outputDir, {\n    language: emitter.language,\n    header,\n  });\n\n  if (writeResult.merged.length > 0) {\n    console.log(`Merged into ${writeResult.merged.length} existing files (additive only)`);\n  }\n  if (writeResult.ignored.length > 0) {\n    console.log(`Ignored ${writeResult.ignored.length} files (@oagen-ignore-file)`);\n  }\n\n  const outputEmittedPaths = withHeaders.map((f) => f.path);\n  await applyManifestPrune({\n    dir: options.outputDir,\n    label: 'Output',\n    prevManifest: outputPrevManifest,\n    currentPaths: outputEmittedPaths,\n    language: emitter.language,\n    header,\n    noPrune,\n    operations,\n    scoped,\n  });\n\n  // Format output files so the emitter's formatter runs even without --target.\n  const allOutputFiles = [...writeResult.written, ...writeResult.merged];\n  if (allOutputFiles.length > 0) {\n    await formatTargetFiles(emitter, options.outputDir, allOutputFiles);\n  }\n\n  // Target integration pass\n  if (options.target) {\n    // Reuse the manifest we already read to build the emitter context.  This\n    // is correct because nothing between the two reads writes the manifest.\n    const targetPrevManifest = targetManifestForCtx;\n\n    const targetResult = await integrateGeneratedFiles({\n      files: withHeaders,\n      language: emitter.language,\n      targetDir: options.target,\n      header,\n    });\n\n    if (targetResult.written.length > 0) {\n      console.log(`Target: created ${targetResult.written.length} new files`);\n    }\n    if (targetResult.merged.length > 0) {\n      console.log(`Target: merged into ${targetResult.merged.length} existing files (additive only)`);\n    }\n    if (targetResult.skipped.length > 0) {\n      console.log(`Target: skipped ${targetResult.skipped.length} files (excluded or no grammar)`);\n    }\n\n    await applyManifestPrune({\n      dir: options.target,\n      label: 'Target',\n      prevManifest: targetPrevManifest,\n      currentPaths: targetResult.emittedPaths,\n      language: emitter.language,\n      header,\n      noPrune,\n      operations,\n      scoped,\n    });\n\n    // Run the emitter's formatter on all written/merged/identical files\n    const allTargetFiles = [...targetResult.written, ...targetResult.merged, ...targetResult.identical];\n    if (allTargetFiles.length > 0) {\n      await formatTargetFiles(emitter, options.target, allTargetFiles);\n    }\n  }\n\n  return withHeaders;\n}\n\n/**\n * Prune files recorded in the previous manifest but absent from the current emission,\n * then write the fresh manifest.  Safe on first adoption (no previous manifest).\n */\nasync function applyManifestPrune(opts: {\n  dir: string;\n  label: string;\n  prevManifest: Awaited<ReturnType<typeof readManifest>>;\n  currentPaths: string[];\n  language: string;\n  header: string;\n  noPrune?: boolean;\n  operations?: Record<string, unknown>;\n  /** When true, union this scoped run's records with the prior manifest. */\n  scoped?: boolean;\n}): Promise<void> {\n  // A scoped run only emits the selected services' files, so the manifest is\n  // merged with the prior records rather than replaced — otherwise unselected\n  // services would be dropped from the manifest and mis-pruned on the next run.\n  const records = opts.scoped\n    ? mergeScopedManifestRecords(opts.prevManifest, opts.currentPaths, opts.operations)\n    : { files: opts.currentPaths, operations: opts.operations };\n  const manifestOpts = { language: opts.language, files: records.files, operations: records.operations };\n  if (opts.noPrune) {\n    // Still refresh the manifest so future runs with pruning enabled have a baseline.\n    await writeManifest(opts.dir, manifestOpts);\n    return;\n  }\n\n  if (!opts.prevManifest) {\n    console.log(\n      `${opts.label}: no ${MANIFEST_FILENAME} found — skipping prune (this baseline manifest will be written now).`,\n    );\n    await writeManifest(opts.dir, manifestOpts);\n    return;\n  }\n\n  const stale = computeStalePaths(opts.prevManifest, opts.currentPaths);\n  if (stale.length > 0) {\n    const { pruned, preserved } = await pruneStaleFiles(opts.dir, stale, { header: opts.header });\n    if (pruned.length > 0) {\n      console.log(`${opts.label}: pruned ${pruned.length} stale file${pruned.length === 1 ? '' : 's'}`);\n    }\n    if (preserved.length > 0) {\n      console.log(\n        `${opts.label}: preserved ${preserved.length} file${preserved.length === 1 ? '' : 's'} in previous manifest but lacking the auto-generated header (possibly hand-edited).`,\n      );\n      for (const p of preserved) console.log(`  ${p}`);\n    }\n  }\n\n  await writeManifest(opts.dir, manifestOpts);\n}\n","import { RegistryError } from '../errors.js';\nimport type { Emitter } from './types.js';\n\nconst emitters = new Map<string, Emitter>();\n\nexport function registerEmitter(emitter: Emitter): void {\n  emitters.set(emitter.language, emitter);\n}\n\nexport function getEmitter(language: string): Emitter {\n  const emitter = emitters.get(language);\n  if (!emitter) {\n    const available = [...emitters.keys()].join(', ') || '(none)';\n    throw new RegistryError(\n      `Unknown language: ${language}. Available: ${available}`,\n      `Register an emitter for \"${language}\" via registerEmitter() or check your oagen.config.ts plugin configuration.`,\n    );\n  }\n  return emitter;\n}\n","import type { FieldChange, ParamChange } from './types.js';\n\nexport function classifyFieldChange(kind: FieldChange['kind'], fieldName: string, isRequired?: boolean): FieldChange {\n  switch (kind) {\n    case 'field-added':\n      return {\n        kind,\n        fieldName,\n        classification: isRequired ? 'breaking' : 'additive',\n      };\n    case 'field-removed':\n      return { kind, fieldName, classification: 'breaking' };\n    case 'field-type-changed':\n      return { kind, fieldName, classification: 'breaking' };\n    case 'field-format-changed':\n      // A primitive's `format` changing (e.g., string → string format=email)\n      // is classified additive at the IR level: the wire-format base type is\n      // unchanged, so callers' deserialization keeps working. Per-emitter\n      // compat checks catch any source-level break a specific language layers\n      // on top (e.g., a typed Email value object in TypeScript).\n      return { kind, fieldName, classification: 'additive' };\n    case 'field-required-changed':\n      return {\n        kind,\n        fieldName,\n        classification: isRequired ? 'breaking' : 'additive',\n        details: isRequired ? 'optional → required' : 'required → optional',\n      };\n    case 'field-access-changed':\n      return { kind, fieldName, classification: 'breaking' };\n  }\n}\n\nexport function classifyParamChange(kind: ParamChange['kind'], paramName: string, isRequired?: boolean): ParamChange {\n  switch (kind) {\n    case 'param-added':\n      return {\n        kind,\n        paramName,\n        classification: isRequired ? 'breaking' : 'additive',\n      };\n    case 'param-removed':\n      return { kind, paramName, classification: 'breaking' };\n    case 'param-type-changed':\n      return { kind, paramName, classification: 'breaking' };\n    case 'param-format-changed':\n      // See `field-format-changed`: format-only diffs are additive at the IR\n      // layer.\n      return { kind, paramName, classification: 'additive' };\n    case 'param-required-changed':\n      return {\n        kind,\n        paramName,\n        classification: isRequired ? 'breaking' : 'additive',\n      };\n    case 'param-default-changed':\n      // Removing or changing a default that callers may have implicitly relied on\n      // changes runtime behavior for clients who never set the param explicitly.\n      // We treat this as breaking so it surfaces as a major bump rather than\n      // sliding through as a silent regression.\n      return { kind, paramName, classification: 'breaking' };\n  }\n}\n","import type { Model, TypeRef } from '../ir/types.js';\nimport { assertNever } from '../ir/types.js';\nimport type { Change, FieldChange } from './types.js';\nimport { classifyFieldChange } from './classify.js';\n\nexport function diffModels(oldModels: Model[], newModels: Model[]): Change[] {\n  const changes: Change[] = [];\n  const oldByName = new Map(oldModels.map((m) => [m.name, m]));\n  const newByName = new Map(newModels.map((m) => [m.name, m]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({ kind: 'model-added', name, classification: 'additive' });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({ kind: 'model-removed', name, classification: 'breaking' });\n    }\n  }\n\n  for (const [name, newModel] of newByName) {\n    const oldModel = oldByName.get(name);\n    if (!oldModel) continue;\n\n    const fieldChanges = diffFields(oldModel, newModel);\n    if (fieldChanges.length > 0) {\n      const hasBreaking = fieldChanges.some((fc) => fc.classification === 'breaking');\n      changes.push({\n        kind: 'model-modified',\n        name,\n        fieldChanges,\n        classification: hasBreaking ? 'breaking' : 'additive',\n      });\n    }\n  }\n\n  return changes;\n}\n\nfunction diffFields(oldModel: Model, newModel: Model): FieldChange[] {\n  const changes: FieldChange[] = [];\n  const oldByName = new Map(oldModel.fields.map((f) => [f.name, f]));\n  const newByName = new Map(newModel.fields.map((f) => [f.name, f]));\n\n  for (const [name, field] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push(classifyFieldChange('field-added', name, field.required));\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push(classifyFieldChange('field-removed', name));\n    }\n  }\n\n  for (const [name, newField] of newByName) {\n    const oldField = oldByName.get(name);\n    if (!oldField) continue;\n\n    if (!typeRefsEqual(oldField.type, newField.type)) {\n      if (primitivesDifferOnlyByFormat(oldField.type, newField.type)) {\n        changes.push({\n          ...classifyFieldChange('field-format-changed', name),\n          details: formatChangeDetails(oldField.type, newField.type),\n        });\n      } else {\n        changes.push({\n          kind: 'field-type-changed',\n          fieldName: name,\n          classification: 'breaking',\n          details: `type changed`,\n        });\n      }\n    }\n\n    if (oldField.required !== newField.required) {\n      changes.push(classifyFieldChange('field-required-changed', name, newField.required));\n    }\n\n    if (!!oldField.readOnly !== !!newField.readOnly || !!oldField.writeOnly !== !!newField.writeOnly) {\n      changes.push(classifyFieldChange('field-access-changed', name));\n    }\n  }\n\n  return changes;\n}\n\n/**\n * True when both refs are primitives with the same base `type` but different\n * `format`. Used to downgrade format-only diffs from breaking type changes to\n * additive `field-format-changed` / `param-format-changed` events: the wire\n * base type is unchanged, so the diff is a hint to language emitters rather\n * than a source-level break.\n */\nexport function primitivesDifferOnlyByFormat(a: TypeRef, b: TypeRef): boolean {\n  if (a.kind !== 'primitive' || b.kind !== 'primitive') return false;\n  if (a.type !== b.type) return false;\n  return (a.format ?? '') !== (b.format ?? '');\n}\n\nexport function formatChangeDetails(a: TypeRef, b: TypeRef): string {\n  const oldFmt = a.kind === 'primitive' ? a.format : undefined;\n  const newFmt = b.kind === 'primitive' ? b.format : undefined;\n  return `format ${oldFmt ?? '<unset>'} → ${newFmt ?? '<unset>'}`;\n}\n\nexport function typeRefsEqual(a: TypeRef, b: TypeRef): boolean {\n  if (a.kind !== b.kind) return false;\n\n  switch (a.kind) {\n    case 'primitive':\n      return b.kind === 'primitive' && a.type === b.type && (a.format ?? '') === ((b as typeof a).format ?? '');\n    case 'array':\n      return b.kind === 'array' && typeRefsEqual(a.items, b.items);\n    case 'model':\n      return b.kind === 'model' && a.name === b.name;\n    case 'enum':\n      return b.kind === 'enum' && a.name === b.name;\n    case 'literal':\n      return b.kind === 'literal' && a.value === b.value;\n    case 'nullable':\n      return b.kind === 'nullable' && typeRefsEqual(a.inner, b.inner);\n    case 'union': {\n      if (b.kind !== 'union') return false;\n      if (a.variants.length !== b.variants.length) return false;\n      if (!a.variants.every((v, i) => typeRefsEqual(v, b.variants[i]))) return false;\n      // Compare discriminator\n      if (!a.discriminator && !b.discriminator) return true;\n      if (!a.discriminator || !b.discriminator) return false;\n      if (a.discriminator.property !== b.discriminator.property) return false;\n      const aKeys = Object.keys(a.discriminator.mapping).sort();\n      const bKeys = Object.keys(b.discriminator.mapping).sort();\n      if (aKeys.length !== bKeys.length) return false;\n      return aKeys.every((k, i) => k === bKeys[i] && a.discriminator!.mapping[k] === b.discriminator!.mapping[k]);\n    }\n    case 'map':\n      return b.kind === 'map' && typeRefsEqual(a.valueType, b.valueType);\n  }\n  return assertNever(a);\n}\n","import type { ErrorResponse, Operation } from '../ir/types.js';\nimport type { Change, ParamChange } from './types.js';\nimport { classifyParamChange } from './classify.js';\nimport { formatChangeDetails, primitivesDifferOnlyByFormat, typeRefsEqual } from './models.js';\n\nexport function diffOperations(serviceName: string, oldOps: Operation[], newOps: Operation[]): Change[] {\n  const changes: Change[] = [];\n  const oldByName = new Map(oldOps.map((o) => [o.name, o]));\n  const newByName = new Map(newOps.map((o) => [o.name, o]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({\n        kind: 'operation-added',\n        serviceName,\n        operationName: name,\n        classification: 'additive',\n      });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({\n        kind: 'operation-removed',\n        serviceName,\n        operationName: name,\n        classification: 'breaking',\n      });\n    }\n  }\n\n  for (const [name, newOp] of newByName) {\n    const oldOp = oldByName.get(name);\n    if (!oldOp) continue;\n\n    const paramChanges = diffParams(oldOp, newOp);\n    const responseChanged = !typeRefsEqual(oldOp.response, newOp.response);\n    const requestBodyChanged = !requestBodiesEqual(oldOp.requestBody, newOp.requestBody);\n    const httpMethodChanged = oldOp.httpMethod !== newOp.httpMethod;\n    const pathChanged = oldOp.path !== newOp.path;\n    const paginatedChanged = !!oldOp.pagination !== !!newOp.pagination;\n    const injectIdempotencyKeyChanged = oldOp.injectIdempotencyKey !== newOp.injectIdempotencyKey;\n    const errorsDiff = classifyErrorsChange(oldOp.errors, newOp.errors);\n    const errorsChanged = errorsDiff !== 'none';\n\n    const hasChanges =\n      paramChanges.length > 0 ||\n      responseChanged ||\n      requestBodyChanged ||\n      httpMethodChanged ||\n      pathChanged ||\n      paginatedChanged ||\n      injectIdempotencyKeyChanged ||\n      errorsChanged;\n\n    if (hasChanges) {\n      // paginated: false→true is additive (SDK gains pagination helper)\n      // paginated: true→false is breaking (SDK loses pagination helper)\n      const paginatedBreaking = paginatedChanged && !newOp.pagination;\n      // injectIdempotencyKey: false→true is additive (SDK gains idempotency key)\n      // injectIdempotencyKey: true→false is breaking (SDK loses idempotency key)\n      const injectIdempotencyKeyBreaking = injectIdempotencyKeyChanged && !newOp.injectIdempotencyKey;\n      const errorsBreaking = errorsDiff === 'breaking';\n\n      const hasBreaking =\n        responseChanged ||\n        requestBodyChanged ||\n        httpMethodChanged ||\n        pathChanged ||\n        paginatedBreaking ||\n        injectIdempotencyKeyBreaking ||\n        errorsBreaking ||\n        paramChanges.some((pc) => pc.classification === 'breaking');\n      changes.push({\n        kind: 'operation-modified',\n        serviceName,\n        operationName: name,\n        paramChanges,\n        responseChanged,\n        requestBodyChanged,\n        httpMethodChanged,\n        pathChanged,\n        paginatedChanged,\n        injectIdempotencyKeyChanged,\n        errorsChanged,\n        classification: hasBreaking ? 'breaking' : 'additive',\n      });\n    }\n  }\n\n  return changes;\n}\n\nfunction requestBodiesEqual(a: Operation['requestBody'], b: Operation['requestBody']): boolean {\n  if (!a && !b) return true;\n  if (!a || !b) return false;\n  return typeRefsEqual(a, b);\n}\n\nfunction classifyErrorsChange(\n  oldErrors: ErrorResponse[],\n  newErrors: ErrorResponse[],\n): 'none' | 'additive' | 'breaking' {\n  const oldByCode = new Map(oldErrors.map((e) => [e.statusCode, e]));\n  const newByCode = new Map(newErrors.map((e) => [e.statusCode, e]));\n\n  let hasAdditive = false;\n  let hasBreaking = false;\n\n  // New error codes added → additive (SDK gains new error classes)\n  for (const code of newByCode.keys()) {\n    if (!oldByCode.has(code)) hasAdditive = true;\n  }\n\n  // Old error codes removed → breaking (SDK loses error classes)\n  for (const code of oldByCode.keys()) {\n    if (!newByCode.has(code)) hasBreaking = true;\n  }\n\n  // Shared error codes with changed types → breaking\n  for (const [code, newErr] of newByCode) {\n    const oldErr = oldByCode.get(code);\n    if (!oldErr) continue;\n    if (!oldErr.type && !newErr.type) continue;\n    if (!oldErr.type || !newErr.type || !typeRefsEqual(oldErr.type, newErr.type)) {\n      hasBreaking = true;\n    }\n  }\n\n  if (hasBreaking) return 'breaking';\n  if (hasAdditive) return 'additive';\n  return 'none';\n}\n\nfunction diffParams(oldOp: Operation, newOp: Operation): ParamChange[] {\n  const changes: ParamChange[] = [];\n  const tagged = (loc: 'path' | 'query' | 'header', params: typeof oldOp.queryParams) =>\n    params.map((p) => ({ p, loc }));\n  const allOldParams = [\n    ...tagged('path', oldOp.pathParams),\n    ...tagged('query', oldOp.queryParams),\n    ...tagged('header', oldOp.headerParams),\n  ];\n  const allNewParams = [\n    ...tagged('path', newOp.pathParams),\n    ...tagged('query', newOp.queryParams),\n    ...tagged('header', newOp.headerParams),\n  ];\n  const oldByName = new Map(allOldParams.map((e) => [e.p.name, e]));\n  const newByName = new Map(allNewParams.map((e) => [e.p.name, e]));\n\n  for (const [name, entry] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push(classifyParamChange('param-added', name, entry.p.required));\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push(classifyParamChange('param-removed', name));\n    }\n  }\n\n  for (const [name, newEntry] of newByName) {\n    const oldEntry = oldByName.get(name);\n    if (!oldEntry) continue;\n\n    if (!typeRefsEqual(oldEntry.p.type, newEntry.p.type)) {\n      if (primitivesDifferOnlyByFormat(oldEntry.p.type, newEntry.p.type)) {\n        const change = classifyParamChange('param-format-changed', name);\n        change.details = formatChangeDetails(oldEntry.p.type, newEntry.p.type);\n        changes.push(change);\n      } else {\n        changes.push(classifyParamChange('param-type-changed', name));\n      }\n    }\n\n    if (oldEntry.p.required !== newEntry.p.required) {\n      changes.push(classifyParamChange('param-required-changed', name, newEntry.p.required));\n    }\n\n    const oldDefault = serializeDefault(oldEntry.p.default);\n    const newDefault = serializeDefault(newEntry.p.default);\n    if (oldDefault !== newDefault) {\n      const change = classifyParamChange('param-default-changed', name);\n      change.oldDefault = oldDefault;\n      change.newDefault = newDefault;\n      change.paramLocation = newEntry.loc;\n      change.details = `default ${oldDefault ?? '<unset>'} → ${newDefault ?? '<unset>'}`;\n      changes.push(change);\n    }\n  }\n\n  return changes;\n}\n\nfunction serializeDefault(value: unknown): string | null {\n  if (value === undefined) return null;\n  if (value === null) return 'null';\n  if (typeof value === 'string') return value;\n  if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n  // Objects/arrays: stable JSON. Stringification of equal-valued objects is\n  // deterministic enough for this comparison since callers typically pass\n  // primitives; complex defaults are rare.\n  try {\n    return JSON.stringify(value);\n  } catch {\n    return String(value);\n  }\n}\n","import type { Service } from '../ir/types.js';\nimport type { Change } from './types.js';\nimport { diffOperations } from './operations.js';\n\nexport function diffServices(oldServices: Service[], newServices: Service[]): Change[] {\n  const changes: Change[] = [];\n  const oldByName = new Map(oldServices.map((s) => [s.name, s]));\n  const newByName = new Map(newServices.map((s) => [s.name, s]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({ kind: 'service-added', name, classification: 'additive' });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({ kind: 'service-removed', name, classification: 'breaking' });\n    }\n  }\n\n  for (const [name, newService] of newByName) {\n    const oldService = oldByName.get(name);\n    if (!oldService) continue;\n\n    changes.push(...diffOperations(name, oldService.operations, newService.operations));\n  }\n\n  return changes;\n}\n","import type { ApiSpec, Enum } from '../ir/types.js';\nimport type { BehaviorChange, Change, DiffReport, EnumValueChange } from './types.js';\nimport { diffModels } from './models.js';\nimport { diffServices } from './services.js';\n\nexport function diffSpecs(oldSpec: ApiSpec, newSpec: ApiSpec): DiffReport {\n  const changes: Change[] = [\n    ...diffModels(oldSpec.models, newSpec.models),\n    ...diffEnums(oldSpec.enums, newSpec.enums),\n    ...diffServices(oldSpec.services, newSpec.services),\n  ];\n\n  const behaviorChanges = collectBehaviorChanges(changes);\n\n  return {\n    oldVersion: oldSpec.version,\n    newVersion: newSpec.version,\n    changes,\n    behaviorChanges,\n    summary: { ...summarize(changes), behaviorChanges: behaviorChanges.length },\n  };\n}\n\nfunction collectBehaviorChanges(changes: Change[]): BehaviorChange[] {\n  const out: BehaviorChange[] = [];\n  for (const c of changes) {\n    if (c.kind !== 'operation-modified') continue;\n    for (const pc of c.paramChanges) {\n      if (pc.kind !== 'param-default-changed') continue;\n      out.push({\n        kind: 'param-default-changed',\n        serviceName: c.serviceName,\n        operationName: c.operationName,\n        paramName: pc.paramName,\n        paramLocation: pc.paramLocation ?? 'query',\n        oldDefault: pc.oldDefault ?? null,\n        newDefault: pc.newDefault ?? null,\n        classification: 'breaking',\n      });\n    }\n  }\n  return out;\n}\n\nfunction diffEnums(oldEnums: Enum[], newEnums: Enum[]): Change[] {\n  const changes: Change[] = [];\n  const oldByName = new Map(oldEnums.map((e) => [e.name, e]));\n  const newByName = new Map(newEnums.map((e) => [e.name, e]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({ kind: 'enum-added', name, classification: 'additive' });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({ kind: 'enum-removed', name, classification: 'breaking' });\n    }\n  }\n\n  for (const [name, newEnum] of newByName) {\n    const oldEnum = oldByName.get(name);\n    if (!oldEnum) continue;\n\n    const valueChanges = diffEnumValues(oldEnum, newEnum);\n    if (valueChanges.length > 0) {\n      const hasBreaking = valueChanges.some((vc) => vc.classification === 'breaking');\n      changes.push({\n        kind: 'enum-modified',\n        name,\n        valueChanges,\n        classification: hasBreaking ? 'breaking' : 'additive',\n      });\n    }\n  }\n\n  return changes;\n}\n\nfunction diffEnumValues(oldEnum: Enum, newEnum: Enum): EnumValueChange[] {\n  const changes: EnumValueChange[] = [];\n  const oldByName = new Map(oldEnum.values.map((v) => [v.name, v]));\n  const newByName = new Map(newEnum.values.map((v) => [v.name, v]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({ kind: 'value-added', valueName: name, classification: 'additive' });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({ kind: 'value-removed', valueName: name, classification: 'breaking' });\n    }\n  }\n\n  for (const [name, newVal] of newByName) {\n    const oldVal = oldByName.get(name);\n    if (!oldVal) continue;\n\n    if (oldVal.value !== newVal.value) {\n      changes.push({\n        kind: 'value-changed',\n        valueName: name,\n        classification: 'breaking',\n        details: `value changed from '${oldVal.value}' to '${newVal.value}'`,\n      });\n    }\n  }\n\n  return changes;\n}\n\nfunction summarize(changes: Change[]) {\n  let added = 0;\n  let removed = 0;\n  let modified = 0;\n  let breaking = 0;\n  let additive = 0;\n\n  for (const c of changes) {\n    if (c.kind.endsWith('-added')) added++;\n    else if (c.kind.endsWith('-removed')) removed++;\n    else if (c.kind.endsWith('-modified')) modified++;\n\n    if (c.classification === 'breaking') breaking++;\n    else additive++;\n  }\n\n  return { added, removed, modified, breaking, additive };\n}\n"],"mappings":"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"}