{"version":3,"file":"index.mjs","names":["parseMethods","parseProperties","extractNamespace","safeParse","DEFAULT_EXCEPTION_BASES","isExceptionClass","buildSurface","buildSurface","safeParse","buildSurface","buildSurface","safeParseWith","extractEnumModules","extractEnumModules","parseStructFields","extractPackageName","safeParse","buildSurface","buildSurface","parseEnums","parseTypeAliases","safeParse","buildSurface","buildSurface","stripComments","extractJsonPropertyName","parseClasses","parseMethods","buildSurface","buildSurface","buildSurface","buildSurface"],"sources":["../../src/compat/concepts.ts","../../src/compat/report.ts","../../src/compat/approvals.ts","../../src/compat/extractors/shared.ts","../../src/compat/extractors/node.ts","../../src/compat/extractors/php-parser.ts","../../src/compat/extractors/php-surface.ts","../../src/compat/extractors/php.ts","../../src/compat/extractors/python-parser.ts","../../src/compat/extractors/python-surface.ts","../../src/compat/extractors/python.ts","../../src/compat/extractors/ruby-parser.ts","../../src/compat/extractors/ruby.ts","../../src/compat/extractors/go-parser.ts","../../src/compat/extractors/go-surface.ts","../../src/compat/extractors/go.ts","../../src/compat/extractors/rust-parser.ts","../../src/compat/extractors/rust-surface.ts","../../src/compat/extractors/rust.ts","../../src/compat/extractors/kotlin-parser.ts","../../src/compat/extractors/kotlin-surface.ts","../../src/compat/extractors/kotlin.ts","../../src/compat/extractors/dotnet-parser.ts","../../src/compat/extractors/dotnet-surface.ts","../../src/compat/extractors/dotnet.ts","../../src/compat/extractors/elixir-parser.ts","../../src/compat/extractors/elixir-surface.ts","../../src/compat/extractors/elixir.ts"],"sourcesContent":["/**\n * Conceptual change grouping for cross-language compatibility analysis.\n *\n * Groups related changes across languages into a single conceptual change\n * with per-language severity. This allows reports to say \"parameter rename\n * on Authorization.check is breaking in PHP, Python, Kotlin, and .NET but\n * soft-risk in Go\" rather than treating these as unrelated per-language findings.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\n\n/** A conceptual change with per-language severity. */\nexport interface ConceptualChange {\n  /** Deterministic ID from symbol + category + match details. */\n  id: string;\n  /** IR-level symbol path (language-neutral). */\n  symbol: string;\n  /** The kind of change. */\n  category: CompatChangeCategory;\n  /** Per-language severity mapping. */\n  impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n  /** Human-readable description (from first language that reported it). */\n  message: string;\n  /** Old state details. */\n  old: Record<string, string>;\n  /** New state details. */\n  new: Record<string, string>;\n}\n\n/** Cross-language conceptual rollup. */\nexport interface ConceptualRollup {\n  conceptualChanges: ConceptualChange[];\n}\n\n/**\n * Group classified changes from multiple languages into conceptual changes.\n *\n * Changes are grouped by their `conceptualChangeId` — a deterministic ID\n * derived from the symbol, category, and match details. Changes with the\n * same ID across different languages represent the same conceptual change.\n */\nexport function buildConceptualRollup(\n  perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualRollup {\n  const grouped = new Map<string, ConceptualChange>();\n\n  for (const { diff: result, language } of perLanguageResults) {\n    for (const change of result.changes) {\n      const existing = grouped.get(change.conceptualChangeId);\n      if (existing) {\n        existing.impact[language] = change.severity;\n      } else {\n        grouped.set(change.conceptualChangeId, {\n          id: change.conceptualChangeId,\n          symbol: change.symbol,\n          category: change.category,\n          impact: { [language]: change.severity },\n          message: change.message,\n          old: change.old,\n          new: change.new,\n        });\n      }\n    }\n  }\n\n  return {\n    conceptualChanges: [...grouped.values()],\n  };\n}\n\n/** Get the highest severity across all languages for a conceptual change. */\nexport function highestSeverity(change: ConceptualChange): CompatChangeSeverity {\n  const severities = Object.values(change.impact);\n  if (severities.includes('breaking')) return 'breaking';\n  if (severities.includes('soft-risk')) return 'soft-risk';\n  return 'additive';\n}\n\n/** Count conceptual changes by highest severity. */\nexport function summarizeConceptualChanges(rollup: ConceptualRollup): {\n  breaking: number;\n  softRisk: number;\n  additive: number;\n} {\n  let breaking = 0;\n  let softRisk = 0;\n  let additive = 0;\n  for (const change of rollup.conceptualChanges) {\n    const sev = highestSeverity(change);\n    if (sev === 'breaking') breaking++;\n    else if (sev === 'soft-risk') softRisk++;\n    else additive++;\n  }\n  return { breaking, softRisk, additive };\n}\n","/**\n * Report generation for compatibility verification.\n *\n * Produces machine-readable JSON reports, human-readable terminal summaries,\n * and conceptual cross-language summaries.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory, CompatProvenance } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\nimport { buildConceptualRollup, highestSeverity, summarizeConceptualChanges } from './concepts.js';\n\n// ---------------------------------------------------------------------------\n// Machine-readable report\n// ---------------------------------------------------------------------------\n\n/** Machine-readable compat report for a single language. */\nexport interface CompatReport {\n  schemaVersion: string;\n  language: string;\n  summary: {\n    breaking: number;\n    softRisk: number;\n    additive: number;\n  };\n  changes: CompatReportChange[];\n}\n\n/** A single change entry in the machine-readable report. */\nexport interface CompatReportChange {\n  severity: CompatChangeSeverity;\n  category: CompatChangeCategory;\n  symbol: string;\n  conceptualChangeId: string;\n  provenance: CompatProvenance;\n  old: Record<string, string>;\n  new: Record<string, string>;\n  message?: string;\n  /** Spec-level remediation hint when a recognized upstream pattern was detected. */\n  remediation?: string;\n}\n\n/** Generate a machine-readable compat report from a diff result. */\nexport function generateReport(diff: CompatDiffResult, language?: string): CompatReport {\n  return {\n    schemaVersion: '1',\n    language: language ?? 'unknown',\n    summary: diff.summary,\n    changes: diff.changes.map((c) => ({\n      severity: c.severity,\n      category: c.category,\n      symbol: c.symbol,\n      conceptualChangeId: c.conceptualChangeId,\n      provenance: c.provenance,\n      old: c.old,\n      new: c.new,\n      ...(c.message ? { message: c.message } : {}),\n      ...(c.remediation ? { remediation: c.remediation } : {}),\n    })),\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Human-readable terminal summary\n// ---------------------------------------------------------------------------\n\n/** Generate a human-readable summary string for terminal output. */\nexport function formatHumanSummary(diff: CompatDiffResult, opts?: { explain?: boolean; language?: string }): string {\n  const lines: string[] = [];\n\n  lines.push(`Compat report${opts?.language ? ` for ${opts.language}` : ''}:`);\n  lines.push(\n    `  ${diff.summary.breaking} breaking, ${diff.summary.softRisk} soft-risk, ${diff.summary.additive} additive`,\n  );\n\n  if (diff.changes.length === 0) {\n    lines.push('  No compatibility changes detected.');\n    return lines.join('\\n');\n  }\n\n  // Group by severity for display\n  const breaking = diff.changes.filter((c) => c.severity === 'breaking');\n  const softRisk = diff.changes.filter((c) => c.severity === 'soft-risk');\n  const additive = diff.changes.filter((c) => c.severity === 'additive');\n\n  if (breaking.length > 0) {\n    lines.push('');\n    lines.push('  Breaking:');\n    for (const c of breaking) {\n      lines.push(`    [${c.category}] ${c.symbol} — ${c.message}`);\n      if (c.remediation) {\n        lines.push(`      hint: ${c.remediation}`);\n      }\n      if (opts?.explain && c.provenance !== 'unknown') {\n        lines.push(`      provenance: ${c.provenance}`);\n      }\n    }\n  }\n\n  if (softRisk.length > 0) {\n    lines.push('');\n    lines.push('  Soft-risk:');\n    for (const c of softRisk) {\n      lines.push(`    [${c.category}] ${c.symbol} — ${c.message}`);\n      if (c.remediation) {\n        lines.push(`      hint: ${c.remediation}`);\n      }\n      if (opts?.explain && c.provenance !== 'unknown') {\n        lines.push(`      provenance: ${c.provenance}`);\n      }\n    }\n  }\n\n  if (additive.length > 0) {\n    lines.push('');\n    lines.push(`  Additive: ${additive.length} new symbol(s)`);\n  }\n\n  return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Conceptual cross-language summary\n// ---------------------------------------------------------------------------\n\n/** Conceptual cross-language report. */\nexport interface ConceptualReport {\n  conceptualChanges: {\n    id: string;\n    symbol: string;\n    category: CompatChangeCategory;\n    impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n  }[];\n}\n\n/** Generate a conceptual cross-language report from multiple per-language results. */\nexport function generateConceptualReport(\n  perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualReport {\n  const rollup = buildConceptualRollup(perLanguageResults);\n  return {\n    conceptualChanges: rollup.conceptualChanges.map((c) => ({\n      id: c.id,\n      symbol: c.symbol,\n      category: c.category,\n      impact: c.impact,\n    })),\n  };\n}\n\n/** Format a conceptual cross-language summary for terminal output. */\nexport function formatConceptualSummary(\n  perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): string {\n  const rollup = buildConceptualRollup(perLanguageResults);\n  const summary = summarizeConceptualChanges(rollup);\n  const lines: string[] = [];\n\n  lines.push('Cross-language conceptual summary:');\n  lines.push(`  ${summary.breaking} breaking, ${summary.softRisk} soft-risk, ${summary.additive} additive`);\n\n  if (rollup.conceptualChanges.length === 0) {\n    lines.push('  No cross-language changes.');\n    return lines.join('\\n');\n  }\n\n  for (const change of rollup.conceptualChanges) {\n    const sev = highestSeverity(change);\n    const impactStr = Object.entries(change.impact)\n      .map(([lang, s]) => `${lang}: ${s}`)\n      .join(', ');\n    lines.push(`  [${sev}] ${change.category}: ${change.symbol}`);\n    lines.push(`    impact: ${impactStr}`);\n  }\n\n  return lines.join('\\n');\n}\n","/**\n * Approval matching engine for compatibility verification.\n *\n * Matches CompatApproval entries from oagen.config.ts against classified\n * changes. Approved changes are excluded from failure thresholds.\n *\n * Approvals must be narrow (one symbol, one category, one conceptual change).\n * Overly broad approvals are rejected at validation time.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatApproval } from './config.js';\nimport type { ClassifiedChange } from './classify.js';\n\n/** Result of matching a change against approvals. */\nexport interface ApprovalMatch {\n  /** The change that was matched. */\n  change: ClassifiedChange;\n  /** The approval that matched. null if no approval covers this change. */\n  approval: CompatApproval | null;\n  /** Whether the change is covered by an approval. */\n  approved: boolean;\n}\n\n/** Result of validating an approval for broadness. */\nexport interface ApprovalValidation {\n  valid: boolean;\n  errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Validate that an approval is narrow enough to be accepted. */\nexport function validateApproval(approval: CompatApproval): ApprovalValidation {\n  const errors: string[] = [];\n\n  if (!approval.symbol || approval.symbol.trim() === '') {\n    errors.push('Approval must target a specific symbol');\n  }\n\n  if (!approval.category) {\n    errors.push('Approval must specify a change category');\n  }\n\n  if (!approval.reason || approval.reason.trim() === '') {\n    errors.push('Approval must include a reason');\n  }\n\n  // Wildcard symbols are too broad\n  if (approval.symbol === '*' || approval.symbol.endsWith('.*') || approval.symbol.endsWith('::*')) {\n    errors.push(`Approval symbol \"${approval.symbol}\" is too broad — must target a specific symbol`);\n  }\n\n  return {\n    valid: errors.length === 0,\n    errors,\n  };\n}\n\n/** Validate all approvals in a config. Returns errors keyed by index. */\nexport function validateApprovals(approvals: CompatApproval[]): Map<number, string[]> {\n  const result = new Map<number, string[]>();\n  for (let i = 0; i < approvals.length; i++) {\n    const validation = validateApproval(approvals[i]);\n    if (!validation.valid) {\n      result.set(i, validation.errors);\n    }\n  }\n  return result;\n}\n\n// ---------------------------------------------------------------------------\n// Matching\n// ---------------------------------------------------------------------------\n\n/**\n * Match a classified change against a list of approvals.\n * Returns the first matching approval, or null if none match.\n */\nexport function matchApproval(\n  change: ClassifiedChange,\n  approvals: CompatApproval[],\n  language: LanguageId,\n): CompatApproval | null {\n  for (const approval of approvals) {\n    if (approvalMatchesChange(approval, change, language)) {\n      return approval;\n    }\n  }\n  return null;\n}\n\n/**\n * Apply approvals to a list of changes.\n * Returns matches for every change (approved or not).\n */\nexport function applyApprovals(\n  changes: ClassifiedChange[],\n  approvals: CompatApproval[],\n  language: LanguageId,\n): ApprovalMatch[] {\n  return changes.map((change) => {\n    const approval = matchApproval(change, approvals, language);\n    return {\n      change,\n      approval,\n      approved: approval !== null,\n    };\n  });\n}\n\n/**\n * Filter changes to only those NOT covered by approvals.\n * These are the remaining unapproved changes that may cause failure.\n */\nexport function unapprovedChanges(\n  changes: ClassifiedChange[],\n  approvals: CompatApproval[],\n  language: LanguageId,\n): ClassifiedChange[] {\n  return changes.filter((change) => !matchApproval(change, approvals, language));\n}\n\n// ---------------------------------------------------------------------------\n// Internal matching logic\n// ---------------------------------------------------------------------------\n\nfunction approvalMatchesChange(approval: CompatApproval, change: ClassifiedChange, language: LanguageId): boolean {\n  // Skip inactive approvals\n  if (approval.approved === false) return false;\n\n  // Category must match exactly\n  if (approval.category !== change.category) return false;\n\n  // Symbol must match\n  if (!symbolMatches(approval.symbol, change.symbol)) return false;\n\n  // Language scoping\n  if (!languageMatches(approval.appliesTo, language)) return false;\n\n  // Narrowing match (optional)\n  if (approval.match && !narrowingMatches(approval.match, change)) return false;\n\n  return true;\n}\n\nfunction symbolMatches(approvalSymbol: string, changeSymbol: string): boolean {\n  // Exact match\n  if (approvalSymbol === changeSymbol) return true;\n\n  // Normalize common separators for cross-language matching\n  // PHP uses :: and \\, others use . — normalize to dots for comparison\n  const normalizedApproval = approvalSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n  const normalizedChange = changeSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n  return normalizedApproval === normalizedChange;\n}\n\nfunction languageMatches(appliesTo: CompatApproval['appliesTo'], language: LanguageId): boolean {\n  if (!appliesTo || appliesTo === 'all-impacted-languages') return true;\n  return appliesTo.includes(language);\n}\n\nfunction narrowingMatches(match: NonNullable<CompatApproval['match']>, change: ClassifiedChange): boolean {\n  if (match.parameter) {\n    // Check if the change involves this parameter\n    const paramInOld = change.old.parameter === match.parameter;\n    const paramInNew = change.new.parameter === match.parameter;\n    if (!paramInOld && !paramInNew) return false;\n  }\n  if (match.member) {\n    const memberInOld = change.old.member === match.member;\n    const memberInNew = change.new.member === match.member;\n    if (!memberInOld && !memberInNew) return false;\n  }\n  if (match.oldName) {\n    const nameMatch = Object.values(change.old).some((v) => v === match.oldName);\n    if (!nameMatch) return false;\n  }\n  if (match.newName) {\n    const nameMatch = Object.values(change.new).some((v) => v === match.newName);\n    if (!nameMatch) return false;\n  }\n  return true;\n}\n","/** Sort an object's keys alphabetically. Shared across all extractors for deterministic output. */\nexport function sortRecord<T>(record: Record<string, T>): Record<string, T> {\n  const sorted: Record<string, T> = {};\n  for (const key of Object.keys(record).sort()) {\n    sorted[key] = record[key];\n  }\n  return sorted;\n}\n\n/** Collects per-file export names, deduplicating and sorting on finalization. */\nexport class ExportCollector {\n  private map = new Map<string, Set<string>>();\n\n  add(sourceFile: string, name: string): void {\n    let set = this.map.get(sourceFile);\n    if (!set) {\n      set = new Set();\n      this.map.set(sourceFile, set);\n    }\n    set.add(name);\n  }\n\n  toRecord(): Record<string, string[]> {\n    const result: Record<string, string[]> = {};\n    for (const [file, names] of this.map) {\n      result[file] = [...names].sort();\n    }\n    return result;\n  }\n}\n","import ts from 'typescript';\nimport { readFileSync } from 'node:fs';\nimport path, { resolve, relative } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type {\n  ApiSurface,\n  Extractor,\n  ApiClass,\n  ApiMethod,\n  ApiParam,\n  ApiProperty,\n  ApiInterface,\n  ApiField,\n  ApiTypeAlias,\n  ApiEnum,\n} from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { nodeHints } from '../language-hints.js';\nimport { sortRecord } from './shared.js';\n\nexport const nodeExtractor: Extractor = {\n  language: 'node',\n  hints: nodeHints,\n\n  async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n    const surface = await this.extract(sdkPath);\n    return apiSurfaceToSnapshot(surface);\n  },\n\n  async extract(sdkPath: string): Promise<ApiSurface> {\n    sdkPath = resolve(sdkPath);\n    const configPath = ts.findConfigFile(sdkPath, ts.sys.fileExists, 'tsconfig.json');\n    if (!configPath)\n      throw new ExtractorError(\n        `No tsconfig.json found in ${sdkPath}`,\n        `Create a tsconfig.json in \"${sdkPath}\" or verify the --sdk-path argument points to a TypeScript project root.`,\n      );\n\n    const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n    const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, sdkPath);\n    const program = ts.createProgram(parsedConfig.fileNames, parsedConfig.options);\n    const checker = program.getTypeChecker();\n\n    const entryPoint = resolveEntryPoint(sdkPath, program);\n    const entrySourceFile = program.getSourceFile(entryPoint);\n    if (!entrySourceFile)\n      throw new ExtractorError(\n        `Entry point not found: ${entryPoint}`,\n        `Ensure the file \"${entryPoint}\" exists and is included in the tsconfig.json \"include\" or \"files\" array.`,\n      );\n\n    const moduleSymbol = checker.getSymbolAtLocation(entrySourceFile);\n    if (!moduleSymbol)\n      throw new ExtractorError(\n        'No exports found at entry point',\n        `Verify that \"${entryPoint}\" has at least one \\`export\\` statement. The extractor needs public exports to build an API surface.`,\n      );\n\n    const exportedSymbols = checker.getExportsOfModule(moduleSymbol);\n\n    const classes: Record<string, ApiClass> = {};\n    const interfaces: Record<string, ApiInterface> = {};\n    const typeAliases: Record<string, ApiTypeAlias> = {};\n    const enums: Record<string, ApiEnum> = {};\n\n    for (const sym of exportedSymbols) {\n      const resolved = resolveAlias(sym, checker);\n      const declarations = resolved.getDeclarations();\n      if (!declarations || declarations.length === 0) continue;\n      const decl = declarations[0];\n\n      const sourceFile = relative(sdkPath, decl.getSourceFile().fileName);\n\n      if (ts.isClassDeclaration(decl)) {\n        classes[resolved.name] = { ...extractClass(resolved, checker), sourceFile };\n      } else if (ts.isInterfaceDeclaration(decl)) {\n        interfaces[resolved.name] = { ...extractInterface(resolved, checker), sourceFile };\n      } else if (ts.isTypeAliasDeclaration(decl)) {\n        typeAliases[resolved.name] = { ...extractTypeAlias(resolved, checker), sourceFile };\n      } else if (ts.isEnumDeclaration(decl)) {\n        enums[resolved.name] = { ...extractEnum(resolved, checker), sourceFile };\n      }\n    }\n\n    // Follow property types on extracted classes to discover resource classes\n    // (e.g., Client.widgets: Widgets → extract Widgets)\n    followPropertyTypeClasses(exportedSymbols, checker, classes, sdkPath);\n\n    const exports = buildExportMap(entrySourceFile, checker, sdkPath, program);\n\n    return {\n      language: 'node',\n      extractedFrom: sdkPath,\n      extractedAt: new Date().toISOString(),\n      classes: sortRecord(classes),\n      interfaces: sortRecord(interfaces),\n      typeAliases: sortRecord(typeAliases),\n      enums: sortRecord(enums),\n      exports: sortRecord(exports),\n    };\n  },\n};\n\nfunction followPropertyTypeClasses(\n  exportedSymbols: ts.Symbol[],\n  checker: ts.TypeChecker,\n  classes: Record<string, ApiClass>,\n  sdkPath: string,\n): void {\n  // Build initial set of class symbols from exports\n  const classSymbols = new Map<string, ts.Symbol>();\n  for (const sym of exportedSymbols) {\n    const resolved = resolveAlias(sym, checker);\n    const decls = resolved.getDeclarations();\n    if (decls?.some((d) => ts.isClassDeclaration(d))) {\n      classSymbols.set(resolved.name, resolved);\n    }\n  }\n\n  const toVisit = [...classSymbols.values()];\n  const visited = new Set(classSymbols.keys());\n\n  while (toVisit.length > 0) {\n    const sym = toVisit.pop()!;\n    const type = checker.getDeclaredTypeOfSymbol(sym);\n    const decls = sym.getDeclarations();\n    if (!decls || decls.length === 0) continue;\n\n    for (const prop of type.getProperties()) {\n      const propDecls = prop.getDeclarations();\n      if (!propDecls || propDecls.length === 0) continue;\n      const propDecl = propDecls[0];\n\n      // Skip private/protected\n      const modifiers = ts.canHaveModifiers(propDecl) ? ts.getModifiers(propDecl) : undefined;\n      if (\n        modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword)\n      ) {\n        continue;\n      }\n\n      const propType = checker.getTypeOfSymbolAtLocation(prop, propDecl);\n      const propSymbol = propType.getSymbol();\n      if (!propSymbol) continue;\n\n      const propName = propSymbol.name;\n      if (visited.has(propName)) continue;\n\n      const propSymDecls = propSymbol.getDeclarations();\n      if (!propSymDecls?.some((d) => ts.isClassDeclaration(d))) continue;\n\n      // Found a class referenced by property type — extract it\n      visited.add(propName);\n      const sourceFile = relative(sdkPath, propSymDecls[0].getSourceFile().fileName);\n      classes[propName] = { ...extractClass(propSymbol, checker), sourceFile };\n      toVisit.push(propSymbol);\n    }\n  }\n}\n\nfunction resolveEntryPoint(sdkPath: string, program: ts.Program): string {\n  const pkgPath = resolve(sdkPath, 'package.json');\n  try {\n    const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n    // Check \"exports\" field first\n    if (pkg.exports) {\n      const mainExport =\n        typeof pkg.exports === 'string'\n          ? pkg.exports\n          : (pkg.exports['.']?.import ?? pkg.exports['.']?.default ?? pkg.exports['.']);\n      if (typeof mainExport === 'string') {\n        const resolved = resolveSourceFile(sdkPath, mainExport, program);\n        if (resolved) return resolved;\n      }\n    }\n    // Fallback to \"main\"\n    if (pkg.main) {\n      const resolved = resolveSourceFile(sdkPath, pkg.main, program);\n      if (resolved) return resolved;\n    }\n  } catch {\n    // No package.json or invalid — fall through to default\n  }\n\n  // Default fallback\n  const fallback = resolve(sdkPath, 'src/index.ts');\n  if (program.getSourceFile(fallback)) return fallback;\n  throw new ExtractorError(\n    `No entry point found. Tried: package.json exports/main, src/index.ts`,\n    `Add an \"exports\" or \"main\" field to package.json in \"${sdkPath}\", or create a src/index.ts file that re-exports the public API.`,\n  );\n}\n\nfunction resolveSourceFile(sdkPath: string, entryPath: string, program: ts.Program): string | undefined {\n  // Try the path as-is, then swap .js → .ts, then try index.ts\n  const candidates = [\n    resolve(sdkPath, entryPath),\n    resolve(sdkPath, entryPath.replace(/\\.js$/, '.ts')),\n    resolve(sdkPath, entryPath.replace(/\\.js$/, '/index.ts')),\n  ];\n  for (const candidate of candidates) {\n    if (program.getSourceFile(candidate)) return candidate;\n  }\n  return undefined;\n}\n\nfunction resolveAlias(sym: ts.Symbol, checker: ts.TypeChecker): ts.Symbol {\n  if (sym.flags & ts.SymbolFlags.Alias) {\n    return checker.getAliasedSymbol(sym);\n  }\n  return sym;\n}\n\nfunction extractClass(sym: ts.Symbol, checker: ts.TypeChecker): ApiClass {\n  const type = checker.getDeclaredTypeOfSymbol(sym);\n  const methods: Record<string, ApiMethod[]> = {};\n  const properties: Record<string, ApiProperty> = {};\n  const constructorParams: ApiParam[] = [];\n  let deprecationMessage: string | undefined;\n\n  // Extract constructor params\n  const declarations = sym.getDeclarations();\n  if (declarations) {\n    for (const decl of declarations) {\n      if (ts.isClassDeclaration(decl)) {\n        // Look for `@deprecated` in the class's JSDoc.  JSDoc nodes are\n        // attached to the declaration's parent range; TS exposes them via\n        // ts.getJSDocDeprecatedTag.\n        const deprecatedTag = ts.getJSDocDeprecatedTag(decl);\n        if (deprecatedTag) {\n          const comment = deprecatedTag.comment;\n          if (typeof comment === 'string') {\n            deprecationMessage = comment.trim() || '';\n          } else if (Array.isArray(comment)) {\n            deprecationMessage =\n              comment\n                .map((c) => c.text)\n                .join('')\n                .trim() || '';\n          } else {\n            deprecationMessage = '';\n          }\n        }\n        for (const member of decl.members) {\n          if (ts.isConstructorDeclaration(member)) {\n            for (const param of member.parameters) {\n              const { name: paramName, isDestructured } = extractParameterInfo(param, param.name.getText());\n              const paramType = param.type ? checker.typeToString(checker.getTypeFromTypeNode(param.type)) : 'any';\n              constructorParams.push({\n                name: paramName,\n                type: paramType,\n                optional: !!param.questionToken || !!param.initializer,\n                passingStyle: isDestructured ? 'options_object' : 'positional',\n              });\n            }\n          }\n        }\n      }\n    }\n  }\n\n  // Extract methods and properties from the type\n  for (const prop of type.getProperties()) {\n    // Skip private/protected members\n    const propDeclarations = prop.getDeclarations();\n    if (propDeclarations && propDeclarations.length > 0) {\n      const decl = propDeclarations[0];\n      const modifiers = ts.canHaveModifiers(decl) ? ts.getModifiers(decl) : undefined;\n      if (\n        modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword)\n      ) {\n        continue;\n      }\n    }\n\n    const propType = checker.getTypeOfSymbolAtLocation(prop, declarations![0]);\n    const callSignatures = propType.getCallSignatures();\n\n    if (callSignatures.length > 0) {\n      if (!methods[prop.name]) methods[prop.name] = [];\n      // Extract ALL overloads, not just the first\n      for (const sig of callSignatures) {\n        methods[prop.name].push({\n          name: prop.name,\n          params: sig.getParameters().map((p) => extractParam(p, checker)),\n          returnType: checker.typeToString(sig.getReturnType()),\n          async: checker.typeToString(sig.getReturnType()).startsWith('Promise<'),\n        });\n      }\n    } else {\n      const typeStr = checker.typeToString(propType);\n      const isReadonly = propDeclarations?.some((d) => {\n        const mods = ts.canHaveModifiers(d) ? ts.getModifiers(d) : undefined;\n        return mods?.some((m) => m.kind === ts.SyntaxKind.ReadonlyKeyword);\n      });\n      properties[prop.name] = {\n        name: prop.name,\n        type: typeStr,\n        readonly: !!isReadonly,\n      };\n    }\n  }\n\n  return {\n    name: sym.name,\n    methods: sortRecord(methods),\n    properties: sortRecord(properties),\n    constructorParams,\n    ...(deprecationMessage !== undefined && { deprecationMessage }),\n  };\n}\n\nfunction extractParam(sym: ts.Symbol, checker: ts.TypeChecker): ApiParam {\n  const decl = sym.getDeclarations()?.[0];\n  const isOptional = decl && ts.isParameter(decl) ? !!decl.questionToken || !!decl.initializer : false;\n  const type = checker.getTypeOfSymbolAtLocation(sym, decl!);\n  const { name, isDestructured } = extractParameterInfo(decl, sym.name);\n  const typeStr = checker.typeToString(type);\n\n  // Detect options object pattern:\n  // - destructured object binding ({a, b}: Options)\n  // - single non-primitive param with an object/interface type\n  let passingStyle: ApiParam['passingStyle'];\n  if (isDestructured) {\n    passingStyle = 'options_object';\n  } else {\n    const resolvedType = checker.getTypeOfSymbolAtLocation(sym, decl!);\n    // An optional param (`options?: Options`) has type `Options | undefined`,\n    // a union — which is neither a class/interface nor a TypeFlags.Object — so\n    // strip the nullable arm before the object-like check. Without this an\n    // all-optional options param reads as 'positional', which makes the next\n    // regeneration drop its baseline and rename the options type.\n    const objectType = checker.getNonNullableType(resolvedType);\n    const isObjectLike = objectType.isClassOrInterface() || (objectType.getFlags() & ts.TypeFlags.Object) !== 0;\n    const isPrimitive = [\n      'string',\n      'number',\n      'boolean',\n      'undefined',\n      'null',\n      'void',\n      'never',\n      'any',\n      'unknown',\n    ].includes(typeStr);\n    if (isObjectLike && !isPrimitive && !typeStr.startsWith('Promise<')) {\n      passingStyle = 'options_object';\n    } else {\n      passingStyle = 'positional';\n    }\n  }\n\n  return {\n    name,\n    type: typeStr,\n    optional: isOptional,\n    passingStyle,\n  };\n}\n\nfunction extractParameterInfo(\n  decl: ts.Declaration | undefined,\n  fallback: string,\n): { name: string; isDestructured: boolean } {\n  if (!decl || !ts.isParameter(decl)) return { name: fallback, isDestructured: false };\n  if (ts.isIdentifier(decl.name)) return { name: decl.name.text, isDestructured: false };\n\n  const parentWithParameters = decl.parent as ts.Node & { parameters?: ts.NodeArray<ts.ParameterDeclaration> };\n  const index = parentWithParameters.parameters?.indexOf(decl) ?? -1;\n  const suffix = index > 0 ? String(index) : '';\n\n  if (ts.isObjectBindingPattern(decl.name)) return { name: `options${suffix}`, isDestructured: true };\n  if (ts.isArrayBindingPattern(decl.name)) return { name: `args${suffix}`, isDestructured: false };\n\n  return { name: fallback, isDestructured: false };\n}\n\nfunction extractInterface(sym: ts.Symbol, checker: ts.TypeChecker): ApiInterface {\n  const type = checker.getDeclaredTypeOfSymbol(sym);\n  const fields: Record<string, ApiField> = {};\n  const extendsNames: string[] = [];\n\n  // Get extends clauses\n  const declarations = sym.getDeclarations();\n  if (declarations) {\n    for (const decl of declarations) {\n      if (ts.isInterfaceDeclaration(decl) && decl.heritageClauses) {\n        for (const clause of decl.heritageClauses) {\n          for (const typeExpr of clause.types) {\n            extendsNames.push(typeExpr.getText());\n          }\n        }\n      }\n    }\n  }\n\n  for (const prop of type.getProperties()) {\n    const propType = checker.getTypeOfSymbolAtLocation(prop, declarations![0]);\n    const propDecl = prop.getDeclarations()?.[0];\n    const isOptional = propDecl && ts.isPropertySignature(propDecl) ? !!propDecl.questionToken : false;\n    let typeStr = checker.typeToString(propType);\n    if (isOptional) {\n      typeStr = stripUndefined(typeStr);\n    }\n    fields[prop.name] = {\n      name: prop.name,\n      type: typeStr,\n      optional: isOptional,\n    };\n  }\n\n  // Fallback: walk AST declaration members for fields that type.getProperties() missed.\n  // This handles generic interfaces (e.g., List<T>) where the checker may not resolve\n  // all properties when the type parameter is unbound.\n  if (declarations) {\n    for (const decl of declarations) {\n      if (ts.isInterfaceDeclaration(decl)) {\n        for (const member of decl.members) {\n          if (ts.isPropertySignature(member) && member.name) {\n            const memberName = member.name.getText();\n            if (!fields[memberName]) {\n              const memberType = member.type ? checker.typeToString(checker.getTypeFromTypeNode(member.type)) : 'any';\n              const isOpt = !!member.questionToken;\n              fields[memberName] = {\n                name: memberName,\n                type: isOpt ? stripUndefined(memberType) : memberType,\n                optional: isOpt,\n              };\n            }\n          }\n        }\n      }\n    }\n  }\n\n  return {\n    name: sym.name,\n    fields: sortRecord(fields),\n    extends: extendsNames.sort(),\n  };\n}\n\nfunction extractTypeAlias(sym: ts.Symbol, checker: ts.TypeChecker): ApiTypeAlias {\n  const type = checker.getDeclaredTypeOfSymbol(sym);\n  return {\n    name: sym.name,\n    value: checker.typeToString(type, undefined, ts.TypeFormatFlags.InTypeAlias | ts.TypeFormatFlags.NoTruncation),\n  };\n}\n\nfunction extractEnum(sym: ts.Symbol, checker: ts.TypeChecker): ApiEnum {\n  const members: Record<string, string | number> = {};\n  const type = checker.getDeclaredTypeOfSymbol(sym);\n\n  if (type.isUnion()) {\n    for (const memberType of type.types) {\n      if (memberType.symbol) {\n        const constValue = checker.getConstantValue(memberType.symbol.getDeclarations()![0] as ts.EnumMember);\n        if (constValue !== undefined) {\n          members[memberType.symbol.name] = constValue;\n        }\n      }\n    }\n  }\n\n  return {\n    name: sym.name,\n    members: sortRecord(members),\n  };\n}\n\nfunction buildExportMap(\n  entryFile: ts.SourceFile,\n  checker: ts.TypeChecker,\n  sdkPath: string,\n  program: ts.Program,\n): Record<string, string[]> {\n  const exports: Record<string, string[]> = {};\n  const visited = new Set<string>();\n\n  function walk(sourceFile: ts.SourceFile): void {\n    const absPath = sourceFile.fileName;\n    if (visited.has(absPath)) return;\n    visited.add(absPath);\n\n    const relPath = relative(sdkPath, absPath);\n    const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n    if (moduleSymbol) {\n      const names = checker.getExportsOfModule(moduleSymbol).map((s) => s.name);\n      if (names.length > 0) {\n        exports[relPath] = names.sort();\n      }\n    }\n\n    for (const stmt of sourceFile.statements) {\n      if (ts.isExportDeclaration(stmt) && stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)) {\n        const target = stmt.moduleSpecifier.text;\n        const resolved = resolveSourceFile(path.dirname(absPath), target, program);\n        if (resolved) {\n          const targetFile = program.getSourceFile(resolved);\n          if (targetFile) {\n            walk(targetFile);\n          }\n        }\n      }\n    }\n  }\n\n  walk(entryFile);\n  return exports;\n}\n\nfunction stripUndefined(typeStr: string): string {\n  return typeStr.replace(/\\s*\\|\\s*undefined$/, '').replace(/^undefined\\s*\\|\\s*/, '');\n}\n","/**\n * PHP source parser — tree-sitter-based extraction of classes, interfaces,\n * methods, properties, and constants from PHP source files.\n */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport PhpGrammar from 'tree-sitter-php';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface PhpParam {\n  name: string;\n  type: string;\n  optional: boolean;\n}\n\nexport interface PhpMethod {\n  name: string;\n  visibility: 'public' | 'protected' | 'private';\n  isStatic: boolean;\n  params: PhpParam[];\n  returnType: string;\n}\n\nexport interface PhpConstant {\n  name: string;\n  value: string;\n}\n\nexport interface PhpProperty {\n  name: string;\n  type: string;\n  visibility: 'public' | 'protected' | 'private';\n}\n\nexport interface PhpClass {\n  name: string;\n  namespace: string;\n  extends: string | null;\n  isInterface: boolean;\n  methods: PhpMethod[];\n  properties: PhpProperty[];\n  constants: PhpConstant[];\n  resourceAttributes: string[];\n  /** True if the class defines its own constructFromResponse method (not inherited). */\n  hasCustomConstructor: boolean;\n  sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst phpParser = new Parser();\nphpParser.setLanguage(PhpGrammar.php_only);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkPhpFiles(dir: string): string[] {\n  const results: string[] = [];\n  let entries: string[];\n  try {\n    entries = readdirSync(dir);\n  } catch {\n    return results;\n  }\n  for (const entry of entries) {\n    const fullPath = join(dir, entry);\n    let stat;\n    try {\n      stat = statSync(fullPath);\n    } catch {\n      continue;\n    }\n    if (stat.isDirectory()) {\n      if (entry.startsWith('.') || entry === 'vendor' || entry === 'tests' || entry === 'test') continue;\n      results.push(...walkPhpFiles(fullPath));\n    } else if (entry.endsWith('.php')) {\n      results.push(fullPath);\n    }\n  }\n  return results.sort();\n}\n\ninterface PhpDocInfo {\n  params: Map<string, string>; // $name → type\n  returnType: string;\n}\n\nfunction parsePhpDoc(commentText: string): PhpDocInfo {\n  const params = new Map<string, string>();\n  let returnType = '';\n\n  const lines = commentText.split('\\n');\n  for (const line of lines) {\n    // Match @param type $name\n    const paramMatch = line.match(/@param\\s+(\\S+)\\s+\\$(\\w+)/);\n    if (paramMatch) {\n      params.set(paramMatch[2], paramMatch[1]);\n    }\n    // Match @return type\n    const returnMatch = line.match(/@return\\s+(\\S+)/);\n    if (returnMatch) {\n      returnType = returnMatch[1];\n    }\n  }\n\n  return { params, returnType };\n}\n\n/** Find the doc comment immediately preceding a node. */\nfunction findDocComment(node: SyntaxNode): PhpDocInfo | null {\n  // Walk backward through siblings to find comment\n  let sibling = node.previousNamedSibling;\n  if (sibling && sibling.type === 'comment' && sibling.text.startsWith('/**')) {\n    return parsePhpDoc(sibling.text);\n  }\n  return null;\n}\n\nfunction getVisibility(node: SyntaxNode): 'public' | 'protected' | 'private' {\n  for (const child of node.children) {\n    if (child.type === 'visibility_modifier') {\n      const text = child.text.toLowerCase();\n      if (text === 'public') return 'public';\n      if (text === 'protected') return 'protected';\n      if (text === 'private') return 'private';\n    }\n  }\n  return 'public'; // PHP default\n}\n\nfunction isStaticMethod(node: SyntaxNode): boolean {\n  for (const child of node.children) {\n    if (child.type === 'static_modifier') return true;\n  }\n  return false;\n}\n\n/** Parse a PHP array literal to extract string values: [\"id\", \"name\", ...] */\nfunction parseArrayLiteral(node: SyntaxNode): string[] {\n  const values: string[] = [];\n  // In tree-sitter-php, array elements contain encapsed_string → string_content\n  // For simple indexed arrays, each array_element_initializer has one encapsed_string\n  for (const elemInit of node.descendantsOfType('array_element_initializer')) {\n    const strings = elemInit.namedChildren.filter((c) => c.type === 'encapsed_string' || c.type === 'string');\n    // For indexed arrays (no =>), there's one string per element\n    if (strings.length === 1) {\n      const contentNode = strings[0].namedChildren.find((c) => c.type === 'string_content');\n      if (contentNode) {\n        values.push(contentNode.text);\n      }\n    }\n  }\n  return values;\n}\n\n/** Extract the name and value from a const_element node. */\nfunction parseConstElement(constElement: SyntaxNode): { name: string; value: string } | null {\n  const nameNode = constElement.namedChildren.find((c) => c.type === 'name');\n  if (!nameNode) return null;\n\n  const constName = nameNode.text;\n\n  // Skip RESOURCE_ATTRIBUTES and RESPONSE_TO_RESOURCE_KEY (they're arrays, not scalar constants)\n  if (constName === 'RESOURCE_ATTRIBUTES' || constName === 'RESPONSE_TO_RESOURCE_KEY') return null;\n\n  // Find the value node (encapsed_string, string, integer, etc.)\n  const valueNode = constElement.namedChildren.find((c) => c.type !== 'name');\n  if (!valueNode) return null;\n\n  // For string values, extract string_content\n  if (valueNode.type === 'encapsed_string') {\n    const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n    return { name: constName, value: contentNode ? contentNode.text : '' };\n  }\n  if (valueNode.type === 'string') {\n    const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n    return { name: constName, value: contentNode ? contentNode.text : '' };\n  }\n\n  // For other types (integers, etc.), use the raw text\n  return { name: constName, value: valueNode.text };\n}\n\n// ---------------------------------------------------------------------------\n// Method extraction\n// ---------------------------------------------------------------------------\n\nfunction parseMethods(classBody: SyntaxNode): { methods: PhpMethod[]; promotedProperties: PhpProperty[] } {\n  const methods: PhpMethod[] = [];\n  const allPromotedProperties: PhpProperty[] = [];\n\n  for (const child of classBody.namedChildren) {\n    if (child.type !== 'method_declaration') continue;\n\n    const nameNode = child.childForFieldName('name');\n    if (!nameNode) continue;\n    const methodName = nameNode.text;\n\n    // Skip magic methods except __construct\n    if (methodName.startsWith('__') && methodName !== '__construct') continue;\n\n    const visibility = getVisibility(child);\n    const isStatic = isStaticMethod(child);\n\n    // Get PHPDoc info\n    const docInfo = findDocComment(child);\n\n    // Parse parameters. Two PHP parameter shapes are accepted:\n    //   - `simple_parameter`: standard `Type $name = default`\n    //   - `property_promotion_parameter`: PHP 8 constructor-promoted\n    //     property `public Type $name`. These declare *both* a parameter\n    //     on the constructor AND a property on the class. Without accepting\n    //     this node type the parser skips the parameter\n    //     entirely, model fields disappear from the surface, and the\n    //     compat differ has no field-level signal to pair renamed types.\n    const promotedProperties: PhpProperty[] = [];\n    const params: PhpParam[] = [];\n    const paramsList = child.childForFieldName('parameters');\n    if (paramsList) {\n      for (const paramNode of paramsList.namedChildren) {\n        if (paramNode.type !== 'simple_parameter' && paramNode.type !== 'property_promotion_parameter') continue;\n\n        const paramNameNode = paramNode.namedChildren.find((c) => c.type === 'variable_name');\n        if (!paramNameNode) continue;\n\n        const paramName = paramNameNode.text.replace(/^\\$/, '');\n\n        // Check for native type hint\n        let paramType = '';\n        const typeNode = paramNode.childForFieldName('type');\n        if (typeNode) {\n          paramType = typeNode.text;\n        }\n        // Fall back to PHPDoc\n        if (!paramType && docInfo) {\n          paramType = docInfo.params.get(paramName) || 'mixed';\n        }\n        if (!paramType) {\n          paramType = 'mixed';\n        }\n\n        // Check for default value (means optional)\n        const defaultNode = paramNode.childForFieldName('default_value');\n        const hasDefault = defaultNode !== null;\n\n        params.push({\n          name: paramName,\n          type: paramType,\n          optional: hasDefault,\n        });\n\n        // When the parameter carries a visibility modifier it is a\n        // *promoted property* — `public Type $field` declares the field\n        // on the class. Surface as a property so model classes pick up\n        // their fields without needing a separate `property_declaration`.\n        if (paramNode.type === 'property_promotion_parameter') {\n          const visibilityNode = paramNode.namedChildren.find((c) => c.type === 'visibility_modifier');\n          const visibility = (visibilityNode?.text as 'public' | 'protected' | 'private' | undefined) ?? 'public';\n          promotedProperties.push({\n            name: paramName,\n            type: paramType,\n            visibility,\n          });\n        }\n      }\n    }\n\n    // Return type\n    let returnType = '';\n    const returnTypeNode = child.childForFieldName('return_type');\n    if (returnTypeNode) {\n      returnType = returnTypeNode.text;\n    }\n    if (!returnType && docInfo) {\n      returnType = docInfo.returnType || 'mixed';\n    }\n    if (!returnType) {\n      returnType = 'mixed';\n    }\n\n    methods.push({\n      name: methodName,\n      visibility,\n      isStatic,\n      params,\n      returnType,\n    });\n\n    // Promoted properties surface only from `__construct`. PHP's grammar\n    // technically allows them on any method, but only the constructor's\n    // promoted-properties create class fields per the language spec.\n    if (methodName === '__construct') {\n      allPromotedProperties.push(...promotedProperties);\n    }\n  }\n\n  return { methods, promotedProperties: allPromotedProperties };\n}\n\n// ---------------------------------------------------------------------------\n// Property extraction\n// ---------------------------------------------------------------------------\n\nfunction parseProperties(classBody: SyntaxNode): PhpProperty[] {\n  const properties: PhpProperty[] = [];\n\n  for (const child of classBody.namedChildren) {\n    if (child.type !== 'property_declaration') continue;\n\n    const visibility = getVisibility(child);\n\n    // Get property name from property_element → variable_name\n    for (const propElement of child.namedChildren) {\n      if (propElement.type !== 'property_element') continue;\n      const varNameNode = propElement.namedChildren.find((c) => c.type === 'variable_name');\n      if (!varNameNode) continue;\n\n      const propName = varNameNode.text.replace(/^\\$/, '');\n\n      // Check for type hint\n      let propType = 'mixed';\n      const typeNode = child.namedChildren.find(\n        (c) =>\n          c.type === 'union_type' ||\n          c.type === 'named_type' ||\n          c.type === 'optional_type' ||\n          c.type === 'primitive_type',\n      );\n      if (typeNode) {\n        propType = typeNode.text;\n      }\n\n      properties.push({\n        name: propName,\n        type: propType,\n        visibility,\n      });\n    }\n  }\n\n  return properties;\n}\n\n// ---------------------------------------------------------------------------\n// Constant extraction\n// ---------------------------------------------------------------------------\n\nfunction parseConstants(classBody: SyntaxNode): PhpConstant[] {\n  const constants: PhpConstant[] = [];\n\n  for (const child of classBody.namedChildren) {\n    if (child.type !== 'const_declaration') continue;\n\n    for (const constElement of child.namedChildren) {\n      if (constElement.type !== 'const_element') continue;\n\n      const parsed = parseConstElement(constElement);\n      if (parsed) {\n        constants.push(parsed);\n      }\n    }\n  }\n\n  return constants;\n}\n\n// ---------------------------------------------------------------------------\n// Resource attributes extraction\n// ---------------------------------------------------------------------------\n\nfunction parseResourceAttributes(classBody: SyntaxNode): string[] {\n  for (const child of classBody.namedChildren) {\n    if (child.type !== 'const_declaration') continue;\n\n    for (const constElement of child.namedChildren) {\n      if (constElement.type !== 'const_element') continue;\n\n      const nameNode = constElement.namedChildren.find((c) => c.type === 'name');\n      if (!nameNode || nameNode.text !== 'RESOURCE_ATTRIBUTES') continue;\n\n      const arrayNode = constElement.namedChildren.find((c) => c.type === 'array_creation_expression');\n      if (!arrayNode) continue;\n\n      return parseArrayLiteral(arrayNode);\n    }\n  }\n  return [];\n}\n\n// ---------------------------------------------------------------------------\n// Namespace extraction\n// ---------------------------------------------------------------------------\n\nfunction extractNamespace(tree: Parser.Tree): string {\n  for (const node of tree.rootNode.namedChildren) {\n    if (node.type === 'namespace_definition') {\n      const nameNode = node.childForFieldName('name');\n      return nameNode ? nameNode.text : '';\n    }\n  }\n  return '';\n}\n\n// ---------------------------------------------------------------------------\n// Class/interface extraction\n// ---------------------------------------------------------------------------\n\nfunction parseClassDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n  const classes: PhpClass[] = [];\n\n  for (const node of tree.rootNode.descendantsOfType('class_declaration')) {\n    const nameNode = node.childForFieldName('name');\n    if (!nameNode) continue;\n\n    // Check for extends\n    let extendsName: string | null = null;\n    const baseClause = node.namedChildren.find((c) => c.type === 'base_clause');\n    if (baseClause) {\n      const baseNameNode = baseClause.namedChildren.find((c) => c.type === 'name' || c.type === 'qualified_name');\n      if (baseNameNode) {\n        // Strip leading backslash and namespace qualifiers for base name\n        const fullName = baseNameNode.text.replace(/^\\\\/, '');\n        const parts = fullName.split('\\\\');\n        extendsName = parts[parts.length - 1];\n      }\n    }\n\n    const bodyNode = node.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    const { methods, promotedProperties } = parseMethods(bodyNode);\n    const properties = parseProperties(bodyNode);\n    const constants = parseConstants(bodyNode);\n    const resourceAttributes = parseResourceAttributes(bodyNode);\n\n    const hasCustomConstructor = methods.some((m) => m.name === 'constructFromResponse' && m.isStatic);\n\n    // Merge constructor-promoted properties into the class properties so\n    // model classes (PHP 8 readonly classes that put their fields on the\n    // constructor) carry their field info into the surface.\n    const allProperties: PhpProperty[] = [...properties, ...promotedProperties];\n\n    classes.push({\n      name: nameNode.text,\n      namespace,\n      extends: extendsName,\n      isInterface: false,\n      methods,\n      properties: allProperties,\n      constants,\n      resourceAttributes,\n      hasCustomConstructor,\n      sourceFile,\n    });\n  }\n\n  return classes;\n}\n\nfunction parseInterfaceDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n  const interfaces: PhpClass[] = [];\n\n  for (const node of tree.rootNode.descendantsOfType('interface_declaration')) {\n    const nameNode = node.childForFieldName('name');\n    if (!nameNode) continue;\n\n    const bodyNode = node.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    const { methods } = parseMethods(bodyNode);\n\n    interfaces.push({\n      name: nameNode.text,\n      namespace,\n      extends: null,\n      isInterface: true,\n      methods,\n      properties: [],\n      constants: [],\n      resourceAttributes: [],\n      hasCustomConstructor: false,\n      sourceFile,\n    });\n  }\n\n  return interfaces;\n}\n\n// ---------------------------------------------------------------------------\n// PHP 8.1 enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnumDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n  const enums: PhpClass[] = [];\n\n  for (const node of tree.rootNode.descendantsOfType('enum_declaration')) {\n    const nameNode = node.childForFieldName('name');\n    if (!nameNode) continue;\n\n    const bodyNode = node.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    // Extract enum cases as constants\n    const constants: PhpConstant[] = [];\n    for (const child of bodyNode.namedChildren) {\n      if (child.type !== 'enum_case') continue;\n      const caseNameNode = child.childForFieldName('name');\n      if (!caseNameNode) continue;\n\n      // Get the value (backed enum): case Foo = 'foo'\n      let value = caseNameNode.text;\n      const valueNode = child.namedChildren.find(\n        (c) => c.type === 'encapsed_string' || c.type === 'string' || c.type === 'integer',\n      );\n      if (valueNode) {\n        const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n        value = contentNode ? contentNode.text : valueNode.text;\n      }\n\n      constants.push({ name: caseNameNode.text, value });\n    }\n\n    const { methods } = parseMethods(bodyNode);\n\n    enums.push({\n      name: nameNode.text,\n      namespace,\n      extends: null,\n      isInterface: false,\n      methods,\n      properties: [],\n      constants,\n      resourceAttributes: [],\n      hasCustomConstructor: false,\n      sourceFile,\n    });\n  }\n\n  return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedPhpFile {\n  classes: PhpClass[];\n}\n\n/** Parse a single PHP source file and return all extracted symbols. */\nexport function parsePhpFile(filePath: string, sdkPath: string): ParsedPhpFile {\n  const source = readFileSync(filePath, 'utf-8');\n  const relPath = relative(sdkPath, filePath);\n  const tree = safeParse(phpParser, source);\n  const namespace = extractNamespace(tree);\n\n  const classDecls = parseClassDeclarations(tree, relPath, namespace);\n  const interfaceDecls = parseInterfaceDeclarations(tree, relPath, namespace);\n  const enumDecls = parseEnumDeclarations(tree, relPath, namespace);\n\n  return {\n    classes: [...classDecls, ...interfaceDecls, ...enumDecls],\n  };\n}\n","/**\n * PHP surface builder — transforms parsed PHP classes into an ApiSurface.\n *\n * Mapping:\n *   Class extending a resource base      → ApiInterface (fields from RESOURCE_ATTRIBUTES)\n *   Class with only constants             → ApiEnum (const values)\n *   Service class with public methods     → ApiClass\n *   Static utility class                  → ApiClass\n *   PHP interface declaration             → ApiInterface (methods as fields)\n *   Exception class                       → ApiClass\n */\n\nimport type {\n  ApiClass,\n  ApiMethod,\n  ApiParam,\n  ApiProperty,\n  ApiInterface,\n  ApiField,\n  ApiEnum,\n  LanguageHints,\n} from '../types.js';\nimport type { PhpClass } from './php-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Default resource base classes (empty — consumer provides via hints.modelBaseClasses). */\nconst DEFAULT_RESOURCE_BASES: string[] = [];\n\n/** Default exception base classes. */\nconst DEFAULT_EXCEPTION_BASES = ['Exception', '\\\\Exception'];\n\n/** Check if a class is a resource class (extends a known resource base and has attributes). */\nfunction isResourceClass(cls: PhpClass, resourceBases: Set<string>): boolean {\n  return !!cls.extends && resourceBases.has(cls.extends) && cls.resourceAttributes.length > 0;\n}\n\n/**\n * Check if a class is a \"value object\" — PHP 8 model class whose fields\n * live on the constructor as promoted properties (`public Type $field`).\n * This covers the common generated shape:\n * `readonly class Foo implements \\JsonSerializable { use JsonSerializableTrait;\n * public function __construct(public Type $field, …) {} }`.\n * The parser collects promoted properties under\n * `cls.properties` so any class with at least one public promoted\n * property is a value object — the field set is its identity.\n *\n * Exception classes are explicitly excluded: an exception subclass that\n * happens to declare a public property (e.g. `BaseRequestException` with\n * a `$requestId` field) is still semantically an exception, not a model.\n * The `isExceptionClass` check is performed by the caller so this stays\n * a pure structural test.\n */\nfunction isValueObjectClass(cls: PhpClass): boolean {\n  if (cls.isInterface) return false;\n  if (cls.constants.length > 0) return false; // enum-shaped, not a model\n  return cls.properties.some((p) => p.visibility === 'public');\n}\n\n/** Check if a class is enum-like (only constants, no public methods). */\nfunction isEnumClass(cls: PhpClass): boolean {\n  if (cls.isInterface) return false;\n  if (cls.constants.length === 0) return false;\n  // Must have only constants — no public instance methods (excluding inherited)\n  const publicMethods = cls.methods.filter((m) => m.visibility === 'public' && m.name !== '__construct');\n  return publicMethods.length === 0 && cls.properties.length === 0 && !cls.extends;\n}\n\n/** Check if a class is an exception. */\nfunction isExceptionClass(cls: PhpClass, exceptionBases: Set<string>): boolean {\n  if (!cls.extends) return false;\n  return exceptionBases.has(cls.extends);\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n  allClasses: PhpClass[],\n  hints?: LanguageHints,\n): {\n  classes: Record<string, ApiClass>;\n  interfaces: Record<string, ApiInterface>;\n  enums: Record<string, ApiEnum>;\n  exports: Record<string, string[]>;\n} {\n  const resourceBases = new Set(hints?.modelBaseClasses ?? DEFAULT_RESOURCE_BASES);\n  const exceptionBases = new Set(hints?.exceptionBaseClasses ?? DEFAULT_EXCEPTION_BASES);\n\n  const classes: Record<string, ApiClass> = {};\n  const interfaces: Record<string, ApiInterface> = {};\n  const enums: Record<string, ApiEnum> = {};\n\n  const collector = new ExportCollector();\n\n  for (const cls of allClasses) {\n    if (cls.isInterface) {\n      // PHP interface → ApiInterface\n      const fields: Record<string, ApiField> = {};\n      for (const method of cls.methods) {\n        if (method.visibility !== 'public') continue;\n        fields[method.name] = {\n          name: method.name,\n          type: method.returnType || 'mixed',\n          optional: false,\n        };\n      }\n      interfaces[cls.name] = {\n        name: cls.name,\n        sourceFile: cls.sourceFile,\n        fields: sortRecord(fields),\n        extends: [],\n      };\n      collector.add(cls.sourceFile, cls.name);\n    } else if (isResourceClass(cls, resourceBases)) {\n      // Resource class → ApiInterface with fields from RESOURCE_ATTRIBUTES\n      // Preserve the original field order (don't sort) — it determines toArray() output order\n      const fields: Record<string, ApiField> = {};\n      for (const attr of cls.resourceAttributes) {\n        fields[attr] = {\n          name: attr,\n          type: 'mixed',\n          optional: false,\n        };\n      }\n      interfaces[cls.name] = {\n        name: cls.name,\n        sourceFile: cls.sourceFile,\n        fields, // Intentionally NOT sorted — order matches RESOURCE_ATTRIBUTES\n        extends: cls.extends ? [cls.extends] : [],\n        ...(cls.hasCustomConstructor ? { hasCustomConstructor: true } : {}),\n      };\n      collector.add(cls.sourceFile, cls.name);\n    } else if (isValueObjectClass(cls) && !isExceptionClass(cls, exceptionBases)) {\n      // PHP 8 value-object class (constructor-promoted properties) →\n      // ApiInterface. The promoted properties are the public fields; the\n      // class's `__construct` / `fromArray` / `toArray` helpers don't\n      // contribute identity. Without this branch the class would fall through\n      // to the service-class path below and lose its field info.\n      const fields: Record<string, ApiField> = {};\n      for (const prop of cls.properties) {\n        if (prop.visibility !== 'public') continue;\n        fields[prop.name] = {\n          name: prop.name,\n          type: prop.type,\n          optional: false,\n        };\n      }\n      interfaces[cls.name] = {\n        name: cls.name,\n        sourceFile: cls.sourceFile,\n        fields, // Intentionally NOT sorted — preserves declaration order.\n        extends: cls.extends ? [cls.extends] : [],\n      };\n      collector.add(cls.sourceFile, cls.name);\n    } else if (isEnumClass(cls)) {\n      // Enum-like class → ApiEnum\n      const members: Record<string, string | number> = {};\n      for (const constant of cls.constants) {\n        members[constant.name] = constant.value;\n      }\n      enums[cls.name] = {\n        name: cls.name,\n        sourceFile: cls.sourceFile,\n        members: sortRecord(members),\n      };\n      collector.add(cls.sourceFile, cls.name);\n    } else {\n      // Service class, static utility class, or exception → ApiClass\n      const apiMethods: Record<string, ApiMethod[]> = {};\n      const properties: Record<string, ApiProperty> = {};\n\n      // Only include public methods\n      for (const method of cls.methods) {\n        if (method.visibility !== 'public') continue;\n\n        const params: ApiParam[] = method.params.map((p) => ({\n          name: p.name,\n          type: p.type,\n          optional: p.optional,\n          passingStyle: 'named' as const,\n        }));\n\n        if (!apiMethods[method.name]) apiMethods[method.name] = [];\n        apiMethods[method.name].push({\n          name: method.name,\n          params,\n          returnType: method.returnType || 'mixed',\n          async: false, // PHP is synchronous\n        });\n      }\n\n      // Include public properties\n      for (const prop of cls.properties) {\n        if (prop.visibility !== 'public') continue;\n        properties[prop.name] = {\n          name: prop.name,\n          type: prop.type,\n          readonly: false,\n        };\n      }\n\n      // Only add if there's something meaningful (methods or properties)\n      if (\n        Object.keys(apiMethods).length > 0 ||\n        Object.keys(properties).length > 0 ||\n        isExceptionClass(cls, exceptionBases)\n      ) {\n        classes[cls.name] = {\n          name: cls.name,\n          sourceFile: cls.sourceFile,\n          methods: sortRecord(apiMethods),\n          properties: sortRecord(properties),\n          constructorParams: [],\n        };\n        collector.add(cls.sourceFile, cls.name);\n      }\n    }\n  }\n\n  const exports = collector.toRecord();\n\n  return {\n    classes: sortRecord(classes),\n    interfaces: sortRecord(interfaces),\n    enums: sortRecord(enums),\n    exports: sortRecord(exports),\n  };\n}\n","/**\n * PHP API surface extractor.\n *\n * Walks `.php` files under `lib/` (or `src/`), parses classes, interfaces,\n * methods, properties, and constants, then builds an `ApiSurface`.\n *\n * Parser:  `php-parser.ts`  — tree-sitter-based PHP source analysis\n * Surface: `php-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkPhpFiles, parsePhpFile } from './php-parser.js';\nimport { buildSurface } from './php-surface.js';\nimport type { PhpClass } from './php-parser.js';\nimport { sortRecord } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst PHP_BODY_TYPES = new Set(['array', 'mixed']);\n\nconst phpHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    // ?string → string\n    if (type.startsWith('?')) return type.slice(1);\n    // null|string → string, string|null → string\n    const parts = type.split('|').filter((p) => p.trim().toLowerCase() !== 'null');\n    if (parts.length < type.split('|').length) return parts.join('|');\n    return null;\n  },\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return defaultIsNullableOnlyDifference(this, a, b);\n  },\n  isUnionReorder(a: string, b: string): boolean {\n    // Parse pipe-separated types, sort, compare\n    const sortParts = (t: string) =>\n      t\n        .split('|')\n        .map((s) => s.trim())\n        .sort()\n        .join('|');\n    return a !== b && sortParts(a) === sortParts(b);\n  },\n  isGenericTypeParam(_type: string): boolean {\n    return false; // PHP has no generics\n  },\n  isExtractionArtifact(type: string): boolean {\n    return type === 'mixed' || type === 'Object';\n  },\n  tolerateCategoryMismatch: false,\n  extractReturnTypeName(returnType: string): string | null {\n    // Strip nullable: ?Foo → Foo, null|Foo → Foo\n    const stripped = this.stripNullable(returnType) ?? returnType;\n    if (['string', 'int', 'float', 'bool', 'void', 'array', 'mixed'].includes(stripped)) return null;\n    return stripped.replace(/^\\\\/, '');\n  },\n  extractParamTypeName(paramType: string): string | null {\n    const stripped = this.stripNullable(paramType) ?? paramType;\n    if (['string', 'int', 'float', 'bool', 'void', 'array', 'mixed', 'null', 'callable'].includes(stripped)) {\n      return null;\n    }\n    return stripped.replace(/^\\\\/, '');\n  },\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    // camelCase → PascalCase comparison\n    return propertyName.toLowerCase() === className.toLowerCase();\n  },\n  derivedModelNames(_modelName: string): string[] {\n    return [];\n  },\n\n  isSignatureEquivalent(\n    baseline: import('../types.js').ApiMethod,\n    candidate: import('../types.js').ApiMethod,\n    _candidateSurface: import('../types.js').ApiSurface,\n  ): boolean {\n    // Tolerate return type differences common in PHP SDK compat:\n    // - mixed ≡ any specific return type (resource response ≡ void, etc.)\n    // - array ≡ mixed ≡ specific resource type\n    const returnOk =\n      baseline.returnType === candidate.returnType ||\n      baseline.returnType === 'mixed' ||\n      candidate.returnType === 'mixed' ||\n      (baseline.returnType === 'void' && candidate.returnType === 'void') ||\n      (baseline.returnType === 'array' && candidate.returnType === 'array');\n\n    // More lenient: tolerate any return type difference when one side is a\n    // namespace-qualified resource type.\n    const returnTolerated =\n      returnOk || baseline.returnType.includes('\\\\Resource\\\\') || candidate.returnType.includes('\\\\Resource\\\\');\n\n    if (!returnTolerated) return false;\n\n    // Case 1: Same number of required params, just name differences.\n    // The spec may use generic names (id) while the live SDK uses domain names (organization).\n    // Tolerate when the types match but names differ.\n    if (baseline.params.length === candidate.params.length) {\n      let allTypesMatch = true;\n      for (let i = 0; i < baseline.params.length; i++) {\n        if (baseline.params[i].type !== candidate.params[i].type) {\n          allTypesMatch = false;\n          break;\n        }\n      }\n      if (allTypesMatch) return true;\n    }\n\n    // Case 2: Candidate uses array $options / array $payload for body/query params\n    // while baseline has explicit typed params.\n    // Tolerate when the candidate's params are a prefix of the baseline\n    // followed by an array/mixed param that absorbs the rest.\n    const candHasArrayParam = candidate.params.some((p) => PHP_BODY_TYPES.has(p.type));\n    if (candHasArrayParam) return true;\n\n    // Case 3: Baseline has explicit params that the candidate absorbs into path params\n    // with different names (e.g., organization vs id)\n    if (baseline.params.length >= 1 && candidate.params.length >= 1) {\n      // Check if all param types match (allow name differences)\n      let typeMatch = true;\n      const minLen = Math.min(baseline.params.length, candidate.params.length);\n      for (let i = 0; i < minLen; i++) {\n        if (baseline.params[i].type !== candidate.params[i].type) {\n          typeMatch = false;\n          break;\n        }\n      }\n      // Extra candidate params must be optional\n      if (typeMatch) {\n        const extraCandOk = candidate.params.slice(minLen).every((p) => p.optional);\n        const extraBaseOk = baseline.params.slice(minLen).every((p) => p.optional);\n        if (extraCandOk && extraBaseOk) return true;\n      }\n    }\n\n    return false;\n  },\n\n  modelBaseClasses: [],\n  exceptionBaseClasses: ['Exception', '\\\\Exception'],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a PHP extractor with optional hint overrides. */\nexport function createPhpExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n  const mergedHints: LanguageHints = hintOverrides ? { ...phpHints, ...hintOverrides } : phpHints;\n\n  return {\n    language: 'php',\n    hints: mergedHints,\n\n    async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n      const surface = await this.extract(sdkPath);\n      return apiSurfaceToSnapshot(surface);\n    },\n\n    async extract(sdkPath: string): Promise<ApiSurface> {\n      // Determine the source directory: prefer lib/, fallback to src/\n      let sourceDir: string;\n      const libPath = resolve(sdkPath, 'lib');\n      const srcPath = resolve(sdkPath, 'src');\n\n      try {\n        statSync(libPath);\n        sourceDir = libPath;\n      } catch {\n        try {\n          statSync(srcPath);\n          sourceDir = srcPath;\n        } catch {\n          throw new ExtractorError(\n            `No lib/ or src/ directory found in ${sdkPath}`,\n            `Ensure the --sdk-path argument points to a PHP project root containing a lib/ or src/ directory.`,\n          );\n        }\n      }\n\n      const phpFiles = walkPhpFiles(sourceDir);\n      if (phpFiles.length === 0) {\n        throw new ExtractorError(\n          `No .php files found in ${sourceDir}`,\n          `Ensure the source directory contains PHP source files.`,\n        );\n      }\n\n      const allClasses: PhpClass[] = [];\n\n      for (const filePath of phpFiles) {\n        const parsed = parsePhpFile(filePath, sdkPath);\n        allClasses.push(...parsed.classes);\n      }\n\n      const { classes, interfaces, enums, exports } = buildSurface(allClasses, mergedHints);\n\n      return {\n        language: 'php',\n        extractedFrom: sdkPath,\n        extractedAt: new Date().toISOString(),\n        classes: sortRecord(classes),\n        interfaces: sortRecord(interfaces),\n        typeAliases: {},\n        enums: sortRecord(enums),\n        exports: sortRecord(exports),\n      };\n    },\n  };\n}\n\n/** Default PHP extractor with generic language hints (no SDK-specific bases). */\nexport const phpExtractor: Extractor = createPhpExtractor();\n","/** Python source parser — tree-sitter-based extraction of classes, type aliases, and symbols. */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport Python from 'tree-sitter-python';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface PythonField {\n  name: string;\n  type: string;\n  hasDefault: boolean;\n}\n\nexport interface PythonMethod {\n  name: string;\n  params: {\n    name: string;\n    type: string;\n    optional: boolean;\n    passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n  }[];\n  returnType: string;\n  isAsync: boolean;\n  isProperty: boolean;\n  isClassMethod: boolean;\n  isStaticMethod: boolean;\n}\n\nexport interface PythonClass {\n  name: string;\n  bases: string[];\n  fields: PythonField[];\n  methods: PythonMethod[];\n  decorators: string[];\n  sourceFile: string;\n}\n\nexport interface PythonTypeAlias {\n  name: string;\n  value: string;\n  sourceFile: string;\n}\n\nexport interface PythonImport {\n  names: string[];\n  sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst pythonParser = new Parser();\npythonParser.setLanguage(Python);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkPythonFiles(dir: string): string[] {\n  const results: string[] = [];\n  let entries: string[];\n  try {\n    entries = readdirSync(dir);\n  } catch {\n    return results;\n  }\n  for (const entry of entries) {\n    const fullPath = join(dir, entry);\n    let stat;\n    try {\n      stat = statSync(fullPath);\n    } catch {\n      continue;\n    }\n    if (stat.isDirectory()) {\n      if (\n        entry.startsWith('.') ||\n        entry === '__pycache__' ||\n        entry === 'tests' ||\n        entry === 'test' ||\n        entry === 'node_modules'\n      )\n        continue;\n      results.push(...walkPythonFiles(fullPath));\n    } else if (entry.endsWith('.py')) {\n      // Skip test files\n      if (entry.endsWith('_test.py') || entry.startsWith('test_')) continue;\n      // Skip dunder modules (but include __init__.py). Single-underscore files\n      // like `_resource.py` or `_client.py` are an internal-by-convention\n      // pattern whose symbols get re-exported via `__init__.py`, so they carry\n      // public API surface and must be walked.\n      if (entry.startsWith('__') && entry !== '__init__.py') continue;\n      results.push(fullPath);\n    }\n  }\n  return results.sort();\n}\n\n/** Find the Python source root (prefers `src/`, falls back to top-level package). */\n/** True if a directory looks like a Python package (has __init__.py or .py files). */\nfunction isPythonPackageDir(dir: string): boolean {\n  try {\n    statSync(join(dir, '__init__.py'));\n    return true;\n  } catch {\n    // no __init__.py — check for .py files as a fallback\n    // (generated output may omit __init__.py when it's hand-maintained)\n  }\n  try {\n    const entries = readdirSync(dir);\n    return entries.some((e) => e.endsWith('.py'));\n  } catch {\n    return false;\n  }\n}\n\nexport function findPythonSourceRoot(sdkPath: string): string | null {\n  // Strategy 1: src/ directory\n  const srcDir = join(sdkPath, 'src');\n  try {\n    const stat = statSync(srcDir);\n    if (stat.isDirectory()) {\n      const entries = readdirSync(srcDir);\n      for (const entry of entries) {\n        const pkgDir = join(srcDir, entry);\n        try {\n          const pkgStat = statSync(pkgDir);\n          if (pkgStat.isDirectory() && isPythonPackageDir(pkgDir)) {\n            return srcDir;\n          }\n        } catch {\n          continue;\n        }\n      }\n    }\n  } catch {\n    // no src/, continue\n  }\n\n  // Strategy 2: top-level package directory\n  try {\n    const entries = readdirSync(sdkPath);\n    for (const entry of entries) {\n      if (entry.startsWith('.') || entry === 'tests' || entry === 'test' || entry === 'node_modules') continue;\n      const pkgDir = join(sdkPath, entry);\n      try {\n        const pkgStat = statSync(pkgDir);\n        if (pkgStat.isDirectory() && isPythonPackageDir(pkgDir)) {\n          return sdkPath;\n        }\n      } catch {\n        continue;\n      }\n    }\n  } catch {\n    // can't read sdkPath\n  }\n\n  return null;\n}\n\n/** Get all decorator names from a decorated_definition or class_definition. */\nfunction getDecorators(node: SyntaxNode): string[] {\n  const decorators: string[] = [];\n  // Decorated definition wraps the class or function\n  if (node.type === 'decorated_definition') {\n    for (const child of node.namedChildren) {\n      if (child.type === 'decorator') {\n        const exprNode = child.namedChildren[0];\n        if (exprNode) decorators.push(exprNode.text);\n      }\n    }\n  }\n  return decorators;\n}\n\n/** Extract base class names from a class definition's argument_list. */\nfunction getBaseClasses(classNode: SyntaxNode): string[] {\n  const bases: string[] = [];\n  const argList = classNode.childForFieldName('superclasses');\n  if (!argList) return bases;\n\n  for (const child of argList.namedChildren) {\n    if (child.type === 'identifier' || child.type === 'attribute') {\n      bases.push(child.text);\n    } else if (child.type === 'keyword_argument') {\n      // skip keyword arguments like total=False\n    }\n  }\n  return bases;\n}\n\n/** Extract annotated fields from a class body. */\nfunction extractClassFields(bodyNode: SyntaxNode): PythonField[] {\n  const fields: PythonField[] = [];\n\n  for (const child of bodyNode.namedChildren) {\n    if (child.type !== 'expression_statement') continue;\n\n    const stmtChild = child.namedChildren[0];\n    if (!stmtChild || stmtChild.type !== 'assignment') continue;\n\n    const left = stmtChild.childForFieldName('left');\n    const typeNode = stmtChild.childForFieldName('type');\n\n    // Must be an annotated assignment (has a type annotation)\n    if (!left || !typeNode) continue;\n    // Only simple identifier on left side (not tuple unpacking, etc.)\n    if (left.type !== 'identifier') continue;\n\n    const right = stmtChild.childForFieldName('right');\n\n    fields.push({\n      name: left.text,\n      type: typeNode.text,\n      hasDefault: right !== null,\n    });\n  }\n  return fields;\n}\n\n/** Extract methods from a class body. */\nfunction extractClassMethods(bodyNode: SyntaxNode): PythonMethod[] {\n  const methods: PythonMethod[] = [];\n\n  for (const child of bodyNode.namedChildren) {\n    let funcNode: SyntaxNode | null = null;\n    let decorators: string[] = [];\n\n    if (child.type === 'decorated_definition') {\n      decorators = getDecorators(child);\n      // The actual function/class is the last named child\n      funcNode = child.namedChildren.find((c) => c.type === 'function_definition') || null;\n    } else if (child.type === 'function_definition') {\n      funcNode = child;\n    }\n\n    if (!funcNode) continue;\n\n    const nameNode = funcNode.childForFieldName('name');\n    if (!nameNode) continue;\n    const methodName = nameNode.text;\n\n    // Skip private methods (starting with _) but keep __init__\n    if (methodName.startsWith('_') && methodName !== '__init__') continue;\n\n    const isAsync = funcNode.namedChildren.some((c) => c.type === 'async');\n    const isProperty = decorators.includes('property');\n    const isClassMethod = decorators.includes('classmethod');\n    const isStaticMethod = decorators.includes('staticmethod');\n\n    // Extract parameters\n    const paramsNode = funcNode.childForFieldName('parameters');\n    const params = extractFunctionParams(paramsNode, isStaticMethod || isClassMethod);\n\n    // Extract return type\n    const returnTypeNode = funcNode.childForFieldName('return_type');\n    const returnType = returnTypeNode ? returnTypeNode.text : '';\n\n    methods.push({\n      name: methodName,\n      params,\n      returnType,\n      isAsync,\n      isProperty,\n      isClassMethod,\n      isStaticMethod,\n    });\n  }\n\n  return methods;\n}\n\n/** Extract parameters from a function's parameter list. */\nfunction extractFunctionParams(\n  paramsNode: SyntaxNode | null,\n  skipFirst: boolean,\n): {\n  name: string;\n  type: string;\n  optional: boolean;\n  passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n}[] {\n  if (!paramsNode) return [];\n  const params: {\n    name: string;\n    type: string;\n    optional: boolean;\n    passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n  }[] = [];\n  let skippedFirst = false;\n  let seenStarMarker = false;\n\n  for (const child of paramsNode.namedChildren) {\n    // Skip `self` or `cls` parameter\n    if (!skippedFirst && !skipFirst && child.type === 'identifier' && (child.text === 'self' || child.text === 'cls')) {\n      skippedFirst = true;\n      continue;\n    }\n    if (!skippedFirst && !skipFirst && child.type === 'typed_parameter' && child.namedChildren[0]?.text === 'self') {\n      skippedFirst = true;\n      continue;\n    }\n\n    // `*` separator in parameters (keyword-only marker)\n    if (child.text === '*') {\n      seenStarMarker = true;\n      continue;\n    }\n\n    // *args — variadic positional (also marks subsequent params as keyword-only)\n    if (child.type === 'list_splat_pattern') {\n      seenStarMarker = true;\n      const nameNode = child.namedChildren.find((c: SyntaxNode) => c.type === 'identifier');\n      params.push({\n        name: nameNode ? `*${nameNode.text}` : '*args',\n        type: '',\n        optional: true,\n        passingStyle: 'positional',\n      });\n      continue;\n    }\n\n    // **kwargs — variadic keyword\n    if (child.type === 'dictionary_splat_pattern') {\n      const nameNode = child.namedChildren.find((c: SyntaxNode) => c.type === 'identifier');\n      params.push({\n        name: nameNode ? `**${nameNode.text}` : '**kwargs',\n        type: '',\n        optional: true,\n        passingStyle: 'keyword',\n      });\n      continue;\n    }\n\n    const passingStyle = seenStarMarker ? ('keyword' as const) : ('keyword_or_positional' as const);\n\n    if (child.type === 'typed_parameter') {\n      const nameNode = child.namedChildren.find((c) => c.type === 'identifier');\n      const typeNode = child.childForFieldName('type');\n      if (nameNode) {\n        params.push({\n          name: nameNode.text,\n          type: typeNode ? typeNode.text : '',\n          optional: false,\n          passingStyle,\n        });\n      }\n    } else if (child.type === 'typed_default_parameter') {\n      const nameNode = child.childForFieldName('name');\n      const typeNode = child.childForFieldName('type');\n      if (nameNode) {\n        params.push({\n          name: nameNode.text,\n          type: typeNode ? typeNode.text : '',\n          optional: true,\n          passingStyle,\n        });\n      }\n    } else if (child.type === 'default_parameter') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) {\n        params.push({\n          name: nameNode.text,\n          type: '',\n          optional: true,\n          passingStyle,\n        });\n      }\n    } else if (child.type === 'identifier') {\n      params.push({\n        name: child.text,\n        type: '',\n        optional: false,\n        passingStyle,\n      });\n    }\n  }\n\n  return params;\n}\n\n/** Extract module-level type aliases (e.g., FooType = Literal[\"a\", \"b\"]). */\nfunction extractTypeAliases(tree: Parser.Tree, sourceFile: string): PythonTypeAlias[] {\n  const aliases: PythonTypeAlias[] = [];\n\n  for (const node of tree.rootNode.namedChildren) {\n    // type alias statement (Python 3.12+): type X = ...\n    if (node.type === 'type_alias_statement') {\n      const nameNode = node.childForFieldName('name');\n      const valueNode = node.childForFieldName('value');\n      if (nameNode && valueNode) {\n        aliases.push({ name: nameNode.text, value: valueNode.text, sourceFile });\n      }\n      continue;\n    }\n\n    // Assignment: X = Literal[...] or X = \"SomeResource[...]\"\n    if (node.type === 'expression_statement') {\n      const inner = node.namedChildren[0];\n      if (!inner || inner.type !== 'assignment') continue;\n\n      const left = inner.childForFieldName('left');\n      const right = inner.childForFieldName('right');\n      if (!left || !right) continue;\n\n      // Only consider simple name assignments (not a: type = value)\n      if (left.type !== 'identifier') continue;\n\n      const name = left.text;\n      // Skip private names and dunder names\n      if (name.startsWith('_')) continue;\n      // Skip ALL_CAPS constants that are not type aliases\n      if (/^[A-Z][A-Z_0-9]*$/.test(name)) continue;\n\n      const value = right.text;\n\n      // Only take subscript expressions (Literal[...], SomeResource[...], etc.)\n      // or string literals that look like type aliases\n      if (right.type === 'subscript' || (right.type === 'string' && value.includes('['))) {\n        // For string literals, strip quotes\n        let cleanValue = value;\n        if (right.type === 'string') {\n          cleanValue = value.replace(/^[\"']|[\"']$/g, '');\n        }\n        aliases.push({ name, value: cleanValue, sourceFile });\n      }\n    }\n  }\n\n  return aliases;\n}\n\n/** Extract __all__ exports from a module. */\nfunction extractAllExports(tree: Parser.Tree): string[] {\n  const exports: string[] = [];\n\n  for (const node of tree.rootNode.namedChildren) {\n    if (node.type !== 'expression_statement') continue;\n    const inner = node.namedChildren[0];\n    if (!inner || inner.type !== 'assignment') continue;\n\n    const left = inner.childForFieldName('left');\n    const right = inner.childForFieldName('right');\n    if (!left || !right) continue;\n    if (left.text !== '__all__') continue;\n\n    // __all__ = [\"Foo\", \"Bar\"]\n    if (right.type === 'list') {\n      for (const elem of right.namedChildren) {\n        if (elem.type === 'string') {\n          const text = elem.text.replace(/^[\"']|[\"']$/g, '');\n          exports.push(text);\n        }\n      }\n    }\n  }\n\n  return exports;\n}\n\nfunction extractClassesFromTree(tree: Parser.Tree, sourceFile: string): PythonClass[] {\n  const classes: PythonClass[] = [];\n\n  for (const node of tree.rootNode.namedChildren) {\n    let classNode: SyntaxNode | null = null;\n    let decorators: string[] = [];\n\n    if (node.type === 'decorated_definition') {\n      decorators = getDecorators(node);\n      classNode = node.namedChildren.find((c) => c.type === 'class_definition') || null;\n    } else if (node.type === 'class_definition') {\n      classNode = node;\n    }\n\n    if (!classNode) continue;\n\n    const nameNode = classNode.childForFieldName('name');\n    if (!nameNode) continue;\n    const className = nameNode.text;\n\n    const bases = getBaseClasses(classNode);\n\n    const bodyNode = classNode.childForFieldName('body');\n    if (!bodyNode) {\n      classes.push({ name: className, bases, fields: [], methods: [], decorators, sourceFile });\n      continue;\n    }\n\n    const fields = extractClassFields(bodyNode);\n    const methods = extractClassMethods(bodyNode);\n\n    classes.push({ name: className, bases, fields, methods, decorators, sourceFile });\n  }\n\n  return classes;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedPythonFile {\n  classes: PythonClass[];\n  typeAliases: PythonTypeAlias[];\n  allExports: string[];\n  sourceFile: string;\n}\n\n/** Parse a single Python source file and return all extracted symbols. */\nexport function parsePythonFile(filePath: string, sdkPath: string): ParsedPythonFile {\n  const source = readFileSync(filePath, 'utf-8');\n  const relPath = relative(sdkPath, filePath);\n  const tree = safeParse(pythonParser, source);\n\n  const classes = extractClassesFromTree(tree, relPath);\n  const typeAliases = extractTypeAliases(tree, relPath);\n  const allExports = extractAllExports(tree);\n\n  return { classes, typeAliases, allExports, sourceFile: relPath };\n}\n","/**\n * Python surface builder — transforms parsed Python symbols into an ApiSurface.\n *\n * Mapping:\n *   class Foo(BaseModel/custom model)  → ApiInterface (fields from annotations)\n *   class Foo(TypedDict)              → ApiInterface (fields)\n *   class Foo(Protocol)               → ApiClass (canonical service)\n *   Sync/Async impl classes           → skip (Protocol takes precedence)\n *   FooType = Literal[...]            → ApiEnum (members = literal strings)\n *   FooResource = ListResource[...]    → ApiTypeAlias\n *   Exception subclass                → ApiClass\n *   Other class with methods          → ApiClass\n */\n\nimport type {\n  ApiClass,\n  ApiMethod,\n  ApiParam,\n  ApiInterface,\n  ApiField,\n  ApiTypeAlias,\n  ApiEnum,\n  LanguageHints,\n} from '../types.js';\nimport type { PythonClass, ParsedPythonFile } from './python-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Default model base classes. Overridden by hints.modelBaseClasses when provided. */\nconst DEFAULT_MODEL_BASES: string[] = [];\n\n/** Known dict-like base classes (→ ApiInterface). */\nconst DICT_BASES = new Set(['TypedDict']);\n\n/** Known protocol bases (→ ApiClass as service). */\nconst PROTOCOL_BASES = new Set(['Protocol']);\n\n/** Default exception bases. Overridden by hints.exceptionBaseClasses when provided. */\nconst DEFAULT_EXCEPTION_BASES = ['Exception', 'BaseException'];\n\n/** Check if a class has any of the given base classes (by simple name). */\nfunction hasBase(cls: PythonClass, bases: Set<string>): boolean {\n  return cls.bases.some((b) => bases.has(b));\n}\n\n/**\n * True when the class carries a `@dataclass` decorator (with or without\n * arguments — `@dataclass`, `@dataclass()`, `@dataclass(slots=True)`, etc.).\n *\n * Dataclasses are the canonical \"data-shape\" Python construct: their\n * structural identity is the field set, even when generated alongside\n * helper methods like `from_dict` / `to_dict`. Without this signal the\n * extractor categorizes them as plain method-bearing classes (category 5)\n * and loses the field info — which then prevents the compat differ from\n * recognizing renames structurally.\n */\nfunction isDataclass(cls: PythonClass): boolean {\n  return cls.decorators.some((d) => /^dataclass(\\s*\\(.*\\))?$/.test(d));\n}\n\n/** Check if a class is a model class (inherits from BaseModel or configured model bases,\n *  transitively from another class that does). */\nfunction isModelClass(cls: PythonClass, allClasses: Map<string, PythonClass>, modelBases: Set<string>): boolean {\n  if (hasBase(cls, modelBases)) return true;\n  // Check transitively: if parent class is a model\n  for (const base of cls.bases) {\n    const parentCls = allClasses.get(base);\n    if (parentCls && isModelClass(parentCls, allClasses, modelBases)) return true;\n  }\n  return false;\n}\n\n/** Check if a class is an exception class. */\nfunction isExceptionClass(\n  cls: PythonClass,\n  allClasses: Map<string, PythonClass>,\n  exceptionBases: Set<string>,\n): boolean {\n  if (hasBase(cls, exceptionBases)) return true;\n  for (const base of cls.bases) {\n    const parentCls = allClasses.get(base);\n    if (parentCls && isExceptionClass(parentCls, allClasses, exceptionBases)) return true;\n  }\n  return false;\n}\n\n/** Parse Literal[\"a\", \"b\", \"c\"] into member strings. */\nfunction parseLiteralMembers(value: string): Record<string, string> | null {\n  const match = value.match(/^Literal\\[(.+)\\]$/s);\n  if (!match) return null;\n\n  const inner = match[1];\n  const members: Record<string, string> = {};\n\n  // Split by comma, handling nested brackets\n  const parts: string[] = [];\n  let depth = 0;\n  let current = '';\n  for (const char of inner) {\n    if (char === '[' || char === '(') depth++;\n    else if (char === ']' || char === ')') depth--;\n    else if (char === ',' && depth === 0) {\n      parts.push(current.trim());\n      current = '';\n      continue;\n    }\n    current += char;\n  }\n  if (current.trim()) parts.push(current.trim());\n\n  for (const part of parts) {\n    // Strip quotes\n    const stripped = part.replace(/^[\"']|[\"']$/g, '');\n    if (stripped) {\n      members[stripped] = stripped;\n    }\n  }\n\n  return Object.keys(members).length > 0 ? members : null;\n}\n\n/** Unwrap SyncOrAsync[T] → T. */\nfunction unwrapReturnType(returnType: string): string {\n  const syncOrAsyncMatch = returnType.match(/^SyncOrAsync\\[(.+)\\]$/);\n  if (syncOrAsyncMatch) return syncOrAsyncMatch[1];\n  const awaitableMatch = returnType.match(/^Awaitable\\[(.+)\\]$/);\n  if (awaitableMatch) return awaitableMatch[1];\n  return returnType;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n  parsedFiles: ParsedPythonFile[],\n  hints?: LanguageHints,\n): {\n  classes: Record<string, ApiClass>;\n  interfaces: Record<string, ApiInterface>;\n  typeAliases: Record<string, ApiTypeAlias>;\n  enums: Record<string, ApiEnum>;\n  exports: Record<string, string[]>;\n} {\n  const MODEL_BASES = new Set(hints?.modelBaseClasses ?? DEFAULT_MODEL_BASES);\n  const EXCEPTION_BASES = new Set(hints?.exceptionBaseClasses ?? DEFAULT_EXCEPTION_BASES);\n\n  const classes: Record<string, ApiClass> = {};\n  const interfaces: Record<string, ApiInterface> = {};\n  const typeAliases: Record<string, ApiTypeAlias> = {};\n  const enums: Record<string, ApiEnum> = {};\n\n  // Collect all classes for transitive base lookups\n  const allClassesByName = new Map<string, PythonClass>();\n  for (const file of parsedFiles) {\n    for (const cls of file.classes) {\n      allClassesByName.set(cls.name, cls);\n    }\n  }\n\n  // Track protocol class names to skip sync/async impls\n  const protocolNames = new Set<string>();\n  for (const file of parsedFiles) {\n    for (const cls of file.classes) {\n      if (hasBase(cls, PROTOCOL_BASES)) {\n        protocolNames.add(cls.name);\n      }\n    }\n  }\n\n  // Build export map from __all__ and file-level symbols\n  const collector = new ExportCollector();\n\n  for (const file of parsedFiles) {\n    // Process type aliases\n    for (const alias of file.typeAliases) {\n      const literalMembers = parseLiteralMembers(alias.value);\n      if (literalMembers) {\n        // Literal type alias → ApiEnum\n        enums[alias.name] = {\n          name: alias.name,\n          sourceFile: alias.sourceFile,\n          members: sortRecord(literalMembers),\n        };\n        collector.add(alias.sourceFile, alias.name);\n      } else {\n        // Regular type alias → ApiTypeAlias\n        typeAliases[alias.name] = {\n          name: alias.name,\n          sourceFile: alias.sourceFile,\n          value: alias.value,\n        };\n        collector.add(alias.sourceFile, alias.name);\n      }\n    }\n\n    // Process classes\n    for (const cls of file.classes) {\n      // 1. Protocol classes → ApiClass (canonical service)\n      if (hasBase(cls, PROTOCOL_BASES)) {\n        const apiMethods: Record<string, ApiMethod[]> = {};\n\n        for (const method of cls.methods) {\n          // Skip __init__ for protocols (they don't have constructors)\n          if (method.name === '__init__') continue;\n\n          const params: ApiParam[] = method.params.map((p) => ({\n            name: p.name,\n            type: p.type,\n            optional: p.optional,\n            ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n          }));\n\n          const returnType = unwrapReturnType(method.returnType);\n\n          if (!apiMethods[method.name]) apiMethods[method.name] = [];\n          apiMethods[method.name].push({\n            name: method.name,\n            params,\n            returnType,\n            async: method.isAsync,\n          });\n        }\n\n        classes[cls.name] = {\n          name: cls.name,\n          sourceFile: cls.sourceFile,\n          methods: sortRecord(apiMethods),\n          properties: {},\n          constructorParams: [],\n        };\n        collector.add(cls.sourceFile, cls.name);\n        continue;\n      }\n\n      // 2. Model classes (BaseModel or configured model bases) → ApiInterface\n      if (isModelClass(cls, allClassesByName, MODEL_BASES)) {\n        const fields: Record<string, ApiField> = {};\n        for (const field of cls.fields) {\n          fields[field.name] = {\n            name: field.name,\n            type: field.type,\n            optional: field.hasDefault,\n          };\n        }\n\n        // Compute extends list: filter out model bases themselves\n        const extendsArr = cls.bases.filter((b) => !MODEL_BASES.has(b) && allClassesByName.has(b));\n\n        interfaces[cls.name] = {\n          name: cls.name,\n          sourceFile: cls.sourceFile,\n          fields: sortRecord(fields),\n          extends: extendsArr,\n        };\n        collector.add(cls.sourceFile, cls.name);\n        continue;\n      }\n\n      // 3. TypedDict classes → ApiInterface\n      if (hasBase(cls, DICT_BASES)) {\n        const fields: Record<string, ApiField> = {};\n        for (const field of cls.fields) {\n          fields[field.name] = {\n            name: field.name,\n            type: field.type,\n            optional: field.hasDefault,\n          };\n        }\n\n        interfaces[cls.name] = {\n          name: cls.name,\n          sourceFile: cls.sourceFile,\n          fields: sortRecord(fields),\n          extends: [],\n        };\n        collector.add(cls.sourceFile, cls.name);\n        continue;\n      }\n\n      // 4. Exception classes → ApiClass\n      if (isExceptionClass(cls, allClassesByName, EXCEPTION_BASES)) {\n        const apiMethods: Record<string, ApiMethod[]> = {};\n        // Extract any non-private, non-init methods\n        for (const method of cls.methods) {\n          if (method.name === '__init__') continue;\n          const params: ApiParam[] = method.params.map((p) => ({\n            name: p.name,\n            type: p.type,\n            optional: p.optional,\n            ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n          }));\n          if (!apiMethods[method.name]) apiMethods[method.name] = [];\n          apiMethods[method.name].push({\n            name: method.name,\n            params,\n            returnType: unwrapReturnType(method.returnType),\n            async: method.isAsync,\n          });\n        }\n\n        // Exception fields as properties if they have annotations\n        const fields: Record<string, ApiField> = {};\n        for (const field of cls.fields) {\n          fields[field.name] = {\n            name: field.name,\n            type: field.type,\n            optional: field.hasDefault,\n          };\n        }\n\n        classes[cls.name] = {\n          name: cls.name,\n          sourceFile: cls.sourceFile,\n          methods: sortRecord(apiMethods),\n          properties: {},\n          constructorParams: [],\n        };\n        collector.add(cls.sourceFile, cls.name);\n        continue;\n      }\n\n      // 4b. Dataclasses → ApiInterface. A `@dataclass`-decorated class is\n      //     fundamentally a data-shape; its structural identity is the\n      //     field set even when oagen also emits `from_dict` / `to_dict`\n      //     helper methods on it. Without this branch the class falls\n      //     through to category 5 (ApiClass with methods) and the field\n      //     info is dropped — which prevents the compat differ from\n      //     pairing renamed types structurally.\n      if (isDataclass(cls) && cls.fields.length > 0) {\n        const fields: Record<string, ApiField> = {};\n        for (const field of cls.fields) {\n          fields[field.name] = {\n            name: field.name,\n            type: field.type,\n            optional: field.hasDefault,\n          };\n        }\n        interfaces[cls.name] = {\n          name: cls.name,\n          sourceFile: cls.sourceFile,\n          fields: sortRecord(fields),\n          extends: [],\n        };\n        collector.add(cls.sourceFile, cls.name);\n        continue;\n      }\n\n      // 5. Other class with methods → ApiClass\n      if (cls.methods.length > 0) {\n        const apiMethods: Record<string, ApiMethod[]> = {};\n        const constructorParams: ApiParam[] = [];\n\n        for (const method of cls.methods) {\n          if (method.name === '__init__') {\n            constructorParams.push(\n              ...method.params.map((p) => ({\n                name: p.name,\n                type: p.type,\n                optional: p.optional,\n                ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n              })),\n            );\n            continue;\n          }\n\n          const params: ApiParam[] = method.params.map((p) => ({\n            name: p.name,\n            type: p.type,\n            optional: p.optional,\n            ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n          }));\n          if (!apiMethods[method.name]) apiMethods[method.name] = [];\n          apiMethods[method.name].push({\n            name: method.name,\n            params,\n            returnType: unwrapReturnType(method.returnType),\n            async: method.isAsync,\n          });\n        }\n\n        classes[cls.name] = {\n          name: cls.name,\n          sourceFile: cls.sourceFile,\n          methods: sortRecord(apiMethods),\n          properties: {},\n          constructorParams,\n        };\n        collector.add(cls.sourceFile, cls.name);\n        continue;\n      }\n\n      // 6. Class with only fields and no methods → ApiInterface\n      if (cls.fields.length > 0) {\n        const fields: Record<string, ApiField> = {};\n        for (const field of cls.fields) {\n          fields[field.name] = {\n            name: field.name,\n            type: field.type,\n            optional: field.hasDefault,\n          };\n        }\n        interfaces[cls.name] = {\n          name: cls.name,\n          sourceFile: cls.sourceFile,\n          fields: sortRecord(fields),\n          extends: [],\n        };\n        collector.add(cls.sourceFile, cls.name);\n      }\n    }\n\n    // Add __all__ exports\n    if (file.allExports.length > 0) {\n      for (const name of file.allExports) {\n        collector.add(file.sourceFile, name);\n      }\n    }\n  }\n\n  const exports = collector.toRecord();\n\n  return {\n    classes: sortRecord(classes),\n    interfaces: sortRecord(interfaces),\n    typeAliases: sortRecord(typeAliases),\n    enums: sortRecord(enums),\n    exports: sortRecord(exports),\n  };\n}\n","/**\n * Python API surface extractor.\n *\n * Walks `.py` files under `src/` (fallback to top-level package dirs),\n * parses classes, type aliases, and module exports, then builds an\n * `ApiSurface` with Protocol-based services, Pydantic model interfaces,\n * Literal type enums, and exception classes.\n *\n * Parser:  `python-parser.ts`  — tree-sitter-based Python source analysis\n * Surface: `python-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport {\n  NAMED_TYPE_RE,\n  typeExistsInSurface,\n  namedTypeWordsOverlap,\n  defaultIsNullableOnlyDifference,\n} from '../language-hints.js';\nimport { walkPythonFiles, findPythonSourceRoot, parsePythonFile } from './python-parser.js';\nimport { buildSurface } from './python-surface.js';\nimport type { ParsedPythonFile } from './python-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst PYTHON_PRIMITIVE_TYPES = new Set(['str', 'int', 'float', 'bool', 'bytes']);\n\nconst pythonHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    // Normalize whitespace before matching\n    const normalized = type.replace(/\\s+/g, ' ').trim();\n    // Optional[T] → T\n    const optMatch = normalized.match(/^Optional\\[(.+)\\]$/);\n    if (optMatch) return optMatch[1].trim();\n    // NotRequired[T] → T (TypedDict optionality ≡ nullable for compat purposes)\n    const nrMatch = normalized.match(/^NotRequired\\[(.+)\\]$/);\n    if (nrMatch) return nrMatch[1].trim();\n    // T | None → T, None | T → T\n    const parts = normalized\n      .split('|')\n      .map((p) => p.trim())\n      .filter((p) => p !== 'None');\n    if (parts.length < normalized.split('|').length) return parts.join(' | ');\n    return null;\n  },\n\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return defaultIsNullableOnlyDifference(this, a, b);\n  },\n\n  isUnionReorder(a: string, b: string): boolean {\n    const parseUnion = (t: string) => {\n      const unionMatch = t.match(/^Union\\[(.+)\\]$/);\n      if (unionMatch)\n        return unionMatch[1]\n          .split(',')\n          .map((s) => s.trim())\n          .sort();\n      return t\n        .split('|')\n        .map((s) => s.trim())\n        .sort();\n    };\n    return a !== b && parseUnion(a).join(',') === parseUnion(b).join(',');\n  },\n\n  isGenericTypeParam(type: string): boolean {\n    return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n  },\n\n  isExtractionArtifact(type: string): boolean {\n    return type === 'Any' || type === 'object';\n  },\n\n  tolerateCategoryMismatch: true,\n\n  extractReturnTypeName(returnType: string): string | null {\n    let inner = returnType;\n    const syncOrAsyncMatch = inner.match(/^SyncOrAsync\\[(.+)\\]$/);\n    if (syncOrAsyncMatch) inner = syncOrAsyncMatch[1];\n    const awaitableMatch = inner.match(/^Awaitable\\[(.+)\\]$/);\n    if (awaitableMatch) inner = awaitableMatch[1];\n    const optMatch = inner.match(/^Optional\\[(.+)\\]$/);\n    if (optMatch) inner = optMatch[1];\n    // Unwrap list resource patterns (e.g., SomeListResource[T, ...] → T)\n    for (const pattern of this.listResourcePatterns ?? []) {\n      const prefix = pattern + '[';\n      if (inner.startsWith(prefix)) {\n        // Extract first type arg: everything up to the first comma or closing bracket\n        const rest = inner.slice(prefix.length);\n        const end = rest.search(/[,\\]]/);\n        if (end > 0) {\n          inner = rest.slice(0, end).trim();\n          break;\n        }\n      }\n    }\n    // Sequence[T] → T\n    const seqMatch = inner.match(/^Sequence\\[(.+)\\]$/);\n    if (seqMatch) inner = seqMatch[1];\n    if (['str', 'int', 'float', 'bool', 'None', 'bytes', 'dict', 'list'].includes(inner)) return null;\n    return inner;\n  },\n\n  extractParamTypeName(paramType: string): string | null {\n    let inner = paramType;\n    const optMatch = inner.match(/^Optional\\[(.+)\\]$/);\n    if (optMatch) inner = optMatch[1];\n    if (['str', 'int', 'float', 'bool', 'None', 'bytes', 'dict', 'list'].includes(inner)) return null;\n    return inner;\n  },\n\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n  },\n\n  derivedModelNames(modelName: string): string[] {\n    return [`${modelName}Response`];\n  },\n\n  isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n    // Strip nullable wrappers from both sides\n    const stripNullable = (t: string): string => {\n      const normalized = t.replace(/\\s+/g, ' ').trim();\n      const optMatch = normalized.match(/^Optional\\[(.+)\\]$/);\n      if (optMatch) return optMatch[1].trim();\n      const nrMatch = normalized.match(/^NotRequired\\[(.+)\\]$/);\n      if (nrMatch) return nrMatch[1].trim();\n      const parts = normalized\n        .split('|')\n        .map((p) => p.trim())\n        .filter((p) => p !== 'None');\n      if (parts.length < normalized.split('|').length) return parts.join(' | ');\n      return normalized;\n    };\n    const baseClean = stripNullable(baselineType);\n    const candClean = stripNullable(candidateType);\n\n    // Literal quote style equivalence: Literal[\"foo\"] ≡ Literal['foo']\n    const literalMatch = (t: string) => t.match(/^Literal\\[(['\"])(.+)\\1\\]$/);\n    const baseLit = literalMatch(baseClean);\n    const candLit = literalMatch(candClean);\n    if (baseLit && candLit && baseLit[2] === candLit[2]) return true;\n\n    // LiteralOrUntyped[T] ≡ T (custom wrapper type) — strip recursively\n    const stripWrappers = (t: string): string => {\n      let inner = t;\n      // Strip LiteralOrUntyped[...]\n      const louMatch = inner.match(/^LiteralOrUntyped\\[(.+)\\]$/);\n      if (louMatch) inner = louMatch[1];\n      // Strip Literal[...] to get the enum name if it's a Literal of literals\n      return inner;\n    };\n    const baseUnwrapped = stripWrappers(baseClean);\n    const candUnwrapped = stripWrappers(candClean);\n    if (baseUnwrapped !== baseClean || candUnwrapped !== candClean) {\n      // After unwrapping, check equivalence\n      if (baseUnwrapped === candClean || candUnwrapped === baseClean) return true;\n      if (baseUnwrapped === candUnwrapped) return true;\n      // LiteralOrUntyped[Literal[\"a\", \"b\"]] ≡ enum type\n      if (baseUnwrapped.startsWith('Literal[') && candidateSurface.enums[candClean]) return true;\n      if (candUnwrapped.startsWith('Literal[') && candidateSurface.enums?.[baseClean]) return true;\n    }\n\n    // Sequence[T] ≡ list[T] ≡ List[T]\n    const seqPattern = /^(?:Sequence|list|List)\\[(.+)\\]$/;\n    const baseSeq = baseClean.match(seqPattern);\n    const candSeq = candClean.match(seqPattern);\n    if (baseSeq && candSeq) {\n      if (baseSeq[1] === candSeq[1]) return true;\n      // Inner types may differ by named type (InlineRole vs DirectoryUserRole)\n      const baseInner = baseSeq[1];\n      const candInner = candSeq[1];\n      if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n        if (typeExistsInSurface(candInner, candidateSurface)) {\n          if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n          if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n        }\n      }\n      // Tolerate model collection vs primitive collection: Sequence[OrganizationDomain] ≡ list[str]\n      // The spec may define a field as a primitive array while the live SDK wraps it in a model.\n      const primitiveTypes = PYTHON_PRIMITIVE_TYPES;\n      if (\n        (primitiveTypes.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n        (primitiveTypes.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n      ) {\n        return true;\n      }\n    }\n    // Cross-container tolerance: Sequence[T] vs list[str] (different container names)\n    if (baseSeq && !candSeq) {\n      const candListMatch = candClean.match(/^(?:list|List)\\[(.+)\\]$/);\n      if (candListMatch) {\n        const baseInner = baseSeq[1];\n        const candInner = candListMatch[1];\n        if (baseInner === candInner) return true;\n        const primitiveTypes = PYTHON_PRIMITIVE_TYPES;\n        if (\n          (primitiveTypes.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n          (primitiveTypes.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n        ) {\n          return true;\n        }\n      }\n    }\n\n    // Mapping[K, V] ≡ dict[K, V] (Mapping is the ABC for dict)\n    const mappingPattern = /^(?:Mapping|dict|Dict)\\[(.+)\\]$/;\n    const baseMapping = baseClean.match(mappingPattern);\n    const candMapping = candClean.match(mappingPattern);\n    if (baseMapping && candMapping) {\n      // Both are map-like — compare key/value types loosely\n      return true;\n    }\n\n    // dict map equivalence: dict[str, str] ≡ dict[str, Any] ≡ Dict[str, Any] ≡ dict[str, str | float | bool]\n    const dictLikePattern = /^(?:dict|Dict|Mapping)\\[str,\\s*.+\\]$/;\n    if (dictLikePattern.test(baseClean) && dictLikePattern.test(candClean)) return true;\n\n    // Named metadata type ≡ dict[str, ...] (custom type alias for dict)\n    const isMapType = (t: string) => dictLikePattern.test(t) || /^(?:Metadata|\\w+Metadata)$/.test(t);\n    if (isMapType(baseClean) && isMapType(candClean)) return true;\n\n    // Named type alias for a map/dict type ≡ inline dict expression\n    // e.g., AuditLogMetadata ≡ dict[str, str | float | bool]\n    if (NAMED_TYPE_RE.test(baseClean) && dictLikePattern.test(candClean)) {\n      // Assume named types ending in \"Metadata\" or \"Attributes\" are dict aliases\n      if (/(?:Metadata|Attributes)$/.test(baseClean)) return true;\n    }\n    if (NAMED_TYPE_RE.test(candClean) && dictLikePattern.test(baseClean)) {\n      if (/(?:Metadata|Attributes)$/.test(candClean)) return true;\n    }\n\n    // str ≡ Literal[\"...\"] (literal string type vs plain str)\n    if (baseClean === 'str' && candClean.startsWith('Literal[')) return true;\n    if (candClean === 'str' && baseClean.startsWith('Literal[')) return true;\n\n    // Literal[...] ≡ enum name (candidate has an enum, baseline has Literal)\n    if (baseClean.startsWith('Literal[') && candidateSurface.enums[candClean]) return true;\n    if (candClean.startsWith('Literal[') && candidateSurface.enums?.[baseClean]) return true;\n\n    // str ≡ enum type (baseline says str, candidate uses enum)\n    if (baseClean === 'str' && candidateSurface.enums[candClean]) return true;\n    if (candClean === 'str' && candidateSurface.enums?.[baseClean]) return true;\n\n    // int ≡ float (JSON number coercion)\n    const numericTypes = new Set(['int', 'float']);\n    if (numericTypes.has(baseClean) && numericTypes.has(candClean)) return true;\n\n    // Named type tolerance\n    if (NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n      if (typeExistsInSurface(candClean, candidateSurface)) {\n        if (candClean.includes(baseClean) || baseClean.includes(candClean)) return true;\n        const baseNoResp = baseClean.replace(/Response$/, '');\n        const candNoResp = candClean.replace(/Response$/, '');\n        if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n        if (namedTypeWordsOverlap(baseClean, candClean)) return true;\n      }\n    }\n\n    return false;\n  },\n\n  isSignatureEquivalent(\n    baseline: import('../types.js').ApiMethod,\n    candidate: import('../types.js').ApiMethod,\n    _candidateSurface: ApiSurface,\n  ): boolean {\n    // Tolerate methods where the candidate uses a body dict (payload: dict[str, Any])\n    // while the baseline unpacks the body into individual typed params.\n    // The first N params that match by name and type are consumed, then the remaining\n    // baseline params are tolerated if the candidate has a dict payload param.\n\n    // Return types must be equivalent (use named type tolerance)\n    if (baseline.returnType !== candidate.returnType) {\n      const baseRet = baseline.returnType;\n      const candRet = candidate.returnType;\n      if (!(NAMED_TYPE_RE.test(baseRet) && NAMED_TYPE_RE.test(candRet))) return false;\n      // Check named-type containment or word overlap\n      if (!candRet.includes(baseRet) && !baseRet.includes(candRet)) {\n        if (!namedTypeWordsOverlap(baseRet, candRet)) return false;\n      }\n    }\n\n    // Check if candidate has a body dict param\n    const bodyDictTypes = new Set(['dict[str, Any]', 'Dict[str, Any]', 'dict']);\n    const candBodyIdx = candidate.params.findIndex(\n      (p) => bodyDictTypes.has(p.type) && (p.name === 'payload' || p.name === 'body' || p.name === 'data'),\n    );\n    if (candBodyIdx < 0) return false;\n\n    // All candidate params before the body dict must match baseline params by name and type\n    for (let i = 0; i < candBodyIdx; i++) {\n      if (i >= baseline.params.length) return false;\n      if (baseline.params[i].name !== candidate.params[i].name) return false;\n      if (baseline.params[i].type !== candidate.params[i].type) return false;\n    }\n\n    // Remaining baseline params after the matched prefix are tolerated as body fields\n    return true;\n  },\n\n  // Consumers should configure modelBaseClasses for their framework (e.g., ['BaseModel'] for Pydantic)\n  modelBaseClasses: [],\n  exceptionBaseClasses: ['Exception', 'BaseException'],\n  listResourcePatterns: [],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a Python extractor with optional hint overrides. */\nexport function createPythonExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n  const mergedHints: LanguageHints = hintOverrides ? { ...pythonHints, ...hintOverrides } : pythonHints;\n\n  return {\n    language: 'python',\n    hints: mergedHints,\n\n    async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n      const surface = await this.extract(sdkPath);\n      return apiSurfaceToSnapshot(surface);\n    },\n\n    async extract(sdkPath: string): Promise<ApiSurface> {\n      const sourceRoot = findPythonSourceRoot(sdkPath);\n      if (!sourceRoot) {\n        throw new ExtractorError(\n          `No Python package found in ${sdkPath}`,\n          `Ensure the --sdk-path argument points to a Python project root containing a package directory with __init__.py.`,\n        );\n      }\n\n      const pyFiles = walkPythonFiles(sourceRoot);\n      if (pyFiles.length === 0) {\n        throw new ExtractorError(\n          `No .py files found in ${sdkPath}`,\n          `Ensure the project contains Python source files.`,\n        );\n      }\n\n      const parsedFiles: ParsedPythonFile[] = [];\n      for (const filePath of pyFiles) {\n        const parsed = parsePythonFile(filePath, sdkPath);\n        parsedFiles.push(parsed);\n      }\n\n      const { classes, interfaces, typeAliases, enums, exports } = buildSurface(parsedFiles, mergedHints);\n\n      return {\n        language: 'python',\n        extractedFrom: sdkPath,\n        extractedAt: new Date().toISOString(),\n        classes,\n        interfaces,\n        typeAliases,\n        enums,\n        exports,\n      };\n    },\n  };\n}\n\n/** Default Python extractor with generic language hints (no SDK-specific bases). */\nexport const pythonExtractor: Extractor = createPythonExtractor();\n","/**\n * Ruby entity extraction — tree-sitter-based parsing of classes, service modules,\n * and enum modules from Ruby source files.\n */\n\nimport Parser from 'tree-sitter';\nimport Ruby from 'tree-sitter-ruby';\nimport type { SyntaxNode } from 'tree-sitter';\nimport type { ApiClass, ApiEnum, ApiMethod, ApiParam, ApiProperty } from '../types.js';\nimport { safeParse as safeParseWith } from '../../utils/tree-sitter.js';\nimport { sortRecord } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst rubyParser = new Parser();\nrubyParser.setLanguage(Ruby);\n\nfunction safeParse(source: string): Parser.Tree {\n  return safeParseWith(rubyParser, source);\n}\n\n// ---------------------------------------------------------------------------\n// Public API — called from ruby.ts\n// ---------------------------------------------------------------------------\n\n/** Parse a Ruby source string and return all class declarations (excluding service modules). */\nexport function extractClasses(source: string): ApiClass[] {\n  const tree = safeParse(source);\n  const classes: ApiClass[] = [];\n\n  // Collect line ranges of service modules so we can skip nested classes\n  const serviceModuleNodes = findServiceModulesFromTree(tree.rootNode);\n  const serviceRanges = serviceModuleNodes.map((n) => [n.startPosition.row, n.endPosition.row] as [number, number]);\n\n  for (const node of tree.rootNode.descendantsOfType('class')) {\n    // Skip singleton_class nodes (class << self)\n    if (node.type !== 'class') continue;\n\n    // Skip classes inside service modules\n    if (isInsideRanges(node.startPosition.row, serviceRanges)) continue;\n\n    // Skip if this class contains a singleton_class (class << self) — those are service modules\n    if (node.descendantsOfType('singleton_class').length > 0) continue;\n\n    // Skip enum-shaped classes — they're handled by `extractEnumModules`\n    // (which also picks up class-shape enums alongside module-shape ones).\n    // Without this skip we'd double-emit the same name as both an\n    // ApiClass and an ApiEnum.\n    if (isEnumShapedClass(node)) continue;\n\n    const nameNode = node.childForFieldName('name');\n    if (!nameNode) continue;\n    const className = nameNode.text;\n\n    const bodyNode = node.childForFieldName('body');\n\n    const methods: Record<string, ApiMethod[]> = {};\n    const properties: Record<string, ApiProperty> = {};\n    const constructorParams: ApiParam[] = [];\n\n    // Only extract body content if body exists (single-line classes like `class Foo < Bar; end` may not have a body)\n    if (bodyNode) {\n      // Extract attr_accessor/attr_reader\n      extractAttributes(bodyNode, properties);\n\n      // Extract methods (respecting visibility)\n      const extractedMethods = extractMethodsFromBody(bodyNode);\n      for (const method of extractedMethods) {\n        if (method.name === 'initialize') {\n          constructorParams.push(...method.params);\n        } else {\n          if (!methods[method.name]) methods[method.name] = [];\n          methods[method.name].push(method);\n        }\n      }\n    }\n\n    classes.push({\n      name: className,\n      methods: sortRecord(methods),\n      properties: sortRecord(properties),\n      constructorParams,\n    });\n  }\n\n  return classes;\n}\n\n/** Extract service modules (modules with `class << self` at immediate depth). */\nexport function extractServiceModules(source: string): ApiClass[] {\n  const tree = safeParse(source);\n  const services: ApiClass[] = [];\n\n  for (const moduleNode of findServiceModulesFromTree(tree.rootNode)) {\n    const nameNode = moduleNode.childForFieldName('name');\n    if (!nameNode) continue;\n    const moduleName = nameNode.text;\n\n    const bodyNode = moduleNode.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    // Find the singleton_class (class << self) at immediate depth\n    const singletonNode = findImmediateSingletonClass(bodyNode);\n    if (!singletonNode) continue;\n\n    const singletonBody = singletonNode.childForFieldName('body');\n    if (!singletonBody) continue;\n\n    const methods: Record<string, ApiMethod[]> = {};\n    const properties: Record<string, ApiProperty> = {};\n\n    // Extract methods from the singleton class body\n    const extractedMethods = extractMethodsFromBody(singletonBody);\n    for (const method of extractedMethods) {\n      if (!methods[method.name]) methods[method.name] = [];\n      methods[method.name].push(method);\n    }\n\n    // Extract constants as properties\n    extractConstantsAsProperties(singletonBody, properties);\n\n    if (Object.keys(methods).length > 0 || Object.keys(properties).length > 0) {\n      services.push({\n        name: moduleName,\n        methods: sortRecord(methods),\n        properties: sortRecord(properties),\n        constructorParams: [],\n      });\n    }\n  }\n\n  return services;\n}\n\n/**\n * True when a `class` node looks like a Ruby enum: only constant\n * assignments, no methods, no attr_*, no singleton class. The\n * `extractEnumModules` pass picks these up; `extractClasses` skips\n * them to avoid double-emission. Shared so the two stay in sync.\n */\nfunction isEnumShapedClass(classNode: SyntaxNode): boolean {\n  const bodyNode = classNode.childForFieldName('body');\n  if (!bodyNode) return false;\n  // Reject if the class has any method-shaped or call-shaped child\n  // (call covers attr_accessor / attr_reader / include).\n  for (const c of bodyNode.namedChildren) {\n    if (c.type === 'method' || c.type === 'singleton_method' || c.type === 'call') return false;\n  }\n  // Must have at least 2 scalar constants to be considered an enum.\n  const constants = extractEnumConstants(bodyNode);\n  return Object.keys(constants).length >= 2;\n}\n\n/** Extract enum-like modules (modules with string/number constants, no class << self). */\nexport function extractEnumModules(source: string): ApiEnum[] {\n  const tree = safeParse(source);\n  const enums: ApiEnum[] = [];\n\n  const serviceModuleNodes = findServiceModulesFromTree(tree.rootNode);\n  const serviceRanges = serviceModuleNodes.map((n) => [n.startPosition.row, n.endPosition.row] as [number, number]);\n\n  for (const node of tree.rootNode.descendantsOfType('module')) {\n    // Skip modules inside service modules\n    if (isInsideRanges(node.startPosition.row, serviceRanges)) continue;\n\n    // Skip modules that have singleton_class (service modules)\n    if (node.descendantsOfType('singleton_class').length > 0) continue;\n\n    const nameNode = node.childForFieldName('name');\n    if (!nameNode) continue;\n\n    const bodyNode = node.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    const constants = extractEnumConstants(bodyNode);\n    if (Object.keys(constants).length < 2) continue;\n\n    enums.push({\n      name: nameNode.text,\n      members: sortRecord(constants),\n    });\n  }\n\n  // Also extract enum-shaped *classes*: some Ruby SDKs emit deduped ordering\n  // enums and similar value-set types as\n  // `class ApplicationsOrder; ASC = \"asc\"; …; ALL = [...].freeze; end`\n  // — a class with only constants (no instance methods, no constructor).\n  // Without this branch they fall through to `extractClasses`, become\n  // ApiClass with no methods/properties, and surface as `kind:\n  // 'service_accessor'` with no enum_member children — which the compat\n  // differ can't pair on for canonical-flip detection.\n  for (const node of tree.rootNode.descendantsOfType('class')) {\n    if (node.type !== 'class') continue;\n    if (isInsideRanges(node.startPosition.row, serviceRanges)) continue;\n    if (node.descendantsOfType('singleton_class').length > 0) continue;\n\n    const nameNode = node.childForFieldName('name');\n    if (!nameNode) continue;\n\n    const bodyNode = node.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    // Reject if the class has any non-constant declarations (methods,\n    // attr_accessor, etc.). The `ALL` aggregator constant (`ALL = [A,\n    // B, C].freeze`) is allowed and skipped — `extractEnumConstants`\n    // only collects scalar string/number values, so non-scalar\n    // constants (arrays) are naturally excluded.\n    const hasNonConstantBody = bodyNode.namedChildren.some(\n      (c) => c.type === 'method' || c.type === 'singleton_method' || c.type === 'call',\n    );\n    if (hasNonConstantBody) continue;\n\n    const constants = extractEnumConstants(bodyNode);\n    if (Object.keys(constants).length < 2) continue;\n\n    enums.push({\n      name: nameNode.text,\n      members: sortRecord(constants),\n    });\n  }\n\n  return enums;\n}\n\n/** Extract autoload declarations to build the export map. */\nexport function extractAutoloads(source: string): string[] {\n  const tree = safeParse(source);\n  const names: string[] = [];\n\n  for (const callNode of tree.rootNode.descendantsOfType('call')) {\n    const methodNode = callNode.childForFieldName('method');\n    if (!methodNode || methodNode.text !== 'autoload') continue;\n\n    const argsNode = callNode.childForFieldName('arguments');\n    if (!argsNode) continue;\n\n    // First argument is the symbol name\n    const firstArg = argsNode.namedChildren[0];\n    if (firstArg && (firstArg.type === 'simple_symbol' || firstArg.type === 'symbol')) {\n      names.push(firstArg.text.replace(/^:/, ''));\n    }\n  }\n\n  return names;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: finding service modules\n// ---------------------------------------------------------------------------\n\n/** Find module nodes that have `class << self` at their immediate body level. */\nfunction findServiceModulesFromTree(rootNode: SyntaxNode): SyntaxNode[] {\n  const result: SyntaxNode[] = [];\n\n  for (const moduleNode of rootNode.descendantsOfType('module')) {\n    const bodyNode = moduleNode.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    if (findImmediateSingletonClass(bodyNode)) {\n      result.push(moduleNode);\n    }\n  }\n\n  return result;\n}\n\n/** Find a singleton_class (class << self) at the immediate body level (not nested). */\nfunction findImmediateSingletonClass(bodyNode: SyntaxNode): SyntaxNode | null {\n  for (const child of bodyNode.namedChildren) {\n    if (child.type === 'singleton_class') return child;\n  }\n  return null;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: method extraction with visibility tracking\n// ---------------------------------------------------------------------------\n\n/** Extract methods from a body_statement, respecting private/protected/public markers. */\nfunction extractMethodsFromBody(bodyNode: SyntaxNode): ApiMethod[] {\n  const methods: ApiMethod[] = [];\n  let isPrivate = false;\n\n  for (const child of bodyNode.namedChildren) {\n    // Track visibility markers: bare `private`, `public`, `protected` calls\n    if (child.type === 'identifier') {\n      if (child.text === 'private') {\n        isPrivate = true;\n        continue;\n      }\n      if (child.text === 'public') {\n        isPrivate = false;\n        continue;\n      }\n      if (child.text === 'protected') {\n        isPrivate = true;\n        continue;\n      }\n    }\n\n    if (isPrivate) continue;\n\n    if (child.type === 'method') {\n      const nameNode = child.childForFieldName('name');\n      if (!nameNode) continue;\n\n      const params = extractMethodParams(child);\n      methods.push({\n        name: nameNode.text,\n        params,\n        returnType: 'Object',\n        async: false,\n      });\n    }\n  }\n\n  return methods;\n}\n\n/** Extract parameters from a method node. */\nfunction extractMethodParams(methodNode: SyntaxNode): ApiParam[] {\n  const paramsNode = methodNode.childForFieldName('parameters');\n  if (!paramsNode) return [];\n\n  const params: ApiParam[] = [];\n\n  for (const paramNode of paramsNode.namedChildren) {\n    switch (paramNode.type) {\n      case 'identifier': {\n        // Plain positional argument\n        params.push({ name: paramNode.text, type: 'Object', optional: false, passingStyle: 'positional' as const });\n        break;\n      }\n      case 'optional_parameter': {\n        // Positional argument with default: name = value\n        const nameNode = paramNode.childForFieldName('name');\n        if (nameNode) {\n          params.push({ name: nameNode.text, type: 'Object', optional: true, passingStyle: 'positional' as const });\n        }\n        break;\n      }\n      case 'keyword_parameter': {\n        // Keyword argument: name: or name: default\n        const nameNode = paramNode.childForFieldName('name');\n        if (nameNode) {\n          const valueNode = paramNode.childForFieldName('value');\n          params.push({\n            name: nameNode.text,\n            type: 'Object',\n            optional: valueNode !== null,\n            passingStyle: 'keyword' as const,\n          });\n        }\n        break;\n      }\n      case 'splat_parameter': {\n        // *args — variadic positional\n        const nameNode = paramNode.childForFieldName('name');\n        params.push({\n          name: nameNode ? `*${nameNode.text}` : '*args',\n          type: 'Object',\n          optional: true,\n          passingStyle: 'positional' as const,\n        });\n        break;\n      }\n      case 'hash_splat_parameter': {\n        // **kwargs — variadic keyword\n        const nameNode = paramNode.childForFieldName('name');\n        params.push({\n          name: nameNode ? `**${nameNode.text}` : '**kwargs',\n          type: 'Object',\n          optional: true,\n          passingStyle: 'keyword' as const,\n        });\n        break;\n      }\n      case 'block_parameter': {\n        // &block — block argument\n        const nameNode = paramNode.childForFieldName('name');\n        params.push({\n          name: nameNode ? `&${nameNode.text}` : '&block',\n          type: 'Object',\n          optional: true,\n          passingStyle: 'positional' as const,\n        });\n        break;\n      }\n      default:\n        break;\n    }\n  }\n\n  return params;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: attribute extraction\n// ---------------------------------------------------------------------------\n\n/** Extract attr_accessor/attr_reader calls into properties. */\nfunction extractAttributes(bodyNode: SyntaxNode, properties: Record<string, ApiProperty>): void {\n  for (const callNode of bodyNode.descendantsOfType('call')) {\n    const methodNode = callNode.childForFieldName('method');\n    if (!methodNode) continue;\n    const methodName = methodNode.text;\n    if (methodName !== 'attr_accessor' && methodName !== 'attr_reader') continue;\n\n    const isReadonly = methodName === 'attr_reader';\n\n    const argsNode = callNode.childForFieldName('arguments');\n    if (!argsNode) continue;\n\n    for (const argNode of argsNode.namedChildren) {\n      if (argNode.type === 'simple_symbol' || argNode.type === 'symbol') {\n        const name = argNode.text.replace(/^:/, '');\n        properties[name] = { name, type: 'Object', readonly: isReadonly };\n      }\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Internal: constant extraction\n// ---------------------------------------------------------------------------\n\n/** Extract UPPER_CASE constants from a body as readonly properties. */\nfunction extractConstantsAsProperties(bodyNode: SyntaxNode, properties: Record<string, ApiProperty>): void {\n  for (const child of bodyNode.namedChildren) {\n    if (child.type !== 'assignment') continue;\n    const leftNode = child.childForFieldName('left');\n    if (!leftNode || leftNode.type !== 'constant') continue;\n    const name = leftNode.text;\n    if (!/^[A-Z][A-Z_0-9]*$/.test(name)) continue;\n    properties[name] = { name, type: 'Object', readonly: true };\n  }\n}\n\n/** Extract enum-style constants (ConstantName = 'value') from a module body. */\nfunction extractEnumConstants(bodyNode: SyntaxNode): Record<string, string | number> {\n  const constants: Record<string, string | number> = {};\n\n  for (const child of bodyNode.namedChildren) {\n    if (child.type !== 'assignment') continue;\n    const leftNode = child.childForFieldName('left');\n    if (!leftNode || leftNode.type !== 'constant') continue;\n    const name = leftNode.text;\n    if (name === 'ALL') continue; // Skip aggregate constants\n\n    const rightNode = child.childForFieldName('right');\n    if (!rightNode) continue;\n\n    const value = extractLiteralValue(rightNode);\n    if (value !== undefined) {\n      constants[name] = value;\n    }\n  }\n\n  return constants;\n}\n\n/** Extract a literal string or number value from a tree-sitter node. */\nfunction extractLiteralValue(node: SyntaxNode): string | number | undefined {\n  if (node.type === 'string' || node.type === 'string_content') {\n    // String: strip surrounding quotes\n    const text = node.text;\n    if ((text.startsWith(\"'\") && text.endsWith(\"'\")) || (text.startsWith('\"') && text.endsWith('\"'))) {\n      return text.slice(1, -1);\n    }\n    // For string_content (inside a string node), return as-is\n    return text;\n  }\n  if (node.type === 'integer') {\n    return Number(node.text);\n  }\n  if (node.type === 'float') {\n    return Number(node.text);\n  }\n  // For strings, tree-sitter wraps in a `string` node with `string_content` children\n  if (node.type === 'string') {\n    const contentNode = node.namedChildren.find((c) => c.type === 'string_content');\n    if (contentNode) return contentNode.text;\n  }\n  return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: tree traversal helpers\n// ---------------------------------------------------------------------------\n\n/** Check if a line number falls inside any of the given ranges. */\nfunction isInsideRanges(line: number, ranges: Array<[number, number]>): boolean {\n  for (const [start, end] of ranges) {\n    if (line > start && line < end) return true;\n  }\n  return false;\n}\n\nexport { sortRecord } from './shared.js';\n","/**\n * Ruby API surface extractor.\n *\n * Walks `.rb` files under `lib/`, parses class/module declarations,\n * and builds an `ApiSurface` with classes, service modules, and enum modules.\n *\n * Parser: `ruby-parser.ts` — tree-sitter-based class/module/enum extraction\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { resolve, relative, join } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { ApiSurface, Extractor, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport {\n  extractClasses,\n  extractServiceModules,\n  extractEnumModules,\n  extractAutoloads,\n  sortRecord,\n} from './ruby-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst rubyHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    const match = type.match(/^T\\.nilable\\((.+)\\)$/);\n    return match ? match[1] : null;\n  },\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return defaultIsNullableOnlyDifference(this, a, b);\n  },\n  isUnionReorder(_a: string, _b: string): boolean {\n    return false;\n  },\n  isGenericTypeParam(type: string): boolean {\n    return type === 'T.untyped';\n  },\n  isExtractionArtifact(type: string): boolean {\n    return type === 'T.untyped' || type === 'BasicObject';\n  },\n  tolerateCategoryMismatch: false,\n  extractReturnTypeName(returnType: string): string | null {\n    return returnType || null;\n  },\n  extractParamTypeName(paramType: string): string | null {\n    if (['String', 'Integer', 'Float', 'Boolean', 'NilClass'].includes(paramType)) return null;\n    return paramType;\n  },\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n  },\n  derivedModelNames(_modelName: string): string[] {\n    return [];\n  },\n};\n\n// ---------------------------------------------------------------------------\n// File collection\n// ---------------------------------------------------------------------------\n\n/** Recursively collect all .rb files under a directory. */\nfunction collectRbFiles(dir: string): string[] {\n  const result: string[] = [];\n  const entries = readdirSync(dir);\n  for (const entry of entries.sort()) {\n    const full = join(dir, entry);\n    const stat = statSync(full);\n    if (stat.isDirectory()) {\n      result.push(...collectRbFiles(full));\n    } else if (entry.endsWith('.rb')) {\n      result.push(full);\n    }\n  }\n  return result;\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const rubyExtractor: Extractor = {\n  language: 'ruby',\n  hints: rubyHints,\n\n  async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n    const surface = await this.extract(sdkPath);\n    return apiSurfaceToSnapshot(surface);\n  },\n\n  async extract(sdkPath: string): Promise<ApiSurface> {\n    const libPath = resolve(sdkPath, 'lib');\n    try {\n      statSync(libPath);\n    } catch {\n      throw new ExtractorError(\n        `No lib/ directory found in ${sdkPath}`,\n        `Verify the --sdk-path argument points to a Ruby project root containing a lib/ directory.`,\n      );\n    }\n\n    const rbFiles = collectRbFiles(libPath);\n    if (rbFiles.length === 0) {\n      throw new ExtractorError(\n        `No .rb files found in ${libPath}`,\n        `Ensure the lib/ directory contains Ruby source files.`,\n      );\n    }\n\n    const classes: Record<string, import('../types.js').ApiClass> = {};\n    const enums: Record<string, import('../types.js').ApiEnum> = {};\n    const exports: Record<string, string[]> = {};\n\n    for (const absPath of rbFiles) {\n      const relPath = relative(sdkPath, absPath);\n      const source = readFileSync(absPath, 'utf-8');\n\n      const fileExports: string[] = [];\n\n      // Extract classes (model classes and struct classes)\n      const extractedClasses = extractClasses(source);\n      for (const cls of extractedClasses) {\n        classes[cls.name] = { ...cls, sourceFile: relPath };\n        fileExports.push(cls.name);\n      }\n\n      // Extract service modules (modules with class << self)\n      const extractedServices = extractServiceModules(source);\n      for (const svc of extractedServices) {\n        classes[svc.name] = { ...svc, sourceFile: relPath };\n        fileExports.push(svc.name);\n      }\n\n      // Extract enum-like modules (modules with constants)\n      const extractedEnums = extractEnumModules(source);\n      for (const en of extractedEnums) {\n        enums[en.name] = { ...en, sourceFile: relPath };\n        fileExports.push(en.name);\n      }\n\n      // Extract autoload declarations as exports\n      const autoloadNames = extractAutoloads(source);\n      if (autoloadNames.length > 0) {\n        fileExports.push(...autoloadNames);\n      }\n\n      if (fileExports.length > 0) {\n        exports[relPath] = [...new Set(fileExports)].sort();\n      }\n    }\n\n    return {\n      language: 'ruby',\n      extractedFrom: sdkPath,\n      extractedAt: new Date().toISOString(),\n      classes: sortRecord(classes),\n      interfaces: {},\n      typeAliases: {},\n      enums: sortRecord(enums),\n      exports: sortRecord(exports),\n    };\n  },\n};\n","/**\n * Go source parser — tree-sitter-based extraction of structs, functions, types,\n * and const blocks from Go source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport Go from 'tree-sitter-go';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface GoStructField {\n  name: string;\n  type: string;\n  jsonTag?: string;\n  optional: boolean;\n}\n\nexport interface GoStruct {\n  name: string;\n  fields: GoStructField[];\n  sourceFile: string;\n  packageName: string;\n}\n\nexport interface GoFunc {\n  receiverType: string | null;\n  name: string;\n  params: { name: string; type: string }[];\n  returnTypes: string[];\n  sourceFile: string;\n  packageName: string;\n}\n\nexport interface GoConst {\n  name: string;\n  typeName: string;\n  value: string;\n  sourceFile: string;\n  packageName: string;\n}\n\nexport interface GoTypeDecl {\n  name: string;\n  underlyingType: string;\n  isAlias: boolean;\n  sourceFile: string;\n  packageName: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst goParser = new Parser();\ngoParser.setLanguage(Go);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkGoFiles(dir: string): string[] {\n  const results: string[] = [];\n  let entries: string[];\n  try {\n    entries = readdirSync(dir);\n  } catch {\n    return results;\n  }\n  for (const entry of entries) {\n    const fullPath = join(dir, entry);\n    let stat;\n    try {\n      stat = statSync(fullPath);\n    } catch {\n      continue;\n    }\n    if (stat.isDirectory()) {\n      if (entry.startsWith('.') || entry === 'vendor' || entry === 'testdata' || entry === 'internal') continue;\n      results.push(...walkGoFiles(fullPath));\n    } else if (entry.endsWith('.go') && !entry.endsWith('_test.go')) {\n      results.push(fullPath);\n    }\n  }\n  return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Node helpers\n// ---------------------------------------------------------------------------\n\n/** Get the text of a child node by field name, or null. */\nfunction fieldText(node: SyntaxNode, field: string): string | null {\n  const child = node.childForFieldName(field);\n  return child ? child.text : null;\n}\n\n/** Extract the JSON field name from a struct tag. */\nfunction extractJsonTag(tagText: string): { name: string; omitempty: boolean } | null {\n  const match = tagText.match(/json:\"([^\"]*)\"/);\n  if (!match) return null;\n  const parts = match[1].split(',');\n  const name = parts[0].trim();\n  const omitempty = parts.includes('omitempty');\n  if (name === '-') return null;\n  return { name, omitempty };\n}\n\n/** Render a type node back to its Go source representation. */\nfunction typeNodeText(node: SyntaxNode): string {\n  return node.text;\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction parseStructFields(structNode: SyntaxNode): GoStructField[] {\n  const fields: GoStructField[] = [];\n  const fieldList = structNode.namedChildren.find((c) => c.type === 'field_declaration_list');\n  if (!fieldList) return fields;\n\n  for (const fieldDecl of fieldList.namedChildren) {\n    if (fieldDecl.type !== 'field_declaration') continue;\n\n    // Get all field identifiers (there can be multiple: `A, B int`)\n    const nameNodes = fieldDecl.namedChildren.filter((c) => c.type === 'field_identifier');\n    if (nameNodes.length === 0) {\n      // Embedded field (struct composition) — extract the type name as the field name.\n      // e.g., `type Foo struct { Bar }` → field named \"Bar\" of type \"Bar\"\n      const typeNode = fieldDecl.namedChildren.find(\n        (c) => c.type !== 'raw_string_literal' && c.type !== 'interpreted_string_literal',\n      );\n      if (typeNode) {\n        const typeName = typeNode.text.replace(/^\\*/, ''); // strip pointer\n        if (/^[A-Z]/.test(typeName)) {\n          fields.push({\n            name: typeName,\n            type: typeNode.text,\n            optional: false,\n          });\n        }\n      }\n      continue;\n    }\n\n    // The type node: find the first named child that isn't a field_identifier and isn't a tag\n    const typeNode = fieldDecl.namedChildren.find(\n      (c) =>\n        c.type !== 'field_identifier' && c.type !== 'raw_string_literal' && c.type !== 'interpreted_string_literal',\n    );\n    if (!typeNode) continue;\n\n    // Only export fields that start with uppercase\n    const fieldType = typeNodeText(typeNode);\n\n    // Tag is a raw_string_literal child\n    const tagNode = fieldDecl.namedChildren.find(\n      (c) => c.type === 'raw_string_literal' || c.type === 'interpreted_string_literal',\n    );\n    const jsonTag = tagNode ? extractJsonTag(tagNode.text) : null;\n\n    for (const nameNode of nameNodes) {\n      const name = nameNode.text;\n      if (!/^[A-Z]/.test(name)) continue; // skip unexported\n      fields.push({\n        name,\n        type: fieldType,\n        jsonTag: jsonTag?.name || undefined,\n        optional: jsonTag?.omitempty || false,\n      });\n    }\n  }\n  return fields;\n}\n\n// ---------------------------------------------------------------------------\n// Type declarations\n// ---------------------------------------------------------------------------\n\nexport function parseTypeDecls(\n  tree: Parser.Tree,\n  sourceFile: string,\n  packageName: string,\n): { structs: GoStruct[]; types: GoTypeDecl[] } {\n  const structs: GoStruct[] = [];\n  const types: GoTypeDecl[] = [];\n\n  for (const node of tree.rootNode.namedChildren) {\n    if (node.type !== 'type_declaration') continue;\n\n    for (const spec of node.namedChildren) {\n      const name = fieldText(spec, 'name');\n      if (!name || !/^[A-Z]/.test(name)) continue;\n\n      if (spec.type === 'type_spec') {\n        const typeNode = spec.childForFieldName('type');\n        if (!typeNode) continue;\n\n        if (typeNode.type === 'struct_type') {\n          structs.push({ name, fields: parseStructFields(typeNode), sourceFile, packageName });\n        } else if (typeNode.type !== 'interface_type') {\n          types.push({ name, underlyingType: typeNodeText(typeNode), isAlias: false, sourceFile, packageName });\n        }\n      } else if (spec.type === 'type_alias') {\n        const typeNode = spec.childForFieldName('type');\n        if (typeNode) {\n          types.push({ name, underlyingType: typeNodeText(typeNode), isAlias: true, sourceFile, packageName });\n        }\n      }\n    }\n  }\n\n  return { structs, types };\n}\n\n// ---------------------------------------------------------------------------\n// Const blocks\n// ---------------------------------------------------------------------------\n\n/** Strip surrounding quotes from a string value. */\nfunction stripQuotes(value: string): string {\n  if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n    return value.slice(1, -1);\n  }\n  const convMatch = value.match(/^\\w+(?:\\.\\w+)?\\(\"([^\"]*)\"\\)$/);\n  if (convMatch) return convMatch[1];\n  return value;\n}\n\nexport function parseConstBlocks(tree: Parser.Tree, sourceFile: string, packageName: string): GoConst[] {\n  const consts: GoConst[] = [];\n\n  for (const node of tree.rootNode.namedChildren) {\n    if (node.type !== 'const_declaration') continue;\n\n    let lastType = '';\n\n    for (const spec of node.namedChildren) {\n      if (spec.type !== 'const_spec') continue;\n\n      const nameNodes = spec.namedChildren.filter((c) => c.type === 'identifier');\n      if (nameNodes.length === 0) continue;\n      const constName = nameNodes[0].text;\n      if (!/^[A-Z]/.test(constName)) continue;\n\n      // Type field (optional)\n      const typeNode = spec.childForFieldName('type');\n      if (typeNode) {\n        lastType = typeNode.text;\n      }\n\n      // Value field\n      const valueNode = spec.childForFieldName('value');\n      if (valueNode) {\n        // expression_list may contain a single value or a call expression\n        const valueText = valueNode.text.trim();\n        const strippedValue = stripQuotes(valueText);\n\n        // Check for type conversion: TypeName(\"value\") or TypeName(value)\n        if (!typeNode) {\n          const convMatch = valueText.match(/^([A-Z]\\w*)\\((.+)\\)$/);\n          if (convMatch) {\n            consts.push({\n              name: constName,\n              typeName: convMatch[1],\n              value: stripQuotes(convMatch[2].trim()),\n              sourceFile,\n              packageName,\n            });\n            continue;\n          }\n        }\n\n        if (lastType) {\n          consts.push({ name: constName, typeName: lastType, value: strippedValue, sourceFile, packageName });\n        }\n      } else if (lastType) {\n        // iota continuation — no value node\n        consts.push({ name: constName, typeName: lastType, value: constName, sourceFile, packageName });\n      }\n    }\n  }\n\n  return consts;\n}\n\n// ---------------------------------------------------------------------------\n// Function & method declarations\n// ---------------------------------------------------------------------------\n\nfunction parseParamList(paramListNode: SyntaxNode | null): { name: string; type: string }[] {\n  if (!paramListNode) return [];\n  const params: { name: string; type: string }[] = [];\n\n  let unnamedIndex = 0;\n  for (const paramDecl of paramListNode.namedChildren) {\n    if (paramDecl.type !== 'parameter_declaration' && paramDecl.type !== 'variadic_parameter_declaration') continue;\n\n    const nameNode = paramDecl.namedChildren.find((c) => c.type === 'identifier');\n    const typeNode = paramDecl.childForFieldName('type');\n    if (!typeNode) continue;\n\n    // When Go omits the parameter name (e.g., `func Foo(string, int)`),\n    // synthesize a positional name so signature matching doesn't break.\n    const name = nameNode ? nameNode.text : `_arg${unnamedIndex++}`;\n    params.push({\n      name,\n      type: typeNodeText(typeNode),\n    });\n  }\n  return params;\n}\n\nfunction parseReturnTypes(resultNode: SyntaxNode | null): string[] {\n  if (!resultNode) return [];\n\n  if (resultNode.type === 'parameter_list') {\n    // Multiple return values: (Type1, Type2)\n    return resultNode.namedChildren\n      .filter((c) => c.type === 'parameter_declaration')\n      .map((c) => {\n        const t = c.childForFieldName('type');\n        return t ? typeNodeText(t) : c.text;\n      });\n  }\n\n  // Single return value\n  return [typeNodeText(resultNode)];\n}\n\nexport function parseFunctions(tree: Parser.Tree, sourceFile: string, packageName: string): GoFunc[] {\n  const funcs: GoFunc[] = [];\n\n  for (const node of tree.rootNode.namedChildren) {\n    if (node.type === 'function_declaration') {\n      const name = fieldText(node, 'name');\n      if (!name || !/^[A-Z]/.test(name)) continue;\n\n      funcs.push({\n        receiverType: null,\n        name,\n        params: parseParamList(node.childForFieldName('parameters')),\n        returnTypes: parseReturnTypes(node.childForFieldName('result')),\n        sourceFile,\n        packageName,\n      });\n    } else if (node.type === 'method_declaration') {\n      const name = fieldText(node, 'name');\n      if (!name || !/^[A-Z]/.test(name)) continue;\n\n      // Extract receiver type\n      const receiverNode = node.childForFieldName('receiver');\n      let receiverType: string | null = null;\n      if (receiverNode) {\n        const paramDecl = receiverNode.namedChildren.find((c) => c.type === 'parameter_declaration');\n        if (paramDecl) {\n          const typeNode = paramDecl.childForFieldName('type');\n          if (typeNode) {\n            // Strip pointer: *Foo → Foo\n            receiverType = typeNode.text.replace(/^\\*/, '');\n          }\n        }\n      }\n\n      funcs.push({\n        receiverType,\n        name,\n        params: parseParamList(node.childForFieldName('parameters')),\n        returnTypes: parseReturnTypes(node.childForFieldName('result')),\n        sourceFile,\n        packageName,\n      });\n    }\n  }\n  return funcs;\n}\n\n// ---------------------------------------------------------------------------\n// Package name extraction\n// ---------------------------------------------------------------------------\n\nexport function extractPackageName(tree: Parser.Tree): string {\n  const pkgClause = tree.rootNode.namedChildren.find((c) => c.type === 'package_clause');\n  if (!pkgClause) return 'unknown';\n  const nameNode = pkgClause.namedChildren.find((c) => c.type === 'package_identifier');\n  return nameNode ? nameNode.text : 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedGoFile {\n  structs: GoStruct[];\n  types: GoTypeDecl[];\n  funcs: GoFunc[];\n  consts: GoConst[];\n}\n\n/** Parse a single Go source file and return all extracted symbols. */\nexport function parseGoFile(filePath: string, sdkPath: string): ParsedGoFile {\n  const source = readFileSync(filePath, 'utf-8');\n  const relPath = relative(sdkPath, filePath);\n  const tree = safeParse(goParser, source);\n  const packageName = extractPackageName(tree);\n\n  const { structs, types } = parseTypeDecls(tree, relPath, packageName);\n  const funcs = parseFunctions(tree, relPath, packageName);\n  const consts = parseConstBlocks(tree, relPath, packageName);\n\n  return { structs, types, funcs, consts };\n}\n","/**\n * Go surface builder — transforms parsed Go symbols into an ApiSurface\n * with proper package-qualified names for collision avoidance.\n */\n\nimport { basename, dirname } from 'node:path';\nimport type {\n  ApiClass,\n  ApiMethod,\n  ApiParam,\n  ApiProperty,\n  ApiInterface,\n  ApiField,\n  ApiTypeAlias,\n  ApiEnum,\n} from '../types.js';\nimport type { GoStruct, GoTypeDecl, GoFunc, GoConst } from './go-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction goTypeToString(t: string): string {\n  return t.replace(/json\\.RawMessage/g, '[]byte').replace(/\\bcontext\\.Context\\b/g, 'context.Context');\n}\n\nfunction buildReturnType(returnTypes: string[]): string {\n  const nonError = returnTypes.filter((r) => r !== 'error');\n  if (nonError.length === 0) return 'error';\n  if (nonError.length === 1) return goTypeToString(nonError[0]);\n  return `(${nonError.map(goTypeToString).join(', ')})`;\n}\n\n/** Get the package directory name from a source file relative path. */\nfunction getPackageDirName(relPath: string): string {\n  const dir = dirname(relPath);\n  return basename(dir) || 'root';\n}\n\n// ---------------------------------------------------------------------------\n// Qualified name resolution\n// ---------------------------------------------------------------------------\n\n/**\n * When multiple packages define the same exported symbol, qualify with the\n * package directory name (e.g., \"organizations.Client\", \"sso.Client\").\n * Unique symbols keep their bare name.\n */\nfunction buildQualifiedNames(\n  items: Array<{ name: string; packageName: string; sourceFile: string }>,\n): Map<string, string> {\n  const nameToPackages = new Map<string, Set<string>>();\n  for (const item of items) {\n    if (!nameToPackages.has(item.name)) nameToPackages.set(item.name, new Set());\n    nameToPackages.get(item.name)!.add(item.packageName);\n  }\n\n  const result = new Map<string, string>();\n  for (const item of items) {\n    const key = `${item.sourceFile}:${item.name}`;\n    const packages = nameToPackages.get(item.name)!;\n    result.set(key, packages.size > 1 ? `${getPackageDirName(item.sourceFile)}.${item.name}` : item.name);\n  }\n  return result;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n  allStructs: GoStruct[],\n  allTypes: GoTypeDecl[],\n  allFuncs: GoFunc[],\n  allConsts: GoConst[],\n): {\n  classes: Record<string, ApiClass>;\n  interfaces: Record<string, ApiInterface>;\n  typeAliases: Record<string, ApiTypeAlias>;\n  enums: Record<string, ApiEnum>;\n  exports: Record<string, string[]>;\n} {\n  const classes: Record<string, ApiClass> = {};\n  const interfaces: Record<string, ApiInterface> = {};\n  const typeAliases: Record<string, ApiTypeAlias> = {};\n  const enums: Record<string, ApiEnum> = {};\n\n  // Group consts by (packageName, typeName)\n  const constsByPkgAndType = new Map<string, GoConst[]>();\n  for (const c of allConsts) {\n    const key = `${c.packageName}:${c.typeName}`;\n    if (!constsByPkgAndType.has(key)) constsByPkgAndType.set(key, []);\n    constsByPkgAndType.get(key)!.push(c);\n  }\n\n  // Group methods by (packageName, receiverType)\n  const methodsByPkgAndReceiver = new Map<string, GoFunc[]>();\n  const packageFuncs: GoFunc[] = [];\n  for (const fn of allFuncs) {\n    if (fn.receiverType) {\n      const key = `${fn.packageName}:${fn.receiverType}`;\n      if (!methodsByPkgAndReceiver.has(key)) methodsByPkgAndReceiver.set(key, []);\n      methodsByPkgAndReceiver.get(key)!.push(fn);\n    } else {\n      packageFuncs.push(fn);\n    }\n  }\n\n  // Build qualified names\n  const allSymbols: Array<{ name: string; packageName: string; sourceFile: string }> = [];\n  for (const s of allStructs) allSymbols.push({ name: s.name, packageName: s.packageName, sourceFile: s.sourceFile });\n  for (const t of allTypes) allSymbols.push({ name: t.name, packageName: t.packageName, sourceFile: t.sourceFile });\n  const qualifiedNames = buildQualifiedNames(allSymbols);\n\n  // Process type declarations\n  for (const typeDecl of allTypes) {\n    const qName = qualifiedNames.get(`${typeDecl.sourceFile}:${typeDecl.name}`) || typeDecl.name;\n    const typeConsts = constsByPkgAndType.get(`${typeDecl.packageName}:${typeDecl.name}`);\n\n    if (typeDecl.isAlias) {\n      typeAliases[qName] = {\n        name: qName,\n        sourceFile: typeDecl.sourceFile,\n        value: goTypeToString(typeDecl.underlyingType),\n      };\n    } else if (typeConsts && typeConsts.length > 0) {\n      const members: Record<string, string | number> = {};\n      for (const c of typeConsts) {\n        // Strip the type name prefix from enum constant names to produce\n        // consistent short member keys (e.g., \"AuthenticationFactorTypeGenericOtp\"\n        // → \"GenericOtp\"). This matches Go SDK conventions where the type prefix\n        // is an implementation detail, not part of the public API contract.\n        const memberKey = c.name.startsWith(typeDecl.name) ? c.name.slice(typeDecl.name.length) || c.name : c.name;\n        members[memberKey] = c.value;\n      }\n      enums[qName] = { name: qName, sourceFile: typeDecl.sourceFile, members: sortRecord(members) };\n    } else {\n      typeAliases[qName] = {\n        name: qName,\n        sourceFile: typeDecl.sourceFile,\n        value: goTypeToString(typeDecl.underlyingType),\n      };\n    }\n  }\n\n  // Process structs\n  for (const s of allStructs) {\n    const qName = qualifiedNames.get(`${s.sourceFile}:${s.name}`) || s.name;\n    const methods = methodsByPkgAndReceiver.get(`${s.packageName}:${s.name}`);\n\n    if (methods && methods.length > 0) {\n      const apiMethods: Record<string, ApiMethod[]> = {};\n      const properties: Record<string, ApiProperty> = {};\n\n      for (const field of s.fields) {\n        properties[field.name] = { name: field.name, type: goTypeToString(field.type), readonly: false };\n      }\n\n      for (const fn of methods) {\n        const params: ApiParam[] = fn.params\n          .filter((p) => p.type !== 'context.Context')\n          .map((p) => ({\n            name: p.name,\n            type: goTypeToString(p.type),\n            optional: false,\n            passingStyle: 'positional' as const,\n          }));\n        if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n        apiMethods[fn.name].push({ name: fn.name, params, returnType: buildReturnType(fn.returnTypes), async: false });\n      }\n\n      classes[qName] = {\n        name: qName,\n        sourceFile: s.sourceFile,\n        methods: sortRecord(apiMethods),\n        properties: sortRecord(properties),\n        constructorParams: [],\n      };\n    } else {\n      const fields: Record<string, ApiField> = {};\n      for (const field of s.fields) {\n        const fieldName = field.jsonTag || field.name;\n        fields[fieldName] = { name: fieldName, type: goTypeToString(field.type), optional: field.optional };\n      }\n      interfaces[qName] = { name: qName, sourceFile: s.sourceFile, fields: sortRecord(fields), extends: [] };\n    }\n  }\n\n  // Build export map\n  const collector = new ExportCollector();\n\n  for (const [name, cls] of Object.entries(classes)) if (cls.sourceFile) collector.add(cls.sourceFile, name);\n  for (const [name, iface] of Object.entries(interfaces)) if (iface.sourceFile) collector.add(iface.sourceFile, name);\n  for (const [name, ta] of Object.entries(typeAliases)) if (ta.sourceFile) collector.add(ta.sourceFile, name);\n  for (const [name, en] of Object.entries(enums)) if (en.sourceFile) collector.add(en.sourceFile, name);\n  for (const c of allConsts) {\n    const typeDecl = allTypes.find((t) => t.name === c.typeName && t.packageName === c.packageName);\n    if (typeDecl) collector.add(typeDecl.sourceFile, c.name);\n  }\n  for (const fn of packageFuncs) collector.add(fn.sourceFile, fn.name);\n\n  const exports = collector.toRecord();\n\n  return {\n    classes: sortRecord(classes),\n    interfaces: sortRecord(interfaces),\n    typeAliases: sortRecord(typeAliases),\n    enums: sortRecord(enums),\n    exports: sortRecord(exports),\n  };\n}\n","/**\n * Go API surface extractor.\n *\n * Walks `.go` files (excluding `_test.go` and `internal/`), parses exported\n * structs, functions, type declarations, and const blocks, then builds an\n * `ApiSurface` with package-qualified names to avoid collisions when\n * multiple packages define the same symbol (e.g., `Client`).\n *\n * Parser: `go-parser.ts`   — regex-based Go source analysis\n * Surface: `go-surface.ts` — ApiSurface construction & name qualification\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkGoFiles, parseGoFile } from './go-parser.js';\nimport { buildSurface } from './go-surface.js';\nimport type { GoStruct, GoTypeDecl, GoFunc, GoConst } from './go-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\n/**\n * Go acronyms that may differ in casing between hand-written and generated code.\n * e.g., hand-written uses \"Json\" / \"Uri\" while generated uses \"JSON\" / \"URI\".\n */\nconst GO_ACRONYMS = [\n  'ID',\n  'URL',\n  'API',\n  'HTTP',\n  'HTTPS',\n  'JSON',\n  'XML',\n  'SQL',\n  'HTML',\n  'CSS',\n  'URI',\n  'SSO',\n  'IP',\n  'TLS',\n  'SSL',\n  'DNS',\n  'TCP',\n  'UDP',\n  'SSH',\n  'JWT',\n  'MFA',\n  'SAML',\n  'SCIM',\n];\n\n// Precompiled regex matching all acronym forms (uppercase + title-case) in a single pass.\nconst GO_ACRONYM_RE = new RegExp(\n  GO_ACRONYMS.flatMap((a) => [a, a.charAt(0) + a.slice(1).toLowerCase()]).join('|'),\n  'g',\n);\n\n/**\n * Normalize a Go type string so that acronym casing differences don't cause\n * false mismatches. Lowercases all known Go acronyms to a canonical form.\n */\nfunction normalizeGoAcronyms(type: string): string {\n  return type.replace(GO_ACRONYM_RE, (match) => match.toLowerCase());\n}\n\nconst goHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    if (type.startsWith('*')) return type.slice(1);\n    return null;\n  },\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return defaultIsNullableOnlyDifference(this, a, b);\n  },\n  isUnionReorder(_a: string, _b: string): boolean {\n    return false;\n  },\n  isGenericTypeParam(type: string): boolean {\n    return type === 'interface{}' || type === 'any';\n  },\n  isExtractionArtifact(type: string): boolean {\n    return type === 'interface{}' || type === 'any';\n  },\n  tolerateCategoryMismatch: false,\n  extractReturnTypeName(returnType: string): string | null {\n    const stripped = returnType.replace(/^\\*/, '').replace(/\\[\\]/, '');\n    return stripped || null;\n  },\n  extractParamTypeName(paramType: string): string | null {\n    const stripped = paramType.replace(/^\\*/, '');\n    if (['string', 'int', 'int64', 'float64', 'bool'].includes(stripped)) return null;\n    return stripped;\n  },\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    return propertyName.toLowerCase() === className.toLowerCase();\n  },\n  derivedModelNames(_modelName: string): string[] {\n    // Go SDK does not generate *Response wrapper types — models are returned directly.\n    // Don't derive extra names, as they would create false positives in compat checks\n    // when the live SDK has hand-written response wrappers.\n    return [];\n  },\n  isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n    // Normalize Go acronym casing differences (e.g., \"Json\" vs \"JSON\", \"Uri\" vs \"URI\")\n    const normBase = normalizeGoAcronyms(baselineType);\n    const normCand = normalizeGoAcronyms(candidateType);\n    if (normBase === normCand) return true;\n\n    // Also try after stripping nullable wrappers and slice prefixes on both sides\n    const stripType = (t: string) => t.replace(/^\\*/, '').replace(/^\\[\\]/, '');\n    const strippedBase = stripType(normBase);\n    const strippedCand = stripType(normCand);\n    if (strippedBase === strippedCand) return true;\n\n    // Strip package qualifiers (e.g., \"common.RoleResponse\" → \"RoleResponse\")\n    const unqualBase = strippedBase.includes('.') ? strippedBase.split('.').pop()! : strippedBase;\n    const unqualCand = strippedCand.includes('.') ? strippedCand.split('.').pop()! : strippedCand;\n    if (unqualBase === unqualCand) return true;\n\n    // Suffix match: the baseline may use a shorter shared type name while the\n    // generated code prefixes it with the parent struct name.\n    // e.g., baseline \"FactorType\" matches generated \"AuthenticationFactorType\"\n    // Only match if the candidate type actually exists in the generated surface.\n    const candRaw = stripType(candidateType);\n    if (unqualCand.endsWith(unqualBase) && unqualCand.length > unqualBase.length) {\n      const exists =\n        candidateSurface.enums[candRaw] != null ||\n        candidateSurface.interfaces[candRaw] != null ||\n        candidateSurface.classes[candRaw] != null ||\n        candidateSurface.typeAliases[candRaw] != null;\n      if (exists) return true;\n    }\n\n    return false;\n  },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const goExtractor: Extractor = {\n  language: 'go',\n  hints: goHints,\n\n  async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n    const surface = await this.extract(sdkPath);\n    return apiSurfaceToSnapshot(surface);\n  },\n\n  async extract(sdkPath: string): Promise<ApiSurface> {\n    const goFiles = walkGoFiles(sdkPath);\n    if (goFiles.length === 0) {\n      throw new ExtractorError(\n        `No .go files found in ${sdkPath}`,\n        `Ensure the --sdk-path argument points to a Go project root containing .go source files.`,\n      );\n    }\n\n    const allStructs: GoStruct[] = [];\n    const allTypes: GoTypeDecl[] = [];\n    const allFuncs: GoFunc[] = [];\n    const allConsts: GoConst[] = [];\n\n    for (const filePath of goFiles) {\n      const parsed = parseGoFile(filePath, sdkPath);\n      allStructs.push(...parsed.structs);\n      allTypes.push(...parsed.types);\n      allFuncs.push(...parsed.funcs);\n      allConsts.push(...parsed.consts);\n    }\n\n    const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n      allStructs,\n      allTypes,\n      allFuncs,\n      allConsts,\n    );\n\n    return {\n      language: 'go',\n      extractedFrom: sdkPath,\n      extractedAt: new Date().toISOString(),\n      classes,\n      interfaces,\n      typeAliases,\n      enums,\n      exports,\n    };\n  },\n};\n","/**\n * Rust source parser — tree-sitter-based extraction of structs, enums,\n * impl blocks, traits, type aliases, and functions from Rust source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport RustLang from 'tree-sitter-rust';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface RustStructField {\n  name: string;\n  type: string;\n  serdeRename?: string;\n  optional: boolean;\n}\n\nexport interface RustStruct {\n  name: string;\n  fields: RustStructField[];\n  sourceFile: string;\n}\n\nexport interface RustEnum {\n  name: string;\n  variants: RustEnumVariant[];\n  sourceFile: string;\n}\n\nexport interface RustEnumVariant {\n  name: string;\n  serdeRename?: string;\n}\n\nexport interface RustFunc {\n  receiverType: string | null;\n  name: string;\n  params: { name: string; type: string }[];\n  returnType: string;\n  isAsync: boolean;\n  sourceFile: string;\n}\n\nexport interface RustTypeAlias {\n  name: string;\n  underlyingType: string;\n  sourceFile: string;\n}\n\nexport interface RustTrait {\n  name: string;\n  methods: RustFunc[];\n  sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst rustParser = new Parser();\nrustParser.setLanguage(RustLang);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkRustFiles(dir: string): string[] {\n  const results: string[] = [];\n  let entries: string[];\n  try {\n    entries = readdirSync(dir);\n  } catch {\n    return results;\n  }\n  for (const entry of entries) {\n    const fullPath = join(dir, entry);\n    let stat;\n    try {\n      stat = statSync(fullPath);\n    } catch {\n      continue;\n    }\n    if (stat.isDirectory()) {\n      if (entry.startsWith('.') || entry === 'target' || entry === 'benches' || entry === 'examples') continue;\n      results.push(...walkRustFiles(fullPath));\n    } else if (entry.endsWith('.rs') && !entry.endsWith('_test.rs')) {\n      results.push(fullPath);\n    }\n  }\n  return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Serde attribute helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the serde rename value from an attribute_item preceding a node. */\nfunction extractSerdeRename(attributeNode: SyntaxNode): string | null {\n  const attr = attributeNode.namedChildren.find((c) => c.type === 'attribute');\n  if (!attr) return null;\n\n  const ident = attr.namedChildren.find((c) => c.type === 'identifier');\n  if (!ident || ident.text !== 'serde') return null;\n\n  const tokenTree = attr.namedChildren.find((c) => c.type === 'token_tree');\n  if (!tokenTree) return null;\n\n  const renameIdent = tokenTree.namedChildren.find((c) => c.type === 'identifier' && c.text === 'rename');\n  if (!renameIdent) return null;\n\n  const strLit = tokenTree.namedChildren.find((c) => c.type === 'string_literal');\n  if (!strLit) return null;\n\n  const content = strLit.namedChildren.find((c) => c.type === 'string_content');\n  return content ? content.text : null;\n}\n\n/** Check if a node is preceded by a serde(skip) or serde(skip_serializing) attribute. */\nfunction hasSerdeSkip(attributeNode: SyntaxNode): boolean {\n  const attr = attributeNode.namedChildren.find((c) => c.type === 'attribute');\n  if (!attr) return false;\n\n  const ident = attr.namedChildren.find((c) => c.type === 'identifier');\n  if (!ident || ident.text !== 'serde') return false;\n\n  const tokenTree = attr.namedChildren.find((c) => c.type === 'token_tree');\n  if (!tokenTree) return false;\n\n  return tokenTree.namedChildren.some(\n    (c) => c.type === 'identifier' && (c.text === 'skip' || c.text === 'skip_serializing'),\n  );\n}\n\n/** Check if a type is Option<T> and return the inner type. */\nfunction isOptionType(typeText: string): boolean {\n  return typeText.startsWith('Option<') && typeText.endsWith('>');\n}\n\n/** Check if a node has `pub` visibility. */\nfunction isPublic(node: SyntaxNode): boolean {\n  return node.namedChildren.some((c) => c.type === 'visibility_modifier');\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction parseStructFields(bodyNode: SyntaxNode): RustStructField[] {\n  const fields: RustStructField[] = [];\n  let pendingAttr: SyntaxNode | null = null;\n\n  for (const child of bodyNode.namedChildren) {\n    if (child.type === 'attribute_item') {\n      pendingAttr = child;\n      continue;\n    }\n\n    if (child.type === 'field_declaration') {\n      // Skip non-pub fields\n      if (!isPublic(child)) {\n        pendingAttr = null;\n        continue;\n      }\n\n      // Skip serde(skip) fields\n      if (pendingAttr && hasSerdeSkip(pendingAttr)) {\n        pendingAttr = null;\n        continue;\n      }\n\n      const nameNode = child.namedChildren.find((c) => c.type === 'field_identifier');\n      const typeNode = child.childForFieldName('type');\n      if (!nameNode || !typeNode) {\n        pendingAttr = null;\n        continue;\n      }\n\n      const fieldName = nameNode.text;\n      const fieldType = typeNode.text;\n      const serdeRename = pendingAttr ? extractSerdeRename(pendingAttr) : null;\n\n      fields.push({\n        name: fieldName,\n        type: fieldType,\n        serdeRename: serdeRename || undefined,\n        optional: isOptionType(fieldType),\n      });\n\n      pendingAttr = null;\n    } else {\n      pendingAttr = null;\n    }\n  }\n  return fields;\n}\n\nexport function parseStructs(tree: Parser.Tree, sourceFile: string): RustStruct[] {\n  const structs: RustStruct[] = [];\n\n  for (const node of tree.rootNode.descendantsOfType('struct_item')) {\n    if (!isPublic(node)) continue;\n\n    const nameNode = node.childForFieldName('name');\n    if (!nameNode) continue;\n\n    const bodyNode = node.childForFieldName('body');\n    if (!bodyNode || bodyNode.type !== 'field_declaration_list') {\n      // Tuple struct or unit struct — no named fields\n      structs.push({ name: nameNode.text, fields: [], sourceFile });\n      continue;\n    }\n\n    structs.push({ name: nameNode.text, fields: parseStructFields(bodyNode), sourceFile });\n  }\n\n  return structs;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nexport function parseEnums(tree: Parser.Tree, sourceFile: string): RustEnum[] {\n  const enums: RustEnum[] = [];\n\n  for (const node of tree.rootNode.descendantsOfType('enum_item')) {\n    if (!isPublic(node)) continue;\n\n    const nameNode = node.childForFieldName('name');\n    if (!nameNode) continue;\n\n    const bodyNode = node.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    const variants: RustEnumVariant[] = [];\n    let pendingAttr: SyntaxNode | null = null;\n\n    for (const child of bodyNode.namedChildren) {\n      if (child.type === 'attribute_item') {\n        pendingAttr = child;\n        continue;\n      }\n      if (child.type === 'enum_variant') {\n        const variantName = child.childForFieldName('name');\n        if (variantName) {\n          const serdeRename = pendingAttr ? extractSerdeRename(pendingAttr) : null;\n          variants.push({ name: variantName.text, serdeRename: serdeRename || undefined });\n        }\n        pendingAttr = null;\n      } else {\n        pendingAttr = null;\n      }\n    }\n\n    if (variants.length > 0) {\n      enums.push({ name: nameNode.text, variants, sourceFile });\n    }\n  }\n\n  return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Impl & function extraction\n// ---------------------------------------------------------------------------\n\nfunction parseParams(paramsNode: SyntaxNode): { name: string; type: string }[] {\n  const params: { name: string; type: string }[] = [];\n\n  for (const child of paramsNode.namedChildren) {\n    if (child.type === 'self_parameter') continue; // skip &self, &mut self\n\n    if (child.type === 'parameter') {\n      const patternNode = child.childForFieldName('pattern');\n      const typeNode = child.childForFieldName('type');\n      if (patternNode && typeNode) {\n        params.push({ name: patternNode.text, type: typeNode.text });\n      }\n    }\n  }\n\n  return params;\n}\n\nfunction extractReturnType(funcNode: SyntaxNode): string {\n  const retNode = funcNode.childForFieldName('return_type');\n  if (!retNode) return '()';\n  return retNode.text;\n}\n\nfunction isAsyncFunc(funcNode: SyntaxNode): boolean {\n  return funcNode.namedChildren.some((c) => c.type === 'function_modifiers' && c.text.includes('async'));\n}\n\nexport function parseImplBlocks(tree: Parser.Tree, sourceFile: string): RustFunc[] {\n  const funcs: RustFunc[] = [];\n\n  for (const implNode of tree.rootNode.descendantsOfType('impl_item')) {\n    const typeNode = implNode.childForFieldName('type');\n    if (!typeNode) continue;\n    const receiverType = typeNode.text;\n\n    const bodyNode = implNode.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    for (const child of bodyNode.namedChildren) {\n      if (child.type !== 'function_item') continue;\n      if (!isPublic(child)) continue;\n\n      const nameNode = child.childForFieldName('name');\n      if (!nameNode) continue;\n\n      const paramsNode = child.childForFieldName('parameters');\n\n      funcs.push({\n        receiverType,\n        name: nameNode.text,\n        params: paramsNode ? parseParams(paramsNode) : [],\n        returnType: extractReturnType(child),\n        isAsync: isAsyncFunc(child),\n        sourceFile,\n      });\n    }\n  }\n\n  return funcs;\n}\n\n// ---------------------------------------------------------------------------\n// Trait extraction\n// ---------------------------------------------------------------------------\n\nexport function parseTraits(tree: Parser.Tree, sourceFile: string): RustTrait[] {\n  const traits: RustTrait[] = [];\n\n  for (const traitNode of tree.rootNode.descendantsOfType('trait_item')) {\n    if (!isPublic(traitNode)) continue;\n\n    const nameNode = traitNode.childForFieldName('name');\n    if (!nameNode) continue;\n\n    const bodyNode = traitNode.childForFieldName('body');\n    if (!bodyNode) continue;\n\n    const methods: RustFunc[] = [];\n\n    for (const child of bodyNode.namedChildren) {\n      // Trait methods appear as function_signature_item (no body)\n      if (child.type !== 'function_signature_item' && child.type !== 'function_item') continue;\n\n      const methodName = child.childForFieldName('name');\n      if (!methodName) continue;\n\n      const paramsNode = child.childForFieldName('parameters');\n\n      methods.push({\n        receiverType: null,\n        name: methodName.text,\n        params: paramsNode ? parseParams(paramsNode) : [],\n        returnType: extractReturnType(child),\n        isAsync: isAsyncFunc(child),\n        sourceFile,\n      });\n    }\n\n    if (methods.length > 0) {\n      traits.push({ name: nameNode.text, methods, sourceFile });\n    }\n  }\n\n  return traits;\n}\n\n// ---------------------------------------------------------------------------\n// Type alias extraction\n// ---------------------------------------------------------------------------\n\nexport function parseTypeAliases(tree: Parser.Tree, sourceFile: string): RustTypeAlias[] {\n  const aliases: RustTypeAlias[] = [];\n\n  for (const node of tree.rootNode.descendantsOfType('type_item')) {\n    if (!isPublic(node)) continue;\n\n    const nameNode = node.childForFieldName('name');\n    const typeNode = node.childForFieldName('type');\n    if (!nameNode || !typeNode) continue;\n\n    aliases.push({ name: nameNode.text, underlyingType: typeNode.text, sourceFile });\n  }\n\n  return aliases;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedRustFile {\n  structs: RustStruct[];\n  enums: RustEnum[];\n  funcs: RustFunc[];\n  traits: RustTrait[];\n  typeAliases: RustTypeAlias[];\n}\n\nexport function parseRustFile(filePath: string, sdkPath: string): ParsedRustFile {\n  const source = readFileSync(filePath, 'utf-8');\n  const relPath = relative(sdkPath, filePath);\n  const tree = safeParse(rustParser, source);\n\n  return {\n    structs: parseStructs(tree, relPath),\n    enums: parseEnums(tree, relPath),\n    funcs: parseImplBlocks(tree, relPath),\n    traits: parseTraits(tree, relPath),\n    typeAliases: parseTypeAliases(tree, relPath),\n  };\n}\n","/**\n * Rust surface builder — transforms parsed Rust symbols into an ApiSurface.\n *\n * Mapping:\n *   pub struct + impl methods → ApiClass\n *   pub struct (no methods)   → ApiInterface (data-only)\n *   pub enum                  → ApiEnum (serde renames as member values)\n *   pub type X = Y            → ApiTypeAlias\n *   pub trait                 → ApiClass (trait methods as API surface)\n */\n\nimport type {\n  ApiClass,\n  ApiMethod,\n  ApiParam,\n  ApiProperty,\n  ApiInterface,\n  ApiField,\n  ApiTypeAlias,\n  ApiEnum,\n} from '../types.js';\nimport type { RustStruct, RustEnum, RustFunc, RustTrait, RustTypeAlias as RustTypeAliasType } from './rust-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction rustTypeToString(t: string): string {\n  return t;\n}\n\n/** Strip Result<T, E> to just T. */\nfunction unwrapResultType(returnType: string): string {\n  const match = returnType.match(/^Result\\s*<\\s*(.+)\\s*,\\s*.+\\s*>$/);\n  if (match) return match[1].trim();\n  return returnType;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n  allStructs: RustStruct[],\n  allEnums: RustEnum[],\n  allFuncs: RustFunc[],\n  allTraits: RustTrait[],\n  allTypeAliases: RustTypeAliasType[],\n): {\n  classes: Record<string, ApiClass>;\n  interfaces: Record<string, ApiInterface>;\n  typeAliases: Record<string, ApiTypeAlias>;\n  enums: Record<string, ApiEnum>;\n  exports: Record<string, string[]>;\n} {\n  const classes: Record<string, ApiClass> = {};\n  const interfaces: Record<string, ApiInterface> = {};\n  const typeAliases: Record<string, ApiTypeAlias> = {};\n  const enums: Record<string, ApiEnum> = {};\n\n  // Group impl methods by receiver type\n  const methodsByReceiver = new Map<string, RustFunc[]>();\n  for (const fn of allFuncs) {\n    if (!fn.receiverType) continue;\n    if (!methodsByReceiver.has(fn.receiverType)) methodsByReceiver.set(fn.receiverType, []);\n    methodsByReceiver.get(fn.receiverType)!.push(fn);\n  }\n\n  // Process structs\n  for (const s of allStructs) {\n    const methods = methodsByReceiver.get(s.name);\n\n    if (methods && methods.length > 0) {\n      // Struct with impl methods → ApiClass\n      const apiMethods: Record<string, ApiMethod[]> = {};\n      const properties: Record<string, ApiProperty> = {};\n\n      for (const field of s.fields) {\n        const fieldName = field.serdeRename || field.name;\n        properties[fieldName] = {\n          name: fieldName,\n          type: rustTypeToString(field.type),\n          readonly: false,\n        };\n      }\n\n      for (const fn of methods) {\n        const params: ApiParam[] = fn.params.map((p) => ({\n          name: p.name,\n          type: rustTypeToString(p.type),\n          optional: p.type.startsWith('Option<'),\n          passingStyle: 'positional' as const,\n        }));\n        const returnType = unwrapResultType(fn.returnType);\n        if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n        apiMethods[fn.name].push({\n          name: fn.name,\n          params,\n          returnType: rustTypeToString(returnType),\n          async: fn.isAsync,\n        });\n      }\n\n      classes[s.name] = {\n        name: s.name,\n        sourceFile: s.sourceFile,\n        methods: sortRecord(apiMethods),\n        properties: sortRecord(properties),\n        constructorParams: [],\n      };\n    } else {\n      // Struct without methods → ApiInterface\n      const fields: Record<string, ApiField> = {};\n      for (const field of s.fields) {\n        const fieldName = field.serdeRename || field.name;\n        fields[fieldName] = {\n          name: fieldName,\n          type: rustTypeToString(field.type),\n          optional: field.optional,\n        };\n      }\n      interfaces[s.name] = {\n        name: s.name,\n        sourceFile: s.sourceFile,\n        fields: sortRecord(fields),\n        extends: [],\n      };\n    }\n  }\n\n  // Process enums\n  for (const e of allEnums) {\n    const members: Record<string, string | number> = {};\n    for (const v of e.variants) {\n      members[v.name] = v.serdeRename || v.name;\n    }\n    enums[e.name] = { name: e.name, sourceFile: e.sourceFile, members: sortRecord(members) };\n  }\n\n  // Process type aliases\n  for (const ta of allTypeAliases) {\n    typeAliases[ta.name] = { name: ta.name, sourceFile: ta.sourceFile, value: rustTypeToString(ta.underlyingType) };\n  }\n\n  // Process traits → ApiClass (trait methods define the API contract)\n  for (const trait of allTraits) {\n    const apiMethods: Record<string, ApiMethod[]> = {};\n\n    for (const fn of trait.methods) {\n      const params: ApiParam[] = fn.params.map((p) => ({\n        name: p.name,\n        type: rustTypeToString(p.type),\n        optional: p.type.startsWith('Option<'),\n      }));\n      const returnType = unwrapResultType(fn.returnType);\n      if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n      apiMethods[fn.name].push({\n        name: fn.name,\n        params,\n        returnType: rustTypeToString(returnType),\n        async: fn.isAsync,\n      });\n    }\n\n    classes[trait.name] = {\n      name: trait.name,\n      sourceFile: trait.sourceFile,\n      methods: sortRecord(apiMethods),\n      properties: {},\n      constructorParams: [],\n    };\n  }\n\n  // Build export map\n  const collector = new ExportCollector();\n\n  for (const [name, cls] of Object.entries(classes)) if (cls.sourceFile) collector.add(cls.sourceFile, name);\n  for (const [name, iface] of Object.entries(interfaces)) if (iface.sourceFile) collector.add(iface.sourceFile, name);\n  for (const [name, ta] of Object.entries(typeAliases)) if (ta.sourceFile) collector.add(ta.sourceFile, name);\n  for (const [name, en] of Object.entries(enums)) if (en.sourceFile) collector.add(en.sourceFile, name);\n\n  const exports = collector.toRecord();\n\n  return {\n    classes: sortRecord(classes),\n    interfaces: sortRecord(interfaces),\n    typeAliases: sortRecord(typeAliases),\n    enums: sortRecord(enums),\n    exports: sortRecord(exports),\n  };\n}\n","/**\n * Rust API surface extractor.\n *\n * Walks `.rs` files under `src/`, parses pub structs, enums, impl blocks,\n * traits, and type aliases, then builds an ApiSurface.\n *\n * Parser:  `rust-parser.ts`  — tree-sitter-based Rust source analysis\n * Surface: `rust-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkRustFiles, parseRustFile } from './rust-parser.js';\nimport { buildSurface } from './rust-surface.js';\nimport type { RustStruct, RustEnum, RustFunc, RustTrait, RustTypeAlias } from './rust-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst rustHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    const match = type.match(/^Option<(.+)>$/);\n    return match ? match[1] : null;\n  },\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return defaultIsNullableOnlyDifference(this, a, b);\n  },\n  isUnionReorder(_a: string, _b: string): boolean {\n    return false; // Rust doesn't have union types in the TS sense\n  },\n  isGenericTypeParam(type: string): boolean {\n    // Single uppercase letter or T-prefixed: T, U, V, TResult\n    return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n  },\n  isExtractionArtifact(type: string): boolean {\n    return type === 'serde_json::Value' || type === 'Box<dyn std::error::Error>';\n  },\n  tolerateCategoryMismatch: false,\n  extractReturnTypeName(returnType: string): string | null {\n    // Unwrap Result<T, E> → T, Vec<T> → T, Option<T> → T\n    let inner = returnType;\n    const resultMatch = inner.match(/^Result\\s*<\\s*(.+)\\s*,\\s*.+\\s*>$/);\n    if (resultMatch) inner = resultMatch[1].trim();\n    const vecMatch = inner.match(/^Vec\\s*<\\s*(.+)\\s*>$/);\n    if (vecMatch) inner = vecMatch[1].trim();\n    const optMatch = inner.match(/^Option\\s*<\\s*(.+)\\s*>$/);\n    if (optMatch) inner = optMatch[1].trim();\n    // Strip references\n    inner = inner.replace(/^&(?:mut\\s+)?(?:'[a-z]+\\s+)?/, '');\n    if (['()', 'String', 'str', 'bool', 'i32', 'i64', 'u32', 'u64', 'f32', 'f64', 'usize'].includes(inner)) {\n      return null;\n    }\n    return inner;\n  },\n  extractParamTypeName(paramType: string): string | null {\n    let inner = paramType.replace(/^&(?:mut\\s+)?(?:'[a-z]+\\s+)?/, '');\n    if (['String', '&str', 'str', 'bool', 'i32', 'i64', 'u32', 'u64', 'f32', 'f64', 'usize'].includes(inner)) {\n      return null;\n    }\n    return inner;\n  },\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    // snake_case property vs PascalCase class\n    const normalized = propertyName.replace(/_/g, '').toLowerCase();\n    return normalized === className.toLowerCase();\n  },\n  derivedModelNames(modelName: string): string[] {\n    return [`${modelName}Response`];\n  },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const rustExtractor: Extractor = {\n  language: 'rust',\n  hints: rustHints,\n\n  async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n    const surface = await this.extract(sdkPath);\n    return apiSurfaceToSnapshot(surface);\n  },\n\n  async extract(sdkPath: string): Promise<ApiSurface> {\n    const rsFiles = walkRustFiles(sdkPath);\n    if (rsFiles.length === 0) {\n      throw new ExtractorError(\n        `No .rs files found in ${sdkPath}`,\n        `Ensure the --sdk-path argument points to a Rust project root containing .rs source files.`,\n      );\n    }\n\n    const allStructs: RustStruct[] = [];\n    const allEnums: RustEnum[] = [];\n    const allFuncs: RustFunc[] = [];\n    const allTraits: RustTrait[] = [];\n    const allTypeAliases: RustTypeAlias[] = [];\n\n    for (const filePath of rsFiles) {\n      const parsed = parseRustFile(filePath, sdkPath);\n      allStructs.push(...parsed.structs);\n      allEnums.push(...parsed.enums);\n      allFuncs.push(...parsed.funcs);\n      allTraits.push(...parsed.traits);\n      allTypeAliases.push(...parsed.typeAliases);\n    }\n\n    const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n      allStructs,\n      allEnums,\n      allFuncs,\n      allTraits,\n      allTypeAliases,\n    );\n\n    return {\n      language: 'rust',\n      extractedFrom: sdkPath,\n      extractedAt: new Date().toISOString(),\n      classes,\n      interfaces,\n      typeAliases,\n      enums,\n      exports,\n    };\n  },\n};\n","/**\n * Kotlin source parser — regex-based extraction of classes, data classes,\n * enum classes, functions, and type aliases from Kotlin source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface KotlinField {\n  name: string;\n  type: string;\n  jsonName?: string;\n  optional: boolean;\n}\n\nexport interface KotlinDataClass {\n  name: string;\n  fields: KotlinField[];\n  sourceFile: string;\n  packageName: string;\n}\n\nexport interface KotlinClass {\n  name: string;\n  constructorParams: { name: string; type: string }[];\n  methods: KotlinMethod[];\n  sourceFile: string;\n  packageName: string;\n}\n\nexport interface KotlinMethod {\n  name: string;\n  params: { name: string; type: string; optional: boolean }[];\n  returnType: string;\n  visibility: string;\n}\n\nexport interface KotlinEnum {\n  name: string;\n  members: Record<string, string>;\n  sourceFile: string;\n  packageName: string;\n}\n\nexport interface KotlinTypeAlias {\n  name: string;\n  value: string;\n  sourceFile: string;\n  packageName: string;\n}\n\nexport interface ParsedKotlinFile {\n  dataClasses: KotlinDataClass[];\n  classes: KotlinClass[];\n  enums: KotlinEnum[];\n  typeAliases: KotlinTypeAlias[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkKotlinFiles(dir: string): string[] {\n  const results: string[] = [];\n  let entries: string[];\n  try {\n    entries = readdirSync(dir);\n  } catch {\n    return results;\n  }\n  for (const entry of entries) {\n    const fullPath = join(dir, entry);\n    let stat;\n    try {\n      stat = statSync(fullPath);\n    } catch {\n      continue;\n    }\n    if (stat.isDirectory()) {\n      if (entry.startsWith('.') || entry === 'build' || entry === 'test' || entry === 'androidTest') continue;\n      results.push(...walkKotlinFiles(fullPath));\n    } else if (entry.endsWith('.kt') && !entry.endsWith('Test.kt')) {\n      results.push(fullPath);\n    }\n  }\n  return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the package name from a Kotlin source file. */\nfunction extractPackageName(source: string): string {\n  const match = source.match(/^package\\s+([\\w.]+)/m);\n  return match ? match[1] : 'unknown';\n}\n\n/** Strip single-line and block comments from source to avoid false matches. */\nfunction stripComments(source: string): string {\n  // Remove block comments\n  let result = source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n  // Remove single-line comments\n  result = result.replace(/\\/\\/[^\\n]*/g, '');\n  return result;\n}\n\n/**\n * Extract the @JsonProperty(\"name\") annotation value before a parameter.\n * Looks for the pattern immediately preceding the parameter declaration.\n */\nfunction extractJsonPropertyName(text: string): string | null {\n  const match = text.match(/@JsonProperty\\(\"([^\"]+)\"\\)/);\n  return match ? match[1] : null;\n}\n\n/**\n * Parse constructor parameters from a data class or class declaration.\n * Handles multi-line parameter lists with annotations.\n */\nfunction parseConstructorParams(paramsBlock: string): KotlinField[] {\n  const fields: KotlinField[] = [];\n\n  // Split by top-level commas (not nested in angle brackets or parens)\n  const params = splitTopLevelCommas(paramsBlock);\n\n  for (const param of params) {\n    const trimmed = param.trim();\n    if (!trimmed) continue;\n\n    // Extract JsonProperty annotation if present\n    const jsonName = extractJsonPropertyName(trimmed);\n\n    // Match val/var name: Type pattern, possibly with default value\n    const paramMatch = trimmed.match(\n      /(?:(?:override|private|protected)\\s+)?(?:val|var)\\s+(\\w+)\\s*:\\s*([^=,]+?)(?:\\s*=\\s*(.+))?$/m,\n    );\n    if (!paramMatch) continue;\n\n    const name = paramMatch[1];\n    const rawType = paramMatch[2].trim();\n    const hasDefault = paramMatch[3] !== undefined;\n\n    // Check if the type is nullable (ends with ?)\n    const isNullable = rawType.endsWith('?');\n    const type = rawType;\n\n    fields.push({\n      name,\n      type,\n      jsonName: jsonName || undefined,\n      optional: isNullable || hasDefault,\n    });\n  }\n\n  return fields;\n}\n\n/** Split a string by top-level commas, ignoring commas inside angle brackets, parens, or strings. */\nfunction splitTopLevelCommas(text: string): string[] {\n  const result: string[] = [];\n  let depth = 0;\n  let current = '';\n  let inString = false;\n  let stringChar = '';\n\n  for (let i = 0; i < text.length; i++) {\n    const ch = text[i];\n\n    if (inString) {\n      current += ch;\n      if (ch === stringChar && text[i - 1] !== '\\\\') {\n        inString = false;\n      }\n      continue;\n    }\n\n    if (ch === '\"' || ch === \"'\") {\n      inString = true;\n      stringChar = ch;\n      current += ch;\n      continue;\n    }\n\n    if (ch === '<' || ch === '(' || ch === '[') {\n      depth++;\n      current += ch;\n    } else if (ch === '>' || ch === ')' || ch === ']') {\n      depth--;\n      current += ch;\n    } else if (ch === ',' && depth === 0) {\n      result.push(current);\n      current = '';\n    } else {\n      current += ch;\n    }\n  }\n\n  if (current.trim()) {\n    result.push(current);\n  }\n\n  return result;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnumClass(source: string, sourceFile: string, packageName: string): KotlinEnum[] {\n  const enums: KotlinEnum[] = [];\n\n  // Match: enum class Name(@JsonValue val value: Type) { Member1(\"val1\"), Member2(\"val2\") }\n  const enumRegex = /enum\\s+class\\s+(\\w+)(?:\\([^)]*\\))?\\s*\\{([^}]*)\\}/g;\n  let match;\n  while ((match = enumRegex.exec(source)) !== null) {\n    const name = match[1];\n    const body = match[2];\n\n    const members: Record<string, string> = {};\n\n    // Match enum members: MemberName(\"value\") or MemberName\n    const memberRegex = /(\\w+)\\s*(?:\\(\"([^\"]*)\"\\))?/g;\n    let memberMatch;\n    while ((memberMatch = memberRegex.exec(body)) !== null) {\n      const memberName = memberMatch[1];\n      // Skip keywords that might match\n      if (['val', 'var', 'fun', 'override', 'companion', 'object'].includes(memberName)) continue;\n      const memberValue = memberMatch[2] !== undefined ? memberMatch[2] : memberName;\n      members[memberName] = memberValue;\n    }\n\n    if (Object.keys(members).length > 0) {\n      enums.push({ name, members, sourceFile, packageName });\n    }\n  }\n\n  return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Data class extraction\n// ---------------------------------------------------------------------------\n\nfunction parseDataClasses(source: string, sourceFile: string, packageName: string): KotlinDataClass[] {\n  const dataClasses: KotlinDataClass[] = [];\n\n  // Match: data class Name(params) or data class Name @Annotation constructor(params)\n  // Use a regex that captures the opening paren, then find the matching close\n  const dataClassStartRegex = /data\\s+class\\s+(\\w+)\\s*(?:@\\w+(?:\\([^)]*\\))?\\s+)?(?:constructor\\s*)?\\(/g;\n  let match;\n  while ((match = dataClassStartRegex.exec(source)) !== null) {\n    const name = match[1];\n    const startIdx = match.index + match[0].length;\n\n    // Find matching closing paren\n    let depth = 1;\n    let idx = startIdx;\n    while (idx < source.length && depth > 0) {\n      if (source[idx] === '(') depth++;\n      else if (source[idx] === ')') depth--;\n      idx++;\n    }\n\n    const paramsBlock = source.slice(startIdx, idx - 1);\n    const fields = parseConstructorParams(paramsBlock);\n\n    dataClasses.push({ name, fields, sourceFile, packageName });\n  }\n\n  return dataClasses;\n}\n\n// ---------------------------------------------------------------------------\n// Class extraction (non-data classes)\n// ---------------------------------------------------------------------------\n\nfunction parseClasses(source: string, sourceFile: string, packageName: string): KotlinClass[] {\n  const classes: KotlinClass[] = [];\n\n  // Match non-data, non-enum classes: class Name(params) { body }\n  // Skip abstract, sealed, and open classes that aren't services\n  const classStartRegex =\n    /(?<!data\\s)(?<!enum\\s)(?<!abstract\\s)(?<!sealed\\s)(?:open\\s+)?class\\s+(\\w+)\\s*(?:\\(([^)]*)\\))?\\s*(?::\\s*[^{]+)?\\s*\\{/g;\n  let match;\n  while ((match = classStartRegex.exec(source)) !== null) {\n    const name = match[1];\n    const constructorBlock = match[2] || '';\n\n    // Find matching closing brace for the class body\n    const braceStart = source.indexOf('{', match.index + match[0].length - 1);\n    let depth = 1;\n    let idx = braceStart + 1;\n    while (idx < source.length && depth > 0) {\n      if (source[idx] === '{') depth++;\n      else if (source[idx] === '}') depth--;\n      idx++;\n    }\n\n    const classBody = source.slice(braceStart + 1, idx - 1);\n\n    // Parse constructor params\n    const constructorParams: { name: string; type: string }[] = [];\n    if (constructorBlock.trim()) {\n      const params = splitTopLevelCommas(constructorBlock);\n      for (const param of params) {\n        const trimmed = param.trim();\n        const paramMatch = trimmed.match(/(?:(?:private|protected)\\s+)?(?:val|var)\\s+(\\w+)\\s*:\\s*(.+)/);\n        if (paramMatch) {\n          constructorParams.push({ name: paramMatch[1], type: paramMatch[2].trim() });\n        }\n      }\n    }\n\n    // Parse methods\n    const methods = parseMethods(classBody);\n\n    if (methods.length > 0) {\n      classes.push({ name, constructorParams, methods, sourceFile, packageName });\n    }\n  }\n\n  return classes;\n}\n\n/** Parse method declarations from a class body. */\nfunction parseMethods(classBody: string): KotlinMethod[] {\n  const methods: KotlinMethod[] = [];\n\n  // Match: fun methodName(params): ReturnType or fun methodName(params)\n  // Handle suspend fun, private fun, etc.\n  const methodRegex =\n    /(private|protected|internal|public)?\\s*(?:suspend\\s+)?fun\\s+(\\w+)\\s*\\(([^)]*)\\)\\s*(?::\\s*([^\\s{]+))?/g;\n  let match;\n  while ((match = methodRegex.exec(classBody)) !== null) {\n    const visibility = match[1] || 'public';\n    const name = match[2];\n    const paramsStr = match[3];\n    const returnType = match[4] || 'Unit';\n\n    // Skip private/protected methods\n    if (visibility === 'private' || visibility === 'protected') continue;\n\n    const params: { name: string; type: string; optional: boolean }[] = [];\n    if (paramsStr.trim()) {\n      const paramParts = splitTopLevelCommas(paramsStr);\n      for (const part of paramParts) {\n        const trimmed = part.trim();\n        const paramMatch = trimmed.match(/(\\w+)\\s*:\\s*([^=]+?)(?:\\s*=\\s*(.+))?$/);\n        if (paramMatch) {\n          const paramType = paramMatch[2].trim();\n          const hasDefault = paramMatch[3] !== undefined;\n          params.push({\n            name: paramMatch[1],\n            type: paramType,\n            optional: paramType.endsWith('?') || hasDefault,\n          });\n        }\n      }\n    }\n\n    methods.push({ name, params, returnType, visibility });\n  }\n\n  return methods;\n}\n\n// ---------------------------------------------------------------------------\n// Type alias extraction\n// ---------------------------------------------------------------------------\n\nfunction parseTypeAliases(source: string, sourceFile: string, packageName: string): KotlinTypeAlias[] {\n  const aliases: KotlinTypeAlias[] = [];\n\n  const aliasRegex = /typealias\\s+(\\w+)\\s*=\\s*([^\\n]+)/g;\n  let match;\n  while ((match = aliasRegex.exec(source)) !== null) {\n    aliases.push({\n      name: match[1],\n      value: match[2].trim(),\n      sourceFile,\n      packageName,\n    });\n  }\n\n  return aliases;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single Kotlin source file and return all extracted symbols. */\nexport function parseKotlinFile(filePath: string, sdkPath: string): ParsedKotlinFile {\n  const source = readFileSync(filePath, 'utf-8');\n  const relPath = relative(sdkPath, filePath);\n  const cleaned = stripComments(source);\n  const packageName = extractPackageName(cleaned);\n\n  return {\n    dataClasses: parseDataClasses(cleaned, relPath, packageName),\n    classes: parseClasses(cleaned, relPath, packageName),\n    enums: parseEnumClass(cleaned, relPath, packageName),\n    typeAliases: parseTypeAliases(cleaned, relPath, packageName),\n  };\n}\n","/**\n * Kotlin surface builder — transforms parsed Kotlin symbols into an ApiSurface.\n */\n\nimport type {\n  ApiClass,\n  ApiMethod,\n  ApiParam,\n  ApiProperty,\n  ApiInterface,\n  ApiField,\n  ApiTypeAlias,\n  ApiEnum,\n} from '../types.js';\nimport type { KotlinDataClass, KotlinClass, KotlinEnum, KotlinTypeAlias } from './kotlin-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n  allDataClasses: KotlinDataClass[],\n  allClasses: KotlinClass[],\n  allEnums: KotlinEnum[],\n  allTypeAliases: KotlinTypeAlias[],\n): {\n  classes: Record<string, ApiClass>;\n  interfaces: Record<string, ApiInterface>;\n  typeAliases: Record<string, ApiTypeAlias>;\n  enums: Record<string, ApiEnum>;\n  exports: Record<string, string[]>;\n} {\n  const classes: Record<string, ApiClass> = {};\n  const interfaces: Record<string, ApiInterface> = {};\n  const typeAliases: Record<string, ApiTypeAlias> = {};\n  const enums: Record<string, ApiEnum> = {};\n\n  const collector = new ExportCollector();\n\n  // Process data classes as interfaces (they represent data models)\n  for (const dc of allDataClasses) {\n    const fields: Record<string, ApiField> = {};\n    for (const field of dc.fields) {\n      const fieldName = field.jsonName || field.name;\n      fields[fieldName] = {\n        name: fieldName,\n        type: field.type,\n        optional: field.optional,\n      };\n    }\n    interfaces[dc.name] = {\n      name: dc.name,\n      sourceFile: dc.sourceFile,\n      fields: sortRecord(fields),\n      extends: [],\n    };\n    collector.add(dc.sourceFile, dc.name);\n  }\n\n  // Process classes (service classes with methods)\n  for (const cls of allClasses) {\n    const methods: Record<string, ApiMethod[]> = {};\n    const properties: Record<string, ApiProperty> = {};\n\n    for (const method of cls.methods) {\n      const params: ApiParam[] = method.params.map((p) => ({\n        name: p.name,\n        type: p.type,\n        optional: p.optional,\n        passingStyle: 'named' as const,\n      }));\n\n      if (!methods[method.name]) methods[method.name] = [];\n      methods[method.name].push({\n        name: method.name,\n        params,\n        returnType: method.returnType,\n        async: false,\n      });\n    }\n\n    const constructorParams: ApiParam[] = cls.constructorParams.map((p) => ({\n      name: p.name,\n      type: p.type,\n      optional: false,\n      passingStyle: 'named' as const,\n    }));\n\n    classes[cls.name] = {\n      name: cls.name,\n      sourceFile: cls.sourceFile,\n      methods: sortRecord(methods),\n      properties: sortRecord(properties),\n      constructorParams,\n    };\n    collector.add(cls.sourceFile, cls.name);\n  }\n\n  // Process enums\n  for (const en of allEnums) {\n    enums[en.name] = {\n      name: en.name,\n      sourceFile: en.sourceFile,\n      members: sortRecord(en.members),\n    };\n    collector.add(en.sourceFile, en.name);\n  }\n\n  // Process type aliases\n  for (const ta of allTypeAliases) {\n    typeAliases[ta.name] = {\n      name: ta.name,\n      sourceFile: ta.sourceFile,\n      value: ta.value,\n    };\n    collector.add(ta.sourceFile, ta.name);\n  }\n\n  const exports = collector.toRecord();\n\n  return {\n    classes: sortRecord(classes),\n    interfaces: sortRecord(interfaces),\n    typeAliases: sortRecord(typeAliases),\n    enums: sortRecord(enums),\n    exports: sortRecord(exports),\n  };\n}\n","/**\n * Kotlin API surface extractor.\n *\n * Walks `.kt` files (excluding test files and build directories), parses\n * data classes, classes, enum classes, and type aliases, then builds an\n * `ApiSurface`.\n *\n * Parser:  `kotlin-parser.ts`  — regex-based Kotlin source analysis\n * Surface: `kotlin-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkKotlinFiles, parseKotlinFile } from './kotlin-parser.js';\nimport { buildSurface } from './kotlin-surface.js';\nimport type { KotlinDataClass, KotlinClass, KotlinEnum, KotlinTypeAlias } from './kotlin-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst kotlinHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    if (type.endsWith('?')) return type.slice(0, -1);\n    return null;\n  },\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return defaultIsNullableOnlyDifference(this, a, b);\n  },\n  isUnionReorder(_a: string, _b: string): boolean {\n    return false; // Kotlin doesn't have union types\n  },\n  isGenericTypeParam(type: string): boolean {\n    return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n  },\n  isExtractionArtifact(type: string): boolean {\n    return type === 'Any' || type === 'Any?';\n  },\n  tolerateCategoryMismatch: true,\n  extractReturnTypeName(returnType: string): string | null {\n    let inner = returnType;\n    // Unwrap nullable\n    if (inner.endsWith('?')) inner = inner.slice(0, -1);\n    // Unwrap List<T> → T\n    const listMatch = inner.match(/^(?:List|MutableList|ArrayList)<(.+)>$/);\n    if (listMatch) inner = listMatch[1];\n    // Unwrap PaginatedList<T> → T\n    const paginatedMatch = inner.match(/^PaginatedList<(.+)>$/);\n    if (paginatedMatch) inner = paginatedMatch[1];\n    // Primitives\n    if (['String', 'Int', 'Long', 'Float', 'Double', 'Boolean', 'Unit', 'Void'].includes(inner)) return null;\n    return inner;\n  },\n  extractParamTypeName(paramType: string): string | null {\n    let inner = paramType;\n    if (inner.endsWith('?')) inner = inner.slice(0, -1);\n    if (['String', 'Int', 'Long', 'Float', 'Double', 'Boolean'].includes(inner)) return null;\n    return inner;\n  },\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    // camelCase property vs PascalCase class\n    return propertyName.toLowerCase() === className.toLowerCase();\n  },\n  derivedModelNames(modelName: string): string[] {\n    return [`${modelName}Response`];\n  },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const kotlinExtractor: Extractor = {\n  language: 'kotlin',\n  hints: kotlinHints,\n\n  async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n    const surface = await this.extract(sdkPath);\n    return apiSurfaceToSnapshot(surface);\n  },\n\n  async extract(sdkPath: string): Promise<ApiSurface> {\n    const ktFiles = walkKotlinFiles(sdkPath);\n    if (ktFiles.length === 0) {\n      throw new ExtractorError(\n        `No .kt files found in ${sdkPath}`,\n        `Ensure the --sdk-path argument points to a Kotlin project root containing .kt source files.`,\n      );\n    }\n\n    const allDataClasses: KotlinDataClass[] = [];\n    const allClasses: KotlinClass[] = [];\n    const allEnums: KotlinEnum[] = [];\n    const allTypeAliases: KotlinTypeAlias[] = [];\n\n    for (const filePath of ktFiles) {\n      const parsed = parseKotlinFile(filePath, sdkPath);\n      allDataClasses.push(...parsed.dataClasses);\n      allClasses.push(...parsed.classes);\n      allEnums.push(...parsed.enums);\n      allTypeAliases.push(...parsed.typeAliases);\n    }\n\n    const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n      allDataClasses,\n      allClasses,\n      allEnums,\n      allTypeAliases,\n    );\n\n    return {\n      language: 'kotlin',\n      extractedFrom: sdkPath,\n      extractedAt: new Date().toISOString(),\n      classes,\n      interfaces,\n      typeAliases,\n      enums,\n      exports,\n    };\n  },\n};\n","/**\n * C# (.NET) source parser — regex-based extraction of classes, enums,\n * properties, and methods from C# source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface CSharpProperty {\n  name: string;\n  type: string;\n  jsonName?: string;\n  readonly: boolean;\n}\n\nexport interface CSharpMethod {\n  name: string;\n  params: { name: string; type: string; optional: boolean }[];\n  returnType: string;\n  visibility: string;\n  isAsync: boolean;\n}\n\nexport interface CSharpClass {\n  name: string;\n  namespace: string;\n  properties: CSharpProperty[];\n  methods: CSharpMethod[];\n  constructorParams: { name: string; type: string }[];\n  isService: boolean;\n  sourceFile: string;\n}\n\nexport interface CSharpEnum {\n  name: string;\n  namespace: string;\n  members: Record<string, string>;\n  sourceFile: string;\n}\n\nexport interface ParsedCSharpFile {\n  classes: CSharpClass[];\n  enums: CSharpEnum[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkCSharpFiles(dir: string): string[] {\n  const results: string[] = [];\n  let entries: string[];\n  try {\n    entries = readdirSync(dir);\n  } catch {\n    return results;\n  }\n  for (const entry of entries) {\n    const fullPath = join(dir, entry);\n    let stat;\n    try {\n      stat = statSync(fullPath);\n    } catch {\n      continue;\n    }\n    if (stat.isDirectory()) {\n      if (entry.startsWith('.') || entry === 'bin' || entry === 'obj' || entry === 'test' || entry === 'tests') {\n        continue;\n      }\n      results.push(...walkCSharpFiles(fullPath));\n    } else if (entry.endsWith('.cs') && !entry.endsWith('Test.cs') && !entry.endsWith('Tests.cs')) {\n      results.push(fullPath);\n    }\n  }\n  return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the namespace from a C# source file. */\nfunction extractNamespace(source: string): string {\n  // File-scoped namespace (C# 10+): namespace Foo.Bar;\n  const fileScopedMatch = source.match(/^namespace\\s+([\\w.]+)\\s*;/m);\n  if (fileScopedMatch) return fileScopedMatch[1];\n\n  // Block-scoped namespace: namespace Foo.Bar { ... }\n  const blockMatch = source.match(/^namespace\\s+([\\w.]+)\\s*\\{/m);\n  if (blockMatch) return blockMatch[1];\n\n  return 'unknown';\n}\n\n/** Strip single-line and block comments from source. */\nfunction stripComments(source: string): string {\n  let result = source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n  result = result.replace(/\\/\\/[^\\n]*/g, '');\n  return result;\n}\n\n/** Extract [JsonProperty(\"name\")] value from text preceding a property. */\nfunction extractJsonPropertyName(text: string): string | null {\n  const match = text.match(/\\[JsonProperty\\(\"([^\"]+)\"\\)\\]/);\n  return match ? match[1] : null;\n}\n\n/** Extract [EnumMember(Value = \"name\")] value from text. */\nfunction extractEnumMemberValue(text: string): string | null {\n  const match = text.match(/\\[EnumMember\\(Value\\s*=\\s*\"([^\"]+)\"\\)\\]/);\n  return match ? match[1] : null;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnums(source: string, sourceFile: string): CSharpEnum[] {\n  const enums: CSharpEnum[] = [];\n  const ns = extractNamespace(source);\n\n  // Match: public enum Name { ... }\n  const enumRegex = /public\\s+enum\\s+(\\w+)\\s*\\{([^}]*)\\}/g;\n  let match;\n  while ((match = enumRegex.exec(source)) !== null) {\n    const name = match[1];\n    const body = match[2];\n    const members: Record<string, string> = {};\n\n    // Split by commas and extract each member\n    const lines = body.split(',');\n    for (const line of lines) {\n      const trimmed = line.trim();\n      if (!trimmed) continue;\n\n      const enumValue = extractEnumMemberValue(trimmed);\n      const memberNameMatch = trimmed.match(/(\\w+)\\s*$/);\n      if (memberNameMatch) {\n        const memberName = memberNameMatch[1];\n        members[memberName] = enumValue || memberName;\n      }\n    }\n\n    if (Object.keys(members).length > 0) {\n      enums.push({ name, namespace: ns, members, sourceFile });\n    }\n  }\n\n  return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Class extraction\n// ---------------------------------------------------------------------------\n\nfunction parseClasses(source: string, sourceFile: string): CSharpClass[] {\n  const classes: CSharpClass[] = [];\n  const ns = extractNamespace(source);\n\n  // Match: public class Name { ... } — need to handle nested braces\n  const classStartRegex = /public\\s+class\\s+(\\w+)(?:\\s*:\\s*[\\w.,\\s<>]+)?\\s*\\{/g;\n  let match;\n  while ((match = classStartRegex.exec(source)) !== null) {\n    const name = match[1];\n    const braceStart = source.indexOf('{', match.index + match[0].length - 1);\n\n    // Find matching closing brace\n    let depth = 1;\n    let idx = braceStart + 1;\n    while (idx < source.length && depth > 0) {\n      if (source[idx] === '{') depth++;\n      else if (source[idx] === '}') depth--;\n      idx++;\n    }\n\n    const classBody = source.slice(braceStart + 1, idx - 1);\n\n    // Parse properties\n    const properties = parseProperties(classBody);\n\n    // Parse methods\n    const methods = parseMethods(classBody);\n\n    // Parse constructor params\n    const constructorParams = parseConstructor(classBody, name);\n\n    // A class is a \"service\" if it has methods\n    const isService = methods.length > 0;\n\n    classes.push({\n      name,\n      namespace: ns,\n      properties,\n      methods,\n      constructorParams,\n      isService,\n      sourceFile,\n    });\n  }\n\n  return classes;\n}\n\n/** Parse properties from a class body. */\nfunction parseProperties(classBody: string): CSharpProperty[] {\n  const properties: CSharpProperty[] = [];\n\n  // Split into lines so we can look at annotations on the line above\n  const lines = classBody.split('\\n');\n  let pendingJsonName: string | null = null;\n\n  for (const line of lines) {\n    const trimmed = line.trim();\n\n    // Check for JsonProperty annotation\n    const jsonPropMatch = extractJsonPropertyName(trimmed);\n    if (jsonPropMatch) {\n      pendingJsonName = jsonPropMatch;\n      continue;\n    }\n\n    // Match: public Type Name { get; set; } or public Type Name { get; }\n    const propMatch = trimmed.match(/public\\s+(\\S+(?:<[^>]+>)?(?:\\?)?)\\s+(\\w+)\\s*\\{\\s*get;\\s*(set;\\s*)?\\}/);\n    if (propMatch) {\n      const type = propMatch[1];\n      const name = propMatch[2];\n      const hasSetter = !!propMatch[3];\n\n      properties.push({\n        name,\n        type,\n        jsonName: pendingJsonName || undefined,\n        readonly: !hasSetter,\n      });\n      pendingJsonName = null;\n      continue;\n    }\n\n    // Reset pending annotation if we hit a non-annotation, non-property line\n    if (!trimmed.startsWith('[') && trimmed.length > 0) {\n      pendingJsonName = null;\n    }\n  }\n\n  return properties;\n}\n\n/** Parse methods from a class body. */\nfunction parseMethods(classBody: string): CSharpMethod[] {\n  const methods: CSharpMethod[] = [];\n\n  // Match: public [async] ReturnType MethodName(params)\n  const methodRegex =\n    /(private|protected|internal|public)\\s+(?:(static)\\s+)?(?:(async)\\s+)?(\\S+(?:<[^>]+>)?)\\s+(\\w+)\\s*\\(([^)]*)\\)/g;\n  let match;\n  while ((match = methodRegex.exec(classBody)) !== null) {\n    const visibility = match[1];\n    const isAsync = match[3] === 'async';\n    const returnType = match[4];\n    const name = match[5];\n    const paramsStr = match[6];\n\n    // Skip private/protected methods and constructors\n    if (visibility === 'private' || visibility === 'protected') continue;\n\n    const params: { name: string; type: string; optional: boolean }[] = [];\n    if (paramsStr.trim()) {\n      const paramParts = paramsStr.split(',');\n      for (const part of paramParts) {\n        const trimmed = part.trim();\n        // Match: Type name or Type name = default\n        const paramMatch = trimmed.match(/(\\S+(?:<[^>]+>)?(?:\\?)?)\\s+(\\w+)(?:\\s*=\\s*(.+))?/);\n        if (paramMatch) {\n          const paramType = paramMatch[1];\n          const paramName = paramMatch[2];\n          const hasDefault = paramMatch[3] !== undefined;\n          params.push({\n            name: paramName,\n            type: paramType,\n            optional: paramType.endsWith('?') || hasDefault,\n          });\n        }\n      }\n    }\n\n    methods.push({\n      name,\n      params,\n      returnType,\n      visibility,\n      isAsync,\n    });\n  }\n\n  return methods;\n}\n\n/** Parse constructor parameters. */\nfunction parseConstructor(classBody: string, className: string): { name: string; type: string }[] {\n  const params: { name: string; type: string }[] = [];\n\n  // Match: public ClassName(params) — use indexOf to find the constructor\n  const ctorPrefix = `public ${className}`;\n  const ctorIdx = classBody.indexOf(ctorPrefix);\n  if (ctorIdx < 0) return params;\n  const afterCtor = classBody.slice(ctorIdx + ctorPrefix.length);\n  const match = afterCtor.match(/^\\s*\\(([^)]*)\\)/);\n  if (!match) return params;\n\n  const paramsStr = match[1];\n  if (!paramsStr.trim()) return params;\n\n  const paramParts = paramsStr.split(',');\n  for (const part of paramParts) {\n    const trimmed = part.trim();\n    const paramMatch = trimmed.match(/(\\S+(?:<[^>]+>)?)\\s+(\\w+)/);\n    if (paramMatch) {\n      params.push({ name: paramMatch[2], type: paramMatch[1] });\n    }\n  }\n\n  return params;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single C# source file and return all extracted symbols. */\nexport function parseCSharpFile(filePath: string, sdkPath: string): ParsedCSharpFile {\n  const source = readFileSync(filePath, 'utf-8');\n  const relPath = relative(sdkPath, filePath);\n  const cleaned = stripComments(source);\n\n  return {\n    classes: parseClasses(cleaned, relPath),\n    enums: parseEnums(cleaned, relPath),\n  };\n}\n","/**\n * DotNet (.NET/C#) surface builder — transforms parsed C# symbols into an ApiSurface.\n */\n\nimport type {\n  ApiClass,\n  ApiMethod,\n  ApiParam,\n  ApiProperty,\n  ApiInterface,\n  ApiField,\n  ApiEnum,\n  LanguageHints,\n} from '../types.js';\nimport type { CSharpClass, CSharpEnum } from './dotnet-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n  allClasses: CSharpClass[],\n  allEnums: CSharpEnum[],\n  _hints: LanguageHints,\n): {\n  classes: Record<string, ApiClass>;\n  interfaces: Record<string, ApiInterface>;\n  enums: Record<string, ApiEnum>;\n  exports: Record<string, string[]>;\n} {\n  const classes: Record<string, ApiClass> = {};\n  const interfaces: Record<string, ApiInterface> = {};\n  const enums: Record<string, ApiEnum> = {};\n\n  const collector = new ExportCollector();\n\n  // Process classes\n  for (const cls of allClasses) {\n    if (cls.isService) {\n      // Service class — has methods\n      const methods: Record<string, ApiMethod[]> = {};\n      const properties: Record<string, ApiProperty> = {};\n\n      for (const method of cls.methods) {\n        const params: ApiParam[] = method.params.map((p) => ({\n          name: p.name,\n          type: p.type,\n          optional: p.optional,\n          passingStyle: 'named' as const,\n        }));\n\n        if (!methods[method.name]) methods[method.name] = [];\n        methods[method.name].push({\n          name: method.name,\n          params,\n          returnType: method.returnType,\n          async: method.isAsync,\n        });\n      }\n\n      // Add public properties to service class\n      for (const prop of cls.properties) {\n        const propName = prop.jsonName || prop.name;\n        properties[propName] = {\n          name: propName,\n          type: prop.type,\n          readonly: prop.readonly,\n        };\n      }\n\n      const constructorParams: ApiParam[] = cls.constructorParams.map((p) => ({\n        name: p.name,\n        type: p.type,\n        optional: false,\n        passingStyle: 'named' as const,\n      }));\n\n      classes[cls.name] = {\n        name: cls.name,\n        sourceFile: cls.sourceFile,\n        methods: sortRecord(methods),\n        properties: sortRecord(properties),\n        constructorParams,\n      };\n    } else {\n      // Data class — no methods, treat as interface\n      const fields: Record<string, ApiField> = {};\n      for (const prop of cls.properties) {\n        const fieldName = prop.jsonName || prop.name;\n        const isNullable = prop.type.endsWith('?');\n        fields[fieldName] = {\n          name: fieldName,\n          type: prop.type,\n          optional: isNullable,\n        };\n      }\n\n      interfaces[cls.name] = {\n        name: cls.name,\n        sourceFile: cls.sourceFile,\n        fields: sortRecord(fields),\n        extends: [],\n      };\n    }\n    collector.add(cls.sourceFile, cls.name);\n  }\n\n  // Process enums\n  for (const en of allEnums) {\n    enums[en.name] = {\n      name: en.name,\n      sourceFile: en.sourceFile,\n      members: sortRecord(en.members),\n    };\n    collector.add(en.sourceFile, en.name);\n  }\n\n  const exports = collector.toRecord();\n\n  return {\n    classes: sortRecord(classes),\n    interfaces: sortRecord(interfaces),\n    enums: sortRecord(enums),\n    exports: sortRecord(exports),\n  };\n}\n","/**\n * DotNet (C#) API surface extractor.\n *\n * Walks `.cs` files (excluding test, bin, and obj directories), parses\n * classes, enums, properties, and methods, then builds an `ApiSurface`.\n *\n * Parser:  `dotnet-parser.ts`  — regex-based C# source analysis\n * Surface: `dotnet-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport {\n  NAMED_TYPE_RE,\n  typeExistsInSurface,\n  namedTypeWordsOverlap,\n  defaultIsNullableOnlyDifference,\n} from '../language-hints.js';\nimport { walkCSharpFiles, parseCSharpFile } from './dotnet-parser.js';\nimport { buildSurface } from './dotnet-surface.js';\nimport type { CSharpClass, CSharpEnum } from './dotnet-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst DOTNET_PRIMITIVE_TYPES = new Set(['string', 'int', 'long', 'float', 'double', 'bool', 'decimal']);\n\nconst dotnetHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    // Nullable<T> → T\n    const nullableMatch = type.match(/^Nullable<(.+)>$/);\n    if (nullableMatch) return nullableMatch[1];\n    // T? → T\n    if (type.endsWith('?')) return type.slice(0, -1);\n    return null;\n  },\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return defaultIsNullableOnlyDifference(this, a, b);\n  },\n  isUnionReorder(_a: string, _b: string): boolean {\n    return false; // C# doesn't have union types\n  },\n  isGenericTypeParam(type: string): boolean {\n    return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n  },\n  isExtractionArtifact(type: string): boolean {\n    return type === 'object' || type === 'dynamic';\n  },\n  tolerateCategoryMismatch: false,\n  extractReturnTypeName(returnType: string): string | null {\n    let inner = returnType;\n    // Unwrap Task<T> → T\n    const taskMatch = inner.match(/^Task<(.+)>$/);\n    if (taskMatch) inner = taskMatch[1];\n    // Unwrap Task → void\n    if (inner === 'Task') return null;\n    // Unwrap nullable\n    if (inner.endsWith('?')) inner = inner.slice(0, -1);\n    // Unwrap List<T> → T\n    const listMatch = inner.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n    if (listMatch) inner = listMatch[1];\n    // Primitives\n    if (['string', 'int', 'long', 'float', 'double', 'bool', 'void', 'decimal'].includes(inner)) return null;\n    return inner;\n  },\n  extractParamTypeName(paramType: string): string | null {\n    let inner = paramType;\n    if (inner.endsWith('?')) inner = inner.slice(0, -1);\n    if (['string', 'int', 'long', 'float', 'double', 'bool', 'decimal'].includes(inner)) return null;\n    return inner;\n  },\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    return propertyName.toLowerCase() === className.toLowerCase();\n  },\n  derivedModelNames(modelName: string): string[] {\n    return [`${modelName}Response`];\n  },\n\n  isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n    // Strip nullable from both sides for comparison\n    const stripNullable = (t: string) => {\n      if (t.endsWith('?')) return t.slice(0, -1);\n      const m = t.match(/^Nullable<(.+)>$/);\n      return m ? m[1] : t;\n    };\n    const baseClean = stripNullable(baselineType);\n    const candClean = stripNullable(candidateType);\n\n    // Map/dictionary equivalence: Dictionary<string, string> ≡ Dictionary<string, object>\n    const dictPattern = /^Dictionary<string,\\s*(string|object|dynamic|Object)>$/;\n    if (dictPattern.test(baseClean) && dictPattern.test(candClean)) {\n      return true;\n    }\n\n    // Array notation equivalence: T[] ≡ List<T>\n    const arrayMatch = baseClean.match(/^(.+)\\[\\]$/);\n    const listMatch = candClean.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n    if (arrayMatch && listMatch) {\n      // Compare inner types — allow named type tolerance\n      const baseInner = arrayMatch[1];\n      const candInner = listMatch[1];\n      if (baseInner === candInner) return true;\n      // Recurse for named type equivalence\n      if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n        if (typeExistsInSurface(candInner, candidateSurface)) {\n          if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n          const baseNoResp = baseInner.replace(/Response$/, '');\n          const candNoResp = candInner.replace(/Response$/, '');\n          if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n          // Word overlap\n          if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n        }\n      }\n      // Tolerate model collection vs primitive collection: OrganizationDomain[] ≡ List<string>\n      // The spec may define a field as a primitive array while the live SDK wraps it in a model.\n      if (\n        (DOTNET_PRIMITIVE_TYPES.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n        (DOTNET_PRIMITIVE_TYPES.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n      ) {\n        return true;\n      }\n    }\n    // Also handle reverse: baseline is List<T>, candidate is T[]\n    const baseListMatch = baseClean.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n    const candArrayMatch = candClean.match(/^(.+)\\[\\]$/);\n    if (baseListMatch && candArrayMatch) {\n      const baseInner = baseListMatch[1];\n      const candInner = candArrayMatch[1];\n      if (baseInner === candInner) return true;\n      if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n        if (typeExistsInSurface(candInner, candidateSurface)) {\n          if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n        }\n      }\n    }\n\n    // Generic container equivalence: List<T> vs List<U>, T[] vs U[]\n    // where T and U are different named types for the same concept\n    const genericPattern = /^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/;\n    const baseGeneric = baseClean.match(genericPattern);\n    const candGeneric = candClean.match(genericPattern);\n    if (baseGeneric && candGeneric) {\n      const baseInner = baseGeneric[1];\n      const candInner = candGeneric[1];\n      if (baseInner === candInner) return true;\n      if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n        if (typeExistsInSurface(candInner, candidateSurface)) {\n          if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n          const baseNoResp = baseInner.replace(/Response$/, '');\n          const candNoResp = candInner.replace(/Response$/, '');\n          if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n          if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n        }\n      }\n    }\n\n    // Named type tolerance: different PascalCase names for the same concept\n    // (e.g., EmailObject vs DirectoryUsersEmail, RoleResponse vs DirectoryUserRole)\n    if (NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n      if (typeExistsInSurface(candClean, candidateSurface)) {\n        if (candClean.includes(baseClean) || baseClean.includes(candClean)) return true;\n        const baseNoResp = baseClean.replace(/Response$/, '');\n        const candNoResp = candClean.replace(/Response$/, '');\n        if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n        // Word-component overlap\n        if (namedTypeWordsOverlap(baseClean, candClean)) return true;\n      }\n    }\n\n    // Numeric type equivalence: int ≡ double, long ≡ double (JSON numbers)\n    const numericTypes = new Set(['int', 'long', 'float', 'double', 'decimal']);\n    if (numericTypes.has(baseClean) && numericTypes.has(candClean)) return true;\n\n    // Date type equivalence: DateTime ≡ string (spec uses string with date-time format)\n    if ((baseClean === 'DateTime' && candClean === 'string') || (baseClean === 'string' && candClean === 'DateTime')) {\n      return true;\n    }\n\n    // Enum name vs string equivalence (candidate has an enum, baseline says string)\n    if (baseClean === 'string' && candidateSurface.enums[candClean]) return true;\n    if (candClean === 'string' && candidateSurface.enums?.[baseClean]) return true;\n\n    return false;\n  },\n\n  modelBaseClasses: [],\n  exceptionBaseClasses: ['Exception'],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a DotNet extractor with optional hint overrides. */\nexport function createDotnetExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n  const mergedHints: LanguageHints = hintOverrides ? { ...dotnetHints, ...hintOverrides } : dotnetHints;\n\n  return {\n    language: 'dotnet',\n    hints: mergedHints,\n\n    async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n      const surface = await this.extract(sdkPath);\n      return apiSurfaceToSnapshot(surface);\n    },\n\n    async extract(sdkPath: string): Promise<ApiSurface> {\n      // Determine the source directory: prefer src/, fallback to root\n      let sourceDir: string;\n      const srcPath = resolve(sdkPath, 'src');\n\n      try {\n        statSync(srcPath);\n        sourceDir = srcPath;\n      } catch {\n        sourceDir = sdkPath;\n      }\n\n      const csFiles = walkCSharpFiles(sourceDir);\n      if (csFiles.length === 0) {\n        throw new ExtractorError(\n          `No .cs files found in ${sdkPath}`,\n          `Ensure the --sdk-path argument points to a .NET project root containing .cs source files.`,\n        );\n      }\n\n      const allClasses: CSharpClass[] = [];\n      const allEnums: CSharpEnum[] = [];\n\n      for (const filePath of csFiles) {\n        const parsed = parseCSharpFile(filePath, sdkPath);\n        allClasses.push(...parsed.classes);\n        allEnums.push(...parsed.enums);\n      }\n\n      const { classes, interfaces, enums, exports } = buildSurface(allClasses, allEnums, mergedHints);\n\n      return {\n        language: 'dotnet',\n        extractedFrom: sdkPath,\n        extractedAt: new Date().toISOString(),\n        classes,\n        interfaces,\n        typeAliases: {},\n        enums,\n        exports,\n      };\n    },\n  };\n}\n\n/** Default DotNet extractor with generic language hints. */\nexport const dotnetExtractor: Extractor = createDotnetExtractor();\n","/**\n * Elixir source parser — regex-based extraction of modules, structs,\n * functions, and type specs from Elixir source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface ElixirStruct {\n  moduleName: string;\n  fields: string[];\n  sourceFile: string;\n}\n\nexport interface ElixirFunction {\n  moduleName: string;\n  name: string;\n  arity: number;\n  params: string[];\n  /** Per-param passing style: 'positional' or 'keyword' (for keyword list params). */\n  paramStyles: ('positional' | 'keyword')[];\n  isPrivate: boolean;\n  sourceFile: string;\n}\n\nexport interface ElixirTypeSpec {\n  moduleName: string;\n  name: string;\n  definition: string;\n  sourceFile: string;\n}\n\nexport interface ElixirEnumModule {\n  moduleName: string;\n  members: Record<string, string>;\n  sourceFile: string;\n}\n\nexport interface ParsedElixirFile {\n  structs: ElixirStruct[];\n  functions: ElixirFunction[];\n  typeSpecs: ElixirTypeSpec[];\n  enumModules: ElixirEnumModule[];\n  moduleNames: string[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkElixirFiles(dir: string): string[] {\n  const results: string[] = [];\n  let entries: string[];\n  try {\n    entries = readdirSync(dir);\n  } catch {\n    return results;\n  }\n  for (const entry of entries) {\n    const fullPath = join(dir, entry);\n    let stat;\n    try {\n      stat = statSync(fullPath);\n    } catch {\n      continue;\n    }\n    if (stat.isDirectory()) {\n      if (entry.startsWith('.') || entry === '_build' || entry === 'deps' || entry === 'test') continue;\n      results.push(...walkElixirFiles(fullPath));\n    } else if (entry.endsWith('.ex') && !entry.endsWith('_test.exs')) {\n      results.push(fullPath);\n    }\n  }\n  return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Strip comments and heredoc strings from Elixir source code.\n * This prevents false matches of keywords like `do`/`end` inside strings\n * and doc comments.\n */\nfunction stripCommentsAndHeredocs(source: string): string {\n  // Replace triple-quoted heredocs (@moduledoc \"\"\", @doc \"\"\", etc.)\n  let result = source.replace(/\"\"\"[\\s\\S]*?\"\"\"/g, '\"\"\"\"\"\"');\n  // Remove single-line comments\n  result = result.replace(/#[^\\n]*/g, '');\n  return result;\n}\n\n// ---------------------------------------------------------------------------\n// Module body extraction using line-based do/end counting\n// ---------------------------------------------------------------------------\n\n/**\n * Given the full source and the position right after `defmodule ... do`,\n * find the module body text up to the matching `end`.\n *\n * Uses a character-by-character scan that skips string literals and\n * counts block-level `do`/`end` keywords only when they appear as\n * standalone tokens (word boundaries).\n */\nfunction extractModuleBody(source: string, startIdx: number): string | null {\n  let depth = 1;\n  // Walk through source counting do/end as word boundaries\n  // Skip strings (single and double quoted)\n  let i = startIdx;\n  while (i < source.length && depth > 0) {\n    const ch = source[i];\n\n    // Skip string literals\n    if (ch === '\"') {\n      i++;\n      while (i < source.length && source[i] !== '\"') {\n        if (source[i] === '\\\\') i++; // skip escaped char\n        i++;\n      }\n      i++; // skip closing quote\n      continue;\n    }\n    if (ch === \"'\") {\n      i++;\n      while (i < source.length && source[i] !== \"'\") {\n        if (source[i] === '\\\\') i++;\n        i++;\n      }\n      i++;\n      continue;\n    }\n\n    // Check for word-boundary keywords\n    // Only match `do` and `end` as full words (not `done`, `donut`, `endor`, etc.)\n    if (isWordBoundary(source, i)) {\n      if (source.slice(i, i + 2) === 'do' && isWordEnd(source, i + 2)) {\n        // Make sure this is block `do`, not keyword `do:` form\n        if (source[i + 2] !== ':') {\n          depth++;\n        }\n        i += 2;\n        continue;\n      }\n      if (source.slice(i, i + 2) === 'fn' && isWordEnd(source, i + 2)) {\n        depth++;\n        i += 2;\n        continue;\n      }\n      if (source.slice(i, i + 3) === 'end' && isWordEnd(source, i + 3)) {\n        depth--;\n        if (depth === 0) {\n          return source.slice(startIdx, i);\n        }\n        i += 3;\n        continue;\n      }\n    }\n\n    i++;\n  }\n\n  return null;\n}\n\nfunction isWordBoundary(source: string, idx: number): boolean {\n  if (idx === 0) return true;\n  const prev = source[idx - 1];\n  return !/[a-zA-Z0-9_]/.test(prev);\n}\n\nfunction isWordEnd(source: string, idx: number): boolean {\n  if (idx >= source.length) return true;\n  return !/[a-zA-Z0-9_]/.test(source[idx]);\n}\n\n// ---------------------------------------------------------------------------\n// Module extraction\n// ---------------------------------------------------------------------------\n\ninterface ExtractedModule {\n  name: string;\n  body: string;\n}\n\n/** Find all defmodule blocks and extract their bodies in a single pass. */\nfunction extractModules(source: string): ExtractedModule[] {\n  const modules: ExtractedModule[] = [];\n  const moduleRegex = /defmodule\\s+([\\w.]+)\\s+do\\b/g;\n  let match;\n  while ((match = moduleRegex.exec(source)) !== null) {\n    const body = extractModuleBody(source, match.index + match[0].length);\n    if (body) {\n      modules.push({ name: match[1], body });\n    }\n  }\n  return modules;\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction extractStructs(modules: ExtractedModule[], sourceFile: string): ElixirStruct[] {\n  const structs: ElixirStruct[] = [];\n\n  for (const { name: moduleName, body: moduleBody } of modules) {\n    // Look for defstruct inside this module\n    const structMatch = moduleBody.match(/defstruct\\s+\\[([^\\]]*)\\]/);\n    if (!structMatch) continue;\n\n    const fieldsStr = structMatch[1];\n    const fields: string[] = [];\n    const fieldRegex = /:(\\w+)/g;\n    let fieldMatch;\n    while ((fieldMatch = fieldRegex.exec(fieldsStr)) !== null) {\n      fields.push(fieldMatch[1]);\n    }\n\n    if (fields.length > 0) {\n      structs.push({ moduleName, fields, sourceFile });\n    }\n  }\n\n  return structs;\n}\n\n// ---------------------------------------------------------------------------\n// Function extraction\n// ---------------------------------------------------------------------------\n\nfunction extractFunctions(modules: ExtractedModule[], sourceFile: string): ElixirFunction[] {\n  const functions: ElixirFunction[] = [];\n\n  for (const { name: moduleName, body: moduleBody } of modules) {\n    // Match both styles:\n    // 1. Block: def name(params) do ... end\n    // 2. Keyword: def name(params), do: ...\n    // 3. Keyword no-args: def name, do: ...\n    const funcRegex = /(def|defp)\\s+(\\w+)(?:\\(([^)]*)\\))?(?:\\s+do\\b|\\s*,\\s*do:)/g;\n    let funcMatch;\n    while ((funcMatch = funcRegex.exec(moduleBody)) !== null) {\n      const isPrivate = funcMatch[1] === 'defp';\n      const name = funcMatch[2];\n      const paramsStr = funcMatch[3] || '';\n\n      // Skip module/struct macros\n      if (name === 'defstruct' || name === 'defmodule') continue;\n\n      const params: string[] = [];\n      const paramStyles: ('positional' | 'keyword')[] = [];\n      if (paramsStr.trim()) {\n        const paramParts = paramsStr.split(',');\n        for (const part of paramParts) {\n          const trimmed = part.trim();\n          // Extract parameter name (before :: type annotation or \\\\ default)\n          const paramNameMatch = trimmed.match(/^(\\w+)/);\n          if (paramNameMatch) {\n            params.push(paramNameMatch[1]);\n            // Detect keyword list params: `opts \\\\ []` or `options \\\\ []`\n            const isKeywordList = /\\\\\\\\\\s*\\[/.test(trimmed);\n            paramStyles.push(isKeywordList ? 'keyword' : 'positional');\n          }\n        }\n      }\n\n      functions.push({\n        moduleName,\n        name,\n        arity: params.length,\n        params,\n        paramStyles,\n        isPrivate,\n        sourceFile,\n      });\n    }\n  }\n\n  return functions;\n}\n\n// ---------------------------------------------------------------------------\n// Type spec extraction\n// ---------------------------------------------------------------------------\n\nfunction extractTypeSpecs(modules: ExtractedModule[], sourceFile: string): ElixirTypeSpec[] {\n  const specs: ElixirTypeSpec[] = [];\n\n  for (const { name: moduleName, body: moduleBody } of modules) {\n    // Match @type t :: ... capturing multi-line definitions\n    // The definition continues until we hit a blank line, a new @-attribute, or def/defstruct\n    const typeRegex = /@type\\s+(\\w+)\\s*::\\s*/g;\n    let typeMatch;\n    while ((typeMatch = typeRegex.exec(moduleBody)) !== null) {\n      const typeName = typeMatch[1];\n      const defStart = typeMatch.index + typeMatch[0].length;\n\n      // Find the end of the type definition:\n      // It ends at a blank line, a new @attribute, def, defp, defstruct, or end-of-module\n      let defEnd = defStart;\n      let braceDepth = 0;\n      for (let j = defStart; j < moduleBody.length; j++) {\n        const ch = moduleBody[j];\n        if (ch === '{') braceDepth++;\n        else if (ch === '}') {\n          braceDepth--;\n          if (braceDepth < 0) break;\n          if (braceDepth === 0) {\n            defEnd = j + 1;\n            break;\n          }\n        } else if (braceDepth === 0 && ch === '\\n') {\n          // Check if next non-whitespace line starts a new declaration\n          const remaining = moduleBody.slice(j + 1);\n          const nextLineMatch = remaining.match(/^\\s*\\S/);\n          if (nextLineMatch) {\n            const nextContent = remaining.trimStart();\n            if (\n              nextContent.startsWith('@') ||\n              nextContent.startsWith('def ') ||\n              nextContent.startsWith('defp ') ||\n              nextContent.startsWith('defstruct') ||\n              nextContent.startsWith('defmodule')\n            ) {\n              defEnd = j;\n              break;\n            }\n          } else {\n            // Blank line — end of definition\n            defEnd = j;\n            break;\n          }\n        }\n        defEnd = j + 1;\n      }\n\n      const definition = moduleBody.slice(defStart, defEnd).trim();\n      specs.push({ moduleName, name: typeName, definition, sourceFile });\n    }\n  }\n\n  return specs;\n}\n\n// ---------------------------------------------------------------------------\n// Enum module extraction\n// ---------------------------------------------------------------------------\n\nfunction extractEnumModules(modules: ExtractedModule[], sourceFile: string): ElixirEnumModule[] {\n  const enumModules: ElixirEnumModule[] = [];\n\n  for (const { name: moduleName, body: moduleBody } of modules) {\n    // Check if this module has a `values` function (indicator of enum-like module)\n    if (!moduleBody.match(/def\\s+values[\\s,]/)) continue;\n\n    // Also verify there's no defstruct (structs aren't enums)\n    if (moduleBody.match(/defstruct\\b/)) continue;\n\n    const members: Record<string, string> = {};\n\n    // Extract individual value functions: def name, do: \"value\"\n    const valueFuncRegex = /def\\s+(\\w+),\\s*do:\\s*\"([^\"]+)\"/g;\n    let valueFuncMatch;\n    while ((valueFuncMatch = valueFuncRegex.exec(moduleBody)) !== null) {\n      const funcName = valueFuncMatch[1];\n      const funcValue = valueFuncMatch[2];\n      if (funcName === 'values') continue;\n      members[funcName] = funcValue;\n    }\n\n    if (Object.keys(members).length > 0) {\n      enumModules.push({ moduleName, members, sourceFile });\n    }\n  }\n\n  return enumModules;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single Elixir source file and return all extracted symbols. */\nexport function parseElixirFile(filePath: string, sdkPath: string): ParsedElixirFile {\n  const source = readFileSync(filePath, 'utf-8');\n  const relPath = relative(sdkPath, filePath);\n  const cleaned = stripCommentsAndHeredocs(source);\n  const modules = extractModules(cleaned);\n\n  return {\n    structs: extractStructs(modules, relPath),\n    functions: extractFunctions(modules, relPath),\n    typeSpecs: extractTypeSpecs(modules, relPath),\n    enumModules: extractEnumModules(modules, relPath),\n    moduleNames: modules.map((m) => m.name),\n  };\n}\n","/**\n * Elixir surface builder — transforms parsed Elixir symbols into an ApiSurface.\n *\n * Elixir conventions:\n * - Data types (defstruct) → ApiInterface\n * - Modules with public functions → ApiClass\n * - Enum-like modules (with value functions) → ApiEnum\n */\n\nimport type { ApiClass, ApiMethod, ApiParam, ApiInterface, ApiField, ApiEnum } from '../types.js';\nimport type { ElixirStruct, ElixirFunction, ElixirEnumModule, ElixirTypeSpec } from './elixir-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Get the short name from a fully qualified Elixir module name. */\nfunction shortName(moduleName: string): string {\n  const parts = moduleName.split('.');\n  return parts[parts.length - 1];\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n  allStructs: ElixirStruct[],\n  allFunctions: ElixirFunction[],\n  allEnumModules: ElixirEnumModule[],\n  allTypeSpecs: ElixirTypeSpec[],\n): {\n  classes: Record<string, ApiClass>;\n  interfaces: Record<string, ApiInterface>;\n  enums: Record<string, ApiEnum>;\n  exports: Record<string, string[]>;\n} {\n  const classes: Record<string, ApiClass> = {};\n  const interfaces: Record<string, ApiInterface> = {};\n  const enums: Record<string, ApiEnum> = {};\n\n  const collector = new ExportCollector();\n\n  // Collect struct module names so we can distinguish struct modules from service modules\n  const structModuleNames = new Set(allStructs.map((s) => s.moduleName));\n  const enumModuleNames = new Set(allEnumModules.map((e) => e.moduleName));\n\n  // Process structs as interfaces\n  for (const struct of allStructs) {\n    const name = shortName(struct.moduleName);\n    const fields: Record<string, ApiField> = {};\n\n    // Build fields from struct keys — types come from @type spec if available\n    const typeSpec = allTypeSpecs.find((ts) => ts.moduleName === struct.moduleName && ts.name === 't');\n\n    for (const field of struct.fields) {\n      // Try to extract type from the @type spec\n      let fieldType = 'any';\n      let optional = false;\n\n      if (typeSpec) {\n        // Parse the type definition to find this field's type\n        const fieldPrefix = field + ':';\n        const prefixIdx = typeSpec.definition.indexOf(fieldPrefix);\n        const fieldTypeMatch =\n          prefixIdx >= 0 ? typeSpec.definition.slice(prefixIdx + fieldPrefix.length).match(/^\\s*([^,}]+)/) : null;\n        if (fieldTypeMatch) {\n          fieldType = fieldTypeMatch[1].trim();\n          // Check if nullable (contains | nil)\n          if (fieldType.includes('| nil') || fieldType.includes('nil |')) {\n            optional = true;\n            fieldType = fieldType\n              .replace(/\\s*\\|\\s*nil/g, '')\n              .replace(/nil\\s*\\|\\s*/g, '')\n              .trim();\n          }\n        }\n      }\n\n      fields[field] = {\n        name: field,\n        type: fieldType,\n        optional,\n      };\n    }\n\n    interfaces[name] = {\n      name,\n      sourceFile: struct.sourceFile,\n      fields: sortRecord(fields),\n      extends: [],\n    };\n    collector.add(struct.sourceFile, name);\n  }\n\n  // Process enum modules\n  for (const enumModule of allEnumModules) {\n    const name = shortName(enumModule.moduleName);\n    enums[name] = {\n      name,\n      sourceFile: enumModule.sourceFile,\n      members: sortRecord(enumModule.members),\n    };\n    collector.add(enumModule.sourceFile, name);\n  }\n\n  // Group public functions by module\n  const funcsByModule = new Map<string, ElixirFunction[]>();\n  for (const func of allFunctions) {\n    if (func.isPrivate) continue;\n\n    // Skip functions from struct modules (they are data, not services)\n    // and enum modules (already handled)\n    if (structModuleNames.has(func.moduleName) && !funcsByModule.has(func.moduleName)) {\n      // Struct modules might still have functions, but only if they have\n      // functions beyond just struct-related ones\n    }\n    if (enumModuleNames.has(func.moduleName)) continue;\n\n    if (!funcsByModule.has(func.moduleName)) funcsByModule.set(func.moduleName, []);\n    funcsByModule.get(func.moduleName)!.push(func);\n  }\n\n  // Convert function modules to classes\n  for (const [moduleName, funcs] of funcsByModule) {\n    // Skip if this is a struct-only module (no meaningful functions)\n    if (structModuleNames.has(moduleName)) continue;\n\n    const name = shortName(moduleName);\n    const methods: Record<string, ApiMethod[]> = {};\n\n    // Deduplicate by function name (Elixir allows multiple clauses)\n    const seenFuncs = new Set<string>();\n    for (const func of funcs) {\n      if (seenFuncs.has(func.name)) continue;\n      seenFuncs.add(func.name);\n\n      const params: ApiParam[] = func.params.map((p, i) => ({\n        name: p,\n        type: 'any',\n        optional: false,\n        passingStyle: func.paramStyles[i] ?? ('positional' as const),\n      }));\n\n      if (!methods[func.name]) methods[func.name] = [];\n      methods[func.name].push({\n        name: func.name,\n        params,\n        returnType: 'any',\n        async: false,\n      });\n    }\n\n    if (Object.keys(methods).length > 0) {\n      classes[name] = {\n        name,\n        sourceFile: funcs[0].sourceFile,\n        methods: sortRecord(methods),\n        properties: {},\n        constructorParams: [],\n      };\n      collector.add(funcs[0].sourceFile, name);\n    }\n  }\n\n  const exports = collector.toRecord();\n\n  return {\n    classes: sortRecord(classes),\n    interfaces: sortRecord(interfaces),\n    enums: sortRecord(enums),\n    exports: sortRecord(exports),\n  };\n}\n","/**\n * Elixir API surface extractor.\n *\n * Walks `.ex` files under `lib/` (the standard Elixir source directory),\n * parses modules, structs, functions, and type specs, then builds an\n * `ApiSurface`.\n *\n * Parser:  `elixir-parser.ts`  — regex-based Elixir source analysis\n * Surface: `elixir-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkElixirFiles, parseElixirFile } from './elixir-parser.js';\nimport { buildSurface } from './elixir-surface.js';\nimport type { ElixirStruct, ElixirFunction, ElixirEnumModule, ElixirTypeSpec } from './elixir-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst elixirHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    // T | nil → T\n    if (type.includes('| nil')) return type.replace(/\\s*\\|\\s*nil/g, '').trim();\n    if (type.includes('nil |')) return type.replace(/nil\\s*\\|\\s*/g, '').trim();\n    return null;\n  },\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return defaultIsNullableOnlyDifference(this, a, b);\n  },\n  isUnionReorder(a: string, b: string): boolean {\n    // Parse pipe-separated types, sort, compare\n    const sortParts = (t: string) =>\n      t\n        .split('|')\n        .map((s) => s.trim())\n        .sort()\n        .join('|');\n    return a !== b && sortParts(a) === sortParts(b);\n  },\n  isGenericTypeParam(type: string): boolean {\n    // Elixir doesn't have generic type params in the same sense\n    return type === 'any' || type === 'term';\n  },\n  isExtractionArtifact(type: string): boolean {\n    return type === 'any' || type === 'term' || type === 'any()';\n  },\n  tolerateCategoryMismatch: true,\n  extractReturnTypeName(returnType: string): string | null {\n    let inner = returnType;\n    // Unwrap {:ok, T} → T\n    const okMatch = inner.match(/^\\{:ok,\\s*(.+)\\}$/);\n    if (okMatch) inner = okMatch[1].trim();\n    // Unwrap [T] → T\n    const listMatch = inner.match(/^\\[(.+)\\]$/);\n    if (listMatch) inner = listMatch[1].trim();\n    // Primitives\n    if (['any', 'term', 'atom', 'binary', 'boolean', 'integer', 'float', 'number', 'pid'].includes(inner)) {\n      return null;\n    }\n    // String.t() → String\n    const typeCallMatch = inner.match(/^(\\w+)\\.t\\(\\)$/);\n    if (typeCallMatch) return typeCallMatch[1];\n    return inner || null;\n  },\n  extractParamTypeName(paramType: string): string | null {\n    if (\n      ['any', 'term', 'atom', 'binary', 'boolean', 'integer', 'float', 'number', 'pid', 'keyword'].includes(paramType)\n    ) {\n      return null;\n    }\n    const typeCallMatch = paramType.match(/^(\\w+)\\.t\\(\\)$/);\n    if (typeCallMatch) return typeCallMatch[1];\n    return paramType;\n  },\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    // snake_case → PascalCase comparison\n    return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n  },\n  derivedModelNames(modelName: string): string[] {\n    return [`${modelName}Response`];\n  },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const elixirExtractor: Extractor = {\n  language: 'elixir',\n  hints: elixirHints,\n\n  async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n    const surface = await this.extract(sdkPath);\n    return apiSurfaceToSnapshot(surface);\n  },\n\n  async extract(sdkPath: string): Promise<ApiSurface> {\n    // Determine the source directory: prefer lib/, fallback to root\n    let sourceDir: string;\n    const libPath = resolve(sdkPath, 'lib');\n\n    try {\n      statSync(libPath);\n      sourceDir = libPath;\n    } catch {\n      sourceDir = sdkPath;\n    }\n\n    const exFiles = walkElixirFiles(sourceDir);\n    if (exFiles.length === 0) {\n      throw new ExtractorError(\n        `No .ex files found in ${sdkPath}`,\n        `Ensure the --sdk-path argument points to an Elixir project root containing .ex source files in lib/.`,\n      );\n    }\n\n    const allStructs: ElixirStruct[] = [];\n    const allFunctions: ElixirFunction[] = [];\n    const allEnumModules: ElixirEnumModule[] = [];\n    const allTypeSpecs: ElixirTypeSpec[] = [];\n\n    for (const filePath of exFiles) {\n      const parsed = parseElixirFile(filePath, sdkPath);\n      allStructs.push(...parsed.structs);\n      allFunctions.push(...parsed.functions);\n      allEnumModules.push(...parsed.enumModules);\n      allTypeSpecs.push(...parsed.typeSpecs);\n    }\n\n    const { classes, interfaces, enums, exports } = buildSurface(\n      allStructs,\n      allFunctions,\n      allEnumModules,\n      allTypeSpecs,\n    );\n\n    return {\n      language: 'elixir',\n      extractedFrom: sdkPath,\n      extractedAt: new Date().toISOString(),\n      classes,\n      interfaces,\n      typeAliases: {},\n      enums,\n      exports,\n    };\n  },\n};\n"],"mappings":"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"}