{"version":3,"file":"index.mjs","names":["singularize","singularize","singularize","singularize","extractDeclarationName","declarationKey","path","path","path","defaultNodeHints","path","path","path","path"],"sources":["../../src/ir/sdk-behavior.ts","../../src/errors.ts","../../src/parser/refs.ts","../../src/ir/types.ts","../../src/utils/naming.ts","../../src/parser/inline-models.ts","../../src/parser/schemas.ts","../../src/parser/pagination.ts","../../src/parser/responses.ts","../../src/parser/operations.ts","../../src/parser/normalize-inline-models.ts","../../src/parser/collect-inline-enums.ts","../../src/parser/normalize-model-refs.ts","../../src/parser/parse.ts","../../src/cli/parse.ts","../../src/engine/merge-adapters/url-fingerprint.ts","../../src/engine/merge-adapters/dotnet.ts","../../src/engine/merge-adapters/elixir.ts","../../src/engine/merge-adapters/go.ts","../../src/engine/merge-adapters/kotlin.ts","../../src/engine/merge-adapters/node.ts","../../src/engine/merge-adapters/php.ts","../../src/engine/merge-adapters/python.ts","../../src/engine/merge-adapters/ruby.ts","../../src/engine/merge-adapters/rust.ts","../../src/engine/merge-adapters/index.ts","../../src/utils/tree-sitter.ts","../../src/engine/merger.ts","../../src/engine/json-merge.ts","../../src/engine/writer.ts","../../src/ir/operation-hints.ts","../../src/engine/generate-files.ts","../../src/engine/scoped-services.ts","../../src/engine/integrate.ts","../../src/engine/formatter.ts","../../src/engine/manifest.ts","../../src/engine/orchestrator.ts","../../src/engine/registry.ts","../../src/compat/language-hints.ts","../../src/compat/overlay.ts","../../src/compat/extractor-registry.ts","../../src/engine/manifest-reader.ts","../../src/cli/overlay-loader.ts","../../src/utils/expand-doc-urls.ts","../../src/cli/generate.ts","../../src/differ/classify.ts","../../src/differ/models.ts","../../src/differ/operations.ts","../../src/differ/services.ts","../../src/differ/diff.ts","../../src/cli/diff.ts","../../src/cli/extract.ts","../../src/compat/policy.ts","../../src/compat/schema.ts","../../src/compat/ir.ts","../../src/cli/compat-extract.ts","../../src/compat/config.ts","../../src/compat/classify.ts","../../src/compat/spec-filter.ts","../../src/compat/differ.ts","../../src/compat/concepts.ts","../../src/compat/report.ts","../../src/cli/compat-diff.ts","../../src/cli/compat-summary.ts","../../src/compat/approvals.ts","../../src/verify/run-compat-check.ts","../../src/verify/run-overlay-retry-loop.ts","../../src/compat/staleness.ts","../../src/verify/run-staleness-check.ts","../../src/verify/run-smoke-check.ts","../../src/verify/write-diagnostics.ts","../../src/cli/verify.ts","../../src/cli/templates/init.ts","../../src/cli/init.ts","../../src/cli/resolve.ts","../../src/cli/config-loader.ts","../../src/cli/plugin-loader.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * SDK Behavior IR — language-agnostic runtime policies for generated SDKs.\n *\n * These types capture the \"what\" of SDK behavior (retry, telemetry, errors, etc.)\n * while emitters provide the \"how\" (language-specific mechanism).\n *\n * Emitters access these via `ctx.spec.sdk` — always populated, never undefined.\n */\n\n// ── Retry ──────────────────────────────────────────────────────────\n\n/** Retry policy — when and how to retry failed requests. */\nexport interface RetryPolicy {\n  /** HTTP status codes that trigger a retry. */\n  retryableStatusCodes: number[];\n  /** Maximum number of retry attempts (0 = no retries). */\n  maxRetries: number;\n  /** Whether to retry on connection errors (DNS failure, TCP reset). */\n  retryOnConnectionError: boolean;\n  /** Whether to retry on timeout errors. */\n  retryOnTimeout: boolean;\n  /** Backoff strategy between retries. */\n  backoff: BackoffStrategy;\n}\n\n/** Exponential backoff configuration.\n *\n * Formula: `delay = min(initialDelay * multiplier^attempt, maxDelay)`\n * With jitter: `delay += delay * jitterFactor * random(0, 1)`\n */\nexport interface BackoffStrategy {\n  /** Initial delay in seconds before the first retry. */\n  initialDelay: number;\n  /** Multiplier applied to the delay on each subsequent retry. */\n  multiplier: number;\n  /** Maximum delay in seconds (cap). */\n  maxDelay: number;\n  /** Jitter factor (0..1). 0.5 means up to 50% random jitter added. */\n  jitterFactor: number;\n}\n\n// ── Errors ─────────────────────────────────────────────────────────\n\n/** Error mapping — status codes to named exception kinds. */\nexport interface ErrorPolicy {\n  /** Map from HTTP status code to a logical error kind name (e.g. 400 → 'BadRequest').\n   *  Emitters append language-specific suffixes (e.g. 'BadRequestException'). */\n  statusCodeMap: Record<number, string>;\n  /** Catch-all error kind for 5xx status codes not in the map. */\n  serverErrorKind: string;\n  /** Catch-all error kind for unrecognized status codes. */\n  clientErrorKind: string;\n  /** URL template for error documentation. Use {code} as placeholder for the API error code. */\n  errorDocUrlTemplate?: string;\n}\n\n// ── Telemetry ──────────────────────────────────────────────────────\n\n/** Telemetry — what request metrics to track and send. */\nexport interface TelemetryPolicy {\n  /** Whether telemetry is enabled by default. Users can opt out via constructor param. */\n  enabledByDefault: boolean;\n  /** Header name for client telemetry data (previous request's ID + latency). */\n  headerName: string;\n  /** Response header name for the request ID. */\n  requestIdHeader: string;\n}\n\n// ── Pagination ─────────────────────────────────────────────────────\n\n/** Pagination behavior defaults. */\nexport interface PaginationPolicy {\n  /** Delay in milliseconds between pages during auto-pagination. 0 = no delay. */\n  autoPageDelayMs: number;\n}\n\n// ── Idempotency ────────────────────────────────────────────────────\n\n/** Idempotency auto-generation rules. */\nexport interface IdempotencyPolicy {\n  /** Header name for the idempotency key. */\n  headerName: string;\n  /** Whether to auto-generate a UUID v4 idempotency key for POST requests when retries > 0. */\n  autoGenerateForPost: boolean;\n}\n\n// ── Logging ────────────────────────────────────────────────────────\n\n/** Logging contract — what to log at which level. */\nexport interface LoggingPolicy {\n  /** Whether structured logging hooks are generated. */\n  enabled: boolean;\n  /** Log events that the generated client emits. */\n  events: LogEvent[];\n}\n\n/** A discrete loggable event in the request lifecycle. */\nexport type LogEvent =\n  | 'request.start'\n  | 'request.success'\n  | 'request.retry'\n  | 'request.rate_limited'\n  | 'request.error'\n  | 'request.connection_error';\n\n// ── User-Agent ─────────────────────────────────────────────────────\n\n/** User-Agent construction rules. */\nexport interface UserAgentPolicy {\n  /** Template for the SDK identifier string.\n   *  Placeholders: {name} = spec name, {lang} = emitter language, {version} = SDK version.\n   *  Each emitter interpolates with its own language string and casing conventions.\n   *  Example: '{name} {lang}/{version}' → 'Acme PHP/4.32.0' */\n  sdkIdentifierTemplate: string;\n  /** Whether to append the runtime/language version (e.g. PHP 8.2, Python 3.12). */\n  includeRuntimeVersion: boolean;\n  /** Whether to allow app info enrichment via setAppInfo(name, version, url). */\n  allowAppInfo: boolean;\n  /** AI agent environment variable detection entries. */\n  aiAgentEnvVars: AiAgentEnvVar[];\n}\n\n/** Maps an environment variable to an AI agent slug for User-Agent enrichment. */\nexport interface AiAgentEnvVar {\n  /** Environment variable to check (e.g. 'CLAUDE_CODE'). */\n  envVar: string;\n  /** Agent name to append to User-Agent (e.g. 'ClaudeCode'). */\n  agentName: string;\n}\n\n// ── Request Guards ─────────────────────────────────────────────────\n\n/** Guards that validate request params before sending. */\nexport interface RequestGuardPolicy {\n  /** Keys that should be in RequestOptions, not in params.\n   *  If detected in the body or query params, the SDK throws an error. */\n  optionKeys: string[];\n}\n\n// ── Timeouts ───────────────────────────────────────────────────────\n\n/** Timeout configuration. */\nexport interface TimeoutPolicy {\n  /** Default HTTP request timeout in seconds. */\n  defaultTimeoutSeconds: number;\n  /** Environment variable name to override the timeout (e.g. 'SDK_REQUEST_TIMEOUT'). */\n  timeoutEnvVar?: string;\n}\n\n// ── Root ───────────────────────────────────────────────────────────\n\n/** Language-agnostic runtime policies for generated SDKs.\n *  Attached to `ApiSpec.sdk` and consumed by emitters via `ctx.spec.sdk`. */\nexport interface SdkBehavior {\n  retry: RetryPolicy;\n  errors: ErrorPolicy;\n  telemetry: TelemetryPolicy;\n  pagination: PaginationPolicy;\n  idempotency: IdempotencyPolicy;\n  logging: LoggingPolicy;\n  userAgent: UserAgentPolicy;\n  requestGuard: RequestGuardPolicy;\n  timeout: TimeoutPolicy;\n}\n\n// ── Defaults ───────────────────────────────────────────────────────\n\n/**\n * Canonical SDK behavior defaults. Per-language or per-project overrides can\n * be applied via `mergeSdkBehavior()` in each SDK's `oagen.config.ts`.\n *\n * - Retry: exponential backoff with jitter, retries on 429/5xx\n * - Errors: standard HTTP status → exception kind mapping\n * - Telemetry: enabled by default, tracks request ID + latency\n * - Pagination: no inter-page delay (Node overrides to 350ms)\n * - Idempotency: auto-generate UUID v4 for retryable POSTs\n * - Logging: all lifecycle events enabled\n * - User-Agent: SDK identifier + runtime version + app info + AI agent detection\n * - Request guards: detect misplaced RequestOptions keys in params\n * - Timeout: 60s default (Python overrides to 30s)\n */\nexport function defaultSdkBehavior(): SdkBehavior {\n  return {\n    retry: {\n      retryableStatusCodes: [429, 500, 502, 503, 504],\n      maxRetries: 3,\n      retryOnConnectionError: true,\n      retryOnTimeout: true,\n      backoff: {\n        initialDelay: 1.0,\n        multiplier: 2.0,\n        maxDelay: 30.0,\n        jitterFactor: 0.5,\n      },\n    },\n    errors: {\n      statusCodeMap: {\n        400: 'BadRequest',\n        401: 'Authentication',\n        403: 'Authorization',\n        404: 'NotFound',\n        409: 'Conflict',\n        422: 'UnprocessableEntity',\n        429: 'RateLimitExceeded',\n      },\n      serverErrorKind: 'Server',\n      clientErrorKind: 'Api',\n    },\n    telemetry: {\n      enabledByDefault: true,\n      headerName: 'X-Client-Telemetry',\n      requestIdHeader: 'X-Request-ID',\n    },\n    pagination: {\n      autoPageDelayMs: 0,\n    },\n    idempotency: {\n      headerName: 'Idempotency-Key',\n      autoGenerateForPost: true,\n    },\n    logging: {\n      enabled: true,\n      events: [\n        'request.start',\n        'request.success',\n        'request.retry',\n        'request.rate_limited',\n        'request.error',\n        'request.connection_error',\n      ],\n    },\n    userAgent: {\n      sdkIdentifierTemplate: '{name} {lang}/{version}',\n      includeRuntimeVersion: true,\n      allowAppInfo: true,\n      aiAgentEnvVars: [\n        { envVar: 'CLAUDE_CODE', agentName: 'ClaudeCode' },\n        { envVar: 'CURSOR_AGENT', agentName: 'Cursor' },\n        { envVar: 'CLINE_ACTIVE', agentName: 'Cline' },\n        { envVar: 'WINDSURF_ACTIVE', agentName: 'Windsurf' },\n        { envVar: 'COPILOT_AGENT', agentName: 'Copilot' },\n      ],\n    },\n    requestGuard: {\n      optionKeys: [\n        'api_key',\n        'apiKey',\n        'idempotency_key',\n        'idempotencyKey',\n        'extra_headers',\n        'extraHeaders',\n        'max_retries',\n        'maxRetries',\n        'base_url',\n        'baseUrl',\n      ],\n    },\n    timeout: {\n      defaultTimeoutSeconds: 60,\n    },\n  };\n}\n\n// ── Merge ──────────────────────────────────────────────────────────\n\n/** Recursive partial type for deep overrides. */\nexport type DeepPartial<T> = {\n  [K in keyof T]?: T[K] extends (infer U)[]\n    ? U[] // Arrays replace entirely (don't concat)\n    : T[K] extends object\n      ? DeepPartial<T[K]>\n      : T[K];\n};\n\n/**\n * Deep-merge partial overrides into the canonical defaults.\n * Arrays replace entirely (so `retryableStatusCodes: [429]` replaces the full list,\n * rather than appending). Object properties are merged recursively.\n */\nexport function mergeSdkBehavior(overrides: DeepPartial<SdkBehavior>): SdkBehavior {\n  return deepMerge(\n    defaultSdkBehavior() as unknown as Record<string, unknown>,\n    overrides as unknown as Record<string, unknown>,\n  ) as unknown as SdkBehavior;\n}\n\n/**\n * Self-contained deep merge (no external imports — ir/ is layer 0).\n * Arrays and primitives from `source` replace those in `target`.\n * Objects are merged recursively.\n */\nfunction deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown> {\n  const result: Record<string, unknown> = { ...target };\n  for (const key of Object.keys(source)) {\n    const sourceVal = source[key];\n    const targetVal = target[key];\n    if (sourceVal === undefined) continue;\n    if (\n      sourceVal !== null &&\n      typeof sourceVal === 'object' &&\n      !Array.isArray(sourceVal) &&\n      targetVal !== null &&\n      typeof targetVal === 'object' &&\n      !Array.isArray(targetVal)\n    ) {\n      result[key] = deepMerge(targetVal as Record<string, unknown>, sourceVal as Record<string, unknown>);\n    } else {\n      result[key] = sourceVal;\n    }\n  }\n  return result;\n}\n","/**\n * Structured error hierarchy for oagen.\n *\n * Every error carries a human-readable `hint` that suggests a recovery action.\n * The hint is appended to the `message` so it appears in stack traces and logs.\n */\n\n/** Base class for all oagen errors. */\nexport class OagenError extends Error {\n  readonly hint: string;\n\n  constructor(message: string, hint: string) {\n    const fullMessage = hint ? `${message}\\nHint: ${hint}` : message;\n    super(fullMessage);\n    this.name = 'OagenError';\n    this.hint = hint;\n  }\n}\n\n/** Thrown when a command should terminate with a specific exit code. */\nexport class CommandError extends OagenError {\n  readonly exitCode: number;\n\n  constructor(message: string, hint: string, exitCode: number) {\n    super(message, hint);\n    this.name = 'CommandError';\n    this.exitCode = exitCode;\n  }\n}\n\n/** Thrown when an OpenAPI spec cannot be parsed or has an unsupported version. */\nexport class SpecParseError extends OagenError {\n  constructor(message: string, hint: string) {\n    super(message, hint);\n    this.name = 'SpecParseError';\n  }\n}\n\n/** Thrown when configuration files (manifests, API surfaces, overlays) are missing or malformed. */\nexport class ConfigError extends OagenError {\n  constructor(message: string, hint: string) {\n    super(message, hint);\n    this.name = 'ConfigError';\n  }\n}\n\n/** Thrown when a config file exists but cannot be loaded or evaluated. */\nexport class ConfigLoadError extends ConfigError {\n  constructor(message: string, hint: string) {\n    super(message, hint);\n    this.name = 'ConfigLoadError';\n  }\n}\n\n/** Thrown when a config targets a different IR version than the installed package. */\nexport class ConfigVersionMismatchError extends ConfigError {\n  constructor(message: string, hint: string) {\n    super(message, hint);\n    this.name = 'ConfigVersionMismatchError';\n  }\n}\n\n/** Thrown when an API surface extractor encounters a problem. */\nexport class ExtractorError extends OagenError {\n  constructor(message: string, hint: string) {\n    super(message, hint);\n    this.name = 'ExtractorError';\n  }\n}\n\n/** Thrown when a requested language or extractor is not found in a registry. */\nexport class RegistryError extends OagenError {\n  constructor(message: string, hint: string) {\n    super(message, hint);\n    this.name = 'RegistryError';\n  }\n}\n\n/** Thrown for internal invariant violations that indicate a bug. */\nexport class InternalError extends OagenError {\n  constructor(message: string, hint: string) {\n    super(message, hint);\n    this.name = 'InternalError';\n  }\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { makeDocumentFromString, bundleDocument, createConfig, BaseResolver, Oas3_1Types } from '@redocly/openapi-core';\nimport { SpecParseError } from '../errors.js';\n\nexport interface BundledSpec {\n  parsed: Record<string, unknown>;\n  specPath: string;\n}\n\nexport async function loadAndBundleSpec(specPath: string): Promise<BundledSpec> {\n  const absolutePath = resolve(specPath);\n  const content = await readFile(absolutePath, 'utf-8');\n  const document = makeDocumentFromString(content, pathToFileURL(absolutePath).href);\n\n  const config = await createConfig({});\n  const resolver = new BaseResolver();\n\n  const result = await bundleDocument({\n    document,\n    config,\n    types: Oas3_1Types,\n    externalRefResolver: resolver,\n    dereference: false,\n  });\n\n  if (result.problems.some((p) => p.severity === 'error')) {\n    const errors = result.problems\n      .filter((p) => p.severity === 'error')\n      .map((p) => p.message)\n      .join('\\n');\n    throw new SpecParseError(\n      `Failed to parse spec: ${errors}`,\n      `Check the OpenAPI spec at \"${absolutePath}\" for syntax errors. Run a linter such as \\`npx @redocly/cli lint ${specPath}\\` to identify issues.`,\n    );\n  }\n\n  return {\n    parsed: result.bundle.parsed as Record<string, unknown>,\n    specPath: absolutePath,\n  };\n}\n","import type { SdkBehavior } from './sdk-behavior.js';\n\n/** Authentication scheme extracted from OpenAPI securitySchemes */\nexport type AuthScheme =\n  | { kind: 'bearer' }\n  | { kind: 'apiKey'; in: 'header' | 'query' | 'cookie'; name: string }\n  | { kind: 'oauth2'; flows: Record<string, unknown> };\n\n/** Root IR node representing the full API surface */\n/** A server entry from the OpenAPI servers array */\nexport interface ServerEntry {\n  url: string;\n  description?: string;\n}\n\n/** Root IR node representing the full API surface */\nexport interface ApiSpec {\n  name: string;\n  version: string;\n  description?: string;\n  baseUrl: string;\n  servers?: ServerEntry[];\n  services: Service[];\n  models: Model[];\n  enums: Enum[];\n  auth?: AuthScheme[];\n  /** Language-agnostic runtime policies (retry, errors, telemetry, etc.). */\n  sdk: SdkBehavior;\n}\n\n/** A service groups related operations (maps to an SDK resource class) */\nexport interface Service {\n  name: string;\n  description?: string;\n  operations: Operation[];\n}\n\n/** A single API operation (maps to an SDK method) */\n/** Per-operation security requirement: scheme name → scope list. */\nexport interface SecurityRequirement {\n  schemeName: string;\n  scopes: string[];\n}\n\nexport interface Operation {\n  name: string;\n  description?: string;\n  httpMethod: HttpMethod;\n  path: string;\n  pathParams: Parameter[];\n  queryParams: Parameter[];\n  headerParams: Parameter[];\n  cookieParams?: Parameter[];\n  requestBody?: TypeRef;\n  requestBodyEncoding?: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text';\n  response: TypeRef;\n  successResponses?: SuccessResponse[];\n  errors: ErrorResponse[];\n  pagination?: PaginationMeta;\n  injectIdempotencyKey: boolean;\n  deprecated?: boolean;\n  async?: boolean;\n  /** Per-operation security overrides. When present, overrides the global spec-level security. */\n  security?: SecurityRequirement[];\n  /**\n   * Mutually-exclusive parameter groups parsed from `x-mutually-exclusive-parameter-groups`.\n   * Each group represents a logical choice the caller must (or may) make between\n   * several subsets of query/path/header parameters. The grouped parameters remain\n   * in their original arrays (queryParams, pathParams, etc.) for wire-format purposes;\n   * this field adds the grouping metadata so emitters can render sum types.\n   */\n  parameterGroups?: ParameterGroup[];\n}\n\n/**\n * A mutually-exclusive parameter group. The caller must supply exactly one\n * variant (when `optional` is false) or may omit the group entirely (when true).\n */\nexport interface ParameterGroup {\n  /** Group name from the extension (e.g. \"parent_resource\"). */\n  name: string;\n  /** True when the whole group may be omitted. */\n  optional: boolean;\n  /** Ordered variants (insertion order matches the spec). */\n  variants: ParameterGroupVariant[];\n}\n\n/**\n * One variant within a mutually-exclusive parameter group.\n */\nexport interface ParameterGroupVariant {\n  /** Variant name from the extension (e.g. \"by_id\", \"by_external_id\"). */\n  name: string;\n  /**\n   * References to the actual parameter IR nodes. These are the same\n   * objects that live in operation.queryParams / .pathParams / .headerParams --\n   * shared by identity, not duplicated.\n   */\n  parameters: Parameter[];\n}\n\n/** Structured pagination metadata for auto-paging iterator generation */\nexport interface PaginationMeta {\n  strategy: 'cursor' | 'offset' | 'link-header';\n  param: string;\n  limitParam?: string;\n  dataPath?: string;\n  itemType: TypeRef;\n}\n\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options' | 'trace';\n\nexport interface Parameter {\n  name: string;\n  type: TypeRef;\n  required: boolean;\n  description?: string;\n  deprecated?: boolean;\n  default?: unknown;\n  example?: unknown;\n  style?: 'form' | 'simple' | 'label' | 'matrix';\n  explode?: boolean;\n}\n\n/** Type reference — the core type system of the IR */\nexport type TypeRef = PrimitiveType | ArrayType | ModelRef | EnumRef | UnionType | NullableType | LiteralType | MapType;\n\nexport interface PrimitiveType {\n  kind: 'primitive';\n  type: 'string' | 'integer' | 'number' | 'boolean' | 'unknown';\n  format?: string;\n}\n\nexport interface ArrayType {\n  kind: 'array';\n  items: TypeRef;\n}\n\nexport interface ModelRef {\n  kind: 'model';\n  name: string;\n}\n\nexport interface EnumRef {\n  kind: 'enum';\n  name: string;\n  values?: (string | number)[];\n}\n\nexport interface LiteralType {\n  kind: 'literal';\n  value: string | number | boolean | null;\n}\n\nexport interface UnionType {\n  kind: 'union';\n  variants: TypeRef[];\n  discriminator?: { property: string; mapping: Record<string, string> };\n  /** Which OAS composition keyword produced this union. Emitters can use this to\n   *  distinguish inheritance (allOf) from exclusive union (oneOf) from open union (anyOf). */\n  compositionKind?: 'allOf' | 'oneOf' | 'anyOf';\n}\n\nexport interface NullableType {\n  kind: 'nullable';\n  inner: TypeRef;\n}\n\nexport interface MapType {\n  kind: 'map';\n  valueType: TypeRef;\n  keyType?: TypeRef;\n}\n\n/**\n * A generic type parameter on a model.\n * Example: `DirectoryUser<TCustomAttributes = Record<string, unknown>>`\n * → `{ name: 'TCustomAttributes', default: { kind: 'map', valueType: { kind: 'primitive', type: 'unknown' } } }`\n */\nexport interface TypeParam {\n  name: string;\n  /** Default type when the param is not specified. */\n  default?: TypeRef;\n}\n\n/** Model definition (maps to an SDK model/data class) */\nexport interface Model {\n  name: string;\n  description?: string;\n  fields: Field[];\n  /** Generic type parameters. Empty/undefined for non-generic models. */\n  typeParams?: TypeParam[];\n  /**\n   * When set, this model is a discriminated union over allOf+oneOf variants.\n   * Emitters should generate a dispatcher (factory) instead of a regular dataclass.\n   * The `property` field is the discriminator key (e.g. \"event\"), and `mapping`\n   * maps each discriminator value to the concrete variant model name.\n   */\n  discriminator?: {\n    property: string;\n    mapping: Record<string, string>;\n  };\n}\n\nexport interface Field {\n  name: string;\n  /**\n   * Optional domain-facing name override. When set, emitters derive the\n   * domain-side identifier (in their own casing) from this instead of `name`,\n   * while serialization still uses `name` for the wire key. Lets an SDK expose\n   * a wire field under a friendlier name (e.g. `connection_type` → `type`)\n   * without changing the API contract. Set via the `fieldHints` config and\n   * honored by any emitter that reads it.\n   */\n  domainName?: string;\n  type: TypeRef;\n  required: boolean;\n  description?: string;\n  readOnly?: boolean;\n  writeOnly?: boolean;\n  deprecated?: boolean;\n  default?: unknown;\n  example?: unknown;\n}\n\n/** Enum definition */\nexport interface Enum {\n  name: string;\n  values: EnumValue[];\n  /** Spec-level default value (the value of `default:` on the schema). Optional. */\n  default?: string | number;\n}\n\nexport interface EnumValue {\n  name: string;\n  value: string | number;\n  description?: string;\n  deprecated?: boolean;\n}\n\n/**\n * Exhaustive check helper for TypeRef switches.\n * If a new kind is added to TypeRef, any switch that doesn't handle it\n * will fail to compile because `never` won't accept the unhandled variant.\n *\n * Usage:\n *   switch (ref.kind) {\n *     case 'primitive': ...\n *     case 'array': ...\n *     // If you forget 'literal', TypeScript errors here:\n *     default: assertNever(ref);\n *   }\n */\nexport function assertNever(x: never): never {\n  // Inline to avoid importing from ../errors.js (ir/ is layer 0, must not import upward)\n  const kind = (x as TypeRef).kind;\n  const err = new Error(\n    `Unexpected TypeRef kind: ${kind}\\nHint: If you added a new TypeRef variant, handle it in every switch/case that calls assertNever.`,\n  );\n  err.name = 'InternalError';\n  throw err;\n}\n\n/**\n * Generic depth-first walker for TypeRef trees.\n * Handles recursion into array/nullable/union/map children and provides\n * an exhaustive `assertNever` check so callers don't need to repeat the\n * switch boilerplate.  Supply callbacks only for the leaf kinds you care about.\n */\nexport function walkTypeRef(\n  ref: TypeRef,\n  visitor: {\n    model?: (ref: ModelRef) => void;\n    enum?: (ref: EnumRef) => void;\n    primitive?: (ref: PrimitiveType) => void;\n    literal?: (ref: LiteralType) => void;\n  },\n): void {\n  switch (ref.kind) {\n    case 'model':\n      visitor.model?.(ref);\n      break;\n    case 'enum':\n      visitor.enum?.(ref);\n      break;\n    case 'array':\n      walkTypeRef(ref.items, visitor);\n      break;\n    case 'nullable':\n      walkTypeRef(ref.inner, visitor);\n      break;\n    case 'union':\n      for (const v of ref.variants) walkTypeRef(v, visitor);\n      break;\n    case 'map':\n      if (ref.keyType) walkTypeRef(ref.keyType, visitor);\n      walkTypeRef(ref.valueType, visitor);\n      break;\n    case 'literal':\n      visitor.literal?.(ref);\n      break;\n    case 'primitive':\n      visitor.primitive?.(ref);\n      break;\n    default:\n      assertNever(ref);\n  }\n}\n\n/**\n * Generic depth-first mapper for TypeRef trees.\n * Like walkTypeRef but returns a transformed value instead of void.\n * Handles recursion into array/nullable/union/map children, passing\n * already-mapped child values to the parent callback.\n */\nexport function mapTypeRef<T>(\n  ref: TypeRef,\n  mapper: {\n    primitive: (ref: PrimitiveType) => T;\n    array: (ref: ArrayType, mappedItems: T) => T;\n    model: (ref: ModelRef) => T;\n    enum: (ref: EnumRef) => T;\n    union: (ref: UnionType, mappedVariants: T[]) => T;\n    nullable: (ref: NullableType, mappedInner: T) => T;\n    literal: (ref: LiteralType) => T;\n    map: (ref: MapType, mappedValue: T, mappedKey?: T) => T;\n  },\n): T {\n  switch (ref.kind) {\n    case 'primitive':\n      return mapper.primitive(ref);\n    case 'array':\n      return mapper.array(ref, mapTypeRef(ref.items, mapper));\n    case 'model':\n      return mapper.model(ref);\n    case 'enum':\n      return mapper.enum(ref);\n    case 'union':\n      return mapper.union(\n        ref,\n        ref.variants.map((v) => mapTypeRef(v, mapper)),\n      );\n    case 'nullable':\n      return mapper.nullable(ref, mapTypeRef(ref.inner, mapper));\n    case 'literal':\n      return mapper.literal(ref);\n    case 'map':\n      return mapper.map(\n        ref,\n        mapTypeRef(ref.valueType, mapper),\n        ref.keyType ? mapTypeRef(ref.keyType, mapper) : undefined,\n      );\n    default:\n      return assertNever(ref);\n  }\n}\n\n// --- IR traversal utilities ---\n\n/**\n * Collect all model names referenced (directly or transitively) by a TypeRef.\n */\nexport function collectModelRefs(ref: TypeRef): string[] {\n  const names: string[] = [];\n  walkTypeRef(ref, { model: (r) => names.push(r.name) });\n  return names;\n}\n\n/**\n * Collect all enum names referenced by a TypeRef.\n */\nexport function collectEnumRefs(ref: TypeRef): string[] {\n  const names: string[] = [];\n  walkTypeRef(ref, { enum: (r) => names.push(r.name) });\n  return names;\n}\n\n/**\n * Collect all TypeRef-referenced model and enum names from a model's fields.\n * Returns { models, enums } sets for generating import statements.\n */\nexport function collectFieldDependencies(model: Model): {\n  models: Set<string>;\n  enums: Set<string>;\n} {\n  const models = new Set<string>();\n  const enums = new Set<string>();\n\n  for (const field of model.fields) {\n    for (const name of collectModelRefs(field.type)) {\n      if (name !== model.name) models.add(name);\n    }\n    for (const name of collectEnumRefs(field.type)) {\n      enums.add(name);\n    }\n  }\n\n  return { models, enums };\n}\n\n/**\n * Assign each model to the service that first references it.\n * Models referenced by multiple services are assigned to the first.\n * Models not referenced by any service are unassigned (absent from the map).\n *\n * @param hints - Optional pin overrides keyed by IR model name → IR service\n *   name. Applied after the natural assignment loop. Both names must exist in\n *   the spec; unknown keys/values throw a config-style error so typos fail\n *   loud at generation time.\n */\nexport function assignModelsToServices(\n  models: Model[],\n  services: Service[],\n  hints?: Record<string, string>,\n): Map<string, string> {\n  const modelToService = new Map<string, string>();\n  const modelNames = new Set(models.map((m) => m.name));\n\n  for (const service of services) {\n    const referencedModels = new Set<string>();\n\n    for (const op of service.operations) {\n      if (op.requestBody) {\n        for (const name of collectModelRefs(op.requestBody)) {\n          referencedModels.add(name);\n        }\n      }\n      for (const name of collectModelRefs(op.response)) {\n        referencedModels.add(name);\n      }\n      for (const param of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n        for (const name of collectModelRefs(param.type)) {\n          referencedModels.add(name);\n        }\n      }\n      if (op.pagination) {\n        for (const name of collectModelRefs(op.pagination.itemType)) {\n          referencedModels.add(name);\n        }\n      }\n    }\n\n    // Transitively collect models referenced by the directly-referenced models\n    const toVisit = [...referencedModels];\n    while (toVisit.length > 0) {\n      const name = toVisit.pop()!;\n      const model = models.find((m) => m.name === name);\n      if (!model) continue;\n      for (const field of model.fields) {\n        for (const ref of collectModelRefs(field.type)) {\n          if (!referencedModels.has(ref) && modelNames.has(ref)) {\n            referencedModels.add(ref);\n            toVisit.push(ref);\n          }\n        }\n      }\n    }\n\n    for (const name of referencedModels) {\n      if (!modelToService.has(name)) {\n        modelToService.set(name, service.name);\n      }\n    }\n  }\n\n  if (hints) {\n    const serviceNames = new Set(services.map((s) => s.name));\n    for (const [modelName, serviceName] of Object.entries(hints)) {\n      if (!modelNames.has(modelName)) {\n        const err = new Error(\n          `modelHints: unknown model \"${modelName}\". Hint keys must match an IR model name (post-cleanSchemaName/schemaNameTransform).`,\n        );\n        err.name = 'ConfigError';\n        throw err;\n      }\n      if (!serviceNames.has(serviceName)) {\n        const err = new Error(\n          `modelHints: unknown service \"${serviceName}\" for model \"${modelName}\". Hint values must match an IR service name (PascalCase, derived from the operation's first tag).`,\n        );\n        err.name = 'ConfigError';\n        throw err;\n      }\n      modelToService.set(modelName, serviceName);\n    }\n  }\n\n  return modelToService;\n}\n\n/**\n * Collect all model names referenced as request bodies across all services.\n */\nexport function collectRequestBodyModels(services: Service[]): Set<string> {\n  const result = new Set<string>();\n  for (const service of services) {\n    for (const op of service.operations) {\n      if (op.requestBody) {\n        for (const name of collectModelRefs(op.requestBody)) {\n          result.add(name);\n        }\n      }\n    }\n  }\n  return result;\n}\n\nexport interface ErrorResponse {\n  statusCode: number;\n  type?: TypeRef;\n}\n\n/** A successful response entry from a 2xx status code */\nexport interface SuccessResponse {\n  statusCode: number;\n  type: TypeRef;\n}\n","/**\n * Known compound tokens that the regex-based splitter over-splits.\n * Each entry is [lowercase-word-sequence, canonical-form].\n * Sorted longest-first so greedy matching works correctly.\n */\nconst COMPOUND_WORDS: [string[], string][] = [\n  [['m', '2', 'm'], 'M2M'],\n  [['o', 'auth'], 'OAuth'],\n];\n\n/**\n * Recombine adjacent words that form a known compound token.\n */\nfunction recombineCompounds(words: string[]): string[] {\n  const result: string[] = [];\n  let i = 0;\n  while (i < words.length) {\n    let matched = false;\n    for (const [pattern, canonical] of COMPOUND_WORDS) {\n      if (i + pattern.length <= words.length) {\n        const matches = pattern.every((p, j) => words[i + j].toLowerCase() === p);\n        if (matches) {\n          result.push(canonical);\n          i += pattern.length;\n          matched = true;\n          break;\n        }\n      }\n    }\n    if (!matched) {\n      result.push(words[i]);\n      i++;\n    }\n  }\n  return result;\n}\n\n/**\n * Split a string into words, handling:\n * - camelCase / PascalCase boundaries\n * - snake_case / kebab-case separators\n * - Consecutive capitals (e.g., \"HTTPClient\" → [\"HTTP\", \"Client\"])\n * - Numbers as word boundaries (e.g., \"OAuth2Token\" → [\"OAuth\", \"2\", \"Token\"])\n * - Known compounds are recombined (e.g., \"M2M\" stays as one word)\n */\nexport function splitWords(s: string): string[] {\n  if (!s) return [];\n\n  const words = s\n    .replace(/[^a-zA-Z0-9_\\-\\s.]/g, '_') // replace non-alphanumeric chars with separator\n    .replace(/([a-z])([A-Z])/g, '$1\\0$2') // camelCase boundary\n    .replace(/([A-Z]+)([A-Z][a-z])/g, '$1\\0$2') // consecutive caps boundary\n    .replace(/([a-zA-Z])(\\d)/g, '$1\\0$2') // letter to number\n    .replace(/(\\d)([a-zA-Z])/g, '$1\\0$2') // number to letter\n    .split(/[\\0_\\-\\s.]+/)\n    .filter((w) => w.length > 0);\n\n  return recombineCompounds(words);\n}\n\nexport const ACRONYM_SET = new Set(['SSO', 'FGA', 'SAML', 'SCIM', 'JWT', 'HMAC', 'M2M']);\n\nexport function toPascalCase(s: string, acronyms?: Set<string>): string {\n  const merged = acronyms ? new Set([...ACRONYM_SET, ...acronyms]) : ACRONYM_SET;\n  return splitWords(s)\n    .map((w) => {\n      const upper = w.toUpperCase();\n      if (merged.has(upper)) return upper;\n      // Special case: OAuth should stay as OAuth, not OAUTH\n      if (upper === 'OAUTH') return 'OAuth';\n      return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();\n    })\n    .join('');\n}\n\nexport function toCamelCase(s: string, acronyms?: Set<string>): string {\n  const merged = acronyms ? new Set([...ACRONYM_SET, ...acronyms]) : ACRONYM_SET;\n  const words = splitWords(s);\n  if (words.length === 0) return '';\n  return words\n    .map((w, i) => {\n      if (i === 0) return w.toLowerCase();\n      const upper = w.toUpperCase();\n      if (merged.has(upper)) return upper;\n      if (upper === 'OAUTH') return 'OAuth';\n      return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();\n    })\n    .join('');\n}\n\nexport function toSnakeCase(s: string): string {\n  return splitWords(s)\n    .map((w) => w.toLowerCase())\n    .join('_');\n}\n\nexport function toKebabCase(s: string): string {\n  return splitWords(s)\n    .map((w) => w.toLowerCase())\n    .join('-');\n}\n\nexport function toUpperSnakeCase(s: string): string {\n  return splitWords(s)\n    .map((w) => w.toUpperCase())\n    .join('_');\n}\n\nconst BACKEND_SUFFIXES = ['Controller'];\n\nexport function stripBackendSuffixes(name: string): string {\n  for (const suffix of BACKEND_SUFFIXES) {\n    if (name.endsWith(suffix) && name.length > suffix.length) {\n      return name.slice(0, -suffix.length);\n    }\n  }\n  return name;\n}\n\nexport function stripBackendPrefixes(name: string): string {\n  return name.replace(/Userland/g, '').replace(/Controller/g, '');\n}\n\n/**\n * Remove ListItem / ByExternalId / ByResourceId / ForResource markers from PascalCase names.\n * E.g. \"DirectoriesListItemState\" → \"DirectoriesState\"\n */\nexport function stripListItemMarkers(name: string): string {\n  return name\n    .replace(/ListItem/g, '')\n    .replace(/ByExternalId/g, '')\n    .replace(/ByResourceId/g, '')\n    .replace(/ForResource/g, '');\n}\n\n/** Words that look plural but must NOT be singularized. */\nconst SINGULAR_SAFE_LIST = new Set([\n  'Status',\n  'Address',\n  'Access',\n  'Process',\n  'Progress',\n  'Success',\n  'Radius',\n  'Canvas',\n  'Alias',\n  'Basis',\n  'Bus',\n  'Species',\n  'Series',\n]);\n\n/**\n * Conservative singularize for the leading PascalCase word.\n * Only applied to the first word of a PascalCase name (the resource word).\n * - `ies` → `y` (e.g. Directories → Directory)\n * - trailing `s` for words >4 chars (e.g. Organizations → Organization)\n * Safe-listed words are never singularized.\n */\nexport function singularize(word: string): string {\n  if (SINGULAR_SAFE_LIST.has(word)) return word;\n  if (word.endsWith('ies') && word.length > 4) {\n    return word.slice(0, -3) + 'y';\n  }\n  if (word.endsWith('ses') && word.length > 4) {\n    // e.g. \"Processes\" — but \"Process\" is safe-listed, this handles non-safe ones\n    return word.slice(0, -2);\n  }\n  if (word.endsWith('s') && !word.endsWith('ss') && word.length > 4) {\n    return word.slice(0, -1);\n  }\n  return word;\n}\n\n/**\n * Compose all backend name cleaning transforms in order:\n * 1. Strip backend prefixes (Userland, Controller)\n * 2. Strip backend suffixes (Dto, DTO, Controller)\n * 3. Strip ListItem / ByExternalId markers\n * 4. Singularize leading resource word\n *\n * Must be idempotent: `cleanSchemaName(cleanSchemaName(x)) === cleanSchemaName(x)`\n */\n/** Strip `.js` extensions from import/export specifiers for dedup comparison. */\nexport function normalizeJsExtension(text: string): string {\n  return text.replace(/\\.js(['\"])/g, '$1');\n}\n\nexport function cleanSchemaName(name: string): string {\n  let result = stripBackendPrefixes(stripBackendSuffixes(name));\n  result = stripListItemMarkers(result);\n\n  // Singularize the leading PascalCase word\n  const match = result.match(/^([A-Z][a-z]*)/);\n  if (match) {\n    const leadWord = match[1];\n    const singular = singularize(leadWord);\n    if (singular !== leadWord) {\n      result = singular + result.slice(leadWord.length);\n    }\n  }\n\n  return result;\n}\n","import type { Model, Field } from '../ir/types.js';\nimport { toPascalCase, stripListItemMarkers, singularize } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { buildFieldFromSchema, resolveSchemaName } from './schemas.js';\n\n/**\n * Qualify an inline model name with the parent schema name.\n * If `parentName` is provided and the field name doesn't already start with\n * the parent, the result is `${parentName}${PascalField}` with the trailing\n * word singularized (e.g., Connection + Domains → ConnectionDomain).\n */\nexport function qualifyInlineModelName(baseName: string, parentName?: string): string {\n  if (!parentName) return baseName;\n  // Strip ListItem/ByExternalId markers from parent name so inline model names\n  // are clean and match the names produced by qualifyNestedName() in responses.ts.\n  // e.g., ConnectionListItem + Domains → Connection + Domain = ConnectionDomain\n  const cleanParent = stripListItemMarkers(parentName);\n  if (baseName.startsWith(cleanParent)) return baseName;\n  // Singularize the trailing PascalCase word of the combined name.\n  // Split baseName into leading words + trailing word, singularize trailing.\n  const trailingMatch = baseName.match(/^(.*?)([A-Z][a-z]*)$/);\n  if (trailingMatch) {\n    const [, prefix, trailingWord] = trailingMatch;\n    const singular = singularize(trailingWord);\n    return `${cleanParent}${prefix}${singular}`;\n  }\n  return `${cleanParent}${baseName}`;\n}\n\n/**\n * Walk all component schemas and extract inline Model definitions for fields\n * that are objects with properties (or arrays of such objects).\n * These correspond to the ModelRef entries created by schemaToTypeRef.\n */\nexport function extractInlineModelsFromSchemas(schemas: Record<string, SchemaObject> | undefined): Model[] {\n  if (!schemas) return [];\n\n  const inlineModels: Model[] = [];\n\n  for (const [schemaName, schema] of Object.entries(schemas)) {\n    const parentName = resolveSchemaName(schemaName);\n    extractInlineModelsFromProperties(schema, inlineModels, parentName);\n  }\n\n  return inlineModels;\n}\n\nfunction extractInlineModelsFromProperties(schema: SchemaObject, results: Model[], parentName?: string): void {\n  const properties = schema.properties ?? {};\n  const allOfSchemas = schema.allOf ?? [];\n\n  for (const sub of allOfSchemas) {\n    if (sub.properties) {\n      extractInlineModelsFromProperties(sub, results, parentName);\n    }\n  }\n\n  for (const [fieldName, fieldSchema] of Object.entries(properties)) {\n    if (!fieldSchema) continue;\n    // Direct inline object with properties (with or without explicit type: 'object')\n    if (fieldSchema.properties && (fieldSchema.type === 'object' || !fieldSchema.type)) {\n      const baseName = toPascalCase(fieldName);\n      const modelName = qualifyInlineModelName(baseName, parentName);\n      results.push(buildInlineModel(modelName, fieldSchema));\n      extractInlineModelsFromProperties(fieldSchema, results, modelName);\n    }\n\n    // Array of inline objects\n    if (fieldSchema.type === 'array' && fieldSchema.items) {\n      const items = fieldSchema.items;\n      if (items.properties && (items.type === 'object' || !items.type)) {\n        const baseName = toPascalCase(fieldName);\n        const modelName = qualifyInlineModelName(baseName, parentName);\n        results.push(buildInlineModel(modelName, items));\n        extractInlineModelsFromProperties(items, results, modelName);\n      }\n    }\n\n    // oneOf containing objects — extract every inline object variant as a\n    // model so each gets its own typed class. Variant 0 keeps the bare\n    // qualified inline name (e.g. `ApiKeyCreatedDataOwner`); subsequent\n    // variants are prefixed by their const-discriminator value via\n    // `nameOneOfVariant` (e.g. `UserApiKeyCreatedDataOwner`). When the\n    // oneOf doesn't have a const-discriminator (single object variant + null\n    // for nullable, or single object variant only), only variant 0 is\n    // extracted and the bare name pattern preserves backward compat.\n    if (fieldSchema.oneOf) {\n      const inlineObjectVariants = fieldSchema.oneOf.filter(\n        (v) => !v.$ref && v.properties && (v.type === 'object' || !v.type),\n      );\n      if (inlineObjectVariants.length > 0) {\n        const baseName = toPascalCase(fieldName);\n        const modelName = qualifyInlineModelName(baseName, parentName);\n        const existingNames = new Set(results.map((r) => r.name));\n        const namingDiscProp = deriveOneOfNamingDiscriminator(inlineObjectVariants);\n        const emittedNames: string[] = [];\n        for (const variant of inlineObjectVariants) {\n          const variantName = nameOneOfVariant(variant, modelName, emittedNames, namingDiscProp);\n          emittedNames.push(variantName);\n          if (!existingNames.has(variantName)) {\n            existingNames.add(variantName);\n            results.push(buildInlineModel(variantName, variant));\n            extractInlineModelsFromProperties(variant, results, variantName);\n          }\n        }\n      }\n    }\n  }\n}\n\n/** Find a single string-const-valued property shared by every variant whose\n *  values are all distinct — the implicit discriminator. Returns null when no\n *  such property exists. Mirrors `deriveConstNamingDiscriminator` in schemas.ts. */\nfunction deriveOneOfNamingDiscriminator(variants: SchemaObject[]): string | null {\n  if (variants.length < 2) return null;\n  const candidates = Object.keys(variants[0]?.properties ?? {});\n  for (const propName of candidates) {\n    const values = variants.map((v) => readConstString(v.properties?.[propName]));\n    if (values.some((v) => v === null)) continue;\n    if (new Set(values).size !== values.length) continue;\n    return propName;\n  }\n  return null;\n}\n\nfunction readConstString(prop: SchemaObject | undefined): string | null {\n  if (!prop) return null;\n  if (typeof prop.const === 'string') return prop.const;\n  if (Array.isArray(prop.enum) && prop.enum.length === 1 && typeof prop.enum[0] === 'string') {\n    return prop.enum[0];\n  }\n  return null;\n}\n\n/** Produce a per-variant model name. Variant 0 keeps the bare parent name;\n *  later variants are prefixed by the const-derived label. Mirrors\n *  `nameVariantModel` in schemas.ts. Falls back to a numeric suffix when no\n *  discriminator is available, the const value PascalCases to nothing, or\n *  the derived candidate collides with the parent or an already-emitted name. */\nfunction nameOneOfVariant(\n  variant: SchemaObject,\n  parentName: string,\n  alreadyEmitted: string[],\n  discriminatorProperty: string | null,\n): string {\n  if (alreadyEmitted.length === 0) return parentName;\n  if (discriminatorProperty) {\n    const constValue = readConstString(variant.properties?.[discriminatorProperty]);\n    if (constValue) {\n      const prefix = toPascalCase(constValue);\n      if (prefix) {\n        const candidate = parentName.startsWith(prefix) ? parentName : `${prefix}${parentName}`;\n        const collision = candidate === parentName || alreadyEmitted.includes(candidate);\n        if (!collision) return candidate;\n      }\n    }\n  }\n  return `${parentName}${alreadyEmitted.length + 1}`;\n}\n\nfunction buildInlineModel(name: string, schema: SchemaObject): Model {\n  const requiredSet = new Set(schema.required ?? []);\n  const fields: Field[] = [];\n\n  for (const [fieldName, fieldSchema] of Object.entries(schema.properties ?? {})) {\n    if (!fieldSchema) continue;\n    fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n  }\n\n  return { name, description: schema.description, fields };\n}\n","import type { Model, Enum, EnumValue, Field, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport {\n  toPascalCase,\n  toUpperSnakeCase,\n  cleanSchemaName,\n  singularize,\n  stripListItemMarkers,\n  splitWords,\n} from '../utils/naming.js';\n\n/**\n * Module-level transform set during extractSchemas(). Used by schemaToTypeRef()\n * to apply the same name transform to $ref model/enum references.\n */\nlet activeSchemaNameTransform: ((name: string) => string) | null = null;\n\n/**\n * Module-level set of resolved schema names whose components/schemas entry is\n * an enum (i.e. has `enum:`). Populated by extractSchemas() so schemaToTypeRef()\n * can classify a `$ref` to a top-level enum schema as `kind: 'enum'` instead of\n * `kind: 'model'`. Without this, every `$ref` was naively returned as a model\n * ref, even when the target was a shared enum like `PaginationOrder`.\n */\nlet activeEnumSchemaNames: Set<string> = new Set();\n\n/** Apply cleanSchemaName + the active transform (if any) to a raw schema name. */\nexport function resolveSchemaName(rawName: string): string {\n  let name = cleanSchemaName(toPascalCase(rawName));\n  if (activeSchemaNameTransform) name = activeSchemaNameTransform(name);\n  return name;\n}\n\nexport interface SchemaExtractionOptions {\n  schemaNameTransform?: (name: string) => string;\n}\n\nexport interface SchemaObject {\n  type?: string | string[];\n  format?: string;\n  description?: string;\n  properties?: Record<string, SchemaObject | undefined>;\n  required?: string[];\n  items?: SchemaObject;\n  enum?: (string | number)[];\n  allOf?: SchemaObject[];\n  oneOf?: SchemaObject[];\n  anyOf?: SchemaObject[];\n  discriminator?: { propertyName: string; mapping?: Record<string, string> };\n  readOnly?: boolean;\n  writeOnly?: boolean;\n  nullable?: boolean;\n  $ref?: string;\n  additionalProperties?: boolean | SchemaObject;\n  const?: unknown;\n  patternProperties?: Record<string, SchemaObject>;\n  deprecated?: boolean;\n  default?: unknown;\n  example?: unknown;\n  [key: string]: unknown;\n}\n\nexport interface ExtractedSchemas {\n  models: Model[];\n  enums: Enum[];\n}\n\nexport function extractSchemas(\n  schemas: Record<string, SchemaObject> | undefined,\n  options?: SchemaExtractionOptions,\n): ExtractedSchemas {\n  const enums: Enum[] = [];\n\n  if (!schemas) return { models: [], enums };\n\n  // Build collision-safe transform if provided\n  if (options?.schemaNameTransform) {\n    const transform = options.schemaNameTransform;\n    const rawNames = Object.keys(schemas);\n    const cleanedNames = rawNames.map((n) => cleanSchemaName(toPascalCase(n)));\n    const transformedToOriginals = new Map<string, string[]>();\n    for (const cleaned of cleanedNames) {\n      const transformed = transform(cleaned);\n      if (!transformedToOriginals.has(transformed)) transformedToOriginals.set(transformed, []);\n      transformedToOriginals.get(transformed)!.push(cleaned);\n    }\n    const unsafeToTransform = new Set<string>();\n    for (const [, originals] of transformedToOriginals) {\n      if (originals.length > 1) {\n        for (const n of originals) unsafeToTransform.add(n);\n      }\n    }\n    activeSchemaNameTransform = (name: string) => (unsafeToTransform.has(name) ? name : transform(name));\n  } else {\n    activeSchemaNameTransform = null;\n  }\n\n  // Pre-compute the set of resolved names whose component schema is an enum so\n  // schemaToTypeRef() can classify `$ref` targets correctly. Built in a separate\n  // pass because the per-schema loop mutates models/enums and we want this map\n  // available before any TypeRef is resolved (operations + nested fields both\n  // call schemaToTypeRef during extraction).\n  activeEnumSchemaNames = new Set();\n  for (const [name, schema] of Object.entries(schemas)) {\n    if (schema.enum) activeEnumSchemaNames.add(resolveSchemaName(name));\n  }\n\n  const modelsByCleanName = new Map<string, Model>();\n\n  for (const [name, schema] of Object.entries(schemas)) {\n    const pascalName = resolveSchemaName(name);\n\n    if (schema.enum) {\n      enums.push(extractEnum(pascalName, schema));\n    } else {\n      const model = extractModel(pascalName, schema, schemas);\n      const existing = modelsByCleanName.get(pascalName);\n      if (existing) {\n        // Keep the model with more fields when names collide after cleaning\n        if (model.fields.length > existing.fields.length) {\n          modelsByCleanName.set(pascalName, model);\n        }\n      } else {\n        modelsByCleanName.set(pascalName, model);\n      }\n\n      for (const inlineModel of extractDiscriminatedAllOfVariantModels(schema, pascalName)) {\n        const existingInline = modelsByCleanName.get(inlineModel.name);\n        if (existingInline) {\n          if (inlineModel.fields.length > existingInline.fields.length) {\n            modelsByCleanName.set(inlineModel.name, inlineModel);\n          }\n        } else {\n          modelsByCleanName.set(inlineModel.name, inlineModel);\n        }\n      }\n    }\n  }\n\n  const models = [...modelsByCleanName.values()];\n\n  // Collect inline models from nested object/oneOf properties\n  // that schemaToTypeRef created model refs for but weren't extracted\n  const modelNames = new Set(models.map((m) => m.name));\n  const inlineQueue: Model[] = [...models];\n  while (inlineQueue.length > 0) {\n    const model = inlineQueue.pop()!;\n    for (const field of model.fields) {\n      collectNestedInlineModels(field.type, field.name, model.name, schemas ?? {}, models, modelNames, inlineQueue);\n    }\n  }\n\n  // Collect inline enums from model fields\n  for (const model of models) {\n    collectInlineEnums(model.fields, enums);\n  }\n\n  // NOTE: activeSchemaNameTransform is intentionally NOT cleared here.\n  // extractOperations() calls schemaToTypeRef() for $ref resolution and\n  // needs the same transform active. parseSpec() calls clearSchemaNameTransform()\n  // after all extraction is complete.\n  return { models, enums };\n}\n\n/** Clear the module-level schemaNameTransform. Called by parseSpec() after all extraction phases. */\nexport function clearSchemaNameTransform(): void {\n  activeSchemaNameTransform = null;\n  activeEnumSchemaNames = new Set();\n}\n\n/**\n * Walk a single TypeRef and extract inline enum refs as top-level enum definitions.\n * Shared by both schemas.ts (field-level) and parse.ts (model-level) collection passes.\n */\nexport function collectInlineEnumFromRef(ref: TypeRef, enums: Enum[], seen: Set<string>): void {\n  walkTypeRef(ref, {\n    enum: (r) => {\n      if (r.values && !seen.has(r.name)) {\n        seen.add(r.name);\n        enums.push({\n          name: r.name,\n          values: r.values.map((v) => ({\n            name: toUpperSnakeCase(String(v)),\n            value: v,\n            description: undefined,\n          })),\n        });\n      }\n    },\n  });\n}\n\n/**\n * Walk model fields and extract inline enum refs as top-level enum definitions.\n * This ensures type alias files are generated for inline enums.\n */\nfunction collectInlineEnums(fields: Field[], enums: Enum[]): void {\n  const seen = new Set(enums.map((e) => e.name));\n  for (const field of fields) {\n    collectInlineEnumFromRef(field.type, enums, seen);\n  }\n}\n\n/**\n * Walk a TypeRef tree and extract inline models for any model refs that point\n * to schemas with inline object properties (not in components/schemas).\n * This handles nested objects like `totp: { oneOf: [{ type: object, properties: {...} }] }`\n * that schemaToTypeRef turns into model refs but aren't extracted from components.\n */\nfunction collectNestedInlineModels(\n  ref: TypeRef,\n  fieldName: string,\n  parentModelName: string,\n  schemas: Record<string, SchemaObject>,\n  models: Model[],\n  modelNames: Set<string>,\n  queue: Model[],\n): void {\n  walkTypeRef(ref, {\n    model: (modelRef) => {\n      if (modelNames.has(modelRef.name)) return; // already extracted\n      // Check if this model name corresponds to a component schema\n      // by checking all possible original names that would map to this PascalCase name\n      const isComponent = Object.keys(schemas).some((k) => resolveSchemaName(k) === modelRef.name);\n      if (isComponent) return; // will be extracted from components\n\n      // This is a reference to a nested inline model that wasn't extracted.\n      // Look up the field schema in the parent model's component schema to extract it.\n      const parentSchema = findSchemaByName(parentModelName, schemas);\n      if (!parentSchema) return;\n\n      const fieldSchema = findNestedFieldSchema(fieldName, parentSchema, schemas);\n      if (!fieldSchema) return;\n\n      // Extract inline models from the field schema\n      const extracted = extractNestedSchema(modelRef.name, fieldSchema);\n      for (const m of extracted) {\n        if (!modelNames.has(m.name)) {\n          models.push(m);\n          modelNames.add(m.name);\n          queue.push(m); // re-scan for deeper nesting\n        }\n      }\n    },\n  });\n}\n\n/** Find a component schema by PascalCase name. */\nfunction findSchemaByName(pascalName: string, schemas: Record<string, SchemaObject>): SchemaObject | null {\n  for (const [k, v] of Object.entries(schemas)) {\n    if (resolveSchemaName(k) === pascalName) return v;\n  }\n  return null;\n}\n\n/** Walk into a schema to find a field's sub-schema, resolving allOf and oneOf/anyOf. */\nfunction findNestedFieldSchema(\n  fieldName: string,\n  parentSchema: SchemaObject,\n  schemas: Record<string, SchemaObject>,\n): SchemaObject | null {\n  if (parentSchema.properties?.[fieldName]) {\n    return parentSchema.properties[fieldName]!;\n  }\n  if (parentSchema.allOf) {\n    for (const sub of parentSchema.allOf) {\n      let resolved = sub;\n      if (sub.$ref) {\n        const segments = sub.$ref.split('/');\n        const refName = segments[segments.length - 1];\n        if (refName && schemas[refName]) resolved = schemas[refName];\n      }\n      if (resolved.properties?.[fieldName]) {\n        return resolved.properties[fieldName]!;\n      }\n    }\n  }\n  // Also check inside oneOf/anyOf variants (pure oneOf schemas flatten variant\n  // properties into the model, so the field may live inside a variant).\n  for (const variant of [...(parentSchema.oneOf ?? []), ...(parentSchema.anyOf ?? [])]) {\n    let resolved = variant;\n    if (variant.$ref) {\n      const segments = variant.$ref.split('/');\n      const refName = segments[segments.length - 1];\n      if (refName && schemas[refName]) resolved = schemas[refName];\n    }\n    if (resolved.properties?.[fieldName]) {\n      return resolved.properties[fieldName]!;\n    }\n  }\n  return null;\n}\n\n/** Extract a model (and nested models) from an inline field schema. */\nfunction extractNestedSchema(name: string, schema: SchemaObject): Model[] {\n  // Handle oneOf: extract each object variant as its own model\n  if (schema.oneOf) {\n    const models: Model[] = [];\n\n    // Collect the inline object variants up front. When every variant pins\n    // the same property to a const value, we can derive meaningful names\n    // from the const (e.g. `UserApiKeyOwner` instead of `ApiKeyOwner2`)\n    // — much friendlier for SDK consumers than numeric suffixes.\n    const inlineObjectVariants: SchemaObject[] = schema.oneOf.filter(\n      (v) => !v.$ref && v.properties && (v.type === 'object' || !v.type),\n    );\n    const constNamingDiscriminator = deriveConstNamingDiscriminator(inlineObjectVariants);\n\n    for (const variant of schema.oneOf) {\n      if (variant.$ref) continue;\n      if (variant.properties && (variant.type === 'object' || !variant.type)) {\n        const requiredSet = new Set(variant.required ?? []);\n        const fields: Field[] = [];\n        for (const [fn, fs] of Object.entries(variant.properties)) {\n          if (!fs) continue;\n          fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n        }\n        const variantName = nameVariantModel(variant, name, models, constNamingDiscriminator);\n        models.push({ name: variantName, description: variant.description, fields });\n      }\n    }\n    return models;\n  }\n\n  // Handle direct object\n  if (schema.properties && (schema.type === 'object' || !schema.type)) {\n    const requiredSet = new Set(schema.required ?? []);\n    const fields: Field[] = [];\n    for (const [fn, fs] of Object.entries(schema.properties)) {\n      if (!fs) continue;\n      fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n    }\n    return [{ name, description: schema.description, fields }];\n  }\n\n  // Handle array with inline items\n  if (schema.type === 'array' && schema.items?.properties) {\n    const requiredSet = new Set(schema.items.required ?? []);\n    const fields: Field[] = [];\n    for (const [fn, fs] of Object.entries(schema.items.properties)) {\n      if (!fs) continue;\n      fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n    }\n    return [{ name, description: schema.items.description, fields }];\n  }\n\n  return [];\n}\n\n/**\n * Derive a meaningful name for a oneOf object variant past the first,\n * falling back to the numeric-suffix scheme (`Foo2`, `Foo3`) when no\n * better signal is available. The \"better signal\" is a const-valued\n * discriminator property that distinguishes one variant from the others.\n *\n * For a schema like `ApiKey.owner` whose oneOf has two variants — one\n * with `type: { const: \"organization\" }` and one with `type: { const:\n * \"user\" }` — this returns `ApiKeyOwner` for the first variant (the\n * baseline name that the union TypeRef will reference, so consumer-\n * visible typed fields stay backward-compatible) and `UserApiKeyOwner`\n * for the second instead of `ApiKeyOwner2`. SDK consumers reading the\n * generated types can tell the variants apart at a glance.\n *\n * The first variant always keeps the bare parent name because\n * `schemaToTypeRef` builds union variants whose model refs collapse to\n * `qualifyInlineModelName(field, parent)` — so the first model name\n * must match for the union's degenerate-collapse to land on a valid\n * type. Renaming variant 0 would orphan it.\n *\n * Falls back to numeric suffix when:\n *   - The variant has no discriminator property (no shared const\n *     property across all object variants), OR\n *   - The const value PascalCases to an empty/whitespace name, OR\n *   - The derived name collides with the parent name or an already-\n *     emitted variant name (numeric keeps uniqueness).\n */\nfunction nameVariantModel(\n  variant: SchemaObject,\n  parentName: string,\n  alreadyEmitted: Model[],\n  discriminator: { property: string } | null,\n): string {\n  // Variant 0 keeps the bare parent name so the union TypeRef's degenerate\n  // collapse target exists in the model registry.\n  if (alreadyEmitted.length === 0) return parentName;\n\n  if (discriminator) {\n    const constValue = getConstPropertyValue(variant, discriminator.property);\n    if (constValue) {\n      const prefix = toPascalCase(constValue);\n      if (prefix) {\n        const candidate = parentName.startsWith(prefix) ? parentName : `${prefix}${parentName}`;\n        const collision = candidate === parentName || alreadyEmitted.some((m) => m.name === candidate);\n        if (!collision) return candidate;\n      }\n    }\n  }\n  return `${parentName}${alreadyEmitted.length + 1}`;\n}\n\n/**\n * Returns a discriminator descriptor when every inline object variant in a\n * oneOf has a string-const value on the same property — the signature of a\n * discriminated union without an explicit `discriminator:` keyword. Used by\n * `nameVariantModel` to derive variant names from the const values.\n *\n * Distinct from `detectConstPropertyDiscriminator` (which requires every\n * variant to carry a `$ref` or `title` so a name mapping can be built):\n * this pass operates on inline anonymous variants, where naming is exactly\n * what we're trying to derive.\n */\nfunction deriveConstNamingDiscriminator(variants: SchemaObject[]): { property: string } | null {\n  if (variants.length < 2) return null;\n  const candidates = Object.keys(variants[0]?.properties ?? {});\n  for (const propName of candidates) {\n    const values = variants.map((v) => getConstPropertyValue(v, propName));\n    if (values.some((v) => v === null)) continue;\n    if (new Set(values).size !== values.length) continue; // collisions = no signal\n    return { property: propName };\n  }\n  return null;\n}\n\n/** Build a single Field from a schema property entry. Shared across all extraction sites. */\nexport function buildFieldFromSchema(\n  fieldName: string,\n  fieldSchema: SchemaObject,\n  contextName: string,\n  requiredSet: Set<string>,\n): Field {\n  return {\n    name: fieldName,\n    type: schemaToTypeRef(fieldSchema, fieldName, contextName),\n    required: requiredSet.has(fieldName),\n    description: fieldSchema.description,\n    readOnly: fieldSchema.readOnly || undefined,\n    writeOnly: fieldSchema.writeOnly || undefined,\n    deprecated: fieldSchema.deprecated || undefined,\n    default: fieldSchema.default,\n    example: fieldSchema.example,\n  };\n}\n\n/**\n * If every non-null oneOf/anyOf variant is a string-valued const, return the\n * list of those const values so the union can collapse into a single enum.\n * Returns null when any variant isn't a pure string-const (model ref,\n * number const, nullable, etc.).\n */\nfunction collectLiteralStringConsts(variants: SchemaObject[]): string[] | null {\n  if (variants.length === 0) return null;\n  const values: string[] = [];\n  for (const v of variants) {\n    // A single-element enum is semantically identical to const.\n    if (typeof v.const === 'string') {\n      values.push(v.const);\n      continue;\n    }\n    if (Array.isArray(v.enum) && v.enum.length === 1 && typeof v.enum[0] === 'string') {\n      values.push(v.enum[0]);\n      continue;\n    }\n    return null;\n  }\n  return values;\n}\n\n/** Build an EnumRef the same way the regular enum path does for naming. */\nfunction buildSyntheticEnumRef(\n  values: string[],\n  contextName: string | undefined,\n  parentModelName: string | undefined,\n): TypeRef {\n  const baseName = toPascalCase(contextName ?? 'UnknownEnum');\n  const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : undefined;\n  const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;\n  // Run the same `schemaNameTransform` we apply to component-schema names so\n  // a project-level rename map (e.g. `RadarAction` → `RadarListAction` in\n  // `oagen.config.ts`) catches inline parameter enums too.\n  const finalName = activeSchemaNameTransform ? activeSchemaNameTransform(qualifiedName) : qualifiedName;\n  return { kind: 'enum', name: finalName, values };\n}\n\n/**\n * Detect an implicit discriminator on an oneOf where every variant is an\n * object schema that pins the same property to a const value. Returns\n * { property, mapping } so the IR can represent the union as discriminated\n * without needing an explicit `discriminator:` key in the spec.\n *\n * Both shapes are supported:\n *   { properties: { event: { const: \"x\" } }, required: [\"event\"] }\n *   { properties: { event: { type: \"string\", enum: [\"x\"] } } }\n *\n * Returns null when any variant doesn't fit the pattern or when variants\n * disagree on which property carries the discriminator.\n */\nfunction detectConstPropertyDiscriminator(\n  variants: SchemaObject[],\n): { property: string; mapping: Record<string, string> } | null {\n  if (variants.length < 2) return null;\n\n  // Find properties whose const value is present on every variant.\n  let candidateProperty: string | null = null;\n  const candidates = Object.keys(variants[0]?.properties ?? {});\n  for (const propName of candidates) {\n    if (variants.every((v) => getConstPropertyValue(v, propName) !== null)) {\n      candidateProperty = propName;\n      break;\n    }\n  }\n\n  if (!candidateProperty) return null;\n\n  const mapping: Record<string, string> = {};\n  for (const v of variants) {\n    const value = getConstPropertyValue(v, candidateProperty);\n    if (value === null) return null;\n    // Require a $ref or title so we have a concrete model name to map to.\n    const variantName = resolveVariantModelName(v);\n    if (!variantName) return null;\n    mapping[value] = variantName;\n  }\n\n  return { property: candidateProperty, mapping };\n}\n\nfunction getConstPropertyValue(schema: SchemaObject, property: string): string | null {\n  const prop = schema.properties?.[property];\n  if (!prop) return null;\n  if (typeof prop.const === 'string') return prop.const;\n  if (Array.isArray(prop.enum) && prop.enum.length === 1 && typeof prop.enum[0] === 'string') {\n    return prop.enum[0];\n  }\n  return null;\n}\n\nfunction resolveVariantModelName(schema: SchemaObject): string | null {\n  if (schema.$ref) {\n    return resolveSchemaName(schema.$ref.replace(/^#\\/components\\/schemas\\//, ''));\n  }\n  const title = typeof schema['title'] === 'string' ? (schema['title'] as string) : null;\n  if (title) return resolveSchemaName(title);\n  return null;\n}\n\n/** Look up the discriminator's mapped variant name for an inline object\n *  variant by reading its const-valued discriminator property. Returns null\n *  when the variant doesn't pin the property to a string const, or when\n *  the value isn't in the mapping. */\nfunction mapVariantToDiscriminatorEntry(\n  variant: SchemaObject,\n  discriminator: { property: string; mapping: Record<string, string> },\n): string | null {\n  const value = getConstPropertyValue(variant, discriminator.property);\n  if (value === null) return null;\n  return discriminator.mapping[value] ?? null;\n}\n\n/**\n * Derive a discriminator value → variant model name mapping for an inline-\n * variant `oneOf` whose explicit `discriminator:` has no `mapping:` clause.\n *\n * Each variant model name is reproduced via `nameVariantModel` so it matches\n * what `extractNestedSchema` registered when it walked the same `oneOf` to\n * pull variants out as named models. Variant 0 keeps the bare parent name\n * (e.g. `ApiKeyOwner`); subsequent variants get a const-derived prefix\n * (e.g. `UserApiKeyOwner` for the `type: const: user` variant).\n *\n * The \"parent name\" used here mirrors the one `collectNestedInlineModels`\n * passes to `extractNestedSchema`: it's the qualified inline model name\n * built from `contextName` (the field name) plus `parentModelName` (the\n * containing model). Returns null when any non-object variant is present\n * or when a variant lacks a const value on the discriminator property.\n */\nfunction deriveInlineVariantMapping(\n  variants: SchemaObject[],\n  discriminatorProperty: string,\n  contextName: string | undefined,\n  parentModelName: string | undefined,\n): Record<string, string> | null {\n  if (variants.length === 0 || !contextName) return null;\n  const inlineObjectVariants = variants.filter((v) => !v.$ref && v.properties && (v.type === 'object' || !v.type));\n  if (inlineObjectVariants.length !== variants.length) return null;\n\n  const baseInlineName = qualifyInlineModelName(toPascalCase(contextName), parentModelName);\n  const namingDiscriminator = { property: discriminatorProperty };\n  const mapping: Record<string, string> = {};\n  const emittedSoFar: Model[] = [];\n  for (const variant of inlineObjectVariants) {\n    const constValue = getConstPropertyValue(variant, discriminatorProperty);\n    if (constValue === null) return null;\n    const variantName = nameVariantModel(variant, baseInlineName, emittedSoFar, namingDiscriminator);\n    mapping[constValue] = variantName;\n    emittedSoFar.push({ name: variantName, fields: [] });\n  }\n  return mapping;\n}\n\nfunction extractEnum(name: string, schema: SchemaObject): Enum {\n  const values: EnumValue[] = (schema.enum ?? []).map((v) => ({\n    name: toUpperSnakeCase(String(v)),\n    value: typeof v === 'number' ? v : String(v),\n    description: undefined,\n  }));\n\n  const rawDefault = schema.default;\n  const def =\n    rawDefault !== undefined && values.some((v) => v.value === rawDefault)\n      ? (rawDefault as string | number)\n      : undefined;\n\n  return { name, values, default: def };\n}\nfunction extractModel(name: string, schema: SchemaObject, schemas?: Record<string, SchemaObject>): Model {\n  if (schema.allOf) {\n    return extractAllOfModel(name, schema, schemas);\n  }\n\n  const requiredSet = new Set(schema.required ?? []);\n  const fields: Field[] = [];\n\n  for (const [fieldName, fieldSchema] of Object.entries(schema.properties ?? {})) {\n    if (!fieldSchema) continue;\n    fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n  }\n\n  // Pure oneOf/anyOf schemas (no allOf, no properties): merge variant fields\n  // as optional. This handles schemas like UpdateOrganizationMembership which\n  // is a oneOf with mutually exclusive field groups (role_slug vs role_slugs).\n  if (fields.length === 0 && (schema.oneOf || schema.anyOf)) {\n    const variants = schema.oneOf ?? schema.anyOf ?? [];\n    const emptyRequired = new Set<string>();\n    const seenFieldNames = new Set<string>();\n    for (const variant of variants) {\n      if (!variant.properties) continue;\n      for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n        if (!fieldSchema || seenFieldNames.has(fieldName)) continue;\n        seenFieldNames.add(fieldName);\n        fields.push(buildFieldFromSchema(fieldName, fieldSchema as SchemaObject, name, emptyRequired));\n      }\n    }\n  }\n\n  // When additionalProperties is an object schema alongside properties,\n  // surface it as a catch-all map field so emitters can generate Map<string, T>.\n  if (schema.additionalProperties && typeof schema.additionalProperties === 'object' && schema.properties) {\n    const apKeys = Object.keys(schema.additionalProperties);\n    if (apKeys.length > 0) {\n      const valueType = schemaToTypeRef(schema.additionalProperties as SchemaObject, 'additionalProperties', name);\n      fields.push({\n        name: 'additionalProperties',\n        type: { kind: 'map', valueType },\n        required: false,\n        description: 'Additional properties not captured by named fields',\n      });\n    }\n  }\n\n  return { name, description: schema.description, fields };\n}\n\nfunction extractAllOfModel(name: string, schema: SchemaObject, schemas?: Record<string, SchemaObject>): Model {\n  const fields: Field[] = [];\n  const requiredSet = new Set<string>();\n  let resultDiscriminator: { property: string; mapping: Record<string, string> } | undefined;\n\n  for (const subSchema of schema.allOf ?? []) {\n    // Resolve $ref sub-schemas by looking up the referenced component schema\n    let resolved = subSchema;\n    if (subSchema.$ref && schemas) {\n      const segments = subSchema.$ref.split('/');\n      const refName = segments[segments.length - 1];\n      if (refName && schemas[refName]) {\n        resolved = schemas[refName];\n      }\n    }\n\n    // If the resolved schema is itself an allOf, recursively extract its fields\n    if (resolved.allOf) {\n      const nested = extractAllOfModel(name, resolved, schemas);\n      for (const f of nested.fields) {\n        fields.push({ ...f, required: false }); // will be re-set below\n        if (f.required) requiredSet.add(f.name);\n      }\n    } else if (resolved.oneOf || resolved.anyOf) {\n      const variants = resolved.oneOf ?? resolved.anyOf ?? [];\n      // Detect discriminated union: every variant pins the same property to a\n      // distinct const value (e.g. EventSchema where each variant has event: const).\n      // When detected, store the discriminator instead of flattening variant fields —\n      // the base allOf schema already captures the common fields.\n      const discriminatorInfo = detectAllOfVariantDiscriminator(variants, name);\n      if (discriminatorInfo) {\n        resultDiscriminator = discriminatorInfo;\n      } else {\n        // Flatten oneOf/anyOf variant fields into the parent model as optional\n        // fields. This handles the common allOf + oneOf pattern where the spec\n        // uses mutually exclusive variant groups (e.g. password vs password_hash).\n        const emptyRequired = new Set<string>();\n        const seenFieldNames = new Set(fields.map((f) => f.name));\n        for (const variant of variants) {\n          if (!variant.properties) continue;\n          for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n            if (!fieldSchema || seenFieldNames.has(fieldName)) continue;\n            seenFieldNames.add(fieldName);\n            fields.push(buildFieldFromSchema(fieldName, fieldSchema as SchemaObject, name, emptyRequired));\n          }\n        }\n        // Do NOT add variant-level required to the requiredSet — these fields\n        // are optional at the parent level because they come from mutually\n        // exclusive branches.\n      }\n    } else {\n      if (resolved.required) {\n        for (const r of resolved.required) requiredSet.add(r);\n      }\n      if (resolved.properties) {\n        // Use an empty requiredSet — required flags are set in the final pass below\n        const emptyRequired = new Set<string>();\n        for (const [fieldName, fieldSchema] of Object.entries(resolved.properties)) {\n          if (!fieldSchema) continue;\n          fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, emptyRequired));\n        }\n      }\n    }\n  }\n\n  // Also collect required from the outer schema\n  if (schema.required) {\n    for (const r of schema.required) requiredSet.add(r);\n  }\n\n  // Set required flags\n  for (const f of fields) {\n    f.required = requiredSet.has(f.name);\n  }\n\n  return {\n    name,\n    description: schema.description,\n    fields,\n    ...(resultDiscriminator ? { discriminator: resultDiscriminator } : {}),\n  };\n}\n\n/**\n * Walk through `allOf` wrappers to collect the effective top-level properties\n * of a schema. Stops at `oneOf` / `anyOf` boundaries — those are different\n * variant axes, not part of the same flat object.\n *\n * Used by `detectAllOfVariantDiscriminator` and `deriveDiscriminatedVariantName`\n * so a oneOf variant of the form `{ allOf: [{ properties: { … } }, { oneOf: […] }] }`\n * still surfaces its top-level `properties` (in particular its discriminator\n * `const`) instead of being treated as having none.\n */\nfunction getEffectiveProperties(schema: SchemaObject): Record<string, SchemaObject> {\n  const props: Record<string, SchemaObject> = {};\n  const visit = (s: SchemaObject): void => {\n    if (s.properties) {\n      for (const [k, v] of Object.entries(s.properties)) {\n        if (!(k in props) && v) props[k] = v;\n      }\n    }\n    if (s.allOf) {\n      for (const sub of s.allOf) visit(sub);\n    }\n    // Do NOT walk into oneOf / anyOf — those are alternatives, not\n    // simultaneously-present properties.\n  };\n  visit(schema);\n  return props;\n}\n\nfunction getEffectiveConstPropertyValue(schema: SchemaObject, property: string): string | null {\n  const direct = getConstPropertyValue(schema, property);\n  if (direct !== null) return direct;\n  const effective = getEffectiveProperties(schema)[property];\n  if (!effective) return null;\n  if (typeof effective.const === 'string') return effective.const;\n  if (Array.isArray(effective.enum) && effective.enum.length === 1 && typeof effective.enum[0] === 'string') {\n    return effective.enum[0];\n  }\n  return null;\n}\n\n/**\n * Detect an implicit discriminator on an allOf+oneOf where every variant is an\n * object that pins the same property to a distinct const value. Unlike\n * detectConstPropertyDiscriminator (which requires $ref or title for variant\n * model names), this version derives model names from the const value itself\n * using deriveDiscriminatedVariantName — matching how extractDiscriminatedAllOfVariantModels\n * names those models.\n *\n * Walks through allOf wrappers on each variant so a oneOf branch like\n *   { allOf: [{ properties: { type: { const: 'oauth' } } }, { oneOf: […] }] }\n * still surfaces `type` as a candidate discriminator.\n *\n * Returns null when no discriminator can be reliably detected.\n */\nfunction detectAllOfVariantDiscriminator(\n  variants: SchemaObject[],\n  fallbackName: string,\n): { property: string; mapping: Record<string, string> } | null {\n  if (variants.length < 2) return null;\n\n  // Find a property whose const value is present on every variant\n  // (looking through allOf wrappers on each variant).\n  const firstProps = getEffectiveProperties(variants[0] ?? {});\n  let candidateProperty: string | null = null;\n  for (const propName of Object.keys(firstProps)) {\n    if (variants.every((v) => getEffectiveConstPropertyValue(v, propName) !== null)) {\n      candidateProperty = propName;\n      break;\n    }\n  }\n  if (!candidateProperty) return null;\n\n  const mapping: Record<string, string> = {};\n  const seenModelNames = new Set<string>();\n  for (const v of variants) {\n    const value = getEffectiveConstPropertyValue(v, candidateProperty);\n    if (value === null) return null;\n    const modelName = deriveDiscriminatedVariantName(v, fallbackName);\n    // If two variants map to the same model name, the discriminator is ambiguous\n    if (seenModelNames.has(modelName)) return null;\n    seenModelNames.add(modelName);\n    mapping[value] = modelName;\n  }\n\n  return { property: candidateProperty, mapping };\n}\n\nfunction extractDiscriminatedAllOfVariantModels(schema: SchemaObject, fallbackName: string): Model[] {\n  const models: Model[] = [];\n  const seenNames = new Set<string>();\n\n  // Collect base-object properties + required from the allOf wrapper so each\n  // variant can be emitted as a complete, self-contained type. Schemas like\n  // `EventSchema` repeat the base fields inside every variant in the spec\n  // (so this merge is a no-op there), but `ConnectApplication`'s OAuth /\n  // M2M variants don't — without this, dispatcher consumers would get a\n  // variant that's missing the shared `id` / `name` / `object` etc.\n  const baseProperties: Record<string, SchemaObject> = {};\n  const baseRequired = new Set<string>();\n  for (const subSchema of schema.allOf ?? []) {\n    if (subSchema.oneOf) continue; // the variant axis, handled below\n    const flat = subSchema.allOf ? flattenVariantForExtraction(subSchema) : subSchema;\n    if (flat.properties) {\n      for (const [k, v] of Object.entries(flat.properties)) {\n        if (!(k in baseProperties) && v) baseProperties[k] = v;\n      }\n    }\n    if (flat.required) for (const r of flat.required) baseRequired.add(r);\n  }\n\n  for (const subSchema of schema.allOf ?? []) {\n    for (const variant of subSchema.oneOf ?? []) {\n      // Flatten any allOf wrapper on the variant (e.g. `ConnectApplication`'s\n      // OAuth branch is `allOf: [{ properties: {…} }, { oneOf: [first-party\n      // sub-variants] }]`). The flattened object has merged properties and\n      // an inlined sub-variant `oneOf` so `extractInlineModelDeep` can pull\n      // out a complete variant model.\n      const flat = flattenVariantForExtraction(variant);\n      if (!flat.properties || (flat.type !== undefined && flat.type !== 'object')) continue;\n\n      // Merge base fields into the variant. Variant-specific properties win\n      // on name collisions because the spec may pin a base field to a more\n      // specific shape inside a variant.\n      const mergedProperties: Record<string, SchemaObject> = { ...baseProperties };\n      for (const [k, v] of Object.entries(flat.properties)) {\n        if (v) mergedProperties[k] = v;\n      }\n      const mergedRequired = new Set<string>([...baseRequired, ...(flat.required ?? [])]);\n      const merged: SchemaObject = {\n        type: 'object',\n        properties: mergedProperties,\n        required: [...mergedRequired],\n      };\n\n      const variantName = deriveDiscriminatedVariantName(variant, fallbackName);\n      for (const model of extractInlineModelDeep(variantName, merged)) {\n        if (seenNames.has(model.name)) continue;\n        seenNames.add(model.name);\n        models.push(model);\n      }\n    }\n  }\n\n  return models;\n}\n\n/**\n * Flatten a oneOf variant schema into a single object-shaped schema for\n * variant-model extraction. Recursively merges `allOf` members and folds\n * any nested `oneOf` into an inline-oneOf field group whose properties are\n * the union across sub-branches (required only when present in every\n * sub-branch). Returns the schema unchanged when no flattening is needed.\n */\nfunction flattenVariantForExtraction(variant: SchemaObject): SchemaObject {\n  if (!variant.allOf) return variant;\n\n  const mergedProperties: Record<string, SchemaObject> = {};\n  const mergedRequired = new Set<string>();\n  const nestedOneOfs: SchemaObject[][] = [];\n\n  const collect = (s: SchemaObject): void => {\n    if (s.properties) {\n      for (const [k, v] of Object.entries(s.properties)) {\n        if (!(k in mergedProperties) && v) mergedProperties[k] = v;\n      }\n    }\n    if (s.required) {\n      for (const r of s.required) mergedRequired.add(r);\n    }\n    if (s.allOf) {\n      for (const sub of s.allOf) collect(sub);\n    }\n    if (s.oneOf) nestedOneOfs.push(s.oneOf);\n  };\n  collect(variant);\n\n  // Fold each nested oneOf into the merged shape: any field appearing in any\n  // sub-branch is included as optional (or required iff present-and-required\n  // in every sub-branch). Conflicting literal types widen to their primitive\n  // base. This handles the `is_first_party: true | false` widening on the\n  // OAuth variant's first-party sub-oneOf.\n  for (const branches of nestedOneOfs) {\n    const flatBranches = branches.map(flattenVariantForExtraction);\n    const branchKeys = new Set<string>();\n    for (const b of flatBranches) {\n      for (const k of Object.keys(b.properties ?? {})) branchKeys.add(k);\n    }\n    for (const key of branchKeys) {\n      const schemas: SchemaObject[] = [];\n      for (const b of flatBranches) {\n        const s = b.properties?.[key];\n        if (s) schemas.push(s);\n      }\n      const merged = mergeBranchPropertySchemas(schemas);\n      if (!(key in mergedProperties)) mergedProperties[key] = merged;\n      const inAllBranches = flatBranches.every((b) => b.properties && key in b.properties);\n      const requiredInAll = inAllBranches && flatBranches.every((b) => (b.required ?? []).includes(key));\n      if (requiredInAll) mergedRequired.add(key);\n    }\n  }\n\n  return {\n    type: 'object',\n    properties: mergedProperties,\n    required: [...mergedRequired],\n  };\n}\n\n/**\n * Merge same-named property schemas from across sub-variants. If every\n * occurrence is a boolean const, widen to plain boolean; if every occurrence\n * is a distinct string const, widen to plain string. Otherwise return the\n * first occurrence — emitters that build their own widened types (e.g. the\n * Node discriminated-models module) re-derive from the raw spec.\n */\nfunction mergeBranchPropertySchemas(schemas: SchemaObject[]): SchemaObject {\n  if (schemas.length === 0) return {};\n  if (schemas.length === 1) return schemas[0];\n\n  const allBoolConst = schemas.every((s) => s.type === 'boolean' && typeof s.const === 'boolean');\n  if (allBoolConst) {\n    return { type: 'boolean', description: schemas[0].description };\n  }\n  const allStringConst = schemas.every((s) => s.type === 'string' && typeof s.const === 'string');\n  if (allStringConst) {\n    const values = schemas.map((s) => s.const as string);\n    if (new Set(values).size === 1) return schemas[0];\n    return { type: 'string', description: schemas[0].description };\n  }\n  return schemas[0];\n}\n\nfunction deriveDiscriminatedVariantName(schema: SchemaObject, fallbackName: string): string {\n  // Walk through allOf wrappers so a variant of the form\n  // `{ allOf: [{ properties: { type: const: 'oauth' } }, { oneOf: […] }] }`\n  // still surfaces its discriminator const value for naming.\n  const effective = getEffectiveProperties(schema);\n  if (Object.keys(effective).length === 0) return fallbackName;\n\n  const pickConst = (name: string): string | null => {\n    const field = effective[name];\n    if (!field) return null;\n    if (typeof field.const === 'string') return field.const;\n    if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n      return field.enum[0];\n    }\n    return null;\n  };\n\n  let constValue: string | null = null;\n  for (const preferred of ['event', 'type', 'object']) {\n    constValue = pickConst(preferred);\n    if (constValue) break;\n  }\n  if (constValue === null) {\n    for (const name of Object.keys(effective)) {\n      constValue = pickConst(name);\n      if (constValue) break;\n    }\n  }\n  if (constValue === null) return fallbackName;\n\n  const pascal = toPascalCase(constValue);\n  if (!pascal) return fallbackName;\n\n  // A single-word const like `oauth` or `m2m` is too generic to stand alone\n  // as a top-level model name — it would collide with unrelated schemas. Pair\n  // it with the parent name so the variant resolves to e.g. `ConnectApplicationOAuth`\n  // / `ConnectApplicationM2M`. Multi-word consts like `action.authentication.denied`\n  // are already specific enough on their own, matching the established\n  // EventSchema variant naming.\n  const wordCount = splitWords(constValue).length;\n  if (wordCount >= 2) return pascal;\n  if (pascal === fallbackName) return pascal;\n  if (fallbackName.startsWith(pascal)) return fallbackName;\n  if (pascal.endsWith(fallbackName)) return pascal;\n  return `${fallbackName}${pascal}`;\n}\n\nfunction extractInlineModelDeep(name: string, schema: SchemaObject): Model[] {\n  const requiredSet = new Set(schema.required ?? []);\n  const fields: Field[] = [];\n  const properties = schema.properties ?? {};\n  const nestedModels: Model[] = [];\n\n  for (const [fieldName, fieldSchema] of Object.entries(properties)) {\n    if (!fieldSchema) continue;\n    fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n\n    if (fieldSchema.type === 'object' && fieldSchema.properties) {\n      nestedModels.push(...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), fieldSchema));\n    }\n\n    if (fieldSchema.type === 'array' && fieldSchema.items?.properties) {\n      nestedModels.push(...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), fieldSchema.items));\n    }\n\n    if (fieldSchema.allOf) {\n      const mergedProperties: Record<string, SchemaObject | undefined> = {};\n      const mergedRequired: string[] = [];\n      for (const sub of fieldSchema.allOf) {\n        if (sub.properties) Object.assign(mergedProperties, sub.properties);\n        if (sub.required) mergedRequired.push(...sub.required);\n      }\n      if (Object.keys(mergedProperties).length > 0) {\n        nestedModels.push(\n          ...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), {\n            type: 'object',\n            properties: mergedProperties,\n            required: mergedRequired,\n          }),\n        );\n      }\n    }\n\n    if (fieldSchema.oneOf) {\n      const inlineObjectVariants = fieldSchema.oneOf.filter(\n        (v) => !v.$ref && v.properties && (v.type === 'object' || !v.type),\n      );\n      if (inlineObjectVariants.length > 0) {\n        const baseQualified = qualifyNestedInlineName(name, fieldName);\n        const namingDisc = deriveConstNamingDiscriminator(inlineObjectVariants);\n        const emitted: Model[] = [];\n        for (const variant of inlineObjectVariants) {\n          const variantName = nameVariantModel(variant, baseQualified, emitted, namingDisc);\n          emitted.push({ name: variantName, fields: [] });\n          nestedModels.push(...extractInlineModelDeep(variantName, variant));\n        }\n      }\n    }\n  }\n\n  return [{ name, description: schema.description, fields }, ...nestedModels];\n}\n\nfunction qualifyNestedInlineName(parentName: string, fieldName: string): string {\n  const pascalField = toPascalCase(fieldName);\n  if (pascalField.startsWith(parentName)) return pascalField;\n\n  const cleanParent = stripListItemMarkers(parentName);\n  const qualified = `${cleanParent}${pascalField}`;\n  const match = qualified.match(/^(.+?)([A-Z][a-z]+s?)$/);\n  if (match && match[2]) {\n    return match[1] + singularize(match[2]);\n  }\n  return qualified;\n}\n\nexport function schemaToTypeRef(schema: SchemaObject, contextName?: string, parentModelName?: string): TypeRef {\n  // Handle $ref → ModelRef or EnumRef.\n  // A `$ref` to a top-level component schema needs to preserve whether the\n  // target is a model or an enum, because emitters route imports differently\n  // for the two kinds (e.g. com.example.models.X vs com.example.types.X). The\n  // set of enum names is precomputed by extractSchemas() in a first pass so\n  // it's available even when called recursively for nested $refs.\n  if (schema.$ref) {\n    const segments = schema.$ref.split('/');\n    const rawName = segments[segments.length - 1];\n    const resolved = resolveSchemaName(rawName);\n    if (activeEnumSchemaNames.has(resolved)) {\n      return { kind: 'enum', name: resolved };\n    }\n    return { kind: 'model', name: resolved };\n  }\n\n  // Handle OAS 3.1 nullable type arrays: type: [string, null]\n  if (Array.isArray(schema.type)) {\n    const nonNullTypes = schema.type.filter((t: string) => t !== 'null');\n    // type: ['null'] — only null, no real type\n    if (nonNullTypes.length === 0) {\n      return { kind: 'nullable', inner: { kind: 'primitive', type: 'unknown' } };\n    }\n    if (schema.type.includes('null') && nonNullTypes.length === 1) {\n      return {\n        kind: 'nullable',\n        inner: schemaToTypeRef({ ...schema, type: nonNullTypes[0], nullable: false }, contextName),\n      };\n    }\n    // Multiple non-null types → union\n    if (nonNullTypes.length > 1) {\n      const variants = nonNullTypes.map((t: string) => schemaToTypeRef({ ...schema, type: t }, contextName));\n      const ref: TypeRef = { kind: 'union', variants };\n      if (schema.type.includes('null')) {\n        return { kind: 'nullable', inner: ref };\n      }\n      return ref;\n    }\n  }\n\n  // Handle OAS 3.0 nullable flag\n  if (schema.nullable && schema.type) {\n    return {\n      kind: 'nullable',\n      inner: schemaToTypeRef({ ...schema, nullable: false }, contextName),\n    };\n  }\n\n  // Handle allOf — merge properties from all sub-schemas.\n  // This handles patterns like: allOf: [{ type: object, properties: {...} }, { oneOf: [...] }]\n  // which are valid OAS 3.1 but weren't handled for field-level schemas.\n  if (schema.allOf) {\n    // If allOf contains a $ref, prefer the ref (it's a named type)\n    const refItem = schema.allOf.find((s: SchemaObject) => s.$ref);\n    if (refItem) {\n      // If allOf has $ref AND siblings with properties, return a merged model ref\n      // to avoid losing the augmentation properties\n      const hasAugmentation = schema.allOf.some((s: SchemaObject) => !s.$ref && (s.properties || s.type === 'object'));\n      if (hasAugmentation) {\n        const baseName = toPascalCase(contextName ?? 'UnknownModel');\n        return { kind: 'model', name: qualifyInlineModelName(baseName, parentModelName) };\n      }\n      return schemaToTypeRef(refItem, contextName, parentModelName);\n    }\n    // If allOf has a single item, unwrap it\n    if (schema.allOf.length === 1) {\n      return schemaToTypeRef(schema.allOf[0], contextName, parentModelName);\n    }\n    // If allOf items all have properties, treat as a merged model\n    const hasProperties = schema.allOf.some((s: SchemaObject) => s.properties);\n    if (hasProperties) {\n      const baseName = toPascalCase(contextName ?? 'UnknownModel');\n      return {\n        kind: 'model',\n        name: qualifyInlineModelName(baseName, parentModelName),\n      };\n    }\n    // Fall through to other checks\n  }\n\n  // Handle oneOf / anyOf → Union or Nullable\n  // Valid OAS 3.1: properties can have { oneOf: [{ type: object }, { type: 'null' }] }\n  // without a wrapping `type` field.\n  if (schema.oneOf || schema.anyOf) {\n    const compositionKind: 'oneOf' | 'anyOf' = schema.oneOf ? 'oneOf' : 'anyOf';\n    const rawVariants: SchemaObject[] = schema.oneOf ?? schema.anyOf ?? [];\n\n    // Check for nullable pattern: oneOf: [realType, { type: 'null' }]\n    const nullVariant = rawVariants.find(\n      (v: SchemaObject) => v.type === 'null' || (Array.isArray(v.type) && v.type.length === 1 && v.type[0] === 'null'),\n    );\n    const nonNullVariants = rawVariants.filter((v) => v !== nullVariant);\n\n    if (nullVariant && nonNullVariants.length === 1) {\n      // Nullable single type — unwrap as nullable\n      return {\n        kind: 'nullable',\n        inner: schemaToTypeRef(nonNullVariants[0], contextName, parentModelName),\n      };\n    }\n\n    // Collapse an oneOf/anyOf whose non-null variants are all string-const\n    // schemas into a single enum. This turns patterns like\n    //   provider: { oneOf: [{ const: \"AppleOAuth\" }, { const: \"GitHubOAuth\" }, ...] }\n    // into a proper enum type with one member per variant instead of a\n    // structurally-opaque union of literal refs.\n    const literalStrings = collectLiteralStringConsts(nonNullVariants);\n    if (literalStrings !== null && literalStrings.length >= 2) {\n      const enumRef = buildSyntheticEnumRef(literalStrings, contextName, parentModelName);\n      return nullVariant ? { kind: 'nullable', inner: enumRef } : enumRef;\n    }\n\n    // Resolve the discriminator. Three sources, in order:\n    //   1. Explicit `discriminator:` with explicit `mapping:` — trust the spec.\n    //   2. Explicit `discriminator:` with no `mapping:` — derive mapping from\n    //      variants' const values on the discriminator property, pairing each\n    //      to its inline-extracted variant model name (built the same way\n    //      `extractNestedSchema` names them via `nameVariantModel`). This\n    //      covers `ApiKey.owner`-shaped schemas where the spec uses\n    //      `discriminator: { propertyName: type }` but lists inline anonymous\n    //      `oneOf` variants instead of `$ref` links.\n    //   3. No explicit discriminator but every variant pins the same const-\n    //      valued property AND the variants are nameable via $ref/title —\n    //      `detectConstPropertyDiscriminator` covers this.\n    //   4. As a last resort, when (3) doesn't apply because variants are\n    //      inline anonymous objects, derive the same const → variant-model-\n    //      name mapping using `nameVariantModel`. This covers\n    //      `ApiKeyCreatedData.owner`-shaped schemas (oneOf with inline\n    //      const-discriminating variants but no `discriminator:` keyword).\n    let resolvedDiscriminator: { property: string; mapping: Record<string, string> } | undefined;\n    if (schema.discriminator) {\n      const property = schema.discriminator.propertyName;\n      const explicitMapping = schema.discriminator.mapping ?? {};\n      let mapping: Record<string, string> = Object.fromEntries(\n        Object.entries(explicitMapping).map(([k, v]) => [k, v.replace(/^#\\/components\\/schemas\\//, '')]),\n      );\n      if (Object.keys(mapping).length === 0) {\n        const inlineMapping = deriveInlineVariantMapping(nonNullVariants, property, contextName, parentModelName);\n        if (inlineMapping) mapping = inlineMapping;\n      }\n      resolvedDiscriminator = { property, mapping };\n    } else if (compositionKind === 'oneOf') {\n      const synthetic = detectConstPropertyDiscriminator(nonNullVariants);\n      if (synthetic) {\n        resolvedDiscriminator = synthetic;\n      } else {\n        const namingDisc = deriveConstNamingDiscriminator(nonNullVariants);\n        if (namingDisc) {\n          const inlineMapping = deriveInlineVariantMapping(\n            nonNullVariants,\n            namingDisc.property,\n            contextName,\n            parentModelName,\n          );\n          if (inlineMapping) {\n            resolvedDiscriminator = { property: namingDisc.property, mapping: inlineMapping };\n          }\n        }\n      }\n    }\n\n    // Build variants. When we have a discriminator with a known mapping and\n    // every non-null variant is an inline object that pins the discriminator\n    // property to a const, route each variant's TypeRef through that mapping.\n    // This avoids the degenerate case where `qualifyInlineModelName` would\n    // assign the same parent-derived name (e.g. `ApiKeyOwner`) to every\n    // inline variant, collapsing the union to a single repeated model ref.\n    const variants: TypeRef[] = [];\n    for (const v of rawVariants) {\n      if (v === nullVariant) continue;\n      const inlineMappingName =\n        resolvedDiscriminator && !v.$ref && v.properties && (v.type === 'object' || !v.type)\n          ? mapVariantToDiscriminatorEntry(v, resolvedDiscriminator)\n          : null;\n      if (inlineMappingName) {\n        variants.push({ kind: 'model', name: inlineMappingName });\n      } else {\n        variants.push(schemaToTypeRef(v, contextName, parentModelName));\n      }\n    }\n    const hasNull = !!nullVariant;\n\n    const union: TypeRef = {\n      kind: 'union',\n      variants,\n      compositionKind,\n      ...(resolvedDiscriminator ? { discriminator: resolvedDiscriminator } : {}),\n    };\n    return hasNull ? { kind: 'nullable', inner: union } : union;\n  }\n\n  // Handle const → LiteralType (supports string, number, boolean)\n  if (schema.const !== undefined) {\n    if (typeof schema.const === 'string' || typeof schema.const === 'number' || typeof schema.const === 'boolean') {\n      return { kind: 'literal', value: schema.const };\n    }\n    // null const → nullable unknown\n    if (schema.const === null) {\n      return { kind: 'nullable', inner: { kind: 'primitive', type: 'unknown' } };\n    }\n    // const of object/array → map or array with unknown values\n    if (typeof schema.const === 'object') {\n      if (Array.isArray(schema.const)) {\n        return { kind: 'array', items: { kind: 'primitive', type: 'unknown' } };\n      }\n      return { kind: 'map', valueType: { kind: 'primitive', type: 'unknown' } };\n    }\n  }\n  if (schema.enum && schema.enum.length === 1) {\n    const v = schema.enum[0];\n    return { kind: 'literal', value: typeof v === 'number' ? v : String(v) };\n  }\n\n  // Handle enum\n  if (schema.enum) {\n    const baseName = toPascalCase(contextName ?? 'UnknownEnum');\n    // Strip ListItem/ByExternalId markers from parent name so enum names are clean:\n    // e.g., DirectoryListItem + State → Directory + State = DirectoryState\n    const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : undefined;\n    // Avoid redundant prefix: Connection + ConnectionType → ConnectionType\n    const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;\n    // Run `schemaNameTransform` so project-level rename maps in\n    // `oagen.config.ts` reach inline parameter/field enums too — without\n    // this, `RadarAction` (built from path param `action` on the Radar\n    // service) couldn't be redirected to `RadarListAction` from config.\n    const finalName = activeSchemaNameTransform ? activeSchemaNameTransform(qualifiedName) : qualifiedName;\n    return {\n      kind: 'enum',\n      name: finalName,\n      values: schema.enum.map((v) => (typeof v === 'number' ? v : String(v))),\n    };\n  }\n\n  // Handle array — pass parentModelName through to qualify inline items\n  if (schema.type === 'array' && schema.items) {\n    return {\n      kind: 'array',\n      items: schemaToTypeRef(schema.items, contextName, parentModelName),\n    };\n  }\n  // Handle array without explicit type but with items (valid OAS 3.1)\n  if (!schema.type && schema.items) {\n    return {\n      kind: 'array',\n      items: schemaToTypeRef(schema.items, contextName, parentModelName),\n    };\n  }\n\n  // Handle object → ModelRef (if it has properties, it's a named model reference)\n  // When additionalProperties is also present, we still return a ModelRef so the\n  // named properties are preserved. The extractModel path will pick up the extra\n  // properties as a catch-all map field named `additionalProperties`.\n  if (schema.type === 'object' && schema.properties) {\n    const baseName = toPascalCase(contextName ?? 'UnknownModel');\n    return {\n      kind: 'model',\n      name: qualifyInlineModelName(baseName, parentModelName),\n    };\n  }\n\n  // Handle freeform object with additionalProperties or patternProperties → Map<string, T>\n  if (schema.type === 'object' && !schema.properties) {\n    let valueType: TypeRef = { kind: 'primitive', type: 'unknown' };\n    if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {\n      // Empty additionalProperties ({}) means \"any value\" — keep as unknown\n      const apKeys = Object.keys(schema.additionalProperties);\n      if (apKeys.length > 0) {\n        valueType = schemaToTypeRef(schema.additionalProperties as SchemaObject, contextName);\n      }\n    } else if (schema.patternProperties) {\n      // patternProperties: { \"pattern\": schema } → use the first pattern's schema as value type\n      const patterns = Object.values(schema.patternProperties);\n      if (patterns.length > 0) {\n        valueType = schemaToTypeRef(patterns[0], contextName);\n      }\n    }\n    return {\n      kind: 'map',\n      valueType,\n    };\n  }\n\n  // Handle primitives\n  const primitiveMap: Record<string, 'string' | 'integer' | 'number' | 'boolean'> = {\n    string: 'string',\n    integer: 'integer',\n    number: 'number',\n    boolean: 'boolean',\n  };\n\n  const typeStr = Array.isArray(schema.type) ? schema.type[0] : schema.type;\n  if (typeStr && primitiveMap[typeStr]) {\n    return {\n      kind: 'primitive',\n      type: primitiveMap[typeStr],\n      ...(schema.format ? { format: schema.format } : {}),\n    };\n  }\n\n  // Handle schemas with no type — if it has properties, treat as model\n  if (!schema.type && schema.properties) {\n    const baseName = toPascalCase(contextName ?? 'UnknownModel');\n    return {\n      kind: 'model',\n      name: qualifyInlineModelName(baseName, parentModelName),\n    };\n  }\n\n  // Empty schema {} → unknown\n  if (\n    !schema.type &&\n    !schema.$ref &&\n    !schema.oneOf &&\n    !schema.anyOf &&\n    !schema.allOf &&\n    !schema.enum &&\n    !schema.properties &&\n    !schema.items\n  ) {\n    return { kind: 'primitive', type: 'unknown' };\n  }\n\n  // Fallback: treat unknown schemas as unknown\n  if (contextName) {\n    console.warn(`[oagen] Warning: Unknown schema shape treated as unknown (context: ${contextName})`);\n  }\n  return { kind: 'primitive', type: 'unknown' };\n}\n\nimport { qualifyInlineModelName } from './inline-models.js';\n\nexport { qualifyInlineModelName, extractInlineModelsFromSchemas } from './inline-models.js';\n","import type { TypeRef, Parameter, PaginationMeta } from '../ir/types.js';\n\nconst CURSOR_PARAMS = ['cursor', 'after', 'before', 'starting_after', 'ending_before', 'page_token', 'next_token'];\n\nconst OFFSET_PARAMS = ['offset', 'page', 'page_number', 'skip'];\nconst LIMIT_PARAMS = ['limit', 'page_size', 'per_page', 'size', 'count'];\n\n/**\n * Detect if an operation uses pagination and return structured metadata\n * for auto-paging iterator generation.\n *\n * Supports two strategies:\n * 1. **Cursor-based**: query params include a cursor-like parameter\n * 2. **Offset-based**: query params include both an offset-like and limit-like parameter\n *\n * Returns null if no pagination pattern is detected.\n */\nexport function detectPagination(\n  response: TypeRef,\n  queryParams: Parameter[],\n  dataPath?: string,\n): PaginationMeta | null {\n  // Try cursor-based first (preferred). Scan in CURSOR_PARAMS priority order\n  // rather than queryParams order so that an endpoint exposing both `before`\n  // and `after` reports `after` (forward iteration) — matches the wire\n  // convention where `after` advances through pages.\n  const cursorParam = CURSOR_PARAMS.map((name) => queryParams.find((p) => p.name === name)).find(\n    (p): p is Parameter => p !== undefined,\n  );\n\n  if (cursorParam) {\n    const itemType: TypeRef = response.kind === 'array' ? response.items : response;\n    return {\n      strategy: 'cursor',\n      param: cursorParam.name,\n      dataPath: dataPath,\n      itemType,\n    };\n  }\n\n  // Try offset-based pagination\n  const offsetParam = queryParams.find((p) => OFFSET_PARAMS.includes(p.name));\n  const limitParam = queryParams.find((p) => LIMIT_PARAMS.includes(p.name));\n\n  if (offsetParam && limitParam) {\n    const itemType: TypeRef = response.kind === 'array' ? response.items : response;\n    return {\n      strategy: 'offset',\n      param: offsetParam.name,\n      limitParam: limitParam.name,\n      dataPath: dataPath,\n      itemType,\n    };\n  }\n\n  return null;\n}\n","import type { TypeRef, Model, Field } from '../ir/types.js';\nimport { toPascalCase, singularize, stripListItemMarkers } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { schemaToTypeRef, buildFieldFromSchema } from './schemas.js';\n\nexport interface ResponseExtractionResult {\n  /** The TypeRef to use as the operation's response type */\n  response: TypeRef;\n  /** Any inline models discovered during extraction (to merge into ir.models) */\n  inlineModels: Model[];\n  /** Whether this response indicates a paginated list */\n  isPaginated: boolean;\n  /** Path to the data array within the response envelope (e.g., 'data') */\n  dataPath?: string;\n  /** TypeRef of individual items in a paginated list */\n  itemType?: TypeRef;\n}\n\nexport function classifyAndExtractResponse(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n  // 1. If schema is a $ref, resolve to model name (Phase 1)\n  if (schema.$ref) {\n    return { response: schemaToTypeRef(schema, contextName), inlineModels: [], isPaginated: false };\n  }\n\n  // 2. Check for list envelope (structural detection: array prop + non-array companion)\n  const envelope = detectListEnvelope(schema);\n  if (envelope.isEnvelope) {\n    return extractListResponse(schema, contextName, envelope.dataPath!);\n  }\n\n  // 3. Check for single-resource wrapper ({ resource_name: { object: \"...\", ... } })\n  if (isSingleResourceWrapper(schema)) {\n    return extractWrappedResource(schema, contextName);\n  }\n\n  // 4. Direct resource or plain inline object\n  return extractDirectResource(schema, contextName);\n}\n\ninterface ListEnvelopeResult {\n  isEnvelope: boolean;\n  dataPath: string | null;\n}\n\nconst KNOWN_DATA_PATHS = new Set(['data', 'items', 'results', 'records', 'entries', 'values', 'nodes', 'edges']);\n\nconst PAGINATION_METADATA_PATTERNS = [\n  'meta',\n  'metadata',\n  'pagination',\n  'cursor',\n  'has_more',\n  'page_info',\n  'total',\n  'next_page',\n  'previous_page',\n  'offset',\n];\n\nfunction detectListEnvelope(schema: SchemaObject): ListEnvelopeResult {\n  // Collect all property sources (allOf sub-schemas or flat schema)\n  const propSources: Record<string, SchemaObject | undefined>[] = [];\n  if (schema.allOf) {\n    for (const sub of schema.allOf) {\n      if (sub.properties) propSources.push(sub.properties);\n    }\n  }\n  if (schema.properties) {\n    propSources.push(schema.properties);\n  }\n\n  if (propSources.length === 0) return { isEnvelope: false, dataPath: null };\n\n  // Merge all properties into a single view\n  const mergedProps: Record<string, SchemaObject | undefined> = {};\n  for (const source of propSources) {\n    Object.assign(mergedProps, source);\n  }\n\n  // Find array-typed properties and non-array companion properties\n  const arrayProps: string[] = [];\n  const nonArrayKeys: string[] = [];\n\n  for (const [key, propSchema] of Object.entries(mergedProps)) {\n    if (!propSchema) continue;\n    if (propSchema.type === 'array') {\n      arrayProps.push(key);\n    } else {\n      nonArrayKeys.push(key);\n    }\n  }\n\n  // List envelope heuristic: exactly one array property + at least one non-array companion\n  // that looks like pagination metadata.  A `data` array alone (e.g. with only an\n  // `object` discriminant companion) is NOT sufficient — the companion must indicate\n  // actual pagination (cursor, metadata, total, etc.).\n  if (arrayProps.length === 1 && nonArrayKeys.length >= 1) {\n    const arrayPropName = arrayProps[0];\n\n    const hasPaginationCompanion = nonArrayKeys.some((key) =>\n      PAGINATION_METADATA_PATTERNS.some((pattern) => key.toLowerCase().includes(pattern)),\n    );\n\n    if (KNOWN_DATA_PATHS.has(arrayPropName) && hasPaginationCompanion) {\n      return { isEnvelope: true, dataPath: arrayPropName };\n    }\n\n    // Non-standard array property name — still treat as envelope if pagination companion exists\n    if (hasPaginationCompanion) {\n      return { isEnvelope: true, dataPath: arrayPropName };\n    }\n  }\n\n  return { isEnvelope: false, dataPath: null };\n}\n\nfunction extractListResponse(schema: SchemaObject, contextName: string, dataPath: string): ResponseExtractionResult {\n  let itemTypeRef: TypeRef = { kind: 'primitive', type: 'string' };\n  const inlineModels: Model[] = [];\n\n  // Collect all property sources (allOf sub-schemas or flat schema)\n  const propSources: Record<string, SchemaObject | undefined>[] = [];\n  if (schema.allOf) {\n    for (const sub of schema.allOf) {\n      if (sub.properties) propSources.push(sub.properties);\n    }\n  }\n  if (schema.properties) {\n    propSources.push(schema.properties);\n  }\n\n  for (const props of propSources) {\n    const dataProp = props[dataPath];\n    if (!dataProp) continue;\n\n    if (dataProp.type === 'array' && dataProp.items) {\n      const items = dataProp.items;\n      if (items.$ref) {\n        itemTypeRef = schemaToTypeRef(items, contextName);\n      } else if (items.type === 'object' && items.properties) {\n        const itemName = contextName.replace(/Response$/, '') + 'Item';\n        itemTypeRef = { kind: 'model', name: itemName };\n        inlineModels.push(...extractInlineModel(itemName, items));\n      }\n    }\n  }\n\n  return {\n    response: { kind: 'array', items: itemTypeRef },\n    inlineModels,\n    isPaginated: true,\n    dataPath,\n    itemType: itemTypeRef,\n  };\n}\n\nfunction hasDiscriminantConstField(schema: SchemaObject): { property: string; value: string } | null {\n  if (!schema.properties) return null;\n\n  // Prefer well-known discriminant properties for backward compatibility\n  const preferred = ['object', 'type'];\n  for (const name of preferred) {\n    const field = schema.properties[name];\n    if (!field) continue;\n    if (field.const !== undefined && typeof field.const === 'string') {\n      return { property: name, value: field.const };\n    }\n    if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n      return { property: name, value: field.enum[0] };\n    }\n  }\n\n  // Fall back to any property with a const or single-value enum\n  for (const [name, field] of Object.entries(schema.properties)) {\n    if (!field) continue;\n    if (field.const !== undefined && typeof field.const === 'string') {\n      return { property: name, value: field.const };\n    }\n    if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n      return { property: name, value: field.enum[0] };\n    }\n  }\n\n  return null;\n}\n\nfunction isSingleResourceWrapper(schema: SchemaObject): boolean {\n  if (schema.type !== 'object') return false;\n  if (!schema.properties) return false;\n\n  // Find the wrapper property: use required[0] if available, or the single property key\n  let wrapperKey: string | undefined;\n  if (schema.required && schema.required.length === 1) {\n    wrapperKey = schema.required[0];\n  } else {\n    const propKeys = Object.keys(schema.properties);\n    if (propKeys.length === 1) {\n      wrapperKey = propKeys[0];\n    }\n  }\n  if (!wrapperKey) return false;\n\n  const propSchema = schema.properties[wrapperKey];\n  if (!propSchema) return false;\n\n  // Direct object with a discriminant const field\n  if (propSchema.type === 'object' && hasDiscriminantConstField(propSchema) !== null) return true;\n\n  // oneOf with object + null (nullable resource)\n  if (propSchema.oneOf) {\n    return propSchema.oneOf.some((v) => v.type === 'object' && hasDiscriminantConstField(v) !== null);\n  }\n\n  return false;\n}\n\nfunction extractWrappedResource(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n  const props = schema.properties!;\n  const wrapperKey = schema.required && schema.required.length === 1 ? schema.required[0] : Object.keys(props)[0];\n  const propSchema = props[wrapperKey]!;\n  const inlineModels: Model[] = [];\n\n  // Derive model name from the object const value or wrapper property name\n  const resourceName = contextName.replace(/Response$/, '');\n\n  if (propSchema.oneOf) {\n    const objectVariant = propSchema.oneOf.find((v) => v.type === 'object' && hasDiscriminantConstField(v) !== null);\n\n    if (objectVariant) {\n      const modelName = deriveModelName(objectVariant, resourceName);\n      inlineModels.push(...extractInlineModel(modelName, objectVariant));\n\n      const hasNullVariant = propSchema.oneOf.some(\n        (v) => v.type === 'null' || (Array.isArray(v.type) && v.type.includes('null')),\n      );\n\n      const modelRef: TypeRef = { kind: 'model', name: modelName };\n      return {\n        response: hasNullVariant ? { kind: 'nullable', inner: modelRef } : modelRef,\n        inlineModels,\n        isPaginated: false,\n      };\n    }\n  }\n\n  // Direct object\n  const modelName = deriveModelName(propSchema, resourceName);\n  inlineModels.push(...extractInlineModel(modelName, propSchema));\n\n  return {\n    response: { kind: 'model', name: modelName },\n    inlineModels,\n    isPaginated: false,\n  };\n}\n\nfunction extractDirectResource(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n  const inlineModels: Model[] = [];\n\n  // Direct object with properties (with or without explicit type: 'object')\n  if (schema.properties && (schema.type === 'object' || !schema.type)) {\n    const modelName = deriveModelName(schema, contextName);\n    inlineModels.push(...extractInlineModel(modelName, schema));\n    return {\n      response: { kind: 'model', name: modelName },\n      inlineModels,\n      isPaginated: false,\n    };\n  }\n\n  // allOf with properties — merge into a single model\n  if (schema.allOf) {\n    const mergedProperties: Record<string, SchemaObject | undefined> = {};\n    const mergedRequired: string[] = [];\n    for (const sub of schema.allOf) {\n      if (sub.properties) {\n        Object.assign(mergedProperties, sub.properties);\n      }\n      if (sub.required) {\n        mergedRequired.push(...sub.required);\n      }\n    }\n    if (Object.keys(mergedProperties).length > 0) {\n      const merged: SchemaObject = { type: 'object', properties: mergedProperties, required: mergedRequired };\n      const modelName = deriveModelName(merged, contextName);\n      inlineModels.push(...extractInlineModel(modelName, merged));\n      return {\n        response: { kind: 'model', name: modelName },\n        inlineModels,\n        isPaginated: false,\n      };\n    }\n  }\n\n  // oneOf — delegate to schemaToTypeRef (returns union) but also extract inline models\n  // from object variants so the model refs resolve\n  if (schema.oneOf) {\n    for (const variant of schema.oneOf) {\n      if (variant.properties && (variant.type === 'object' || !variant.type)) {\n        const modelName = deriveModelName(variant, contextName);\n        const existingNames = new Set(inlineModels.map((m) => m.name));\n        if (!existingNames.has(modelName)) {\n          inlineModels.push(...extractInlineModel(modelName, variant));\n        }\n      }\n    }\n  }\n\n  // Array with inline object items — extract the item model\n  if (schema.type === 'array' && schema.items) {\n    const items = schema.items;\n    if (items.$ref) {\n      return {\n        response: { kind: 'array', items: schemaToTypeRef(items, contextName) },\n        inlineModels,\n        isPaginated: false,\n      };\n    }\n    if (items.properties && (items.type === 'object' || !items.type)) {\n      const itemName = contextName.replace(/Response$/, '') + 'Item';\n      inlineModels.push(...extractInlineModel(itemName, items));\n      return {\n        response: { kind: 'array', items: { kind: 'model', name: itemName } },\n        inlineModels,\n        isPaginated: false,\n      };\n    }\n  }\n\n  // Non-object schema (primitive, union, etc.) — delegate to schemaToTypeRef\n  return {\n    response: schemaToTypeRef(schema, contextName),\n    inlineModels,\n    isPaginated: false,\n  };\n}\n\nfunction deriveModelName(schema: SchemaObject, fallback: string): string {\n  if (!schema.properties) return toPascalCase(fallback);\n\n  // Prefer well-known discriminant properties for backward compatibility\n  const preferred = ['object', 'type'];\n  for (const name of preferred) {\n    const field = schema.properties[name];\n    if (field && field.const && typeof field.const === 'string') {\n      return toPascalCase(field.const);\n    }\n  }\n\n  // Fall back to any property with a const string value\n  for (const [, field] of Object.entries(schema.properties)) {\n    if (field && field.const && typeof field.const === 'string') {\n      return toPascalCase(field.const);\n    }\n  }\n\n  return toPascalCase(fallback);\n}\n\n/**\n * Qualify a nested inline model name with its parent to avoid generic names.\n * e.g., parent=\"Connection\" + field=\"domains\" → \"ConnectionDomain\" (singularized)\n * Only qualifies when the field name alone would be too generic.\n */\nfunction qualifyNestedName(parentName: string, fieldName: string): string {\n  const pascalField = toPascalCase(fieldName);\n  // If the field name already starts with the parent name, don't double-prefix\n  if (pascalField.startsWith(parentName)) return pascalField;\n  // Qualify with parent and singularize:\n  // Connection + Domains → ConnectionDomains → singularize lead word → ConnectionDomain\n  const cleanParent = stripListItemMarkers(parentName);\n  const qualified = `${cleanParent}${pascalField}`;\n  // Singularize the trailing word: ConnectionDomains → ConnectionDomain\n  const match = qualified.match(/^(.+?)([A-Z][a-z]+s?)$/);\n  if (match && match[2]) {\n    const trailing = singularize(match[2]);\n    return match[1] + trailing;\n  }\n  return qualified;\n}\n\nfunction extractInlineModel(name: string, schema: SchemaObject): Model[] {\n  const requiredSet = new Set(schema.required ?? []);\n  const fields: Field[] = [];\n  const properties = schema.properties ?? {};\n  const nestedModels: Model[] = [];\n\n  for (const [fieldName, fieldSchema] of Object.entries(properties)) {\n    if (!fieldSchema) continue;\n    fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n\n    // Recursively extract nested inline objects — qualify with parent name\n    // to avoid generic names like \"Domains\" when multiple parents have a \"domains\" field\n    if (fieldSchema.type === 'object' && fieldSchema.properties) {\n      const nestedName = qualifyNestedName(name, fieldName);\n      nestedModels.push(...extractInlineModel(nestedName, fieldSchema));\n    }\n    if (fieldSchema.type === 'array' && fieldSchema.items) {\n      const items = fieldSchema.items;\n      if (items.type === 'object' && items.properties) {\n        const nestedName = qualifyNestedName(name, fieldName);\n        nestedModels.push(...extractInlineModel(nestedName, items));\n      }\n    }\n    // Handle allOf with inline object properties — merge into a single nested model\n    if (fieldSchema.allOf) {\n      const mergedProperties: Record<string, SchemaObject | undefined> = {};\n      const mergedRequired: string[] = [];\n      for (const sub of fieldSchema.allOf) {\n        if (sub.properties) Object.assign(mergedProperties, sub.properties);\n        if (sub.required) mergedRequired.push(...sub.required);\n      }\n      if (Object.keys(mergedProperties).length > 0) {\n        const nestedName = qualifyNestedName(name, fieldName);\n        const merged: SchemaObject = { type: 'object', properties: mergedProperties, required: mergedRequired };\n        const existingNames = new Set(nestedModels.map((m) => m.name));\n        if (!existingNames.has(nestedName)) {\n          nestedModels.push(...extractInlineModel(nestedName, merged));\n        }\n      }\n    }\n    // Handle oneOf containing inline objects — extract the first non-null object variant\n    if (fieldSchema.oneOf) {\n      const objectVariant = fieldSchema.oneOf.find((v) => v.properties && (v.type === 'object' || !v.type));\n      if (objectVariant) {\n        const nestedName = qualifyNestedName(name, fieldName);\n        const existingNames = new Set(nestedModels.map((m) => m.name));\n        if (!existingNames.has(nestedName)) {\n          nestedModels.push(...extractInlineModel(nestedName, objectVariant));\n        }\n      }\n    }\n  }\n\n  return [{ name, description: schema.description, fields }, ...nestedModels];\n}\n","import type {\n  Service,\n  Operation,\n  HttpMethod,\n  Parameter,\n  ParameterGroup,\n  TypeRef,\n  ErrorResponse,\n  SuccessResponse,\n  SecurityRequirement,\n  Model,\n  Field,\n  PaginationMeta,\n} from '../ir/types.js';\nimport { toPascalCase, toCamelCase, cleanSchemaName } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { schemaToTypeRef, buildFieldFromSchema } from './schemas.js';\nimport { detectPagination } from './pagination.js';\nimport { classifyAndExtractResponse } from './responses.js';\n\ninterface PathItem {\n  get?: OperationObject;\n  post?: OperationObject;\n  put?: OperationObject;\n  patch?: OperationObject;\n  delete?: OperationObject;\n  head?: OperationObject;\n  options?: OperationObject;\n  trace?: OperationObject;\n  parameters?: ParameterObject[];\n}\n\ninterface ParameterGroupExtension {\n  optional: boolean;\n  variants: Record<string, string[]>;\n}\n\ninterface OperationObject {\n  operationId?: string;\n  summary?: string;\n  description?: string;\n  tags?: string[];\n  parameters?: ParameterObject[];\n  requestBody?: RequestBodyObject;\n  responses?: Record<string, ResponseObject>;\n  deprecated?: boolean;\n  'x-oagen-async'?: boolean;\n  security?: Array<Record<string, string[]>>;\n  'x-mutually-exclusive-parameter-groups'?: Record<string, ParameterGroupExtension>;\n  'x-mutually-exclusive-body-groups'?: Record<string, ParameterGroupExtension>;\n}\n\ninterface ParameterObject {\n  name: string;\n  in: 'path' | 'query' | 'header' | 'cookie';\n  required?: boolean;\n  description?: string;\n  schema?: SchemaObject;\n  deprecated?: boolean;\n  example?: unknown;\n  style?: string;\n  explode?: boolean;\n}\n\ninterface RequestBodyObject {\n  required?: boolean;\n  content?: Record<string, { schema?: SchemaObject }>;\n}\n\ninterface ResponseObject {\n  description?: string;\n  content?: Record<string, { schema?: SchemaObject }>;\n}\n\nconst HTTP_METHODS: HttpMethod[] = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'];\n\nexport interface OperationExtractionResult {\n  services: Service[];\n  inlineModels: Model[];\n}\n\nexport function extractOperations(\n  paths: Record<string, PathItem> | undefined,\n  operationIdTransform?: (id: string) => string,\n  componentSchemas?: Record<string, SchemaObject>,\n): OperationExtractionResult {\n  if (!paths) return { services: [], inlineModels: [] };\n\n  const serviceMap = new Map<string, Operation[]>();\n  const inlineModels: Model[] = [];\n\n  for (const [path, pathItem] of Object.entries(paths)) {\n    const pathLevelParams = pathItem.parameters ?? [];\n\n    for (const method of HTTP_METHODS) {\n      const op = pathItem[method];\n      if (!op) continue;\n\n      const serviceName = inferServiceName(path, op.tags?.[0]);\n\n      const { operation, inlineModels: opModels } = buildOperation(\n        method,\n        path,\n        op,\n        pathLevelParams,\n        operationIdTransform,\n        serviceName,\n        componentSchemas,\n      );\n      inlineModels.push(...opModels);\n      const ops = serviceMap.get(serviceName) ?? [];\n      ops.push(operation);\n      serviceMap.set(serviceName, ops);\n    }\n  }\n\n  // Split services when a single tag groups operations from multiple path prefixes.\n  // Example: /organizations and /organization_domains both tagged \"organizations\"\n  // should become separate services based on their first path segment.\n  for (const [serviceName, operations] of serviceMap) {\n    const pathGroups = new Map<string, Operation[]>();\n    for (const op of operations) {\n      const firstSeg = op.path.split('/').filter(Boolean)[0] ?? '';\n      const groupKey = firstSeg.startsWith('{') ? serviceName : toPascalCase(firstSeg);\n      const group = pathGroups.get(groupKey) ?? [];\n      group.push(op);\n      pathGroups.set(groupKey, group);\n    }\n    // Only split if there are multiple distinct path-prefix groups AND\n    // at least one group name differs from the current service name\n    if (pathGroups.size > 1) {\n      const needsSplit = [...pathGroups.keys()].some((k) => k !== serviceName);\n      if (needsSplit) {\n        serviceMap.delete(serviceName);\n        for (const [groupName, groupOps] of pathGroups) {\n          const existing = serviceMap.get(groupName) ?? [];\n          existing.push(...groupOps);\n          serviceMap.set(groupName, existing);\n        }\n      }\n    }\n  }\n\n  // Disambiguate operation names within each service.\n  // Multiple operations can get the same name (e.g., several \"list\" endpoints\n  // in UserManagement for users, invitations, auth factors, etc.).\n  for (const [, operations] of serviceMap) {\n    disambiguateOperationNames(operations);\n  }\n\n  const services = Array.from(serviceMap.entries()).map(([name, operations]) => ({\n    name,\n    operations,\n  }));\n\n  return { services, inlineModels };\n}\n\nfunction inferServiceName(path: string, tag?: string): string {\n  // Prefer OpenAPI tag when available — tags represent the logical grouping\n  // (e.g., \"multi-factor-auth\" for /auth/factors/* endpoints).\n  if (tag) {\n    return toPascalCase(tag);\n  }\n  // Fallback: extract first meaningful path segment: /widgets/{id}/sub → \"Widgets\"\n  const segments = path.split('/').filter(Boolean);\n  const first = segments[0] ?? 'Default';\n  // Skip path params\n  if (first.startsWith('{')) return 'Default';\n  return toPascalCase(first);\n}\n\n/**\n * Strip overload indices (e.g. NestJS emits `Foo_bar[0]` when a controller\n * method handles multiple routes) from an operationId so derived names never\n * leak the bracketed digit. Without this, `authenticate[0]` would surface as\n * `authenticate0` in method names and `Authenticate0Request` in body model\n * names. Brackets at the end (or with trailing whitespace) are common in\n * NestJS-style backends; this regex is intentionally narrow to avoid eating\n * legitimate digits like `oauth2`.\n */\nfunction normalizeOperationIdForNaming(operationId: string): string {\n  return operationId.replace(/\\[\\d+\\]\\s*$/, '');\n}\n\nfunction inferOperationName(\n  method: HttpMethod,\n  path: string,\n  operationId?: string,\n  operationIdTransform?: (id: string) => string,\n): string {\n  if (operationId) {\n    const normalized = normalizeOperationIdForNaming(operationId);\n    if (operationIdTransform) {\n      return operationIdTransform(normalized);\n    }\n    return toCamelCase(normalized);\n  }\n\n  // Fallback when no operationId is available — use method + path to build\n  // a descriptive name like \"listUsers\", \"getOrganization\", \"deleteAuthFactor\"\n  const verb = inferVerb(method, path);\n  const resource = inferResourceFromPath(path);\n  return resource ? toCamelCase(`${verb}_${resource}`) : verb;\n}\n\n/**\n * Infer the CRUD verb from HTTP method and path shape.\n */\nfunction inferVerb(method: HttpMethod, path: string): string {\n  const segments = path.split('/').filter(Boolean);\n  const hasTrailingParam = segments.length > 0 && segments[segments.length - 1].startsWith('{');\n\n  switch (method) {\n    case 'get':\n      return hasTrailingParam ? 'get' : 'list';\n    case 'post':\n      return 'create';\n    case 'put':\n    case 'patch':\n      return 'update';\n    case 'delete':\n      return 'delete';\n    case 'head':\n      return 'check';\n    case 'options':\n      return 'options';\n    case 'trace':\n      return 'trace';\n    default:\n      return method;\n  }\n}\n\n/**\n * Extract a resource noun from the path for operation naming.\n * Uses the last non-param segment (the resource being operated on).\n *\n * Examples:\n *   /accounts/users → \"Users\"\n *   /accounts/users/{id} → \"User\" (singular for item operations)\n *   /accounts/users/{id}/auth_factors → \"AuthFactors\"\n *   /organizations/{id}/api_keys → \"ApiKeys\"\n *   /auth/authorize → \"Authorize\" (action endpoint)\n */\nfunction inferResourceFromPath(path: string): string | null {\n  const segments = path.split('/').filter(Boolean);\n  if (segments.length <= 1) return null;\n\n  // Find the last meaningful (non-param) segment\n  let resourceSegment: string | null = null;\n  for (let i = segments.length - 1; i >= 0; i--) {\n    if (!segments[i].startsWith('{')) {\n      resourceSegment = segments[i];\n      break;\n    }\n  }\n\n  if (!resourceSegment) return null;\n  // Skip the service name (first segment) — it would be redundant\n  if (resourceSegment === segments[0]) return null;\n\n  return toPascalCase(resourceSegment);\n}\n\n/**\n * Detect and resolve name collisions within a service's operations.\n *\n * When multiple operations share the same name (e.g., several \"list\" from\n * different sub-resources), disambiguate by appending the resource noun\n * from the path. Only renames operations on DIFFERENT paths — same-name\n * operations on the same path (e.g., PUT + PATCH both \"update\") are left as-is\n * since they represent the same logical resource.\n */\nfunction disambiguateOperationNames(operations: Operation[]): void {\n  // Group by name\n  const byName = new Map<string, Operation[]>();\n  for (const op of operations) {\n    const group = byName.get(op.name) ?? [];\n    group.push(op);\n    byName.set(op.name, group);\n  }\n\n  for (const [name, group] of byName) {\n    if (group.length <= 1) continue;\n\n    // Check if these are genuinely different resources (different paths)\n    // vs the same resource with different methods (PUT + PATCH)\n    const uniquePaths = new Set(group.map((op) => op.path));\n    if (uniquePaths.size <= 1) continue; // same path, different methods — no disambiguation needed\n\n    for (const op of group) {\n      const resource = inferResourceFromPath(op.path);\n      if (resource) {\n        const newName = toCamelCase(`${name}_${resource}`);\n        (op as { name: string }).name = newName;\n      }\n    }\n\n    // If disambiguation still left collisions (same sub-resource),\n    // use the full distinguishing path segment chain\n    const renamed = new Map<string, Operation[]>();\n    for (const op of group) {\n      const rGroup = renamed.get(op.name) ?? [];\n      rGroup.push(op);\n      renamed.set(op.name, rGroup);\n    }\n    for (const [, rGroup] of renamed) {\n      if (rGroup.length <= 1) continue;\n      // Still colliding — different paths map to same resource name.\n      // Use deeper path context to disambiguate.\n      for (const op of rGroup) {\n        const deeper = inferDeeperContext(op.path);\n        if (deeper) {\n          (op as { name: string }).name = toCamelCase(`${op.name}_${deeper}`);\n        }\n      }\n    }\n  }\n}\n\n/**\n * Extract a deeper disambiguation context from the path when the last\n * segment isn't unique enough. Uses the second-to-last non-param segment.\n *\n * /users/{id}/auth_factors → already captured as \"AuthFactors\"\n * /users/external_id/{external_id} → \"ExternalId\" (special path, not a sub-resource)\n */\nfunction inferDeeperContext(path: string): string | null {\n  const segments = path.split('/').filter(Boolean);\n  const nonParams = segments.filter((s) => !s.startsWith('{'));\n  // Skip first (service) and last (already used) — use the middle ones\n  if (nonParams.length >= 3) {\n    return toPascalCase(nonParams.slice(1, -1).join('_'));\n  }\n  return null;\n}\n\n/**\n * Extract mutually-exclusive parameter groups from the `x-mutually-exclusive-parameter-groups`\n * operation extension. Cross-references grouped parameter names against the already-extracted\n * IR parameter arrays so emitters get object-identity references.\n */\nfunction extractParameterGroups(\n  op: OperationObject,\n  allIRParams: Parameter[],\n  operationContext: string,\n): ParameterGroup[] | undefined {\n  const raw = op['x-mutually-exclusive-parameter-groups'];\n  if (!raw || typeof raw !== 'object') return undefined;\n\n  const paramByName = new Map<string, Parameter>();\n  for (const p of allIRParams) {\n    paramByName.set(p.name, p);\n  }\n\n  const groups: ParameterGroup[] = [];\n\n  for (const [groupName, groupDef] of Object.entries(raw)) {\n    if (!groupDef || typeof groupDef !== 'object') {\n      throw new Error(\n        `Malformed x-mutually-exclusive-parameter-groups.${groupName} in ${operationContext}: expected an object with \"optional\" and \"variants\".`,\n      );\n    }\n\n    if (typeof groupDef.optional !== 'boolean') {\n      throw new Error(\n        `Malformed x-mutually-exclusive-parameter-groups.${groupName}.optional in ${operationContext}: expected a boolean.`,\n      );\n    }\n\n    if (!groupDef.variants || typeof groupDef.variants !== 'object') {\n      throw new Error(\n        `Malformed x-mutually-exclusive-parameter-groups.${groupName}.variants in ${operationContext}: expected an object mapping variant names to parameter name arrays.`,\n      );\n    }\n\n    if (Object.keys(groupDef.variants).length === 0) {\n      throw new Error(\n        `Malformed x-mutually-exclusive-parameter-groups.${groupName} in ${operationContext}: group has zero variants.`,\n      );\n    }\n\n    const variants = Object.entries(groupDef.variants).map(([variantName, paramNames]) => {\n      if (!Array.isArray(paramNames) || paramNames.length === 0) {\n        throw new Error(\n          `Malformed x-mutually-exclusive-parameter-groups.${groupName}.variants.${variantName} in ${operationContext}: expected a non-empty array of parameter names.`,\n        );\n      }\n      const parameters: Parameter[] = paramNames.map((pName) => {\n        const irParam = paramByName.get(pName);\n        if (!irParam) {\n          throw new Error(\n            `x-mutually-exclusive-parameter-groups.${groupName}.variants.${variantName} references parameter \"${pName}\" which does not exist in the operation's parameters[] (${operationContext}).`,\n          );\n        }\n        return irParam;\n      });\n      return { name: variantName, parameters };\n    });\n\n    groups.push({\n      name: groupName,\n      optional: groupDef.optional,\n      variants,\n    });\n  }\n\n  return groups.length > 0 ? groups : undefined;\n}\n\n/**\n * Extract mutually-exclusive body parameter groups from the\n * `x-mutually-exclusive-body-groups` operation extension. Unlike query\n * parameter groups (whose parameters live in operation.queryParams), body\n * group parameters are synthetic — built from the oneOf variant schemas in\n * the request body. Emitters use the group's presence to generate sum-type\n * interfaces and custom JSON marshalling instead of flat optional fields.\n */\nfunction extractBodyParameterGroups(op: OperationObject, operationContext: string): ParameterGroup[] | undefined {\n  const raw = op['x-mutually-exclusive-body-groups'];\n  if (!raw || typeof raw !== 'object') return undefined;\n\n  // Collect the body schema's oneOf variant fields so we can resolve types.\n  // The body schema has been structurally rewritten to allOf: [base, { oneOf: [...] }]\n  // by the spec generator; the variant properties live inside oneOf branches.\n  const bodySchema = op.requestBody?.content?.['application/json']?.schema;\n  const variantFieldSchemas = new Map<string, SchemaObject>();\n\n  if (bodySchema) {\n    // Walk allOf → oneOf → variant.properties to find all variant fields\n    for (const sub of bodySchema.allOf ?? []) {\n      for (const variant of sub.oneOf ?? []) {\n        if (variant.properties) {\n          for (const [name, fieldSchema] of Object.entries(variant.properties)) {\n            if (fieldSchema) variantFieldSchemas.set(name, fieldSchema);\n          }\n        }\n      }\n    }\n    // Also check top-level oneOf (for inline schemas that aren't wrapped in allOf)\n    for (const variant of bodySchema.oneOf ?? []) {\n      if (variant.properties) {\n        for (const [name, fieldSchema] of Object.entries(variant.properties)) {\n          if (fieldSchema) variantFieldSchemas.set(name, fieldSchema);\n        }\n      }\n    }\n  }\n\n  const groups: ParameterGroup[] = [];\n\n  for (const [groupName, groupDef] of Object.entries(raw)) {\n    if (!groupDef || typeof groupDef !== 'object') continue;\n    if (typeof groupDef.optional !== 'boolean') continue;\n    if (!groupDef.variants || typeof groupDef.variants !== 'object') continue;\n    if (Object.keys(groupDef.variants).length === 0) continue;\n\n    const variants = Object.entries(groupDef.variants).map(([variantName, paramNames]) => {\n      if (!Array.isArray(paramNames) || paramNames.length === 0) {\n        throw new Error(\n          `Malformed x-mutually-exclusive-body-groups.${groupName}.variants.${variantName} in ${operationContext}: expected a non-empty array of parameter names.`,\n        );\n      }\n      const parameters: Parameter[] = paramNames.map((pName) => {\n        const fieldSchema = variantFieldSchemas.get(pName);\n        const fieldType: TypeRef = fieldSchema\n          ? schemaToTypeRef(fieldSchema, toPascalCase(pName))\n          : { kind: 'primitive', type: 'string' };\n        return {\n          name: pName,\n          type: fieldType,\n          required: false, // group variant fields are always optional at the struct level\n          description: fieldSchema?.description,\n        };\n      });\n      return { name: variantName, parameters };\n    });\n\n    groups.push({\n      name: groupName,\n      optional: groupDef.optional,\n      variants,\n    });\n  }\n\n  return groups.length > 0 ? groups : undefined;\n}\n\nfunction buildOperation(\n  method: HttpMethod,\n  path: string,\n  op: OperationObject,\n  pathLevelParams: ParameterObject[],\n  operationIdTransform?: (id: string) => string,\n  serviceName?: string,\n  componentSchemas?: Record<string, SchemaObject>,\n): { operation: Operation; inlineModels: Model[] } {\n  const allParams = [...pathLevelParams, ...(op.parameters ?? [])];\n\n  const hasIdempotencyHeader = allParams.some((p) => p.in === 'header' && p.name.toLowerCase() === 'idempotency-key');\n\n  // Use the service name as context so inline parameter enums get qualified\n  // names. e.g., service \"Auth\" + param \"provider\" → \"AuthProvider\".\n  const opContext = serviceName;\n  const pathParams = extractParams(allParams, 'path', opContext, componentSchemas);\n  const queryParams = extractParams(allParams, 'query', opContext, componentSchemas);\n  const headerParams = extractParams(allParams, 'header', opContext, componentSchemas).filter(\n    (p) => p.name.toLowerCase() !== 'idempotency-key',\n  );\n  const cookieParams = extractParams(allParams, 'cookie', opContext, componentSchemas);\n\n  const reqBodyModels: Model[] = [];\n  const { body: requestBody, encoding: requestBodyEncoding } = extractRequestBody(op.requestBody, op, reqBodyModels);\n  const {\n    response,\n    successResponses,\n    errors,\n    inlineModels,\n    isPaginated,\n    dataPath: responseDataPath,\n    itemType: responseItemType,\n  } = extractResponses(op.responses, op, path, method);\n  inlineModels.push(...reqBodyModels);\n\n  // Build structured pagination metadata from response classification and query param detection\n  const paginationFromParams = detectPagination(response, queryParams, responseDataPath);\n  let pagination: PaginationMeta | undefined;\n  if (isPaginated) {\n    const itemType = responseItemType ?? (response.kind === 'array' ? response.items : response);\n    pagination = {\n      strategy: paginationFromParams?.strategy ?? 'cursor',\n      param: paginationFromParams?.param ?? 'after',\n      limitParam: paginationFromParams?.limitParam,\n      dataPath: responseDataPath ?? paginationFromParams?.dataPath,\n      itemType,\n    };\n  } else if (paginationFromParams) {\n    pagination = paginationFromParams;\n  }\n\n  // Extract per-operation security overrides\n  const security = extractOperationSecurity(op.security);\n\n  // Extract mutually-exclusive parameter groups (query/path/header/cookie)\n  const allIRParams = [...pathParams, ...queryParams, ...headerParams, ...cookieParams];\n  const opLabel = op.operationId ?? `${method.toUpperCase()} ${path}`;\n  const queryParamGroups = extractParameterGroups(op, allIRParams, opLabel);\n\n  // Extract mutually-exclusive body parameter groups\n  const bodyParamGroups = extractBodyParameterGroups(op, opLabel);\n\n  // Merge both sources into a single parameterGroups array\n  const parameterGroups =\n    queryParamGroups || bodyParamGroups ? [...(queryParamGroups ?? []), ...(bodyParamGroups ?? [])] : undefined;\n\n  return {\n    operation: {\n      name: inferOperationName(method, path, op.operationId, operationIdTransform),\n      description: buildDescription(op.summary, op.description),\n      httpMethod: method,\n      path,\n      pathParams,\n      queryParams,\n      headerParams,\n      cookieParams: cookieParams.length > 0 ? cookieParams : undefined,\n      requestBody,\n      requestBodyEncoding,\n      response,\n      successResponses,\n      errors,\n      pagination,\n      injectIdempotencyKey: hasIdempotencyHeader,\n      deprecated: op.deprecated || undefined,\n      async: op['x-oagen-async'],\n      security,\n      parameterGroups,\n    },\n    inlineModels,\n  };\n}\n\n/**\n * Extract per-operation security requirements from an OpenAPI security directive.\n * Returns undefined when the operation uses the spec-level default security.\n *\n * OpenAPI security format: `security: [{ schemeName: [scope1, scope2] }]`\n */\nfunction extractOperationSecurity(\n  security: Array<Record<string, string[]>> | undefined,\n): SecurityRequirement[] | undefined {\n  if (!security || security.length === 0) return undefined;\n\n  const requirements: SecurityRequirement[] = [];\n  for (const entry of security) {\n    for (const [schemeName, scopes] of Object.entries(entry)) {\n      requirements.push({ schemeName, scopes: scopes ?? [] });\n    }\n  }\n  return requirements.length > 0 ? requirements : undefined;\n}\n\nfunction buildDescription(summary: string | undefined, description: string | undefined): string | undefined {\n  if (summary && description && summary !== description) {\n    return `${summary}\\n\\n${description}`;\n  }\n  return description ?? summary;\n}\n\nfunction extractParams(\n  params: ParameterObject[],\n  location: 'path' | 'query' | 'header' | 'cookie',\n  operationContext?: string,\n  componentSchemas?: Record<string, SchemaObject>,\n): Parameter[] {\n  return params\n    .filter((p) => p.in === location)\n    .map((p) => {\n      const refTarget = resolveParamSchemaRef(p.schema, componentSchemas);\n      return {\n        name: p.name,\n        type: p.schema\n          ? schemaToTypeRef(p.schema, p.name, operationContext ? toPascalCase(operationContext) : undefined)\n          : ({ kind: 'primitive', type: 'string' } as TypeRef),\n        required: p.required ?? false,\n        description: p.description,\n        deprecated: p.deprecated || p.schema?.deprecated || refTarget?.deprecated || undefined,\n        default: p.schema?.default ?? refTarget?.default,\n        example: p.example ?? p.schema?.example ?? refTarget?.example,\n        style: p.style as Parameter['style'],\n        explode: p.explode,\n      };\n    });\n}\n\n/**\n * If a parameter's schema is a `$ref` to `#/components/schemas/X`, return the\n * referenced component schema. Used to surface schema-level metadata (default,\n * example, deprecated) that wouldn't otherwise be visible at the param level.\n *\n * Refs are not pre-resolved by the bundler (`dereference: false` in refs.ts),\n * so without this, a param like `schema: { $ref: '.../PaginationOrder' }`\n * silently loses the target's `default: desc` and the SDK stops emitting the\n * spec-mandated default value in generated method signatures.\n */\nfunction resolveParamSchemaRef(\n  schema: SchemaObject | undefined,\n  componentSchemas: Record<string, SchemaObject> | undefined,\n): SchemaObject | undefined {\n  if (!schema || !componentSchemas) return undefined;\n  const ref = (schema as { $ref?: string }).$ref;\n  if (!ref) return undefined;\n  const match = /^#\\/components\\/schemas\\/(.+)$/.exec(ref);\n  if (!match) return undefined;\n  return componentSchemas[match[1]];\n}\n\nfunction extractRequestBody(\n  body: RequestBodyObject | undefined,\n  op: OperationObject | undefined,\n  inlineModels: Model[],\n): { body?: TypeRef; encoding?: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text' } {\n  if (!body?.content) return {};\n\n  // Detect encoding and find schema from content type in priority order\n  let encoding: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text' = 'json';\n  let schema: SchemaObject | undefined;\n\n  if (body.content['application/json']?.schema) {\n    encoding = 'json';\n    schema = body.content['application/json']!.schema;\n  } else if (body.content['multipart/form-data']?.schema) {\n    encoding = 'form-data';\n    schema = body.content['multipart/form-data']!.schema;\n  } else if (body.content['application/x-www-form-urlencoded']?.schema) {\n    encoding = 'form-urlencoded';\n    schema = body.content['application/x-www-form-urlencoded']!.schema;\n  } else if (body.content['application/octet-stream']) {\n    encoding = 'binary';\n    schema = body.content['application/octet-stream']!.schema;\n  } else if (body.content['text/plain']) {\n    encoding = 'text';\n    schema = body.content['text/plain']!.schema;\n  }\n\n  if (!schema) {\n    // For binary/text, a schema is optional — produce a primitive TypeRef\n    if (encoding === 'binary') {\n      return { body: { kind: 'primitive', type: 'string', format: 'binary' }, encoding };\n    }\n    if (encoding === 'text') {\n      return { body: { kind: 'primitive', type: 'string' }, encoding };\n    }\n    return {};\n  }\n\n  const rawName = op?.operationId\n    ? toPascalCase(normalizeOperationIdForNaming(op.operationId)) + 'Request'\n    : 'RequestBody';\n  const contextName = cleanSchemaName(rawName);\n\n  // If the request body is an inline object with properties, extract it as a model\n  if (schema.properties && (schema.type === 'object' || !schema.type)) {\n    const requiredSet = new Set(schema.required ?? []);\n    const fields: Field[] = [];\n    for (const [fieldName, fieldSchema] of Object.entries(schema.properties)) {\n      if (!fieldSchema) continue;\n      fields.push(buildFieldFromSchema(fieldName, fieldSchema, contextName, requiredSet));\n    }\n    inlineModels.push({ name: contextName, description: undefined, fields });\n    return { body: { kind: 'model', name: contextName }, encoding };\n  }\n\n  // If the request body is a oneOf, extract each variant as an inline model\n  // and build a union type pointing to them by name.\n  if (schema.oneOf) {\n    const variants: TypeRef[] = [];\n\n    for (const variant of schema.oneOf) {\n      if (variant.$ref) {\n        const ref = schemaToTypeRef(variant, contextName);\n        variants.push(ref);\n      } else if (variant.type === 'null') {\n        // skip null variant in union, handle separately\n      } else if (variant.properties && (variant.type === 'object' || !variant.type)) {\n        const variantName = deriveOneOfVariantName(variant, contextName, inlineModels);\n        const requiredSet = new Set(variant.required ?? []);\n        const fields: Field[] = [];\n        for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n          if (!fieldSchema) continue;\n          fields.push(buildFieldFromSchema(fieldName, fieldSchema, variantName, requiredSet));\n        }\n        inlineModels.push({ name: variantName, description: variant.description, fields });\n        variants.push({ kind: 'model', name: variantName });\n      } else {\n        variants.push(schemaToTypeRef(variant, contextName));\n      }\n    }\n\n    const hasNull = schema.oneOf.some(\n      (v: SchemaObject) => v.type === 'null' || (Array.isArray(v.type) && v.type.includes('null')),\n    );\n    const union: TypeRef = {\n      kind: 'union',\n      variants,\n      ...(schema.discriminator\n        ? {\n            discriminator: { property: schema.discriminator.propertyName, mapping: schema.discriminator.mapping ?? {} },\n          }\n        : {}),\n    };\n    const body = hasNull ? ({ kind: 'nullable', inner: union } as TypeRef) : union;\n    return { body, encoding };\n  }\n\n  return { body: schemaToTypeRef(schema, contextName), encoding };\n}\n\n/** Derive a unique variant name for a oneOf inline model. */\nfunction deriveOneOfVariantName(variant: SchemaObject, baseName: string, existingModels: Model[]): string {\n  // Try to use a distinguishing property (e.g., \"grant_type\" field's const/enum value)\n  if (variant.properties) {\n    for (const [, propSchema] of Object.entries(variant.properties)) {\n      if (propSchema?.const && typeof propSchema.const === 'string') {\n        return toPascalCase(propSchema.const) + baseName.replace(/Request$/, '') + 'Request';\n      }\n    }\n  }\n  // Fallback: append a numeric suffix\n  const existingNames = new Set(existingModels.map((m) => m.name));\n  let name = baseName;\n  let suffix = 2;\n  while (existingNames.has(name)) {\n    name = `${baseName}${suffix}`;\n    suffix++;\n  }\n  return name;\n}\n\nfunction deriveResponseName(op: OperationObject | undefined, path: string, method: HttpMethod): string {\n  if (op?.operationId) {\n    return cleanSchemaName(toPascalCase(normalizeOperationIdForNaming(op.operationId)) + 'Response');\n  }\n  const segments = path.split('/').filter(Boolean);\n  const resource = segments[0] ?? 'Unknown';\n  return toPascalCase(resource) + toPascalCase(method) + 'Response';\n}\n\nfunction extractResponses(\n  responses?: Record<string, ResponseObject>,\n  op?: OperationObject,\n  path?: string,\n  method?: HttpMethod,\n): {\n  response: TypeRef;\n  successResponses?: SuccessResponse[];\n  errors: ErrorResponse[];\n  inlineModels: Model[];\n  isPaginated: boolean;\n  dataPath?: string;\n  itemType?: TypeRef;\n} {\n  const errors: ErrorResponse[] = [];\n  let response: TypeRef = { kind: 'primitive', type: 'string' };\n  let inlineModels: Model[] = [];\n  let isPaginated = false;\n  let dataPath: string | undefined;\n  let itemType: TypeRef | undefined;\n\n  if (!responses) return { response, errors, inlineModels, isPaginated };\n\n  const allSuccessResponses: SuccessResponse[] = [];\n\n  for (const [statusCode, resp] of Object.entries(responses)) {\n    const code = parseInt(statusCode, 10);\n\n    if (code >= 200 && code < 300) {\n      let extractedType: TypeRef = { kind: 'primitive', type: 'unknown' };\n      const jsonContent = resp.content?.['application/json'];\n      if (jsonContent?.schema) {\n        const contextName = deriveResponseName(op, path ?? '/', method ?? 'get');\n        const result = classifyAndExtractResponse(jsonContent.schema, contextName);\n        extractedType = result.response;\n        // Keep track of inline models and pagination from the latest 2xx with a schema\n        inlineModels = result.inlineModels;\n        isPaginated = result.isPaginated;\n        dataPath = result.dataPath;\n        itemType = result.itemType;\n      } else if (resp.content) {\n        // Handle non-JSON response content types (text/plain, binary, XML, etc.)\n        if (resp.content['application/octet-stream'] || resp.content['application/pdf']) {\n          extractedType = { kind: 'primitive', type: 'string', format: 'binary' };\n        } else if (\n          resp.content['text/plain'] ||\n          resp.content['text/html'] ||\n          resp.content['text/xml'] ||\n          resp.content['application/xml']\n        ) {\n          extractedType = { kind: 'primitive', type: 'string' };\n        } else {\n          // Try the first available content type's schema\n          const firstKey = Object.keys(resp.content)[0];\n          if (firstKey) {\n            const firstContent = resp.content[firstKey];\n            if (firstContent?.schema) {\n              extractedType = schemaToTypeRef(\n                firstContent.schema,\n                deriveResponseName(op, path ?? '/', method ?? 'get'),\n              );\n            }\n          }\n        }\n      }\n      allSuccessResponses.push({ statusCode: code, type: extractedType });\n    } else if (code >= 300 && code < 400) {\n      // 3xx redirects — include so emitter can detect redirect endpoints\n      allSuccessResponses.push({ statusCode: code, type: { kind: 'primitive', type: 'unknown' } });\n    } else if (code >= 400) {\n      const jsonContent = resp.content?.['application/json'];\n      const type = jsonContent?.schema ? schemaToTypeRef(jsonContent.schema, `Error${code}`) : undefined;\n      errors.push({ statusCode: code, type });\n    }\n  }\n\n  // Primary response = lowest 2xx with a body schema, falling back to first 2xx\n  if (allSuccessResponses.length > 0) {\n    const sorted = [...allSuccessResponses].sort((a, b) => a.statusCode - b.statusCode);\n    const primary =\n      sorted.find((r) => r.type.kind !== 'primitive' || (r.type as { type: string }).type !== 'unknown') ?? sorted[0];\n    response = primary.type;\n  }\n\n  const successResponses = allSuccessResponses.length > 1 ? allSuccessResponses : undefined;\n\n  return { response, successResponses, errors, inlineModels, isPaginated, dataPath, itemType };\n}\n","import type { Model, Service, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\n\nfunction keepLargestByName(models: Model[]): Model[] {\n  const byName = new Map<string, Model>();\n  for (const model of models) {\n    const existing = byName.get(model.name);\n    if (!existing || model.fields.length > existing.fields.length) {\n      byName.set(model.name, model);\n    }\n  }\n  return [...byName.values()];\n}\n\nfunction rewriteModelRef(ref: TypeRef, oldName: string, newName: string): void {\n  walkTypeRef(ref, {\n    model: (r) => {\n      if (r.name === oldName) (r as { name: string }).name = newName;\n    },\n  });\n}\n\nfunction rewriteModelRefs(models: Model[], services: Service[], oldName: string, newName: string): void {\n  for (const model of models) {\n    for (const field of model.fields) {\n      rewriteModelRef(field.type, oldName, newName);\n    }\n  }\n  for (const service of services) {\n    for (const op of service.operations) {\n      rewriteModelRef(op.response, oldName, newName);\n      if (op.requestBody) {\n        rewriteModelRef(op.requestBody, oldName, newName);\n      }\n    }\n  }\n}\n\nexport function mergeInlineResponseModels(schemaModels: Model[], inlineModels: Model[]): Model[] {\n  const mergedSchemaModels = [...schemaModels];\n  const schemaModelNames = new Set(mergedSchemaModels.map((m) => m.name));\n  const schemaModelsByName = new Map(mergedSchemaModels.map((m) => [m.name, m]));\n\n  const deduplicatedInlineModels = inlineModels.filter((model) => {\n    if (!schemaModelNames.has(model.name)) return true;\n\n    const existing = schemaModelsByName.get(model.name)!;\n    const existingFieldNames = new Set(existing.fields.map((f) => f.name));\n    const inlineFieldNames = new Set(model.fields.map((f) => f.name));\n    const hasDifference =\n      model.fields.some((f) => !existingFieldNames.has(f.name)) ||\n      existing.fields.some((f) => !inlineFieldNames.has(f.name));\n\n    if (hasDifference && model.fields.length > existing.fields.length) {\n      const idx = mergedSchemaModels.indexOf(existing);\n      if (idx !== -1) mergedSchemaModels[idx] = model;\n      schemaModelsByName.set(model.name, model);\n      console.warn(\n        `[oagen] Warning: Inline model \"${model.name}\" has more fields than component schema (${model.fields.length} vs ${existing.fields.length}) — using inline response model`,\n      );\n    } else if (hasDifference) {\n      console.warn(\n        `[oagen] Warning: Inline model \"${model.name}\" has different fields than component schema — using component schema`,\n      );\n    }\n\n    return false;\n  });\n\n  return [...mergedSchemaModels, ...keepLargestByName(deduplicatedInlineModels)];\n}\n\nexport function mergeFieldInlineModels(existingModels: Model[], fieldInlineModels: Model[]): Model[] {\n  const modelNames = new Set(existingModels.map((m) => m.name));\n  const modelsByName = new Map(existingModels.map((m) => [m.name, m]));\n\n  const deduplicatedFieldModels = fieldInlineModels.filter((model) => {\n    if (!modelNames.has(model.name)) return true;\n\n    const existing = modelsByName.get(model.name)!;\n    const existingFieldNames = new Set(existing.fields.map((f) => f.name));\n    const inlineFieldNames = new Set(model.fields.map((f) => f.name));\n    const hasDifference =\n      model.fields.some((f) => !existingFieldNames.has(f.name)) ||\n      existing.fields.some((f) => !inlineFieldNames.has(f.name));\n\n    if (hasDifference) {\n      console.warn(\n        `[oagen] Warning: Inline model \"${model.name}\" has different fields than component schema — using component schema`,\n      );\n    }\n\n    return false;\n  });\n\n  return [...existingModels, ...keepLargestByName(deduplicatedFieldModels)];\n}\n\nfunction hasModelConstDiscriminant(model: Model): boolean {\n  return model.fields.some(\n    (f) => (f.name === 'object' || f.name === 'type') && f.type.kind === 'literal' && typeof f.type.value === 'string',\n  );\n}\n\nfunction isModelReferencedByOthers(name: string, models: Model[], excludeNames: Set<string>): boolean {\n  for (const model of models) {\n    if (excludeNames.has(model.name)) continue;\n    for (const field of model.fields) {\n      let found = false;\n      walkTypeRef(field.type, {\n        model: (r) => {\n          if (r.name === name) found = true;\n        },\n      });\n      if (found) return true;\n    }\n  }\n  return false;\n}\n\nexport function collapseJsonSuffixModels(models: Model[], services: Service[]): Model[] {\n  const normalizedModels = [...models];\n  const byName = new Map(normalizedModels.map((m) => [m.name, m]));\n\n  // Pass 1: collect merge candidates\n  const mergeCandidates: Array<{ jsonModel: Model; baseModel: Model }> = [];\n  for (const model of normalizedModels) {\n    if (!model.name.endsWith('Json')) continue;\n\n    const baseName = model.name.slice(0, -4);\n    const baseModel = byName.get(baseName);\n    if (!baseModel || model.fields.length <= baseModel.fields.length) continue;\n\n    const isSuperset = baseModel.fields.every((f) => model.fields.some((mf) => mf.name === f.name));\n    if (!isSuperset) continue;\n\n    // Guard: both models have a const discriminant — they are distinct entities\n    if (hasModelConstDiscriminant(model) && hasModelConstDiscriminant(baseModel)) continue;\n\n    // Guard: a third model explicitly references the Json-suffix model\n    if (isModelReferencedByOthers(model.name, normalizedModels, new Set([model.name, baseName]))) continue;\n\n    mergeCandidates.push({ jsonModel: model, baseModel });\n  }\n\n  // Pass 2: apply merges\n  const toRemove = new Set<string>();\n  for (const { jsonModel, baseModel } of mergeCandidates) {\n    baseModel.fields = jsonModel.fields;\n    toRemove.add(jsonModel.name);\n    rewriteModelRefs(normalizedModels, services, jsonModel.name, baseModel.name);\n    console.warn(\n      `[oagen] Merged \"${jsonModel.name}\" into \"${baseModel.name}\" (${jsonModel.fields.length} fields, superset)`,\n    );\n  }\n\n  // Pass 3: cascade renames to inline children of collapsed Json-suffix models.\n  // e.g. when AuditLogSchemaJson → AuditLogSchema, also rename\n  // AuditLogSchemaJsonTarget → AuditLogSchemaTarget.\n  for (const { jsonModel, baseModel } of mergeCandidates) {\n    const jsonPrefix = jsonModel.name;\n    const basePrefix = baseModel.name;\n\n    for (const model of normalizedModels) {\n      if (toRemove.has(model.name)) continue;\n      if (model.name.length <= jsonPrefix.length) continue;\n      if (!model.name.startsWith(jsonPrefix)) continue;\n\n      const newName = basePrefix + model.name.slice(jsonPrefix.length);\n      const existing = byName.get(newName);\n\n      if (existing && !toRemove.has(existing.name)) {\n        toRemove.add(model.name);\n        rewriteModelRefs(normalizedModels, services, model.name, newName);\n        console.warn(`[oagen] Collapsed child \"${model.name}\" into existing \"${newName}\"`);\n      } else {\n        rewriteModelRefs(normalizedModels, services, model.name, newName);\n        model.name = newName;\n        byName.set(newName, model);\n        console.warn(`[oagen] Renamed child \"${jsonPrefix}…\" → \"${newName}\"`);\n      }\n    }\n  }\n\n  return normalizedModels.filter((m) => !toRemove.has(m.name));\n}\n","import type { Enum, Model, Service } from '../ir/types.js';\nimport { collectInlineEnumFromRef } from './schemas.js';\n\nexport function collectInlineEnumsFromModels(models: Model[], enums: Enum[]): void {\n  const enumNames = new Set(enums.map((e) => e.name));\n  for (const model of models) {\n    for (const field of model.fields) {\n      collectInlineEnumFromRef(field.type, enums, enumNames);\n    }\n  }\n}\n\n/**\n * Collect inline enum definitions from operation parameters (query, path, header)\n * and promote them to top-level enums so emitters can generate typed enum files.\n */\nexport function collectInlineEnumsFromOperations(services: Service[], enums: Enum[]): void {\n  const enumNames = new Set(enums.map((e) => e.name));\n  for (const service of services) {\n    for (const op of service.operations) {\n      for (const param of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n        collectInlineEnumFromRef(param.type, enums, enumNames);\n      }\n    }\n  }\n}\n","import type { ApiSpec, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\n\nexport function validateModelRefs(spec: ApiSpec): void {\n  const knownNames = new Set<string>();\n  for (const m of spec.models) knownNames.add(m.name);\n  for (const e of spec.enums) knownNames.add(e.name);\n\n  function walkRef(ref: TypeRef, context: string): void {\n    walkTypeRef(ref, {\n      model: (r) => {\n        if (!knownNames.has(r.name)) {\n          console.warn(`[oagen] Warning: Unresolved model reference \"${r.name}\" (context: ${context})`);\n        }\n      },\n    });\n  }\n\n  for (const model of spec.models) {\n    for (const field of model.fields) {\n      walkRef(field.type, `${model.name}.${field.name}`);\n    }\n  }\n\n  for (const service of spec.services) {\n    for (const op of service.operations) {\n      for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams]) {\n        walkRef(p.type, `${service.name}.${op.name}.${p.name}`);\n      }\n      if (op.requestBody) walkRef(op.requestBody, `${service.name}.${op.name}.requestBody`);\n      walkRef(op.response, `${service.name}.${op.name}.response`);\n    }\n  }\n}\n","import type { ApiSpec, AuthScheme, ServerEntry } from '../ir/types.js';\nimport { defaultSdkBehavior } from '../ir/sdk-behavior.js';\nimport { SpecParseError } from '../errors.js';\nimport { loadAndBundleSpec } from './refs.js';\nimport { extractSchemas, extractInlineModelsFromSchemas, clearSchemaNameTransform } from './schemas.js';\nimport { extractOperations } from './operations.js';\nimport {\n  mergeInlineResponseModels,\n  collapseJsonSuffixModels,\n  mergeFieldInlineModels,\n} from './normalize-inline-models.js';\nimport { collectInlineEnumsFromModels, collectInlineEnumsFromOperations } from './collect-inline-enums.js';\nimport { validateModelRefs } from './normalize-model-refs.js';\n\n/**\n * A bundled OpenAPI document, post-`$ref` resolution but pre-IR extraction.\n *\n * This is the shape the spec author wrote, with external refs inlined and\n * internal refs left intact. It is intentionally loose (`Record<string,\n * unknown>`) so `transformSpec` can reach arbitrary spec extensions without\n * fighting types — narrow with `as` at use sites.\n */\nexport type OpenApiDocument = Record<string, unknown>;\n\nexport interface ParseOptions {\n  operationIdTransform?: (id: string) => string;\n  schemaNameTransform?: (name: string) => string;\n  /**\n   * Domain-facing field-name overrides, keyed by IR model name then wire field\n   * name: `{ Connection: { connection_type: 'type' } }`. Sets `Field.domainName`\n   * so emitters expose the field under the friendlier name while keeping the\n   * wire key. Language-agnostic — honored by any emitter that reads `domainName`.\n   */\n  fieldHints?: Record<string, Record<string, string>>;\n  /**\n   * Pre-IR overlay applied to the bundled OpenAPI document before any IR\n   * extraction runs. Use this when the upstream spec can't be changed but you\n   * need to patch around a spec quirk that would otherwise emit a breaking SDK\n   * change — e.g. rewriting a path's response `$ref` back to its prior schema,\n   * merging the new fields onto the prior schema, and dropping the fork.\n   *\n   * The function may mutate the document in place and return it, or return a\n   * new object; the returned value is what the rest of oagen sees.\n   *\n   * Runs once, after `$ref` bundling and before schema/operation extraction.\n   * If you need to inspect the resulting IR instead, post-process the\n   * `ApiSpec` returned by `parseSpec`.\n   */\n  transformSpec?: (spec: OpenApiDocument) => OpenApiDocument;\n}\n\nexport async function parseSpec(specPath: string, options?: ParseOptions): Promise<ApiSpec> {\n  const { parsed } = await loadAndBundleSpec(specPath);\n  const transformed = options?.transformSpec ? options.transformSpec(parsed) : parsed;\n\n  const spec = transformed as {\n    openapi?: string;\n    info?: { title?: string; version?: string; description?: string };\n    servers?: Array<{ url?: string; description?: string }>;\n    paths?: Record<string, unknown>;\n    components?: {\n      schemas?: Record<string, unknown>;\n      securitySchemes?: Record<\n        string,\n        { type: string; scheme?: string; in?: string; name?: string; flows?: Record<string, unknown> }\n      >;\n    };\n  };\n\n  // Validate OpenAPI version\n  const version = spec.openapi ?? '';\n  if (!version.startsWith('3.')) {\n    throw new SpecParseError(\n      `Unsupported OpenAPI version: ${version}. oagen requires OpenAPI 3.x`,\n      `Update the spec to OpenAPI 3.0 or 3.1. If you are using Swagger 2.x, convert it first with \\`npx swagger2openapi ${specPath}\\`.`,\n    );\n  }\n\n  const { models, enums } = extractSchemas(\n    spec.components?.schemas as Record<string, Record<string, unknown>> | undefined,\n    { schemaNameTransform: options?.schemaNameTransform },\n  );\n\n  const { services, inlineModels } = extractOperations(\n    spec.paths as Record<string, Record<string, unknown>> | undefined,\n    options?.operationIdTransform,\n    spec.components?.schemas as Record<string, Record<string, unknown>> | undefined,\n  );\n\n  const responseNormalizedModels = mergeInlineResponseModels(models, inlineModels);\n\n  // Extract inline models from model field definitions (objects/arrays with properties).\n  // schemaNameTransform is kept active so inline child names use the\n  // transformed parent name (e.g. AuditLogSchemaJson→AuditLogSchema yields\n  // AuditLogSchemaTarget, not AuditLogSchemaJsonTarget).\n  const fieldInlineModels = extractInlineModelsFromSchemas(\n    spec.components?.schemas as Record<string, Record<string, unknown>> | undefined,\n  );\n  clearSchemaNameTransform();\n  const fieldMergedModels = mergeFieldInlineModels(responseNormalizedModels, fieldInlineModels);\n  const finalModels = collapseJsonSuffixModels(fieldMergedModels, services);\n  applyFieldHints(finalModels, options?.fieldHints);\n  collectInlineEnumsFromModels(finalModels, enums);\n  collectInlineEnumsFromOperations(services, enums);\n\n  const auth = extractAuthSchemes(spec.components?.securitySchemes);\n\n  const serverEntries: ServerEntry[] = (spec.servers ?? [])\n    .map((s) => ({ url: s.url ?? '', description: s.description }))\n    .filter((s) => s.url);\n\n  const result: ApiSpec = {\n    name: spec.info?.title ?? 'Unknown API',\n    version: spec.info?.version ?? '0.0.0',\n    description: spec.info?.description,\n    baseUrl: serverEntries[0]?.url ?? '',\n    servers: serverEntries.length > 0 ? serverEntries : undefined,\n    services,\n    models: finalModels,\n    enums,\n    auth,\n    sdk: defaultSdkBehavior(),\n  };\n\n  validateModelRefs(result);\n\n  return result;\n}\n/**\n * Apply `fieldHints` onto the built models, setting `Field.domainName` for each\n * matching (model name, wire field name) pair. Serialization still uses\n * `Field.name`; only the domain-facing identifier changes.\n */\nfunction applyFieldHints(\n  models: import('../ir/types.js').Model[],\n  fieldHints: Record<string, Record<string, string>> | undefined,\n): void {\n  if (!fieldHints) return;\n  for (const model of models) {\n    const hints = fieldHints[model.name];\n    if (!hints) continue;\n    for (const field of model.fields) {\n      const domainName = hints[field.name];\n      if (domainName) field.domainName = domainName;\n    }\n  }\n}\n\n/** Extract authentication schemes from OpenAPI securitySchemes. */\nfunction extractAuthSchemes(\n  securitySchemes?: Record<\n    string,\n    { type: string; scheme?: string; in?: string; name?: string; flows?: Record<string, unknown> }\n  >,\n): AuthScheme[] | undefined {\n  if (!securitySchemes) return undefined;\n  const schemes: AuthScheme[] = [];\n  for (const [, scheme] of Object.entries(securitySchemes)) {\n    if (scheme.type === 'http' && scheme.scheme === 'bearer') {\n      schemes.push({ kind: 'bearer' });\n    } else if (scheme.type === 'apiKey' && scheme.in && scheme.name) {\n      schemes.push({ kind: 'apiKey', in: scheme.in as 'header' | 'query' | 'cookie', name: scheme.name });\n    } else if (scheme.type === 'oauth2' && scheme.flows) {\n      schemes.push({ kind: 'oauth2', flows: scheme.flows });\n    }\n  }\n  return schemes.length > 0 ? schemes : undefined;\n}\n","import { parseSpec, type OpenApiDocument } from '../parser/parse.js';\n\nexport async function parseCommand(opts: {\n  spec: string;\n  operationIdTransform?: (id: string) => string;\n  schemaNameTransform?: (name: string) => string;\n  transformSpec?: (spec: OpenApiDocument) => OpenApiDocument;\n}): Promise<void> {\n  const ir = await parseSpec(opts.spec, {\n    operationIdTransform: opts.operationIdTransform,\n    schemaNameTransform: opts.schemaNameTransform,\n    transformSpec: opts.transformSpec,\n  });\n  console.log(JSON.stringify(ir, null, 2));\n}\n","import type Parser from 'tree-sitter';\nimport type { UrlFingerprintConfig } from './types.js';\n\n/**\n * Extract a URL path fingerprint from a method body using tree-sitter AST traversal.\n *\n * Walks the AST subtree of the member node looking for the first string literal\n * that starts with '/'. Normalizes interpolation expressions to '{}' and format\n * specifiers (%s, %d, etc.) to '{}' for cross-language comparison.\n *\n * @returns A normalized URL fingerprint like \"/organizations/{}\" or undefined if none found.\n */\nexport function extractUrlFingerprint(memberNode: Parser.SyntaxNode, config: UrlFingerprintConfig): string | undefined {\n  const stringTypes = new Set(config.stringNodeTypes);\n  const contentTypes = new Set(config.contentNodeTypes);\n  const interpolationTypes = new Set(config.interpolationNodeTypes);\n  const formatFns = config.formatFunctionNames ? new Set(config.formatFunctionNames) : null;\n\n  // Iterative DFS through the method's AST subtree\n  const stack: Parser.SyntaxNode[] = [memberNode];\n\n  while (stack.length > 0) {\n    const node = stack.pop()!;\n\n    if (stringTypes.has(node.type)) {\n      const fp = resolveFingerprint(node, contentTypes, interpolationTypes);\n      if (fp?.startsWith('/')) return fp;\n    }\n\n    // For format functions (Go's Sprintf, Rust's format!): check if this call\n    // matches and extract the first string argument.\n    if (formatFns && isFormatCall(node, formatFns)) {\n      const fp = extractFromFormatCall(node, stringTypes, contentTypes, interpolationTypes);\n      if (fp?.startsWith('/')) return fp;\n    }\n\n    // Push children in reverse order so leftmost child is processed first\n    for (let i = node.childCount - 1; i >= 0; i--) {\n      const child = node.child(i);\n      if (child) stack.push(child);\n    }\n  }\n\n  return undefined;\n}\n\n/**\n * Resolve the text content of a string node, normalizing interpolations to '{}'.\n */\nfunction resolveFingerprint(\n  stringNode: Parser.SyntaxNode,\n  contentTypes: Set<string>,\n  interpolationTypes: Set<string>,\n): string | undefined {\n  // Leaf string node (no children besides quotes) — strip quotes\n  if (stringNode.namedChildCount === 0) {\n    return normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n  }\n\n  // Composite string (has content fragments + interpolation children)\n  let result = '';\n  for (let i = 0; i < stringNode.childCount; i++) {\n    const child = stringNode.child(i)!;\n    if (contentTypes.has(child.type)) {\n      result += child.text;\n    } else if (interpolationTypes.has(child.type)) {\n      result += '{}';\n    }\n    // Skip quote delimiters, interpolation markers, etc.\n  }\n\n  return result ? normalizeFormatSpecifiers(result) : normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n}\n\n/** Check if a node is a call to one of the format functions (e.g., fmt.Sprintf, format!). */\nfunction isFormatCall(node: Parser.SyntaxNode, formatFns: Set<string>): boolean {\n  // Rust macro: format!(...) — tree-sitter may parse as macro_invocation\n  if (node.type === 'macro_invocation') {\n    const macroName = node.childForFieldName('macro')?.text;\n    return !!(macroName && formatFns.has(macroName.replace(/!$/, '')));\n  }\n\n  if (node.type !== 'call_expression') return false;\n  const fnNode = node.childForFieldName('function');\n  if (!fnNode) return false;\n\n  // Direct call: Sprintf(...) or format!(...)\n  if (formatFns.has(fnNode.text)) return true;\n\n  // Member call: fmt.Sprintf(...)\n  if (fnNode.type === 'selector_expression' || fnNode.type === 'member_expression') {\n    const prop = fnNode.childForFieldName('field') ?? fnNode.childForFieldName('property');\n    if (prop && formatFns.has(prop.text)) return true;\n  }\n  return false;\n}\n\n/** Extract the first string argument from a format function call. */\nfunction extractFromFormatCall(\n  callNode: Parser.SyntaxNode,\n  stringTypes: Set<string>,\n  contentTypes: Set<string>,\n  interpolationTypes: Set<string>,\n): string | undefined {\n  const args = callNode.childForFieldName('arguments');\n  if (!args) return undefined;\n\n  for (let i = 0; i < args.childCount; i++) {\n    const arg = args.child(i)!;\n    if (stringTypes.has(arg.type)) {\n      return resolveFingerprint(arg, contentTypes, interpolationTypes);\n    }\n  }\n  return undefined;\n}\n\n/** Strip surrounding quote characters from a string literal. */\nfunction stripQuotes(text: string): string {\n  // Handle various quote styles: \"...\", '...', `...`, f\"...\", $\"...\", @\"...\"\n  const match = text.match(/^(?:f|r|b|@|\\$)?(?:\"\"\"([\\s\\S]*)\"\"\"|'''([\\s\\S]*)'''|\"(.*)\"|'(.*)'|`(.*)`)$/s);\n  if (match) return match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? text;\n  return text;\n}\n\n/** Replace printf-style format specifiers (%s, %d, %v, %f) with {}. */\nfunction normalizeFormatSpecifiers(s: string): string {\n  return s.replace(/%[sdvf]/g, '{}');\n}\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst DOTNET_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string_literal', 'interpolated_string_expression'],\n  contentNodeTypes: ['string_content', 'string_literal_content'],\n  interpolationNodeTypes: ['interpolation'],\n};\n\nconst DECLARATION_TYPES = new Set([\n  'class_declaration',\n  'struct_declaration',\n  'interface_declaration',\n  'enum_declaration',\n  'record_declaration',\n]);\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n  if (DECLARATION_TYPES.has(node.type)) {\n    const nameNode = node.childForFieldName('name') ?? node.children.find((c) => c.type === 'identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'namespace_declaration' || node.type === 'file_scoped_namespace_declaration') {\n    const nameNode =\n      node.children.find((c) => c.type === 'qualified_name') ?? node.children.find((c) => c.type === 'identifier');\n    return nameNode ? `__namespace:${nameNode.text}` : null;\n  }\n  return null;\n}\n\nfunction collectPrecedingXmlDocComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('///')) {\n        if (lastIdx === -1) lastIdx = k;\n        firstIdx = k;\n      } else {\n        break;\n      }\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\n/**\n * Collect declarations from a list of sibling nodes (root level or namespace body).\n */\nfunction collectDeclarations(\n  children: Parser.SyntaxNode[],\n  source: string,\n  statements: MergeStatement[],\n  imports: MergeImport[],\n  importAnchors: string[],\n  importInsertionAnchor: { value?: string },\n): void {\n  for (const child of children) {\n    if (child.type === 'comment') continue;\n\n    if (child.type === 'using_directive') {\n      const text = source.slice(child.startIndex, child.endIndex);\n      imports.push({ key: text.trim(), text });\n      importAnchors.push(text);\n      continue;\n    }\n\n    if (child.type === 'file_scoped_namespace_declaration') {\n      importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n      // File-scoped namespace: subsequent declarations are siblings at root\n      continue;\n    }\n\n    if (child.type === 'namespace_declaration') {\n      importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n      // Block namespace: recurse into declaration_list\n      const body = child.children.find((c) => c.type === 'declaration_list');\n      if (body) {\n        collectDeclarations(body.namedChildren, source, statements, imports, importAnchors, importInsertionAnchor);\n      }\n      continue;\n    }\n\n    const name = extractDeclarationName(child);\n    statements.push({\n      key: name,\n      kind: name ? 'declaration' : 'other',\n      text: source.slice(child.startIndex, child.endIndex),\n    });\n  }\n}\n\nexport const dotnetMergeAdapter: MergeAdapter = {\n  language: 'dotnet',\n  grammarModule: 'tree-sitter-c-sharp',\n  testFilePatterns: [/Tests?\\.cs$/],\n  urlFingerprintConfig: DOTNET_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n    const importInsertionAnchor: { value?: string } = {};\n\n    collectDeclarations(tree.rootNode.children, source, statements, imports, importAnchors, importInsertionAnchor);\n\n    return {\n      imports,\n      importAnchors,\n      importInsertionAnchor: importInsertionAnchor.value,\n      statements,\n    };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n\n    function processChildren(children: Parser.SyntaxNode[]): void {\n      for (let i = 0; i < children.length; i++) {\n        const child = children[i];\n\n        // Recurse into namespaces\n        if (child.type === 'namespace_declaration') {\n          const body = child.children.find((c) => c.type === 'declaration_list');\n          if (body) processChildren(body.children);\n          continue;\n        }\n\n        const name = extractDeclarationName(child);\n        if (!name || name.startsWith('__namespace:')) continue;\n\n        const docstring = collectPrecedingXmlDocComments(children, i, source);\n        const members = new Map<string, MemberDocstrings>();\n\n        // Extract member docstrings\n        const body = child.children.find((c) => c.type === 'declaration_list');\n        if (body) {\n          const bodyChildren = body.children;\n          for (let j = 0; j < bodyChildren.length; j++) {\n            const member = bodyChildren[j];\n            if (member.type !== 'method_declaration' && member.type !== 'property_declaration') continue;\n            // For methods, the second identifier is the name (first is return type)\n            const identifiers = member.children.filter((c) => c.type === 'identifier');\n            const memberName =\n              member.type === 'method_declaration'\n                ? identifiers.length >= 2\n                  ? identifiers[1]!.text\n                  : identifiers[0]?.text\n                : identifiers[0]?.text;\n            if (!memberName) continue;\n            const memberDoc = collectPrecedingXmlDocComments(bodyChildren, j, source);\n            members.set(memberName, {\n              docstring: memberDoc,\n              declStartIndex: member.startIndex,\n              declColumn: member.startPosition.column,\n              urlFingerprint: extractUrlFingerprint(member, DOTNET_URL_FINGERPRINT_CONFIG),\n            });\n          }\n        }\n\n        result.set(name, {\n          docstring,\n          declStartIndex: child.startIndex,\n          declColumn: child.startPosition.column,\n          members,\n        });\n      }\n    }\n\n    processChildren(tree.rootNode.children);\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst ELIXIR_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string'],\n  contentNodeTypes: ['quoted_content'],\n  interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isDefmodule(node: Parser.SyntaxNode): boolean {\n  return node.type === 'call' && node.children[0]?.text === 'defmodule';\n}\n\nfunction getModuleName(node: Parser.SyntaxNode): string | null {\n  if (!isDefmodule(node)) return null;\n  const args = node.children.find((c) => c.type === 'arguments');\n  if (!args) return null;\n  const alias = args.children.find((c) => c.type === 'alias');\n  return alias?.text ?? null;\n}\n\nfunction getDoBlock(node: Parser.SyntaxNode): Parser.SyntaxNode | null {\n  return node.children.find((c) => c.type === 'do_block') ?? null;\n}\n\n/** Check if a node is an @moduledoc or @doc attribute. */\nfunction isDocAttribute(node: Parser.SyntaxNode): string | null {\n  if (node.type !== 'unary_operator') return null;\n  const call = node.children.find((c) => c.type === 'call');\n  if (!call) return null;\n  const id = call.children.find((c) => c.type === 'identifier');\n  if (id?.text === 'moduledoc' || id?.text === 'doc') return id.text;\n  return null;\n}\n\n/** Check if a node is a def/defp call. */\nfunction getDefName(node: Parser.SyntaxNode): string | null {\n  if (node.type !== 'call') return null;\n  const id = node.children[0];\n  if (!id || (id.text !== 'def' && id.text !== 'defp')) return null;\n  const args = node.children.find((c) => c.type === 'arguments');\n  if (!args) return null;\n  // The function name is either a simple identifier or a call (for functions with params)\n  for (const arg of args.namedChildren) {\n    if (arg.type === 'identifier') return arg.text;\n    if (arg.type === 'call') {\n      const nameNode = arg.children.find((c) => c.type === 'identifier');\n      return nameNode?.text ?? null;\n    }\n  }\n  return null;\n}\n\n/** Check if a node is an alias/import/require/use call. */\nfunction isImportLike(node: Parser.SyntaxNode): boolean {\n  if (node.type !== 'call') return false;\n  const id = node.children[0];\n  return id?.type === 'identifier' && ['alias', 'import', 'require', 'use'].includes(id.text);\n}\n\nexport const elixirMergeAdapter: MergeAdapter = {\n  language: 'elixir',\n  grammarModule: 'tree-sitter-elixir',\n  testFilePatterns: [/_test\\.exs$/],\n  urlFingerprintConfig: ELIXIR_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      // Top-level alias/import/require/use (rare but possible outside modules)\n      if (isImportLike(child)) {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const moduleName = getModuleName(child);\n      statements.push({\n        key: moduleName,\n        kind: moduleName ? 'declaration' : 'other',\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const moduleName = getModuleName(child);\n      if (!moduleName) continue;\n\n      // Look for @moduledoc inside the do_block\n      let docstring: DocstringInfo | null = null;\n      const doBlock = getDoBlock(child);\n      const members = new Map<string, MemberDocstrings>();\n\n      if (doBlock) {\n        const bodyChildren = doBlock.children;\n\n        // Find @moduledoc\n        for (const bodyChild of bodyChildren) {\n          if (isDocAttribute(bodyChild) === 'moduledoc') {\n            docstring = {\n              text: source.slice(bodyChild.startIndex, bodyChild.endIndex),\n              startIndex: bodyChild.startIndex,\n              endIndex: bodyChild.endIndex,\n            };\n            break;\n          }\n        }\n\n        // Find @doc + def pairs for member docstrings\n        for (let j = 0; j < bodyChildren.length; j++) {\n          const bodyChild = bodyChildren[j];\n          const defName = getDefName(bodyChild);\n          if (!defName) continue;\n\n          // Look for preceding @doc attribute\n          let memberDoc: DocstringInfo | null = null;\n          for (let k = j - 1; k >= 0; k--) {\n            const prev = bodyChildren[k];\n            if (isDocAttribute(prev) === 'doc') {\n              memberDoc = {\n                text: source.slice(prev.startIndex, prev.endIndex),\n                startIndex: prev.startIndex,\n                endIndex: prev.endIndex,\n              };\n              break;\n            }\n            if (prev.type === 'comment') continue;\n            break;\n          }\n\n          members.set(defName, {\n            docstring: memberDoc,\n            declStartIndex: bodyChild.startIndex,\n            declColumn: bodyChild.startPosition.column,\n            urlFingerprint: extractUrlFingerprint(bodyChild, ELIXIR_URL_FINGERPRINT_CONFIG),\n          });\n        }\n      }\n\n      result.set(moduleName, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst GO_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['interpreted_string_literal'],\n  contentNodeTypes: ['interpreted_string_literal_content'],\n  interpolationNodeTypes: [],\n  formatFunctionNames: ['Sprintf'],\n};\n\nfunction lastIdentifier(text: string): string | null {\n  const matches = [...text.matchAll(/[A-Za-z_][A-Za-z0-9_]*/g)];\n  return matches.length > 0 ? matches[matches.length - 1]![0] : null;\n}\n\nfunction receiverKey(node: Parser.SyntaxNode): string | null {\n  const receiver = node.childForFieldName('receiver');\n  if (!receiver) return null;\n  return lastIdentifier(receiver.text);\n}\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n  switch (node.type) {\n    case 'package_clause': {\n      const pkg = lastIdentifier(node.text);\n      return pkg ? `__package:${pkg}` : '__package:';\n    }\n    case 'type_declaration': {\n      const spec = node.firstNamedChild?.type === 'type_spec' ? node.firstNamedChild : node.namedChildren[0];\n      const nameNode = spec?.childForFieldName('name');\n      return nameNode?.text ?? null;\n    }\n    case 'function_declaration': {\n      return node.childForFieldName('name')?.text ?? null;\n    }\n    case 'method_declaration': {\n      const name = node.childForFieldName('name')?.text ?? null;\n      const receiver = receiverKey(node);\n      return name && receiver ? `method:${receiver}.${name}` : name;\n    }\n    case 'const_declaration':\n    case 'var_declaration': {\n      return node.text.split(/\\s+/).slice(0, 3).join(' ');\n    }\n    default:\n      return null;\n  }\n}\n\nfunction importEntries(node: Parser.SyntaxNode, source: string): MergeImport[] {\n  const entries: MergeImport[] = [];\n\n  const collect = (spec: Parser.SyntaxNode): void => {\n    const path = spec.childForFieldName('path')?.text ?? spec.text;\n    const name = spec.childForFieldName('name')?.text ?? '';\n    const text = source.slice(spec.startIndex, spec.endIndex);\n    entries.push({\n      key: `${name}:${path.replace(/^\"|\"$/g, '')}`,\n      text,\n    });\n  };\n\n  for (const child of node.namedChildren) {\n    if (child.type === 'import_spec') {\n      collect(child);\n      continue;\n    }\n    if (child.type === 'import_spec_list') {\n      for (const spec of child.namedChildren) {\n        if (spec.type === 'import_spec') collect(spec);\n      }\n    }\n  }\n\n  return entries;\n}\n\nfunction collectPrecedingGoComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('//')) {\n        if (lastIdx === -1) lastIdx = k;\n        firstIdx = k;\n      } else {\n        break;\n      }\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const goMergeAdapter: MergeAdapter = {\n  language: 'go',\n  grammarModule: 'tree-sitter-go',\n  testFilePatterns: [/_test\\.go$/],\n  urlFingerprintConfig: GO_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    let importInsertionAnchor: string | undefined;\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'package_clause') {\n        importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n      }\n\n      if (child.type === 'import_declaration') {\n        imports.push(...importEntries(child, source));\n        importAnchors.push(source.slice(child.startIndex, child.endIndex));\n        continue;\n      }\n\n      const key = declarationKey(child);\n      statements.push({\n        key,\n        kind: key ? 'declaration' : 'other',\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, importInsertionAnchor, statements };\n  },\n  renderImports(imports) {\n    if (imports.length === 0) return [];\n    if (imports.length === 1) return [`import ${imports[0]!.text}`];\n    return [`import (\\n${imports.map((entry) => `  ${entry.text}`).join('\\n')}\\n)`];\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const key = declarationKey(child);\n      if (!key || key.startsWith('__package:')) continue;\n\n      const docstring = collectPrecedingGoComments(rootChildren, i, source);\n      result.set(key, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members: new Map(),\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  MergeMember,\n  DeepMergeSymbol,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst KOTLIN_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string_literal'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: ['interpolated_expression'],\n};\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n  if (node.type === 'class_declaration') {\n    // Handles class, data class, enum class, etc.\n    const nameNode = node.children.find((c) => c.type === 'type_identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'function_declaration') {\n    const nameNode = node.children.find((c) => c.type === 'simple_identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'object_declaration') {\n    const nameNode = node.children.find((c) => c.type === 'type_identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'type_alias') {\n    const nameNode = node.children.find((c) => c.type === 'type_identifier');\n    return nameNode?.text ?? null;\n  }\n  if (node.type === 'property_declaration') {\n    const nameNode = node.children.find((c) => c.type === 'variable_declaration');\n    if (nameNode) {\n      const id = nameNode.children.find((c) => c.type === 'simple_identifier');\n      return id?.text ?? null;\n    }\n  }\n  return null;\n}\n\nfunction findPrecedingKdoc(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'multiline_comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('/**')) {\n        return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n      }\n      return null;\n    }\n    if (prev.type === 'line_comment') continue;\n    return null;\n  }\n  return null;\n}\n\nfunction extractKotlinClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n  const members: MergeMember[] = [];\n  const children = classBody.namedChildren;\n\n  for (let i = 0; i < children.length; i++) {\n    const child = children[i];\n    let memberName: string | null = null;\n\n    if (child.type === 'property_declaration') {\n      const varDecl = child.children.find((c) => c.type === 'variable_declaration');\n      memberName = varDecl?.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n    } else if (child.type === 'function_declaration') {\n      memberName = child.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n    } else if (child.type === 'companion_object') {\n      memberName = 'companion';\n    }\n\n    if (!memberName) continue;\n\n    // Fold trailing getter/setter into the property's text span\n    let endIdx = child.endIndex;\n    if (child.type === 'property_declaration') {\n      while (i + 1 < children.length) {\n        const next = children[i + 1];\n        if (next.type === 'getter' || next.type === 'setter') {\n          endIdx = next.endIndex;\n          i++;\n        } else {\n          break;\n        }\n      }\n    }\n\n    // Include preceding KDoc comment in the text span so deep merge\n    // inserts the member with its documentation intact.\n    let startIdx = child.startIndex;\n    for (let k = i - 1; k >= 0; k--) {\n      const prev = children[k];\n      if (prev.type === 'multiline_comment') {\n        const text = source.slice(prev.startIndex, prev.endIndex);\n        if (text.startsWith('/**')) startIdx = prev.startIndex;\n        break;\n      }\n      if (prev.type === 'line_comment') continue;\n      break;\n    }\n\n    members.push({ key: memberName, text: source.slice(startIdx, endIdx), startIndex: startIdx, endIndex: endIdx });\n  }\n\n  return members;\n}\n\n/**\n * KDoc signature that identifies a generator-emitted service accessor inside\n * a Kotlin client class. The Kotlin client emitter writes every accessor with this\n * exact doc preamble — when the existing file carries a member with this doc\n * but the regenerated content omits it, the member is stale (its mount target\n * was remapped or removed) and gets pruned.\n */\nconst KOTLIN_MANAGED_ACCESSOR_DOC =\n  /\\/\\*\\*[\\s\\S]*?Lazily-constructed \\[[^\\]]+\\] accessor for this \\[[^\\]]+\\] client\\.[\\s\\S]*?\\*\\//;\n\nexport const kotlinMergeAdapter: MergeAdapter = {\n  language: 'kotlin',\n  grammarModule: 'tree-sitter-kotlin',\n  testFilePatterns: [/Test\\.kt$/],\n  urlFingerprintConfig: KOTLIN_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'multiline_comment' || child.type === 'line_comment') continue;\n\n      if (child.type === 'import_list') {\n        const fullText = source.slice(child.startIndex, child.endIndex);\n        importAnchors.push(fullText);\n        for (const imp of child.namedChildren) {\n          if (imp.type === 'import_header') {\n            const text = source.slice(imp.startIndex, imp.endIndex).trim();\n            // Key on the full import path\n            const idNode = imp.children.find((c) => c.type === 'identifier');\n            const key = idNode?.text ?? text;\n            imports.push({ key, text });\n          }\n        }\n        continue;\n      }\n\n      const name = extractDeclarationName(child);\n      statements.push({\n        key: name,\n        kind: name ? 'declaration' : 'other',\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  isManagedMember(member) {\n    return KOTLIN_MANAGED_ACCESSOR_DOC.test(member.text);\n  },\n  shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n    // Skip if new members reference instance properties that don't exist in the target\n    const newText = newMembers.map((m) => m.text).join('\\n');\n    for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n      const propName = match[1];\n      if (propName && !existingMemberKeys.has(propName)) return true;\n    }\n    return false;\n  },\n  extractMembers(tree, source) {\n    const result = new Map<string, DeepMergeSymbol>();\n\n    for (const child of tree.rootNode.children) {\n      if (child.type !== 'class_declaration') continue;\n      const nameNode = child.children.find((c) => c.type === 'type_identifier');\n      if (!nameNode) continue;\n      const body = child.children.find((c) => c.type === 'class_body');\n      if (!body) continue;\n\n      const members = extractKotlinClassMembers(body, source);\n      const firstMember = body.firstNamedChild;\n      const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n      result.set(nameNode.text, { members, bodyEndLine: body.endPosition.row, memberIndent });\n    }\n\n    return result;\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const name = extractDeclarationName(child);\n      if (!name) continue;\n\n      const docstring = findPrecedingKdoc(rootChildren, i, source);\n      const members = new Map<string, MemberDocstrings>();\n\n      // Extract member docstrings for classes\n      if (child.type === 'class_declaration') {\n        const body = child.children.find((c) => c.type === 'class_body' || c.type === 'enum_class_body');\n        if (body) {\n          const bodyChildren = body.children;\n          for (let j = 0; j < bodyChildren.length; j++) {\n            const member = bodyChildren[j];\n            const memberName = extractDeclarationName(member);\n            if (!memberName) continue;\n            const memberDoc = findPrecedingKdoc(bodyChildren, j, source);\n            members.set(memberName, {\n              docstring: memberDoc,\n              declStartIndex: member.startIndex,\n              declColumn: member.startPosition.column,\n              urlFingerprint: extractUrlFingerprint(member, KOTLIN_URL_FINGERPRINT_CONFIG),\n            });\n          }\n        }\n      }\n\n      result.set(name, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport { normalizeJsExtension } from '../../utils/naming.js';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DeepMergeSymbol,\n  MergeMember,\n  DocstringInfo,\n  SymbolDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst REEXPORT_PREFIX = '__export:';\n\nfunction extractDeclName(node: Parser.SyntaxNode): string | null {\n  const nameNode = node.childForFieldName('name');\n  if (nameNode) return nameNode.text;\n\n  if (node.type === 'lexical_declaration') {\n    const declarator = node.firstNamedChild;\n    if (declarator?.type === 'variable_declarator') {\n      const name = declarator.childForFieldName('name');\n      if (name) return name.text;\n    }\n  }\n\n  return null;\n}\n\nfunction extractNodeKey(node: Parser.SyntaxNode): { key: string | null; kind: MergeStatement['kind'] } {\n  if (node.type === 'export_statement') {\n    const decl = node.childForFieldName('declaration');\n    if (decl) {\n      return { key: extractDeclName(decl), kind: 'declaration' };\n    }\n\n    const source = node.childForFieldName('source');\n    if (source) {\n      return { key: `${REEXPORT_PREFIX}${normalizeJsExtension(source.text)}`, kind: 'reexport' };\n    }\n\n    return { key: null, kind: 'other' };\n  }\n  return { key: extractDeclName(node), kind: extractDeclName(node) ? 'declaration' : 'other' };\n}\n\nfunction extractClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n  const members: MergeMember[] = [];\n  for (const child of classBody.namedChildren) {\n    if (child.type === 'method_definition') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode && nameNode.text !== 'constructor') {\n        members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n      }\n    } else if (child.type === 'public_field_definition') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) {\n        // tree-sitter may exclude the trailing semicolon from\n        // public_field_definition nodes — include it if present\n        let endIdx = child.endIndex;\n        if (source[endIdx] === ';') {\n          endIdx += 1;\n        }\n        members.push({ key: nameNode.text, text: source.slice(child.startIndex, endIdx) });\n      }\n    }\n  }\n  return members;\n}\n\nfunction extractInterfaceMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n  const members: MergeMember[] = [];\n  for (const child of body.namedChildren) {\n    if (child.type === 'property_signature' || child.type === 'method_signature') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) {\n        members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n      }\n    }\n  }\n  return members;\n}\n\nfunction extractEnumMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n  const members: MergeMember[] = [];\n  for (const child of body.namedChildren) {\n    if (child.type === 'enum_assignment') {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) {\n        members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n      }\n    } else if (child.type === 'property_identifier') {\n      members.push({ key: child.text, text: source.slice(child.startIndex, child.endIndex) });\n    }\n  }\n  return members;\n}\n\nfunction isCommentNode(node: Parser.SyntaxNode): boolean {\n  // tree-sitter extras (comments) may report the parent node's type\n  // instead of 'comment' — check grammarType as fallback\n  return node.type === 'comment' || (node as any).grammarType === 'comment';\n}\n\nfunction findPrecedingDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (isCommentNode(prev)) {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('/**')) {\n        return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n      }\n      return null;\n    }\n    if (prev.type === ',' || prev.type === ';' || prev.type === '{') continue;\n    return null;\n  }\n  return null;\n}\n\nconst CLASS_MEMBER_TYPES = new Set(['method_definition', 'public_field_definition']);\nconst INTERFACE_MEMBER_TYPES = new Set(['property_signature', 'method_signature']);\nconst ENUM_MEMBER_TYPES = new Set(['enum_assignment', 'property_identifier']);\n\nconst NODE_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string', 'template_string'],\n  contentNodeTypes: ['string_fragment'],\n  interpolationNodeTypes: ['template_substitution'],\n};\n\nfunction extractBodyMemberDocstrings(\n  body: Parser.SyntaxNode,\n  source: string,\n  memberTypes: Set<string>,\n): Map<\n  string,\n  { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n> {\n  const result = new Map<\n    string,\n    { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n  >();\n  const allChildren = body.children;\n  for (let i = 0; i < allChildren.length; i++) {\n    const child = allChildren[i];\n    if (!memberTypes.has(child.type)) continue;\n    let memberName: string | null = null;\n    if (child.type === 'property_identifier') {\n      memberName = child.text;\n    } else {\n      const nameNode = child.childForFieldName('name');\n      if (nameNode) memberName = nameNode.text;\n    }\n    if (!memberName || memberName === 'constructor') continue;\n    const docstring = findPrecedingDocstring(allChildren, i, source);\n    const fp = extractUrlFingerprint(child, NODE_URL_FINGERPRINT_CONFIG);\n    result.set(memberName, {\n      docstring,\n      declStartIndex: child.startIndex,\n      declColumn: child.startPosition.column,\n      urlFingerprint: fp,\n    });\n  }\n  return result;\n}\n\nexport const nodeMergeAdapter: MergeAdapter = {\n  language: 'node',\n  grammarModule: 'tree-sitter-typescript/bindings/node/typescript.js',\n  normalizeReexport: normalizeJsExtension,\n  testFilePatterns: [/\\.(spec|test)\\.[jt]sx?$/],\n  urlFingerprintConfig: NODE_URL_FINGERPRINT_CONFIG,\n  shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n    // If new members reference instance properties (this.X) that don't exist\n    // in the target class, the merged code would be broken.\n    const newText = newMembers.map((m) => m.text).join('\\n');\n    for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n      const propName = match[1];\n      if (propName && !existingMemberKeys.has(propName)) {\n        return true;\n      }\n    }\n    return false;\n  },\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'import_statement') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        // Key on module path so `import { X }` and `import type { X }` from\n        // the same module are treated as duplicates\n        const sourceNode = child.childForFieldName('source');\n        const modulePath = sourceNode ? normalizeJsExtension(sourceNode.text) : normalizeJsExtension(text.trim());\n        imports.push({ key: modulePath, text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const { key, kind } = extractNodeKey(child);\n      statements.push({\n        key,\n        kind,\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractMembers(tree, source) {\n    const result = new Map<string, DeepMergeSymbol>();\n\n    for (const child of tree.rootNode.children) {\n      if (child.type !== 'export_statement') continue;\n      const decl = child.childForFieldName('declaration');\n      if (!decl) continue;\n\n      const nameNode = decl.childForFieldName('name');\n      if (!nameNode) continue;\n      const symbolName = nameNode.text;\n\n      if (decl.type === 'class_declaration') {\n        const body = decl.childForFieldName('body');\n        if (!body) continue;\n        const members = extractClassMembers(body, source);\n        const firstMember = body.firstNamedChild;\n        const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n        result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n      } else if (decl.type === 'interface_declaration') {\n        const body = decl.childForFieldName('body');\n        if (!body) continue;\n        const members = extractInterfaceMembers(body, source);\n        const firstMember = body.firstNamedChild;\n        const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n        result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n      } else if (decl.type === 'enum_declaration') {\n        const body = decl.childForFieldName('body');\n        if (!body) continue;\n        const members = extractEnumMembers(body, source);\n        const firstMember = body.firstNamedChild;\n        const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n        result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n      }\n    }\n\n    return result;\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      if (child.type !== 'export_statement') continue;\n      const decl = child.childForFieldName('declaration');\n      if (!decl) continue;\n      const nameNode = decl.childForFieldName('name');\n      if (!nameNode) continue;\n\n      // Find preceding JSDoc for this top-level symbol\n      const docstring = findPrecedingDocstring(rootChildren, i, source);\n\n      // Extract member-level docstrings\n      let members = new Map<string, { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number }>();\n      const body = decl.childForFieldName('body');\n      if (body) {\n        if (decl.type === 'class_declaration') {\n          members = extractBodyMemberDocstrings(body, source, CLASS_MEMBER_TYPES);\n        } else if (decl.type === 'interface_declaration') {\n          members = extractBodyMemberDocstrings(body, source, INTERFACE_MEMBER_TYPES);\n        } else if (decl.type === 'enum_declaration') {\n          members = extractBodyMemberDocstrings(body, source, ENUM_MEMBER_TYPES);\n        }\n      }\n\n      result.set(nameNode.text, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PHP_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['encapsed_string', 'string'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: ['variable_name'],\n};\n\nfunction extractPhpDeclarationName(node: Parser.SyntaxNode): string | null {\n  switch (node.type) {\n    case 'class_declaration':\n    case 'interface_declaration':\n    case 'trait_declaration':\n    case 'enum_declaration':\n    case 'function_definition': {\n      const nameNode = node.childForFieldName('name');\n      return nameNode?.text ?? null;\n    }\n    case 'namespace_definition': {\n      const nameNode = node.childForFieldName('name');\n      return nameNode ? `__namespace:${nameNode.text}` : '__namespace:';\n    }\n    default:\n      return null;\n  }\n}\n\nfunction findPhpDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('/**')) {\n        return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n      }\n      return null;\n    }\n    if (prev.type === ';' || prev.type === '{') continue;\n    return null;\n  }\n  return null;\n}\n\nexport const phpMergeAdapter: MergeAdapter = {\n  language: 'php',\n  grammarModule: 'tree-sitter-php',\n  testFilePatterns: [/Test\\.php$/],\n  urlFingerprintConfig: PHP_URL_FINGERPRINT_CONFIG,\n  resolveGrammar: (mod) => {\n    // ESM import wraps in { default: { php, php_only } }\n    const m = (mod as Record<string, unknown>)?.default ?? mod;\n    if (typeof m === 'object' && m !== null && 'php' in (m as Record<string, unknown>))\n      return (m as { php: unknown }).php;\n    return m;\n  },\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    let importInsertionAnchor: string | undefined;\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'namespace_definition') {\n        importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n      }\n\n      if (child.type === 'namespace_use_declaration') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const declarationName = extractPhpDeclarationName(child);\n      const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n      statements.push({\n        key: declarationName,\n        kind,\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, importInsertionAnchor, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const name = extractPhpDeclarationName(child);\n      if (!name || name.startsWith('__namespace:')) continue;\n\n      const docstring = findPhpDocstring(rootChildren, i, source);\n      const members = new Map<string, MemberDocstrings>();\n\n      const body = child.childForFieldName('body');\n      if (body) {\n        const bodyChildren = body.children;\n        for (let j = 0; j < bodyChildren.length; j++) {\n          const member = bodyChildren[j];\n          if (member.type !== 'method_declaration') continue;\n          const memberName = member.childForFieldName('name')?.text;\n          if (!memberName) continue;\n          const memberDoc = findPhpDocstring(bodyChildren, j, source);\n          members.set(memberName, {\n            docstring: memberDoc,\n            declStartIndex: member.startIndex,\n            declColumn: member.startPosition.column,\n            urlFingerprint: extractUrlFingerprint(member, PHP_URL_FINGERPRINT_CONFIG),\n          });\n        }\n      }\n\n      result.set(name, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PYTHON_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: ['interpolation'],\n};\n\nfunction extractPythonDeclarationName(node: Parser.SyntaxNode): string | null {\n  if (node.type === 'class_definition' || node.type === 'function_definition') {\n    const nameNode = node.childForFieldName('name');\n    return nameNode?.text ?? null;\n  }\n\n  // Detect `__all__ = [...]` assignments so they get a key and can be deduplicated\n  if (node.type === 'expression_statement') {\n    const firstChild = node.firstNamedChild;\n    if (firstChild?.type === 'assignment') {\n      const left = firstChild.childForFieldName('left');\n      if (left?.type === 'identifier' && left.text === '__all__') {\n        return '__all__';\n      }\n    }\n  }\n\n  return null;\n}\n\nfunction extractPythonDocstring(bodyNode: Parser.SyntaxNode, source: string): DocstringInfo | null {\n  // Python docstrings are the first expression_statement in a body block\n  // where the expression is a string literal\n  for (const child of bodyNode.namedChildren) {\n    if (child.type === 'expression_statement') {\n      const expr = child.firstNamedChild;\n      if (expr?.type === 'string') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        return { text, startIndex: child.startIndex, endIndex: child.endIndex };\n      }\n    }\n    // Only the FIRST statement can be a docstring\n    break;\n  }\n  return null;\n}\n\nfunction collectPrecedingPythonComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'comment') {\n      if (lastIdx === -1) lastIdx = k;\n      firstIdx = k;\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const pythonMergeAdapter: MergeAdapter = {\n  language: 'python',\n  grammarModule: 'tree-sitter-python',\n  testFilePatterns: [/(?:^|\\/)test_.*\\.py$/, /_test\\.py$/],\n  urlFingerprintConfig: PYTHON_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'import_statement' || child.type === 'import_from_statement') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const declarationName = extractPythonDeclarationName(child);\n      const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n      statements.push({\n        key: declarationName,\n        kind,\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const name = extractPythonDeclarationName(child);\n      if (!name) continue;\n\n      // Python: class/function docstrings are inside the body, OR use # comments before\n      let docstring: DocstringInfo | null = null;\n      const body = child.childForFieldName('body');\n      if (body) {\n        docstring = extractPythonDocstring(body, source);\n      }\n      // Fallback: check for # comments before the declaration\n      if (!docstring) {\n        docstring = collectPrecedingPythonComments(rootChildren, i, source);\n      }\n\n      const members = new Map<string, MemberDocstrings>();\n\n      // Extract method docstrings for classes\n      if (child.type === 'class_definition' && body) {\n        for (const member of body.namedChildren) {\n          if (member.type !== 'function_definition') continue;\n          const memberName = member.childForFieldName('name')?.text;\n          if (!memberName) continue;\n\n          let memberDoc: DocstringInfo | null = null;\n          const memberBody = member.childForFieldName('body');\n          if (memberBody) {\n            memberDoc = extractPythonDocstring(memberBody, source);\n          }\n\n          members.set(memberName, {\n            docstring: memberDoc,\n            declStartIndex: member.startIndex,\n            declColumn: member.startPosition.column,\n            urlFingerprint: extractUrlFingerprint(member, PYTHON_URL_FINGERPRINT_CONFIG),\n          });\n        }\n      }\n\n      result.set(name, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n  MergeAdapter,\n  MergeStatement,\n  MergeImport,\n  DocstringInfo,\n  SymbolDocstrings,\n  MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst RUBY_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isRequireCall(node: Parser.SyntaxNode): boolean {\n  if (node.type !== 'call') return false;\n  const method = node.childForFieldName('method');\n  if (!method) return false;\n  return method.text === 'require' || method.text === 'require_relative';\n}\n\nfunction extractRubyDeclarationName(node: Parser.SyntaxNode): string | null {\n  if (node.type !== 'class' && node.type !== 'module') return null;\n  const nameNode = node.childForFieldName('name');\n  return nameNode?.text ?? null;\n}\n\nfunction collectPrecedingRubyComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    const nodeType = (prev as any).grammarType ?? prev.type;\n    if (nodeType === 'comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('#')) {\n        if (lastIdx === -1) lastIdx = k;\n        firstIdx = k;\n      } else {\n        break;\n      }\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rubyMergeAdapter: MergeAdapter = {\n  language: 'ruby',\n  grammarModule: 'tree-sitter-ruby',\n  testFilePatterns: [/_test\\.rb$/, /_spec\\.rb$/],\n  urlFingerprintConfig: RUBY_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      const declarationName = extractRubyDeclarationName(child);\n      if (isRequireCall(child)) {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n      statements.push({\n        key: declarationName,\n        kind,\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const name = extractRubyDeclarationName(child);\n      if (!name) continue;\n\n      const docstring = collectPrecedingRubyComments(rootChildren, i, source);\n      const members = new Map<string, MemberDocstrings>();\n\n      // Ruby class/module bodies: comments may appear in class children\n      // (before body_statement) or in body_statement children (between methods)\n      if (child.type === 'class' || child.type === 'module') {\n        const allClassChildren = child.children;\n        const body = child.childForFieldName('body');\n\n        // Check for comment before body_statement in class children\n        // (docstring for the first method)\n        let firstMethodDocFromClass: DocstringInfo | null = null;\n        for (let j = 0; j < allClassChildren.length; j++) {\n          if (allClassChildren[j] === body || allClassChildren[j].type === 'body_statement') {\n            firstMethodDocFromClass = collectPrecedingRubyComments(allClassChildren, j, source);\n            break;\n          }\n        }\n\n        if (body) {\n          const bodyChildren = body.children;\n          let firstMethodHandled = false;\n          for (let j = 0; j < bodyChildren.length; j++) {\n            const member = bodyChildren[j];\n            if (member.type !== 'method') continue;\n            const memberName = member.childForFieldName('name')?.text;\n            if (!memberName) continue;\n\n            let memberDoc: DocstringInfo | null;\n            if (!firstMethodHandled && firstMethodDocFromClass) {\n              memberDoc = firstMethodDocFromClass;\n              firstMethodHandled = true;\n            } else {\n              memberDoc = collectPrecedingRubyComments(bodyChildren, j, source);\n              firstMethodHandled = true;\n            }\n\n            members.set(memberName, {\n              docstring: memberDoc,\n              declStartIndex: member.startIndex,\n              declColumn: member.startPosition.column,\n              urlFingerprint: extractUrlFingerprint(member, RUBY_URL_FINGERPRINT_CONFIG),\n            });\n          }\n        }\n      }\n\n      result.set(name, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members,\n      });\n    }\n\n    return result;\n  },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst RUST_URL_FINGERPRINT_CONFIG = {\n  stringNodeTypes: ['string_literal'],\n  contentNodeTypes: ['string_content'],\n  interpolationNodeTypes: [],\n};\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n  switch (node.type) {\n    case 'struct_item':\n    case 'enum_item':\n    case 'function_item':\n    case 'trait_item':\n    case 'type_item':\n    case 'const_item': {\n      return node.childForFieldName('name')?.text ?? null;\n    }\n    case 'impl_item': {\n      const typeName = node.childForFieldName('type')?.text ?? 'unknown';\n      const traitName = node.childForFieldName('trait')?.text;\n      return traitName ? `impl:${traitName}->${typeName}` : `impl:${typeName}`;\n    }\n    default:\n      return null;\n  }\n}\n\nfunction collectPrecedingRustDocComments(\n  children: Parser.SyntaxNode[],\n  index: number,\n  source: string,\n): DocstringInfo | null {\n  let lastIdx = -1;\n  let firstIdx = -1;\n  for (let k = index - 1; k >= 0; k--) {\n    const prev = children[k];\n    if (prev.type === 'line_comment') {\n      const text = source.slice(prev.startIndex, prev.endIndex);\n      if (text.startsWith('///')) {\n        if (lastIdx === -1) lastIdx = k;\n        firstIdx = k;\n      } else {\n        break;\n      }\n    } else {\n      break;\n    }\n  }\n  if (firstIdx === -1) return null;\n  const first = children[firstIdx];\n  const last = children[lastIdx];\n  return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rustMergeAdapter: MergeAdapter = {\n  language: 'rust',\n  grammarModule: 'tree-sitter-rust',\n  testFilePatterns: [/_test\\.rs$/, /(?:^|\\/)tests\\/.*\\.rs$/],\n  urlFingerprintConfig: RUST_URL_FINGERPRINT_CONFIG,\n  parseStatements(tree, source) {\n    const imports: MergeImport[] = [];\n    const importAnchors: string[] = [];\n    const statements: MergeStatement[] = [];\n\n    for (const child of tree.rootNode.children) {\n      if (child.type === 'comment') continue;\n\n      if (child.type === 'use_declaration') {\n        const text = source.slice(child.startIndex, child.endIndex);\n        imports.push({ key: text.trim(), text });\n        importAnchors.push(text);\n        continue;\n      }\n\n      const key = declarationKey(child);\n      statements.push({\n        key,\n        kind: key ? 'declaration' : 'other',\n        text: source.slice(child.startIndex, child.endIndex),\n      });\n    }\n\n    return { imports, importAnchors, statements };\n  },\n  renderImports(imports) {\n    return imports.map((entry) => entry.text);\n  },\n  extractDocstrings(tree, source) {\n    const result = new Map<string, SymbolDocstrings>();\n    const rootChildren = tree.rootNode.children;\n\n    for (let i = 0; i < rootChildren.length; i++) {\n      const child = rootChildren[i];\n      const key = declarationKey(child);\n      if (!key) continue;\n\n      const docstring = collectPrecedingRustDocComments(rootChildren, i, source);\n      result.set(key, {\n        docstring,\n        declStartIndex: child.startIndex,\n        declColumn: child.startPosition.column,\n        members: new Map(),\n      });\n    }\n\n    return result;\n  },\n};\n","import type { MergeAdapter } from './types.js';\nimport { dotnetMergeAdapter } from './dotnet.js';\nimport { elixirMergeAdapter } from './elixir.js';\nimport { goMergeAdapter } from './go.js';\nimport { kotlinMergeAdapter } from './kotlin.js';\nimport { nodeMergeAdapter } from './node.js';\nimport { phpMergeAdapter } from './php.js';\nimport { pythonMergeAdapter } from './python.js';\nimport { rubyMergeAdapter } from './ruby.js';\nimport { rustMergeAdapter } from './rust.js';\n\nconst adapters = new Map<string, MergeAdapter>([\n  ['dotnet', dotnetMergeAdapter],\n  ['elixir', elixirMergeAdapter],\n  ['go', goMergeAdapter],\n  ['kotlin', kotlinMergeAdapter],\n  ['node', nodeMergeAdapter],\n  ['php', phpMergeAdapter],\n  ['python', pythonMergeAdapter],\n  ['ruby', rubyMergeAdapter],\n  ['rust', rustMergeAdapter],\n]);\n\nexport function getMergeAdapter(language: string): MergeAdapter | undefined {\n  return adapters.get(language);\n}\n","/**\n * Shared tree-sitter utilities.\n *\n * tree-sitter 0.21.x has a native binding bug: its internal UTF-16 buffer is\n * 32 768 uint16 units (32 768 characters for BMP text). When the JS input\n * callback returns a string >= 32 768 chars, `napi_get_value_string_utf16`\n * overflows and the C layer throws \"Invalid argument\". Work around this by\n * supplying a chunked callback for large sources instead of a raw string.\n */\n\nimport type Parser from 'tree-sitter';\n\nconst TS_SAFE_CHUNK = 32_767;\n\nexport function safeParse(parser: Parser, source: string): Parser.Tree {\n  if (source.length < TS_SAFE_CHUNK) {\n    return parser.parse(source);\n  }\n  return parser.parse((offset: number) => source.slice(offset, offset + TS_SAFE_CHUNK));\n}\n","/**\n * AST-level file merger using tree-sitter.\n *\n * When generating into a directory that already contains files, the merger\n * parses both the existing and generated content, detects top-level symbols,\n * and only appends symbols that don't already exist. Hand-written code is\n * never modified or removed.\n *\n * Supports any language with a tree-sitter grammar package.\n */\n\nimport Parser from 'tree-sitter';\nimport { getMergeAdapter } from './merge-adapters/index.js';\nimport type { MergeImport, ParsedMergeFile, SymbolDocstrings } from './merge-adapters/types.js';\n\n// Cache parser instances per language\nconst parserCache = new Map<string, Parser>();\n\nimport { safeParse } from '../utils/tree-sitter.js';\n\n// --- @deprecated preservation ---\n\n/**\n * When replacing an existing docstring with a generated one, carry over any\n * `@deprecated` lines from the existing doc that aren't present in the\n * generated doc.  This prevents hand-written deprecation notices from being\n * silently dropped during docstring refresh.\n */\nfunction preserveDeprecatedTags(existingDoc: string, generatedDoc: string): string {\n  // Check if the existing docstring contains @deprecated anywhere\n  if (!existingDoc.includes('@deprecated')) return generatedDoc;\n\n  // If generated doc already has @deprecated, no need to merge\n  if (generatedDoc.includes('@deprecated')) return generatedDoc;\n\n  // Extract the @deprecated content from the existing doc.\n  // Handle both multi-line (`* @deprecated ...`) and one-liner (`/** @deprecated ... */`) formats.\n  const deprecatedParts: string[] = [];\n  for (const line of existingDoc.split('\\n')) {\n    if (/@deprecated\\b/.test(line)) {\n      // Normalize to JSDoc member format: `   * @deprecated ...`\n      const match = line.match(/@deprecated\\b.*/);\n      if (match) {\n        // Strip trailing */ and whitespace (from one-liner JSDoc like `/** @deprecated ... */`)\n        const cleaned = match[0].replace(/\\s*\\*\\/\\s*$/, '');\n        deprecatedParts.push(`   * ${cleaned}`);\n      }\n    }\n  }\n  if (deprecatedParts.length === 0) return generatedDoc;\n\n  // Insert @deprecated lines before the closing */ of the generated doc\n  const closingIdx = generatedDoc.lastIndexOf('*/');\n  if (closingIdx === -1) return generatedDoc;\n  const before = generatedDoc.slice(0, closingIdx);\n  const after = generatedDoc.slice(closingIdx);\n  return before + deprecatedParts.join('\\n') + '\\n ' + after;\n}\n\n// --- @oagen-ignore region helpers ---\n\ninterface IgnoredRegion {\n  startIndex: number;\n  endIndex: number;\n}\n\nfunction findIgnoredRegions(source: string): IgnoredRegion[] {\n  const regions: IgnoredRegion[] = [];\n  const startTag = '@oagen-ignore-start';\n  const endTag = '@oagen-ignore-end';\n  let searchFrom = 0;\n\n  while (true) {\n    const startIdx = source.indexOf(startTag, searchFrom);\n    if (startIdx === -1) break;\n    const endIdx = source.indexOf(endTag, startIdx + startTag.length);\n    if (endIdx === -1) break; // Unclosed — silently ignore\n    regions.push({ startIndex: startIdx, endIndex: endIdx + endTag.length });\n    searchFrom = endIdx + endTag.length;\n  }\n\n  return regions;\n}\n\nfunction buildIgnoredSymbolNames(docstrings: Map<string, SymbolDocstrings>, regions: IgnoredRegion[]): Set<string> {\n  if (regions.length === 0) return new Set();\n  const ignored = new Set<string>();\n  for (const [name, info] of docstrings) {\n    if (regions.some((r) => info.declStartIndex >= r.startIndex && info.declStartIndex <= r.endIndex)) {\n      ignored.add(name);\n    }\n  }\n  return ignored;\n}\n\nfunction clampIndex(value: number, contentLength: number): number {\n  if (!Number.isFinite(value)) return 0;\n  if (value < 0) return 0;\n  if (value > contentLength) return contentLength;\n  return value;\n}\n\n/**\n * Resolve the declaration line start for insertion using the current content,\n * instead of relying on parser column arithmetic. This avoids misplaced inserts\n * when parser columns/offsets drift.\n */\nfunction declarationLineStart(content: string, declStartIndex: number): number {\n  const idx = clampIndex(declStartIndex, content.length);\n  const prevNewline = content.lastIndexOf('\\n', Math.max(0, idx - 1));\n  return prevNewline === -1 ? 0 : prevNewline + 1;\n}\n\n/**\n * Resolve a docstring range by searching for the nearest matching text before\n * the declaration start. Falls back to parser-provided offsets when search fails.\n */\nfunction resolveDocRange(\n  content: string,\n  docText: string,\n  declStartIndex: number,\n  fallbackStart: number,\n  fallbackEnd: number,\n): { start: number; end: number } {\n  const safeDecl = clampIndex(declStartIndex, content.length);\n  const safeFallbackStart = clampIndex(fallbackStart, content.length);\n  const safeFallbackEnd = clampIndex(fallbackEnd, content.length);\n  const found = content.lastIndexOf(docText, safeDecl);\n  if (found !== -1) {\n    return { start: found, end: found + docText.length };\n  }\n  return { start: safeFallbackStart, end: safeFallbackEnd };\n}\n\n/**\n * Check if a tree-sitter grammar is configured for the given language.\n */\nexport function hasGrammar(language: string): boolean {\n  return getMergeAdapter(language) !== undefined;\n}\n\nasync function getParser(language: string): Promise<Parser> {\n  const cached = parserCache.get(language);\n  if (cached) return cached;\n\n  const adapter = getMergeAdapter(language);\n  if (!adapter) {\n    throw new Error(\n      `No tree-sitter grammar configured for language \"${language}\". ` +\n        `Add a merge adapter and install the corresponding tree-sitter grammar package.`,\n    );\n  }\n\n  const mod = await import(adapter.grammarModule);\n  const exported = adapter.resolveGrammar ? adapter.resolveGrammar(mod) : mod;\n  const grammar = (exported as { default?: unknown }).default ?? exported;\n  const parser = new Parser();\n  parser.setLanguage(grammar);\n  parserCache.set(language, parser);\n  return parser;\n}\n\ninterface ParsedSymbols {\n  names: Set<string>;\n  /** Trimmed text of unnamed top-level statements (for text-based dedup) */\n  unnamedTexts: Set<string>;\n}\n\n/**\n * Extract all top-level symbol names (and unnamed statement texts) from source code.\n */\nexport async function extractTopLevelSymbols(source: string, language: string): Promise<ParsedSymbols> {\n  const parser = await getParser(language);\n  const adapter = getMergeAdapter(language);\n  if (!adapter) {\n    throw new Error(`No merge adapter configured for language \"${language}\"`);\n  }\n  if (typeof source !== 'string') {\n    throw new Error(`extractTopLevelSymbols: expected string source, got ${typeof source}`);\n  }\n  const tree = safeParse(parser, source);\n  const names = new Set<string>();\n  const unnamedTexts = new Set<string>();\n  const parsed = adapter.parseStatements(tree, source);\n\n  for (const imp of parsed.imports) {\n    names.add(imp.key);\n  }\n  for (const statement of parsed.statements) {\n    if (statement.key) {\n      names.add(statement.key);\n    } else {\n      unnamedTexts.add(statement.text.trim());\n    }\n  }\n\n  return { names, unnamedTexts };\n}\n\n/** Convenience wrapper that returns only the name set. */\nexport async function extractTopLevelNames(source: string, language: string): Promise<Set<string>> {\n  return (await extractTopLevelSymbols(source, language)).names;\n}\n\n/**\n * Extract top-level statements from generated source with their names\n * and exact text span.\n */\nexport async function extractStatements(source: string, language: string): Promise<ParsedMergeFile> {\n  const parser = await getParser(language);\n  const adapter = getMergeAdapter(language);\n  if (!adapter) {\n    throw new Error(`No merge adapter configured for language \"${language}\"`);\n  }\n  const tree = safeParse(parser, source);\n  return adapter.parseStatements(tree, source);\n}\n\n/**\n * Return a map of top-level class name → { bodyEndLine, bodyEndCol } using\n * tree-sitter.  `bodyEndLine` is 0-based.  For brace-delimited classes the\n * end points at the closing brace line; for indentation-delimited classes\n * it points one past the last line of the class body.\n */\nexport async function extractClassEndLines(\n  source: string,\n  language: string,\n): Promise<Map<string, { bodyEndLine: number }>> {\n  const parser = await getParser(language);\n  const tree = safeParse(parser, source);\n  const map = new Map<string, { bodyEndLine: number }>();\n\n  function processClassNode(node: Parser.SyntaxNode): void {\n    const nameNode =\n      node.childForFieldName('name') ??\n      node.children.find((c) => c.type === 'type_identifier' || c.type === 'identifier');\n    if (!nameNode) return;\n    const name = nameNode.text;\n\n    const body =\n      node.childForFieldName('body') ?? node.children.find((c) => c.type === 'class_body' || c.type === 'body');\n    const endRow = body ? body.endPosition.row : node.endPosition.row;\n    const lastChar = source[body ? body.endIndex - 1 : node.endIndex - 1];\n\n    if (lastChar === '}') {\n      map.set(name, { bodyEndLine: endRow });\n    } else {\n      map.set(name, { bodyEndLine: endRow + 1 });\n    }\n  }\n\n  // Walk the tree recursively. Ruby (and Python) often nest target classes\n  // inside `module Foo` / `class Outer:` containers, so a flat iteration over\n  // root children would miss them.\n  function walk(node: Parser.SyntaxNode): void {\n    if (node.type === 'class' || node.type === 'class_definition' || node.type === 'class_declaration') {\n      processClassNode(node);\n    }\n    if (node.type === 'decorated_definition') {\n      for (const inner of node.namedChildren) {\n        if (inner.type === 'class_definition') processClassNode(inner);\n      }\n    }\n    if (node.type === 'export_statement') {\n      for (const inner of node.namedChildren) {\n        if (inner.type === 'class_declaration') processClassNode(inner);\n      }\n    }\n    for (const child of node.namedChildren) walk(child);\n  }\n  for (const child of tree.rootNode.children) {\n    walk(child);\n  }\n\n  return map;\n}\n\nexport interface MergeResult {\n  content: string;\n  added: number;\n  preserved: number;\n  changed: boolean;\n}\n\n/**\n * Merge generated content into an existing file.\n *\n * - Parses both files with tree-sitter\n * - Detects which top-level symbols already exist\n * - Appends only new symbols\n * - Never modifies or removes existing code\n * - Adds auto-generated header if not present\n */\nexport async function mergeIntoExisting(\n  existingContent: string,\n  generatedContent: string,\n  language: string,\n  header: string,\n): Promise<MergeResult> {\n  const adapter = getMergeAdapter(language);\n  if (!adapter) {\n    throw new Error(`No merge adapter configured for language \"${language}\"`);\n  }\n\n  // Parse existing file once — extract both symbols and statements from the same AST pass\n  const existingStatements = await extractStatements(existingContent, language);\n  const generatedStatements = await extractStatements(generatedContent, language);\n\n  const existingKeys = new Set<string>();\n  const existingUnnamedTexts = new Set<string>();\n  const existingImportKeys = new Set<string>();\n  const existingReexports = new Set<string>();\n  let lastImportEndIndex = -1;\n\n  // Collect import keys AND imported identifiers (to prevent adding declarations\n  // that clash with already-imported names)\n  const existingImportedNames = new Set<string>();\n  for (const imp of existingStatements.imports) {\n    existingImportKeys.add(imp.key);\n    // Extract identifiers from import text: import { Foo, Bar } from '...'\n    const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n    if (braceMatch) {\n      for (const name of braceMatch[1].split(',')) {\n        const trimmed = name.replace(/\\btype\\b/, '').trim();\n        if (trimmed) existingImportedNames.add(trimmed);\n      }\n    }\n  }\n  for (const anchor of existingStatements.importAnchors) {\n    const linesBefore = existingContent.slice(0, existingContent.indexOf(anchor)).split('\\n').length - 1;\n    const stmtLines = anchor.split('\\n').length;\n    lastImportEndIndex = linesBefore + stmtLines - 1;\n  }\n  if (lastImportEndIndex === -1 && existingStatements.importInsertionAnchor) {\n    const linesBefore =\n      existingContent.slice(0, existingContent.indexOf(existingStatements.importInsertionAnchor)).split('\\n').length -\n      1;\n    const stmtLines = existingStatements.importInsertionAnchor.split('\\n').length;\n    lastImportEndIndex = linesBefore + stmtLines - 1;\n  }\n\n  // Track all names exported by existing statements (both direct exports and\n  // re-export aliases like `export { X as Y }`).  Used to prevent the merger\n  // from appending a re-export that introduces a duplicate exported name.\n  const existingExportedNames = new Set<string>();\n\n  for (const stmt of existingStatements.statements) {\n    if (stmt.kind === 'reexport') {\n      existingReexports.add(adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim());\n      // Collect aliased export names from re-exports\n      const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n      if (braceMatch) {\n        for (const part of braceMatch[1].split(',')) {\n          const segments = part.trim().split(/\\s+as\\s+/);\n          const exportedName = (segments[1] ?? segments[0]).trim();\n          if (exportedName) existingExportedNames.add(exportedName);\n        }\n      }\n    }\n    if (stmt.key) {\n      existingKeys.add(stmt.key);\n      existingExportedNames.add(stmt.key);\n    } else {\n      existingUnnamedTexts.add(stmt.text.trim());\n    }\n  }\n\n  const headerLine = header.trim();\n\n  const newImports: MergeImport[] = [];\n  const toAppend: string[] = [];\n  let preserved = 0;\n\n  for (const imp of generatedStatements.imports) {\n    if (imp.text.trim() === headerLine) continue;\n    if (existingImportKeys.has(imp.key)) {\n      // The existing file already imports from this module path.\n      // Check if the generated import adds identifiers not present in\n      // the existing import — if so, create a supplemental import with\n      // only the new identifiers.  The supplemental participates in the\n      // usage-based filter (below) so unused identifiers are dropped.\n      const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n      if (braceMatch) {\n        const names = braceMatch[1]\n          .split(',')\n          .map((n) => n.replace(/\\btype\\b/, '').trim())\n          .filter(Boolean);\n        const newNames = names.filter((n) => !existingImportedNames.has(n) && !existingKeys.has(n));\n        if (newNames.length > 0) {\n          const isTypeImport = imp.text.trimStart().startsWith('import type');\n          const prefix = isTypeImport ? 'import type' : 'import';\n          const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n          if (sourceMatch) {\n            newImports.push({\n              key: imp.key + '#supplemental',\n              text: `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`,\n            });\n          }\n        }\n      }\n      preserved++;\n      continue;\n    }\n    // Strip out identifiers that are already imported from another path.\n    // This prevents duplicates when the generated file uses a specific path\n    // (e.g., '../interfaces/organization.interface') while the existing file\n    // imports the same names from a barrel (e.g., '../interfaces').\n    const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n    if (braceMatch) {\n      const names = braceMatch[1]\n        .split(',')\n        .map((n) => n.replace(/\\btype\\b/, '').trim())\n        .filter(Boolean);\n      // Check against both existing imports AND existing top-level declarations\n      const isAlreadyDefined = (n: string) => existingImportedNames.has(n) || existingKeys.has(n);\n      if (names.length > 0 && names.every(isAlreadyDefined)) {\n        preserved++;\n        continue;\n      }\n      // If only SOME identifiers are already defined, strip them out and keep only new ones\n      if (names.some(isAlreadyDefined)) {\n        const newNames = names.filter((n) => !isAlreadyDefined(n));\n        if (newNames.length === 0) {\n          preserved++;\n          continue;\n        }\n        // Rebuild the import with only new identifiers\n        const isTypeImport = imp.text.trimStart().startsWith('import type');\n        const prefix = isTypeImport ? 'import type' : 'import';\n        const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n        if (sourceMatch) {\n          const newText = `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`;\n          newImports.push({ key: imp.key, text: newText });\n          continue;\n        }\n      }\n    }\n    newImports.push(imp);\n  }\n\n  for (const stmt of generatedStatements.statements) {\n    // Skip the header comment\n    if (stmt.text.trim() === headerLine) continue;\n\n    // Skip re-export statements that duplicate existing re-exports\n    // (e.g., generated uses .js extension but existing doesn't).\n    // Allow genuinely new re-exports through.\n    if (stmt.kind === 'reexport') {\n      const normalizedText = adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim();\n      if (existingReexports.has(normalizedText) || (stmt.key !== null && existingKeys.has(stmt.key))) {\n        preserved++;\n        continue;\n      }\n      // Also skip re-exports whose aliased names are already defined as\n      // top-level exports in the existing file (e.g., generated file has\n      // `export { X as deserializeFoo } from '...'` but existing file\n      // already has `export const deserializeFoo = ...`).\n      const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n      if (braceMatch) {\n        const exportedNames = braceMatch[1]\n          .split(',')\n          .map((n) => {\n            const parts = n.trim().split(/\\s+as\\s+/);\n            return (parts[1] ?? parts[0]).trim();\n          })\n          .filter(Boolean);\n        if (exportedNames.length > 0 && exportedNames.every((n) => existingExportedNames.has(n))) {\n          preserved++;\n          continue;\n        }\n      }\n    }\n\n    if (stmt.key && (existingKeys.has(stmt.key) || existingImportedNames.has(stmt.key))) {\n      preserved++;\n      continue;\n    }\n\n    if (!stmt.key) {\n      if (existingUnnamedTexts.has(stmt.text.trim())) {\n        preserved++;\n        continue;\n      }\n    }\n\n    toAppend.push(stmt.text);\n  }\n\n  if (newImports.length === 0 && toAppend.length === 0) {\n    // No top-level changes — check for deep merge before returning\n    if (!adapter.extractMembers) {\n      // Still need to check docstring refresh below\n    }\n  }\n\n  let result = existingContent;\n\n  // Append new top-level symbols first (so deep merge can see them)\n  if (toAppend.length > 0) {\n    result = result.trimEnd() + '\\n\\n' + toAppend.join('\\n\\n') + '\\n';\n  }\n\n  // Deep merge pass: add new members to existing symbols\n  // Runs after import/symbol merge so line numbers are based on the updated content\n  let deepAdded = 0;\n  let deepPruned = 0;\n  const insertions: { line: number; text: string }[] = [];\n  if (adapter.extractMembers) {\n    const parser = await getParser(language);\n    const resultTree = safeParse(parser, result);\n    const generatedTree = safeParse(parser, generatedContent);\n    const resultSymbols = adapter.extractMembers(resultTree, result);\n    const generatedSymbols = adapter.extractMembers(generatedTree, generatedContent);\n\n    // Build ignored symbol set from @oagen-ignore-start/@oagen-ignore-end regions\n    const existingTree = safeParse(parser, existingContent);\n    const existingDocs = adapter.extractDocstrings(existingTree, existingContent);\n    const deepIgnoredRegions = findIgnoredRegions(existingContent);\n    const deepIgnoredSymbols = buildIgnoredSymbolNames(existingDocs, deepIgnoredRegions);\n\n    // Pass 1: prune stale \"managed\" members (existing members the adapter\n    // recognizes as generator-owned but that no longer appear in the\n    // regenerated content — e.g. accessors whose mount target was remapped).\n    // Done as byte-range deletes before line-based insertions so insertion\n    // line numbers stay valid for the post-prune result.\n    if (adapter.isManagedMember) {\n      const pruneEdits: { start: number; end: number }[] = [];\n      for (const [symbolName, genSymbol] of generatedSymbols) {\n        if (deepIgnoredSymbols.has(symbolName)) continue;\n        const existSymbol = resultSymbols.get(symbolName);\n        if (!existSymbol) continue;\n        const genMemberKeys = new Set(genSymbol.members.map((m) => m.key));\n        for (const existMember of existSymbol.members) {\n          if (genMemberKeys.has(existMember.key)) continue;\n          if (existMember.startIndex === undefined || existMember.endIndex === undefined) continue;\n          if (!adapter.isManagedMember(existMember)) continue;\n          pruneEdits.push({ start: existMember.startIndex, end: existMember.endIndex });\n        }\n      }\n      if (pruneEdits.length > 0) {\n        pruneEdits.sort((a, b) => b.start - a.start);\n        for (const edit of pruneEdits) {\n          let end = edit.end;\n          while (end < result.length && (result[end] === ' ' || result[end] === '\\t')) end++;\n          if (result[end] === '\\n') end++;\n          result = result.slice(0, edit.start) + result.slice(end);\n        }\n        deepPruned = pruneEdits.length;\n        // Re-extract since byte offsets and line numbers shifted.\n        const reTree = safeParse(parser, result);\n        resultSymbols.clear();\n        for (const [k, v] of adapter.extractMembers(reTree, result)) resultSymbols.set(k, v);\n      }\n    }\n\n    // Pass 2: append new members the regenerated content adds.\n    for (const [symbolName, genSymbol] of generatedSymbols) {\n      if (deepIgnoredSymbols.has(symbolName)) continue;\n      const existSymbol = resultSymbols.get(symbolName);\n      if (!existSymbol) continue; // New symbol — handled by top-level append\n\n      const existingMemberKeys = new Set(existSymbol.members.map((m) => m.key));\n      const newMembers = genSymbol.members.filter((m) => !existingMemberKeys.has(m.key));\n\n      if (newMembers.length > 0) {\n        // Let the adapter decide whether to skip deep merge (e.g., when new members\n        // reference dependencies the existing symbol doesn't provide)\n        if (adapter.shouldSkipDeepMerge?.(symbolName, existingMemberKeys, newMembers)) {\n          continue;\n        }\n\n        const indent = existSymbol.memberIndent ?? '  ';\n        const insertText = newMembers.map((m) => indent + m.text).join('\\n\\n');\n        // Leading blank line separates inserted members from existing ones.\n        insertions.push({ line: existSymbol.bodyEndLine, text: '\\n' + insertText });\n        deepAdded += newMembers.length;\n      }\n    }\n\n    if (insertions.length > 0) {\n      // Apply bottom-up to avoid offset shifting\n      insertions.sort((a, b) => b.line - a.line);\n      const resultLines = result.split('\\n');\n      for (const ins of insertions) {\n        resultLines.splice(ins.line, 0, ins.text);\n      }\n      result = resultLines.join('\\n');\n    }\n  }\n\n  // Insert new imports only when new symbols or members were actually added.\n  // This prevents orphaned imports for generated code that wasn't merged in.\n  // Additionally, filter imports to only include identifiers actually used in the\n  // appended/inserted code — prevents orphaned imports for generated code that\n  // referenced types used in other (non-appended) generated functions.\n  if (newImports.length > 0 && (toAppend.length > 0 || deepAdded > 0)) {\n    // Build text of all new code that was actually added (appended + deep-merged members)\n    const addedParts: string[] = [...toAppend];\n    if (insertions) {\n      for (const ins of insertions) {\n        addedParts.push(ins.text);\n      }\n    }\n    const addedCodeText = addedParts.join('\\n');\n\n    // Filter imports to only identifiers that appear in the added code.\n    // Strip individual unused identifiers from each import rather than\n    // keeping/dropping the entire import — prevents orphaned imports when\n    // a generated import line contains both used and unused identifiers\n    // (e.g., `import { deserializeFoo, serializeFoo }` where only\n    // serializeFoo is used in the appended code).\n    const filteredImports: MergeImport[] = [];\n    for (const imp of newImports) {\n      const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n      if (!braceMatch) {\n        // Non-destructured import (e.g., default import) — keep as-is\n        filteredImports.push(imp);\n        continue;\n      }\n      const names = braceMatch[1]\n        .split(',')\n        .map((n) => n.replace(/\\btype\\b/, '').trim())\n        .filter(Boolean);\n      const usedNames = names.filter((name) => addedCodeText.includes(name));\n      if (usedNames.length === 0) continue; // Drop entirely\n      if (usedNames.length === names.length) {\n        // All identifiers used — keep original import\n        filteredImports.push(imp);\n      } else {\n        // Rebuild import with only used identifiers\n        const isTypeImport = imp.text.trimStart().startsWith('import type');\n        const prefix = isTypeImport ? 'import type' : 'import';\n        const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n        if (sourceMatch) {\n          filteredImports.push({\n            key: imp.key,\n            text: `${prefix} { ${usedNames.join(', ')} } from ${sourceMatch[1]};`,\n          });\n        } else {\n          filteredImports.push(imp);\n        }\n      }\n    }\n\n    if (filteredImports.length > 0) {\n      const renderedImports = adapter.renderImports\n        ? adapter.renderImports(filteredImports)\n        : filteredImports.map((entry) => entry.text);\n      const lines = result.split('\\n');\n      const insertIdx = lastImportEndIndex + 1;\n      lines.splice(insertIdx, 0, ...renderedImports);\n      result = lines.join('\\n');\n    }\n  }\n\n  // Docstring refresh pass: update existing docstrings to match generated content\n  let docstringUpdates = 0;\n  {\n    const parser = await getParser(language);\n    const resultTree = safeParse(parser, result);\n    const generatedTree = safeParse(parser, generatedContent);\n    const resultDocs = adapter.extractDocstrings(resultTree, result);\n    const generatedDocs = adapter.extractDocstrings(generatedTree, generatedContent);\n    const docIgnoredRegions = findIgnoredRegions(result);\n    const docIgnoredSymbols = buildIgnoredSymbolNames(resultDocs, docIgnoredRegions);\n\n    const edits: { start: number; end: number; newText: string }[] = [];\n\n    for (const [symbolName, genInfo] of generatedDocs) {\n      const existInfo = resultDocs.get(symbolName);\n      if (!existInfo) continue;\n      if (docIgnoredSymbols.has(symbolName)) continue;\n\n      // Skip header comments being treated as docstrings\n      const genDoc = genInfo.docstring && genInfo.docstring.text.trim() !== headerLine ? genInfo.docstring : null;\n\n      // Top-level docstring\n      if (genDoc) {\n        if (existInfo.docstring) {\n          const isPreserved = existInfo.docstring.text.includes('@oagen-ignore');\n          if (!isPreserved && existInfo.docstring.text !== genDoc.text) {\n            const newText = preserveDeprecatedTags(existInfo.docstring.text, genDoc.text);\n            const range = resolveDocRange(\n              result,\n              existInfo.docstring.text,\n              existInfo.declStartIndex,\n              existInfo.docstring.startIndex,\n              existInfo.docstring.endIndex,\n            );\n            edits.push({\n              start: range.start,\n              end: range.end,\n              newText,\n            });\n            docstringUpdates++;\n          }\n        } else {\n          const lineStart = declarationLineStart(result, existInfo.declStartIndex);\n          const indent = ' '.repeat(existInfo.declColumn);\n          edits.push({\n            start: lineStart,\n            end: lineStart,\n            newText: indent + genDoc.text + '\\n',\n          });\n          docstringUpdates++;\n        }\n      }\n\n      // Member-level docstrings — first pass: match by name\n      const matchedExistMembers = new Set<string>();\n      for (const [memberName, genMember] of genInfo.members) {\n        const existMember = existInfo.members.get(memberName);\n        if (!existMember) continue;\n        matchedExistMembers.add(memberName);\n        if (!genMember.docstring) continue;\n\n        if (existMember.docstring) {\n          const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n          if (!isPreserved && existMember.docstring.text !== genMember.docstring.text) {\n            const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n            const range = resolveDocRange(\n              result,\n              existMember.docstring.text,\n              existMember.declStartIndex,\n              existMember.docstring.startIndex,\n              existMember.docstring.endIndex,\n            );\n            edits.push({\n              start: range.start,\n              end: range.end,\n              newText,\n            });\n            docstringUpdates++;\n          }\n        } else {\n          const lineStart = declarationLineStart(result, existMember.declStartIndex);\n          const indent = ' '.repeat(existMember.declColumn);\n          edits.push({\n            start: lineStart,\n            end: lineStart,\n            newText: indent + genMember.docstring.text + '\\n',\n          });\n          docstringUpdates++;\n        }\n      }\n\n      // Member-level docstrings — second pass: URL fingerprint fallback\n      // Match generated members to existing members by URL pattern when\n      // name-based matching fails (e.g., generated \"find\" vs existing \"getWidget\"\n      // both call this.client.get('/widgets/${id}')).\n      //\n      // Safety: only attempt fingerprint matching when there is exactly ONE\n      // unmatched generated member and ONE unmatched existing member for a\n      // given fingerprint.  When multiple members share the same URL path\n      // (e.g., POST and GET on /authorization/roles), fingerprint matching\n      // is ambiguous and would swap docstrings between methods.\n      const unmatchedGenByFp = new Map<\n        string,\n        { name: string; member: typeof genInfo.members extends Map<string, infer V> ? V : never }[]\n      >();\n      for (const [genName, genMember] of genInfo.members) {\n        if (matchedExistMembers.has(genName)) continue; // name-matched in pass 1 (as an exist member) — skip\n        if (!genMember.docstring || !genMember.urlFingerprint) continue;\n        // Skip if this generated member was already name-matched\n        if (existInfo.members.has(genName)) continue;\n        const bucket = unmatchedGenByFp.get(genMember.urlFingerprint) ?? [];\n        bucket.push({ name: genName, member: genMember });\n        unmatchedGenByFp.set(genMember.urlFingerprint, bucket);\n      }\n      const unmatchedExistByFp = new Map<\n        string,\n        { name: string; member: typeof existInfo.members extends Map<string, infer V> ? V : never }[]\n      >();\n      for (const [existName, existMember] of existInfo.members) {\n        if (matchedExistMembers.has(existName)) continue;\n        if (!existMember.urlFingerprint) continue;\n        const bucket = unmatchedExistByFp.get(existMember.urlFingerprint) ?? [];\n        bucket.push({ name: existName, member: existMember });\n        unmatchedExistByFp.set(existMember.urlFingerprint, bucket);\n      }\n      for (const [fp, genBucket] of unmatchedGenByFp) {\n        if (genBucket.length !== 1) continue; // ambiguous — skip\n        const existBucket = unmatchedExistByFp.get(fp);\n        if (!existBucket || existBucket.length !== 1) continue; // ambiguous — skip\n        const genMember = genBucket[0].member;\n        const existEntry = existBucket[0];\n        const existMember = existEntry.member;\n        if (!genMember.docstring) continue;\n\n        if (existMember.docstring) {\n          const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n          if (isPreserved) continue;\n          if (existMember.docstring.text !== genMember.docstring.text) {\n            const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n            const range = resolveDocRange(\n              result,\n              existMember.docstring.text,\n              existMember.declStartIndex,\n              existMember.docstring.startIndex,\n              existMember.docstring.endIndex,\n            );\n            edits.push({\n              start: range.start,\n              end: range.end,\n              newText,\n            });\n            docstringUpdates++;\n          }\n        } else {\n          const lineStart = declarationLineStart(result, existMember.declStartIndex);\n          const indent = ' '.repeat(existMember.declColumn);\n          edits.push({\n            start: lineStart,\n            end: lineStart,\n            newText: indent + genMember.docstring.text + '\\n',\n          });\n          docstringUpdates++;\n        }\n        matchedExistMembers.add(existEntry.name);\n      }\n    }\n\n    if (edits.length > 0) {\n      edits.sort((a, b) => b.start - a.start);\n      for (const edit of edits) {\n        result = result.slice(0, edit.start) + edit.newText + result.slice(edit.end);\n      }\n    }\n  }\n\n  const importsActuallyAdded =\n    toAppend.length > 0 || deepAdded > 0\n      ? adapter.renderImports\n        ? adapter.renderImports(newImports).length\n        : newImports.length\n      : 0;\n  const topLevelAdded = importsActuallyAdded + toAppend.length;\n  const totalAdded = topLevelAdded + deepAdded;\n\n  if (totalAdded === 0 && docstringUpdates === 0 && deepPruned === 0) {\n    return { content: existingContent, added: 0, preserved, changed: false };\n  }\n\n  return {\n    content: result,\n    added: totalAdded,\n    preserved,\n    changed: true,\n  };\n}\n","/**\n * Deep merge two parsed JSON values.\n *\n * - Objects: recursively merge, preserving existing keys not in generated\n * - Arrays: generated replaces existing entirely (generated owns array contents)\n * - Primitives: generated wins\n */\nexport function deepMergeJson(existing: unknown, generated: unknown): unknown {\n  if (\n    typeof existing === 'object' &&\n    existing !== null &&\n    !Array.isArray(existing) &&\n    typeof generated === 'object' &&\n    generated !== null &&\n    !Array.isArray(generated)\n  ) {\n    const merged: Record<string, unknown> = { ...(existing as Record<string, unknown>) };\n    for (const [key, value] of Object.entries(generated as Record<string, unknown>)) {\n      if (key in merged) {\n        merged[key] = deepMergeJson(merged[key], value);\n      } else {\n        merged[key] = value;\n      }\n    }\n    return merged;\n  }\n\n  // Arrays and primitives: generated wins\n  return generated;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { mergeIntoExisting, hasGrammar, extractClassEndLines, extractStatements } from './merger.js';\nimport { deepMergeJson } from './json-merge.js';\nimport { getMergeAdapter } from './merge-adapters/index.js';\n\nexport interface WriteOptions {\n  /** The emitter language (e.g., \"node\", \"ruby\"). Used to select the\n   *  tree-sitter grammar for AST-level merging. */\n  language?: string;\n  /** The auto-generated file header string. */\n  header?: string;\n}\n\nexport interface WriteResult {\n  written: string[];\n  merged: string[];\n  skipped: string[];\n  identical: string[];\n  ignored: string[];\n}\n\n/**\n * Write generated files to disk with AST-level merging.\n *\n * When a file already exists:\n * - skipIfExists → leave it alone entirely\n * - AST merge available → parse both, append only new symbols\n * - No grammar → skip (never clobber hand-written code)\n *\n * New files are always written in full.\n */\nexport async function writeFiles(\n  files: GeneratedFile[],\n  outputDir: string,\n  options?: WriteOptions,\n): Promise<WriteResult> {\n  const result: WriteResult = {\n    written: [],\n    merged: [],\n    skipped: [],\n    identical: [],\n    ignored: [],\n  };\n  const sorted = [...files].sort((a, b) => a.path.localeCompare(b.path));\n  const language = options?.language;\n  const header = options?.header ?? '';\n\n  for (const file of sorted) {\n    const fullPath = path.join(outputDir, file.path);\n\n    // Repair on-disk casing when an emitter renames a generated file in a\n    // case-only way (e.g. `AuthenticationMfaFailed.kt` → `AuthenticationMFAFailed.kt`\n    // after adding `MFA` to an acronym list). On case-insensitive filesystems\n    // (APFS, NTFS) `writeFile` would otherwise reuse the existing inode and\n    // preserve the stale casing — surfacing later as ktlint/eslint errors.\n    await renameMismatchedCasing(fullPath);\n\n    // Check if file already exists\n    let existingContent: string | null = null;\n    try {\n      existingContent = await fs.readFile(fullPath, 'utf-8');\n    } catch {\n      // File doesn't exist\n    }\n\n    // New file → write in full\n    if (existingContent === null) {\n      await fs.mkdir(path.dirname(fullPath), { recursive: true });\n      await fs.writeFile(fullPath, file.content, 'utf-8');\n      result.written.push(file.path);\n      continue;\n    }\n\n    // skipIfExists → hard skip, no merge (but ensure header is present).\n    // JSON files are skipped from header injection because a leading `//`\n    // comment makes the file invalid JSON.\n    if (file.skipIfExists) {\n      if (header && !existingContent.startsWith(header) && !file.path.endsWith('.json')) {\n        await fs.writeFile(fullPath, header + '\\n\\n' + existingContent, 'utf-8');\n      }\n      result.skipped.push(file.path);\n      continue;\n    }\n\n    // @oagen-ignore-file → skip entirely (existing file opts out of all generation)\n    if (existingContent.includes('@oagen-ignore-file')) {\n      result.ignored.push(file.path);\n      continue;\n    }\n\n    // Don't merge test files into hand-written test files — generated tests are\n    // designed for the standalone generated SDK and will have wrong\n    // signatures/fixtures when merged into hand-written tests.\n    // However, if the existing test file is itself auto-generated (has the oagen\n    // header), allow overwriteExisting to take effect so new methods get coverage.\n    const adapter = language ? getMergeAdapter(language) : undefined;\n    const isTestFile = adapter?.testFilePatterns\n      ? adapter.testFilePatterns.some((p) => p.test(file.path))\n      : isDefaultTestFile(file.path);\n    if (isTestFile) {\n      const isExistingAutoGenerated = header && existingContent.startsWith(header);\n      if (!isExistingAutoGenerated && !file.overwriteExisting) {\n        result.skipped.push(file.path);\n        continue;\n      }\n      // Auto-generated test file or overwriteExisting — fall through to overwriteExisting / identical checks\n    }\n\n    // Identical content → no-op\n    if (existingContent === file.content) {\n      result.identical.push(file.path);\n      continue;\n    }\n\n    // Force overwrite — but preserve any @oagen-ignore regions from existing content\n    if (file.overwriteExisting) {\n      const content =\n        existingContent.includes('@oagen-ignore-start') && language && hasGrammar(language)\n          ? await overwriteWithPreservedRegions(existingContent, file.content, language)\n          : file.content;\n      await fs.writeFile(fullPath, content, 'utf-8');\n      result.written.push(file.path);\n      continue;\n    }\n\n    // JSON files → deep merge preserving existing keys\n    if (file.path.endsWith('.json')) {\n      try {\n        const existingJson = JSON.parse(existingContent);\n        const generatedJson = JSON.parse(file.content);\n        const merged = deepMergeJson(existingJson, generatedJson);\n        const mergedContent = JSON.stringify(merged, null, 2) + '\\n';\n        if (mergedContent === existingContent) {\n          result.identical.push(file.path);\n        } else {\n          await fs.writeFile(fullPath, mergedContent, 'utf-8');\n          result.merged.push(file.path);\n        }\n      } catch {\n        // Parse failed — fall back to overwrite\n        await fs.writeFile(fullPath, file.content, 'utf-8');\n        result.written.push(file.path);\n      }\n      continue;\n    }\n\n    // Source files with grammar → AST-level merge\n    if (language && hasGrammar(language)) {\n      try {\n        const mergeResult = await mergeIntoExisting(existingContent, file.content, language, header);\n\n        // Ensure header is present on merged content\n        let finalContent = mergeResult.content;\n        if (header && !finalContent.startsWith(header)) {\n          finalContent = header + '\\n\\n' + finalContent;\n        }\n\n        if (!mergeResult.changed && finalContent === existingContent) {\n          result.identical.push(file.path);\n          continue;\n        }\n\n        await fs.writeFile(fullPath, finalContent, 'utf-8');\n        result.merged.push(file.path);\n        continue;\n      } catch (err) {\n        // AST merge failed (e.g. tree-sitter grammar ABI issue) — fall back to overwrite\n        console.warn(\n          `[oagen] AST merge failed for ${file.path}, falling back to overwrite.${err instanceof Error ? ` ${err.message}` : ''}`,\n        );\n        await fs.writeFile(fullPath, file.content, 'utf-8');\n        result.written.push(file.path);\n        continue;\n      }\n    }\n\n    // No grammar available → skip to avoid clobbering\n    result.skipped.push(file.path);\n  }\n\n  return result;\n}\n\n/**\n * If a sibling exists with the same name except for letter case, rename it to\n * the requested casing. Uses a two-step rename via a temporary unique name so\n * case-insensitive filesystems (APFS on macOS, NTFS on Windows) actually\n * update the entry — `rename('Foo', 'FOO')` is a no-op on those systems.\n */\nasync function renameMismatchedCasing(fullPath: string): Promise<void> {\n  const dir = path.dirname(fullPath);\n  const target = path.basename(fullPath);\n  let entries: string[];\n  try {\n    entries = await fs.readdir(dir);\n  } catch {\n    return;\n  }\n  if (entries.includes(target)) return;\n  const targetLower = target.toLowerCase();\n  const mismatch = entries.find((e) => e.toLowerCase() === targetLower);\n  if (!mismatch) return;\n  const oldPath = path.join(dir, mismatch);\n  const tempPath = path.join(dir, `.oagen-case-${process.pid}-${Date.now()}-${target}`);\n  await fs.rename(oldPath, tempPath);\n  await fs.rename(tempPath, fullPath);\n}\n\n/** Comprehensive fallback when no adapter is available. */\nfunction isDefaultTestFile(filePath: string): boolean {\n  return (\n    /\\.(spec|test)\\.[jt]sx?$/.test(filePath) ||\n    filePath.endsWith('_test.go') ||\n    filePath.endsWith('_test.rb') ||\n    filePath.endsWith('_spec.rb') ||\n    /(?:^|\\/)test_.*\\.py$/.test(filePath) ||\n    filePath.endsWith('_test.py') ||\n    filePath.endsWith('Test.php') ||\n    filePath.endsWith('_test.rs') ||\n    /(?:^|\\/)tests\\/.*\\.rs$/.test(filePath)\n  );\n}\n\n// --- @oagen-ignore region preservation for overwriteExisting ---\n\n/**\n * Overwrite a file with generated content while preserving\n * `@oagen-ignore-start` / `@oagen-ignore-end` regions (and their\n * required imports) from the existing file.\n *\n * Uses tree-sitter via `extractClassEndLines` to find accurate class\n * boundaries so ignore blocks are inserted at the correct position even\n * when docstrings contain unindented text.\n */\nexport async function overwriteWithPreservedRegions(\n  existingContent: string,\n  generatedContent: string,\n  language: string,\n): Promise<string> {\n  const existingLines = existingContent.split('\\n');\n  const generatedLines = generatedContent.split('\\n');\n\n  // 1. Extract ignore blocks, their containing class, and the anchor line\n  //    (first non-blank line after the block in the existing file).\n  const blocks: { containingClass: string; containingScope: string; lines: string[]; anchor: string }[] = [];\n  for (let i = 0; i < existingLines.length; i++) {\n    if (!existingLines[i].includes('@oagen-ignore-start')) continue;\n    const startIdx = i;\n    while (i < existingLines.length && !existingLines[i].includes('@oagen-ignore-end')) i++;\n    let anchor = '';\n    for (let a = i + 1; a < existingLines.length; a++) {\n      if (existingLines[a].trim()) {\n        anchor = existingLines[a].trimStart();\n        break;\n      }\n    }\n    blocks.push({\n      containingClass: findContainingClass(existingLines, startIdx),\n      containingScope: findContainingDescribeScope(existingLines, startIdx),\n      lines: existingLines.slice(startIdx, i + 1),\n      anchor,\n    });\n  }\n  if (blocks.length === 0) return generatedContent;\n\n  // 2. Splice extra imports from existing into generated.\n  // First strip any `@oagen-ignore-start`..`@oagen-ignore-end` regions the\n  // generator itself emitted: we are about to re-insert the on-disk versions,\n  // and if we left the generator's seed blocks in place we'd end up with two\n  // copies of every ignore block per regeneration (monotonically growing).\n  const result = stripIgnoreRegions(generatedLines);\n  spliceExtraImports(existingLines, result);\n\n  // 3. Build class-end map from the generated content (after import splicing)\n  //    via tree-sitter for accurate boundary detection.\n  const genSource = result.join('\\n');\n  const classEndLines = await extractClassEndLines(genSource, language);\n\n  // 4. Group ignore blocks by class and determine insertion points\n  const blocksByClass = new Map<string, Array<{ containingScope: string; lines: string[]; anchor: string }>>();\n  for (const b of blocks) {\n    if (!blocksByClass.has(b.containingClass)) blocksByClass.set(b.containingClass, []);\n    blocksByClass.get(b.containingClass)!.push({\n      containingScope: b.containingScope,\n      lines: b.lines,\n      anchor: b.anchor,\n    });\n  }\n\n  // 4a. Handle replacement blocks: ignore blocks that redefine their\n  //     containing class replace the generated class entirely.\n  //     Also handles top-level blocks (no containing class) that define\n  //     a class matching one in the generated content.\n  const replacedClasses = new Set<string>();\n  const handledBlockKeys = new Set<string>();\n  const replacements: {\n    startLine: number;\n    endLine: number;\n    content: string[];\n  }[] = [];\n  for (const [className, classBlocks] of blocksByClass) {\n    // Determine the target class for replacement.  When the block has a\n    // containing class, we check if the block redefines that class.  When\n    // there is no containing class (top-level ignore block), we look for a\n    // class definition inside the block that matches a generated class.\n    let targetClass = className;\n    if (!targetClass) {\n      for (const entry of classBlocks) {\n        for (const l of entry.lines) {\n          const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n          if (m && classEndLines.has(m[1])) {\n            targetClass = m[1];\n            break;\n          }\n        }\n        if (targetClass) break;\n      }\n    }\n    if (!targetClass) continue;\n    const isReplacement = classBlocks.some((entry) =>\n      entry.lines.some((l) => {\n        const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n        return m?.[1] === targetClass;\n      }),\n    );\n    if (!isReplacement) continue;\n    const info = classEndLines.get(targetClass);\n    if (!info) continue;\n    const startLine = findClassDeclarationStart(result, targetClass, info.bodyEndLine);\n    if (startLine < 0) continue;\n    const content: string[] = [];\n    for (const entry of classBlocks) {\n      content.push('');\n      content.push(...entry.lines);\n    }\n    replacements.push({ startLine, endLine: info.bodyEndLine, content });\n    replacedClasses.add(targetClass);\n    handledBlockKeys.add(className);\n  }\n  // Apply replacements bottom-up to preserve line indices\n  replacements.sort((a, b) => b.startLine - a.startLine);\n  for (const rep of replacements) {\n    result.splice(rep.startLine, rep.endLine - rep.startLine, ...rep.content);\n  }\n\n  // 4a-bis. Top-level declarations protected by ignore regions win over their\n  //         generated counterparts. For each top-level block, drop generated\n  //         declarations (interface/type/const/function/…) whose names are\n  //         declared inside the block; the block content replaces the first\n  //         such declaration in place. Without this, every regeneration\n  //         re-emits a duplicate of each region-protected declaration.\n  let regionDeclarationEdits = 0;\n  {\n    const topLevelEntries = blocksByClass.get('');\n    if (topLevelEntries) {\n      // When 4a already placed the top-level blocks (as part of a class\n      // replacement), only delete generated duplicates — never re-insert.\n      const alreadyPlaced = handledBlockKeys.has('');\n      const remaining: typeof topLevelEntries = [];\n      for (const entry of topLevelEntries) {\n        const outcome = await applyRegionDeclarationOverride(result, entry.lines, language, !alreadyPlaced);\n        if (outcome.edited) regionDeclarationEdits++;\n        if (!alreadyPlaced && !outcome.placed) remaining.push(entry);\n      }\n      if (!alreadyPlaced) {\n        if (remaining.length === 0) {\n          blocksByClass.delete('');\n        } else {\n          blocksByClass.set('', remaining);\n        }\n      }\n    }\n  }\n\n  // 4b. Standard insertions for non-replacement blocks\n  // Rebuild class end lines if replacements shifted line numbers.\n  let effectiveClassEndLines = classEndLines;\n  if (replacedClasses.size > 0 || regionDeclarationEdits > 0) {\n    effectiveClassEndLines = await extractClassEndLines(result.join('\\n'), language);\n  }\n\n  const insertions: { line: number; order: number; content: string[] }[] = [];\n  let insertionOrder = 0;\n  for (const [className, classBlocks] of blocksByClass) {\n    if (handledBlockKeys.has(className) || replacedClasses.has(className)) continue;\n    const info = className ? effectiveClassEndLines.get(className) : undefined;\n\n    // Insert each block individually so each can use its own anchor.\n    for (const entry of classBlocks) {\n      let insertLine: number | undefined;\n\n      // Try anchor-based positioning: find the first line in the generated\n      // file whose trimmed-start content matches the anchor (the first\n      // non-blank line that followed this block in the existing file).\n      // Skip anchors that are just punctuation (braces, etc.) since they\n      // match too many locations. Accept doc comment starters (/** /// #)\n      // as valid anchors since they're structurally meaningful.\n      // Also skip bare language keywords (`end`, `end;`, `end)`) that appear\n      // on many lines and would match the wrong location (e.g. nesting the\n      // block inside a Ruby method body instead of at class level).\n      const isAmbiguousAnchor = /^end[;)\\s]*$/.test(entry.anchor);\n      if (\n        entry.anchor &&\n        !entry.anchor.includes('@oagen-ignore') &&\n        !isAmbiguousAnchor &&\n        /[a-zA-Z]|^\\/\\*|^\\/\\//.test(entry.anchor)\n      ) {\n        for (let li = 0; li < result.length; li++) {\n          if (result[li].trimStart() === entry.anchor) {\n            insertLine = li;\n            break;\n          }\n        }\n      }\n\n      // Fallback: class body end, or for top-level import blocks, after the\n      // last import line (so they stay near the top of the file, not at the\n      // bottom where they'd trigger E402 lint errors).\n      if (insertLine === undefined) {\n        if (info) {\n          insertLine = info.bodyEndLine;\n        } else {\n          const scopeEndLine = entry.containingScope\n            ? findDescribeScopeEndLine(result, entry.containingScope)\n            : undefined;\n          const blockHasImportsFallback = entry.lines.some((l: string) => /^\\s*(import|from)\\s/.test(l));\n          if (scopeEndLine !== undefined) {\n            insertLine = scopeEndLine;\n          } else if (blockHasImportsFallback || hasTopLevelDeclaration(entry.lines)) {\n            let lastImportLine = 0;\n            for (let li = 0; li < result.length; li++) {\n              const trimmed = result[li].trimStart();\n              if (/^(import|from)\\s/.test(trimmed)) lastImportLine = li + 1;\n            }\n            insertLine = lastImportLine;\n          } else {\n            insertLine = result.length;\n          }\n        }\n      }\n\n      // When inserting an import-containing ignore block, move up past\n      // blank separator lines so the block sits flush with surrounding\n      // imports (e.g., Kotlin's ktlint forbids blank lines within import\n      // blocks).\n      const blockHasImports = entry.lines.some((l: string) => /^\\s*import\\s/.test(l));\n      if (blockHasImports) {\n        while (\n          insertLine >= 2 &&\n          result[insertLine - 1]?.trim() === '' &&\n          /^\\s*(import|using|from)\\s/.test(result[insertLine - 2] ?? '')\n        ) {\n          insertLine--;\n        }\n      }\n\n      // Skip the leading blank line when the block is adjacent to imports\n      // or already preceded by a blank line (avoids double-blank-line gaps).\n      // Exclude C# `using` directives — StyleCop SA1515 requires a blank\n      // line before comments, so collapsing breaks the build.\n      const prevLine = insertLine > 0 ? (result[insertLine - 1]?.trimStart() ?? '') : '';\n      const prevIsImport = /^import\\s/.test(prevLine) || /^from\\s/.test(prevLine);\n      const prevIsBlank = insertLine > 0 && prevLine === '';\n      const blockContent = prevIsImport || prevIsBlank ? [...entry.lines] : ['', ...entry.lines];\n      // Add a trailing blank line when the next line is a doc comment\n      // (C# SA1514 requires a blank line before `///` doc headers).\n      const nextLine = result[insertLine]?.trimStart() ?? '';\n      if (nextLine.startsWith('///')) {\n        blockContent.push('');\n      }\n      insertions.push({ line: insertLine, order: insertionOrder++, content: blockContent });\n    }\n  }\n\n  // Apply bottom-up to preserve line indices. Blocks with the same insertion\n  // line must be applied in reverse discovery order because each splice inserts\n  // at the same index; otherwise repeated generation flips their order.\n  insertions.sort((a, b) => b.line - a.line || b.order - a.order);\n  for (const ins of insertions) {\n    result.splice(ins.line, 0, ...ins.content);\n  }\n\n  removeDuplicateImportsCoveredByIgnoreBlocks(result);\n\n  return result.join('\\n');\n}\n\n/**\n * Remove every `@oagen-ignore-start`..`@oagen-ignore-end` region from the\n * supplied lines, collapsing stretches of blank lines that get left behind.\n * Used to drop generator-emitted seed blocks before splicing the on-disk\n * versions back in — otherwise every regen doubles up.\n */\nfunction stripIgnoreRegions(lines: string[]): string[] {\n  const out: string[] = [];\n  let skipping = false;\n  for (const line of lines) {\n    if (!skipping && line.includes('@oagen-ignore-start')) {\n      skipping = true;\n      // Drop a preceding blank line if we have one queued up — otherwise\n      // regen leaves a stray blank line above the spliced-in block.\n      while (out.length > 0 && out[out.length - 1].trim() === '') out.pop();\n      continue;\n    }\n    if (skipping) {\n      if (line.includes('@oagen-ignore-end')) skipping = false;\n      continue;\n    }\n    out.push(line);\n  }\n  return out;\n}\n\n/** Scan backwards from `lineIdx` to find the nearest class declaration name. */\nfunction findContainingClass(lines: string[], lineIdx: number): string {\n  if (/^\\S/.test(lines[lineIdx] ?? '')) return '';\n  // Allow leading whitespace and language-specific modifiers before `class`.\n  // Covers: `public class Foo` (C#/Java), `export class Foo` (TS),\n  // `class Foo` (Python/Ruby), `internal sealed class Foo` (C#), etc.\n  for (let j = lineIdx - 1; j >= 0; j--) {\n    const m = lines[j].match(\n      /^\\s*(?:(?:export|public|private|protected|internal|abstract|sealed|static|partial)\\s+)*class\\s+(\\w+)/,\n    );\n    if (m) return m[1];\n  }\n  return '';\n}\n\nfunction findContainingDescribeScope(lines: string[], lineIdx: number): string {\n  const markerLine = lines[lineIdx] ?? '';\n  if (/^\\S/.test(markerLine)) return '';\n  const markerIndent = leadingSpaces(markerLine);\n  for (let j = lineIdx - 1; j >= 0; j--) {\n    const line = lines[j];\n    const indent = leadingSpaces(line);\n    if (indent >= markerIndent) continue;\n    const match = line.match(/^\\s*describe\\((['\"`])(.+?)\\1\\s*,/);\n    if (match) return match[2];\n    if (/^\\s*(?:export\\s+)?class\\s+\\w+/.test(line)) return '';\n  }\n  return '';\n}\n\nfunction findDescribeScopeEndLine(lines: string[], scopeName: string): number | undefined {\n  for (let i = 0; i < lines.length; i++) {\n    const match = lines[i].match(/^\\s*describe\\((['\"`])(.+?)\\1\\s*,/);\n    if (!match || match[2] !== scopeName) continue;\n\n    let depth = 0;\n    for (let j = i; j < lines.length; j++) {\n      depth += countChar(lines[j], '{');\n      depth -= countChar(lines[j], '}');\n      if (j > i && depth <= 0) return j;\n    }\n  }\n  return undefined;\n}\n\nfunction leadingSpaces(line: string): number {\n  return line.match(/^\\s*/)?.[0].length ?? 0;\n}\n\nfunction countChar(line: string, char: string): number {\n  return [...line].filter((c) => c === char).length;\n}\n\nfunction hasTopLevelDeclaration(lines: string[]): boolean {\n  return lines.some((line) =>\n    /^(?:export\\s+)?(?:interface|type|class|function|const|let|var|enum)\\s+\\w+/.test(line.trim()),\n  );\n}\n\n/**\n * Find the start line of a class declaration (including decorators above it)\n * by scanning backwards from `beforeLine`.\n */\nfunction findClassDeclarationStart(lines: string[], className: string, beforeLine: number): number {\n  // Match optional indentation so Ruby/Python nested classes are found.\n  const classPattern = new RegExp(`^\\\\s*(?:export\\\\s+)?class\\\\s+${className}\\\\b`);\n  for (let i = beforeLine - 1; i >= 0; i--) {\n    if (!classPattern.test(lines[i])) continue;\n    // Scan backward past decorators\n    let start = i;\n    while (start > 0 && /^\\s*@\\w+/.test(lines[start - 1])) {\n      start--;\n    }\n    return start;\n  }\n  return -1;\n}\n\n// --- region-protected top-level declaration overrides ---\n\n/**\n * Conservative top-level declaration matcher for ignore-block content.\n * Matches column-0 declarations like `export interface X`, `type X = …`,\n * `const X = …`, `function X(…)`, `class X` (export optional). Names found\n * here are only acted on when the language's merge adapter also reports a\n * generated top-level statement with the same key, so false positives are\n * filtered by the real parser.\n */\nconst REGION_DECLARATION_PATTERN =\n  /^(?:export\\s+)?(?:declare\\s+)?(?:interface|type|enum|class|const|let|var|async\\s+function|function)\\s+([A-Za-z_$][\\w$]*)/;\n\n/** Extract top-level symbol names declared inside an ignore block's lines. */\nfunction collectRegionDeclaredNames(blockLines: string[]): Set<string> {\n  const names = new Set<string>();\n  for (const line of blockLines) {\n    if (line.includes('@oagen-ignore')) continue;\n    const m = line.match(REGION_DECLARATION_PATTERN);\n    if (m) names.add(m[1]);\n  }\n  return names;\n}\n\n/** Inclusive line ranges of `@oagen-ignore-start`..`@oagen-ignore-end` regions. */\nfunction collectIgnoreRegionLineRanges(lines: string[]): Array<{ start: number; end: number }> {\n  const ranges: Array<{ start: number; end: number }> = [];\n  let start = -1;\n  for (let i = 0; i < lines.length; i++) {\n    if (start === -1 && lines[i].includes('@oagen-ignore-start')) {\n      start = i;\n      continue;\n    }\n    if (start !== -1 && lines[i].includes('@oagen-ignore-end')) {\n      ranges.push({ start, end: i });\n      start = -1;\n    }\n  }\n  return ranges;\n}\n\n/**\n * Walk upward from a declaration's first line over its contiguous comment\n * block (doc comment), so the comment is dropped together with the\n * declaration. Stops at blank lines, region markers, and line 0 (a comment\n * on line 0 is the file header, not a docstring).\n */\nfunction extendOverPrecedingComments(lines: string[], startLine: number): number {\n  let s = startLine;\n  while (s > 1) {\n    const prev = lines[s - 1].trim();\n    if (prev === '' || prev.includes('@oagen-ignore')) break;\n    const isComment = prev.startsWith('//') || prev.startsWith('/*') || prev.startsWith('*') || prev.startsWith('#');\n    if (!isComment) break;\n    s--;\n  }\n  return s;\n}\n\n/**\n * Drop generated top-level declarations that are redeclared inside an ignore\n * block (\"region wins\"). When `placeBlock` is set and at least one generated\n * declaration matches, the block's lines replace the first match in place\n * (mirroring the class-replacement behavior above); any further matches are\n * deleted. Mutates `result` in place.\n *\n * Returns `placed` (the block content now lives in `result` and must not be\n * inserted again) and `edited` (line numbers shifted).\n */\nasync function applyRegionDeclarationOverride(\n  result: string[],\n  blockLines: string[],\n  language: string,\n  placeBlock: boolean,\n): Promise<{ placed: boolean; edited: boolean }> {\n  const names = collectRegionDeclaredNames(blockLines);\n  if (names.size === 0) return { placed: false, edited: false };\n\n  const source = result.join('\\n');\n  let parsed;\n  try {\n    parsed = await extractStatements(source, language);\n  } catch {\n    return { placed: false, edited: false };\n  }\n\n  const regionRanges = collectIgnoreRegionLineRanges(result);\n  const inRegion = (line: number) => regionRanges.some((r) => line >= r.start && line <= r.end);\n\n  const spans: Array<{ start: number; end: number }> = [];\n  for (const stmt of parsed.statements) {\n    if (stmt.kind !== 'declaration' || !stmt.key || !names.has(stmt.key)) continue;\n    // Locate the statement's line span; skip occurrences inside ignore\n    // regions (those ARE the protected content).\n    let idx = source.indexOf(stmt.text);\n    let startLine = -1;\n    while (idx !== -1) {\n      const line = source.slice(0, idx).split('\\n').length - 1;\n      if (!inRegion(line)) {\n        startLine = line;\n        break;\n      }\n      idx = source.indexOf(stmt.text, idx + 1);\n    }\n    if (startLine === -1) continue;\n    const endLine = startLine + stmt.text.split('\\n').length - 1;\n    spans.push({ start: extendOverPrecedingComments(result, startLine), end: endLine });\n  }\n  if (spans.length === 0) return { placed: false, edited: false };\n\n  spans.sort((a, b) => a.start - b.start);\n\n  // Delete all matches after the first, bottom-up to preserve indices.\n  for (let i = spans.length - 1; i >= 1; i--) {\n    const span = spans[i];\n    let deleteCount = span.end - span.start + 1;\n    // Collapse the blank separator the deletion leaves behind.\n    const prevBlank = span.start === 0 || (result[span.start - 1] ?? '').trim() === '';\n    const nextBlank = (result[span.end + 1] ?? '').trim() === '';\n    if (prevBlank && nextBlank && span.end + 1 < result.length) deleteCount++;\n    result.splice(span.start, deleteCount);\n  }\n\n  const first = spans[0];\n  if (placeBlock) {\n    result.splice(first.start, first.end - first.start + 1, ...blockLines);\n    return { placed: true, edited: true };\n  }\n\n  let deleteCount = first.end - first.start + 1;\n  const prevBlank = first.start === 0 || (result[first.start - 1] ?? '').trim() === '';\n  const nextBlank = (result[first.end + 1] ?? '').trim() === '';\n  if (prevBlank && nextBlank && first.end + 1 < result.length) deleteCount++;\n  result.splice(first.start, deleteCount);\n  return { placed: false, edited: true };\n}\n\n/**\n * Collect `from X import Y, Z` identifiers grouped by module, handling\n * both single-line and multiline (parenthesized) forms.\n */\nfunction collectFromImports(lines: string[]): Map<string, Set<string>> {\n  const byModule = new Map<string, Set<string>>();\n  for (let i = 0; i < lines.length; i++) {\n    if (!/^from\\s+/.test(lines[i])) continue;\n\n    let fullText = lines[i];\n    if (fullText.includes('(') && !fullText.includes(')')) {\n      while (i + 1 < lines.length) {\n        i++;\n        fullText += ' ' + lines[i].trim();\n        if (lines[i].includes(')')) break;\n      }\n    }\n\n    const normalized = fullText.replace(/[()]/g, '').replace(/\\s+/g, ' ').trim();\n    const match = normalized.match(/^from\\s+(\\S+)\\s+import\\s+(.+)$/);\n    if (!match) continue;\n\n    const mod = match[1];\n    if (!byModule.has(mod)) byModule.set(mod, new Set());\n    for (const id of match[2]\n      .split(',')\n      .map((s) => s.trim())\n      .filter(Boolean)) {\n      byModule.get(mod)!.add(id);\n    }\n  }\n  return byModule;\n}\n\n/**\n * Collected TypeScript imports grouped by form. Each map keys on the module\n * specifier (e.g. `./foo`, `node:fs`).\n */\ninterface TsImports {\n  /** `import { X, Y } from 'module'` — module → identifier names. */\n  named: Map<string, Set<string>>;\n  /** `import type { X } from 'module'` — module → identifier names. */\n  typeOnly: Map<string, Set<string>>;\n  /** `import X from 'module'` or `import type X from 'module'` — module → name. */\n  defaults: Map<string, string>;\n  /** `import * as X from 'module'` — module → namespace alias name. */\n  namespaces: Map<string, string>;\n  /** `import 'module'` — modules imported for side effects only. */\n  sideEffects: Set<string>;\n}\n\n/**\n * Collect TypeScript imports, grouped by form. Handles single-line and\n * multi-line `{ … }` named imports. Disjoint from Python's `from X import Y`\n * syntax so this can be called in parallel with `collectFromImports`.\n */\nfunction collectTsImports(lines: string[]): TsImports {\n  const out: TsImports = {\n    named: new Map(),\n    typeOnly: new Map(),\n    defaults: new Map(),\n    namespaces: new Map(),\n    sideEffects: new Set(),\n  };\n\n  for (let i = 0; i < lines.length; i++) {\n    const trimmed = lines[i].trim();\n    if (!/^import(\\s|$)/.test(trimmed)) continue;\n\n    // Accumulate multi-line `{ … }` imports.\n    let fullText = lines[i];\n    if (fullText.includes('{') && !fullText.includes('}')) {\n      while (i + 1 < lines.length) {\n        i++;\n        fullText += ' ' + lines[i].trim();\n        if (lines[i].includes('}')) break;\n      }\n    }\n\n    const normalized = fullText.replace(/\\s+/g, ' ').trim().replace(/;\\s*$/, '');\n\n    // `import 'module'`\n    let m = normalized.match(/^import\\s+['\"]([^'\"]+)['\"]$/);\n    if (m) {\n      out.sideEffects.add(m[1]);\n      continue;\n    }\n\n    // `import * as X from 'module'`\n    m = normalized.match(/^import\\s+\\*\\s+as\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n    if (m) {\n      out.namespaces.set(m[2], m[1]);\n      continue;\n    }\n\n    // `import [Default,] { X, Y as Z } from 'module'` or `import type { X } from 'module'`\n    m = normalized.match(/^import\\s+(type\\s+)?(?:(\\w+)\\s*,\\s*)?\\{\\s*([^}]*)\\s*\\}\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n    if (m) {\n      const isTypeOnly = !!m[1];\n      const defaultName = m[2];\n      const namesRaw = m[3];\n      const mod = m[4];\n      if (defaultName) out.defaults.set(mod, defaultName);\n      const names = namesRaw\n        .split(',')\n        .map((s) => s.trim().replace(/\\s+as\\s+\\w+$/, ''))\n        .filter(Boolean);\n      for (const rawName of names) {\n        const isInlineTypeOnly = rawName.startsWith('type ');\n        const name = rawName.replace(/^type\\s+/, '');\n        const target = isTypeOnly || isInlineTypeOnly ? out.typeOnly : out.named;\n        if (!target.has(mod)) target.set(mod, new Set());\n        target.get(mod)!.add(name);\n      }\n      continue;\n    }\n\n    // `import X from 'module'` or `import type X from 'module'`\n    m = normalized.match(/^import\\s+(?:type\\s+)?(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n    if (m) {\n      out.defaults.set(m[2], m[1]);\n      continue;\n    }\n  }\n\n  return out;\n}\n\n/**\n * Remove the given symbols from generated `import type` bindings, in place.\n *\n * Called when an existing *value* import for the same symbol is being spliced\n * back into the file. A value import satisfies both runtime and type uses, so\n * leaving the generated `import type { X }` would re-declare `X` (TS2300\n * duplicate identifier). Callers guarantee every symbol here is absent from\n * generated *value* imports, so each occurrence is type-only and safe to drop.\n *\n * Handles whole-line `import type { … }` and inline `import { …, type X }`,\n * single- or multi-line. A statement whose bindings all get stripped is\n * removed entirely.\n */\nfunction dropGeneratedTypeOnlyBindings(resultLines: string[], symbols: Set<string>): void {\n  if (symbols.size === 0) return;\n  const out: string[] = [];\n  for (let i = 0; i < resultLines.length; i++) {\n    const line = resultLines[i];\n    const trimmed = line.trim();\n    // Only named imports (with a brace) can carry the symbols we strip.\n    if (!/^import\\b/.test(trimmed) || !trimmed.includes('{')) {\n      out.push(line);\n      continue;\n    }\n    // Gather the full (possibly multi-line) `{ … }` statement.\n    const span = [line];\n    while (!span.join(' ').includes('}') && i + 1 < resultLines.length) {\n      i++;\n      span.push(resultLines[i]);\n    }\n    const normalized = span.join(' ').replace(/\\s+/g, ' ').trim().replace(/;\\s*$/, '');\n    const m = normalized.match(/^import\\s+(type\\s+)?(?:(\\w+)\\s*,\\s*)?\\{\\s*([^}]*)\\s*\\}\\s+from\\s+(['\"][^'\"]+['\"])$/);\n    if (!m) {\n      for (const s of span) out.push(s);\n      continue;\n    }\n    const isTypeOnly = !!m[1];\n    const defaultName = m[2];\n    const items = m[3]\n      .split(',')\n      .map((s) => s.trim())\n      .filter(Boolean);\n    const modQuoted = m[4];\n    const kept = items.filter((raw) => {\n      const isTypeBinding = isTypeOnly || raw.startsWith('type ');\n      const bare = raw.replace(/^type\\s+/, '');\n      return !(isTypeBinding && symbols.has(bare));\n    });\n    if (kept.length === items.length) {\n      // Nothing stripped — preserve the original lines verbatim.\n      for (const s of span) out.push(s);\n      continue;\n    }\n    if (kept.length === 0 && !defaultName) continue; // statement fully emptied\n    const lead = line.match(/^(\\s*)/)?.[1] ?? '';\n    const prefix = isTypeOnly ? 'import type ' : 'import ';\n    const defaultPart = defaultName ? `${defaultName}, ` : '';\n    out.push(`${lead}${prefix}${defaultPart}{ ${kept.join(', ')} } from ${modQuoted};`);\n  }\n  resultLines.splice(0, resultLines.length, ...out);\n}\n\n/**\n * Add imports from the existing file that are absent from the generated\n * result. Handles:\n *\n * - Python: `import X` and `from X import Y`\n * - TypeScript: `import { X } from 'module'`, `import type { X } from 'module'`,\n *   `import X from 'module'`, `import * as X from 'module'`, `import 'module'`\n * - PHP: `use Foo\\Bar;` and `use Foo\\Bar as Baz;` (namespace-qualified only)\n * - Ruby: `require '…'` and `require_relative '…'`\n *\n * Mutates `resultLines` in place.\n */\nfunction filterOutIgnoreRegions(lines: string[]): string[] {\n  const out: string[] = [];\n  let skipping = false;\n  for (const line of lines) {\n    if (!skipping && line.includes('@oagen-ignore-start')) {\n      skipping = true;\n      continue;\n    }\n    if (skipping) {\n      if (line.includes('@oagen-ignore-end')) skipping = false;\n      continue;\n    }\n    out.push(line);\n  }\n  return out;\n}\n\nfunction collectIgnoreRegionUsageText(lines: string[]): string {\n  const out: string[] = [];\n  let skipping = false;\n  for (const line of lines) {\n    if (!skipping && line.includes('@oagen-ignore-start')) {\n      skipping = true;\n      continue;\n    }\n    if (!skipping) continue;\n    if (/^\\s*(import|from)\\s/.test(line)) continue;\n    out.push(line);\n    if (line.includes('@oagen-ignore-end')) skipping = false;\n  }\n  return out.join('\\n');\n}\n\nfunction removeDuplicateImportsCoveredByIgnoreBlocks(lines: string[]): void {\n  const ignoredImports = new Set<string>();\n  const importStatements = collectImportStatements(lines);\n  for (const stmt of importStatements) {\n    if (stmt.inIgnore) ignoredImports.add(normalizeImportStatement(stmt.lines));\n  }\n  if (ignoredImports.size === 0) return;\n\n  for (const stmt of [...importStatements].reverse()) {\n    if (stmt.inIgnore) continue;\n    if (ignoredImports.has(normalizeImportStatement(stmt.lines))) {\n      lines.splice(stmt.start, stmt.end - stmt.start + 1);\n    }\n  }\n}\n\nfunction collectImportStatements(\n  lines: string[],\n): Array<{ start: number; end: number; lines: string[]; inIgnore: boolean }> {\n  const statements: Array<{ start: number; end: number; lines: string[]; inIgnore: boolean }> = [];\n  let inIgnore = false;\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i];\n    if (!inIgnore && line.includes('@oagen-ignore-start')) {\n      inIgnore = true;\n      continue;\n    }\n    if (inIgnore && line.includes('@oagen-ignore-end')) {\n      inIgnore = false;\n      continue;\n    }\n    if (!isImportLine(line)) continue;\n\n    const start = i;\n    let end = i;\n    const statementLines = [line];\n    const opens = (line.match(/[({]/g) ?? []).length;\n    const closes = (line.match(/[)}]/g) ?? []).length;\n    if (opens > closes) {\n      while (end + 1 < lines.length) {\n        end++;\n        statementLines.push(lines[end]);\n        if ((lines[end].match(/[)}]/g) ?? []).length > 0 && /\\bfrom\\b/.test(lines[end])) break;\n      }\n      i = end;\n    }\n    statements.push({ start, end, lines: statementLines, inIgnore });\n  }\n  return statements;\n}\n\nfunction normalizeImportStatement(lines: string[]): string {\n  return lines.join('\\n').replace(/,\\s*}/g, ' }').replace(/\\s+/g, ' ').trim();\n}\n\nfunction isImportLine(line: string): boolean {\n  const trimmed = line.trim();\n  return (\n    /^import(\\s|$)/.test(trimmed) ||\n    /^from\\s+/.test(trimmed) ||\n    /^use\\s+[\\w\\\\]/.test(trimmed) ||\n    /^require(_relative)?\\s+['\"]/.test(trimmed)\n  );\n}\n\nfunction identifierUsed(source: string, identifier: string): boolean {\n  return new RegExp(`\\\\b${identifier.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`).test(source);\n}\n\nfunction spliceExtraImports(existingLines: string[], resultLines: string[]): void {\n  // Imports inside @oagen-ignore regions are converted into normal imports\n  // only when non-import ignore content still references them. This prevents\n  // stale import-only ignore blocks from creating duplicate or unused imports.\n  const existingOutsideIgnore = filterOutIgnoreRegions(existingLines);\n  const ignoreRegionText = collectIgnoreRegionUsageText(existingLines);\n\n  // Python-style `import hashlib`. Excludes TS forms like `import X from '…'`\n  // (have a `from` clause) and TS multi-line type imports whose first line is\n  // `import type {` (have a brace) — both are handled by the TS collector\n  // below.\n  const isPythonSimpleImport = (l: string) => /^import\\s+\\w/.test(l) && !/\\sfrom\\s/.test(l) && !/[{}]/.test(l);\n\n  // Simple imports (import hashlib, import json, …)\n  const existingSimple = new Set(existingOutsideIgnore.filter(isPythonSimpleImport).map((l) => l.trim()));\n  const generatedSimple = new Set(resultLines.filter(isPythonSimpleImport).map((l) => l.trim()));\n  const extraSimple = [...existingSimple].filter((l) => !generatedSimple.has(l));\n\n  // From-imports — compare by module and find extra identifiers\n  const existingFrom = collectFromImports(existingOutsideIgnore);\n  const generatedFrom = collectFromImports(resultLines);\n\n  // Build a set of all identifiers imported by the generated file (across all modules)\n  // so we can detect when an existing barrel import's identifiers are covered by\n  // more-specific generated imports (e.g., `from x.y import Z` covers `from x import Z`).\n  const allGeneratedIds = new Set<string>();\n  for (const ids of generatedFrom.values()) {\n    for (const id of ids) allGeneratedIds.add(id);\n  }\n\n  const extraFromLines: string[] = [];\n  for (const [mod, existIds] of existingFrom) {\n    const genIds = generatedFrom.get(mod);\n    if (!genIds) {\n      // The exact module isn't in the generated file — but check whether every\n      // identifier is already imported from a different (e.g., more-specific) module.\n      const extra = [...existIds].filter((id) => !allGeneratedIds.has(id));\n      if (extra.length > 0) {\n        extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n      }\n    } else {\n      const extra = [...existIds].filter((id) => !genIds.has(id) && !allGeneratedIds.has(id));\n      if (extra.length > 0) {\n        extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n      }\n    }\n  }\n\n  // TypeScript imports.\n  const existingTs = collectTsImports(existingOutsideIgnore);\n  const generatedTs = collectTsImports(resultLines);\n  const extraTsLines: string[] = [];\n\n  // Bindings the generated file imports anywhere, split by capability.\n  //\n  // `allGeneratedTsIds` — every binding regardless of module. The generator\n  // frequently imports a symbol from a concrete file\n  // (`./interfaces/connection.interface`) while the existing hand-written file\n  // imported the same symbol from a barrel (`./interfaces`). Splicing the\n  // barrel form back in would re-declare the binding (TS2300 duplicate\n  // identifier), so a symbol already in scope satisfies a *type* use and is\n  // never re-imported as a type even from a different specifier.\n  //\n  // `generatedValueIds` — only runtime-capable bindings (named / default /\n  // namespace, never `import type`). A *value* use is satisfied only by one of\n  // these: an `import type` binding is erased at compile time and cannot back a\n  // runtime reference inside a preserved region. So a generated `import type`\n  // must NOT suppress an existing value import of the same symbol.\n  const allGeneratedTsIds = new Set<string>();\n  const generatedValueIds = new Set<string>();\n  for (const ids of generatedTs.named.values())\n    for (const id of ids) {\n      allGeneratedTsIds.add(id);\n      generatedValueIds.add(id);\n    }\n  for (const ids of generatedTs.typeOnly.values()) for (const id of ids) allGeneratedTsIds.add(id);\n  for (const name of generatedTs.defaults.values()) {\n    allGeneratedTsIds.add(name);\n    generatedValueIds.add(name);\n  }\n  for (const name of generatedTs.namespaces.values()) {\n    allGeneratedTsIds.add(name);\n    generatedValueIds.add(name);\n  }\n\n  // Symbols the generated file imports type-only that we are nonetheless\n  // re-splicing as value imports (because a preserved region needs the runtime\n  // binding). The spliced value import also covers the type use, so the\n  // generated `import type` for the symbol must be dropped or the two collide\n  // (TS2300). Collected during the loops below, applied just before splicing.\n  const reclaimedValueIds = new Set<string>();\n  const generatedHasValue = (id: string): boolean => generatedValueIds.has(id);\n  const generatedHasTypeOnly = (id: string): boolean => allGeneratedTsIds.has(id) && !generatedValueIds.has(id);\n\n  for (const mod of existingTs.sideEffects) {\n    if (!generatedTs.sideEffects.has(mod)) extraTsLines.push(`import '${mod}';`);\n  }\n  for (const [mod, name] of existingTs.defaults) {\n    if (generatedTs.defaults.has(mod)) continue;\n    if (!identifierUsed(ignoreRegionText, name)) continue;\n    if (generatedHasValue(name)) continue;\n    if (generatedHasTypeOnly(name)) reclaimedValueIds.add(name);\n    extraTsLines.push(`import ${name} from '${mod}';`);\n  }\n  for (const [mod, name] of existingTs.namespaces) {\n    if (!identifierUsed(ignoreRegionText, name)) continue;\n    if (generatedHasValue(name)) continue;\n    if (generatedTs.namespaces.has(mod)) continue;\n    if (generatedHasTypeOnly(name)) reclaimedValueIds.add(name);\n    extraTsLines.push(`import * as ${name} from '${mod}';`);\n  }\n  for (const [mod, existIds] of existingTs.named) {\n    const extra = [...existIds].filter((id) => !generatedHasValue(id) && identifierUsed(ignoreRegionText, id));\n    for (const id of extra) if (generatedHasTypeOnly(id)) reclaimedValueIds.add(id);\n    if (extra.length > 0) extraTsLines.push(`import { ${extra.join(', ')} } from '${mod}';`);\n  }\n  for (const [mod, existIds] of existingTs.typeOnly) {\n    const extra = [...existIds].filter((id) => !allGeneratedTsIds.has(id) && identifierUsed(ignoreRegionText, id));\n    if (extra.length > 0) extraTsLines.push(`import type { ${extra.join(', ')} } from '${mod}';`);\n  }\n\n  // Drop reclaimed symbols from generated `import type` lines so the value\n  // imports spliced above do not duplicate them.\n  dropGeneratedTypeOnlyBindings(resultLines, reclaimedValueIds);\n\n  // PHP `use Foo\\Bar;` and `use Foo\\Bar as Baz;` — namespace-qualified only\n  // (a backslash anywhere in the path) so this doesn't mistakenly hoist\n  // single-segment in-class trait references like `use TraitName;`.\n  const isPhpUseImport = (l: string) => /^use\\s+[\\w\\\\]+\\\\[\\w\\\\]*(\\s+as\\s+\\w+)?\\s*;?$/.test(l);\n  const existingPhpUse = new Set(existingOutsideIgnore.filter(isPhpUseImport).map((l) => l.trim()));\n  const generatedPhpUse = new Set(resultLines.filter(isPhpUseImport).map((l) => l.trim()));\n  const extraPhpUse = [...existingPhpUse].filter((l) => !generatedPhpUse.has(l));\n\n  // Ruby `require '...'` and `require_relative '...'`. Dedupe by (kind, path)\n  // so quote style differs without producing duplicates — e.g. when the\n  // emitter writes `require 'json'` but a Ruby formatter has rewritten the\n  // on-disk copy to `require \"json\"`.\n  const rubyRequireRe = /^(require(?:_relative)?)\\s+['\"]([^'\"]+)['\"]\\s*$/;\n  const rubyRequireKey = (l: string): string | undefined => {\n    const m = l.trim().match(rubyRequireRe);\n    return m ? `${m[1]}\\t${m[2]}` : undefined;\n  };\n  const generatedRubyRequireKeys = new Set<string>();\n  for (const l of resultLines) {\n    const key = rubyRequireKey(l);\n    if (key) generatedRubyRequireKeys.add(key);\n  }\n  const seenExistingKeys = new Set<string>();\n  const extraRubyRequire: string[] = [];\n  for (const l of existingOutsideIgnore) {\n    const key = rubyRequireKey(l);\n    if (!key) continue;\n    if (generatedRubyRequireKeys.has(key)) continue;\n    if (seenExistingKeys.has(key)) continue;\n    seenExistingKeys.add(key);\n    extraRubyRequire.push(l.trim());\n  }\n\n  const allExtra = [...extraSimple, ...extraFromLines, ...extraTsLines, ...extraPhpUse, ...extraRubyRequire];\n  if (allExtra.length === 0) return;\n\n  // Find last import line in resultLines (accounting for multiline imports).\n  // Recognizes Python (`from X import Y`, `import X`), TS (`import …`), PHP\n  // (`use …`), and Ruby (`require`, `require_relative`).\n  const isImportStart = (l: string) =>\n    /^\\s*import(\\s|$)/.test(l) ||\n    /^from\\s+/.test(l) ||\n    /^\\s*use\\s+[\\w\\\\]/.test(l) ||\n    /^\\s*require(_relative)?\\s+['\"]/.test(l);\n  let lastImportIdx = -1;\n  for (let i = 0; i < resultLines.length; i++) {\n    if (!isImportStart(resultLines[i])) continue;\n    lastImportIdx = i;\n    const opens = (resultLines[i].match(/[({]/g) ?? []).length;\n    const closes = (resultLines[i].match(/[)}]/g) ?? []).length;\n    if (opens > closes) {\n      while (i + 1 < resultLines.length) {\n        i++;\n        lastImportIdx = i;\n        if ((resultLines[i].match(/[)}]/g) ?? []).length > 0) break;\n      }\n    }\n  }\n\n  if (lastImportIdx >= 0) {\n    resultLines.splice(lastImportIdx + 1, 0, ...allExtra);\n    return;\n  }\n\n  // No import survived in the generated file (e.g. its only import was a\n  // type-only line reclaimed above). Insert after any leading comment header\n  // so the spliced imports still land at the top of the file.\n  let insertAt = 0;\n  let inBlockComment = false;\n  for (let i = 0; i < resultLines.length; i++) {\n    const t = resultLines[i].trim();\n    if (inBlockComment) {\n      insertAt = i + 1;\n      if (t.includes('*/')) inBlockComment = false;\n      continue;\n    }\n    if (t.startsWith('//')) {\n      insertAt = i + 1;\n      continue;\n    }\n    if (t.startsWith('/*')) {\n      insertAt = i + 1;\n      inBlockComment = !t.includes('*/');\n      continue;\n    }\n    break; // first blank or code line — stop here\n  }\n  resultLines.splice(insertAt, 0, ...allExtra);\n}\n","import type { ApiSpec, Service, Operation, HttpMethod } from './types.js';\n\n/** Minimal snake_case converter for path segments (avoids cross-layer import). */\nfunction toSnake(s: string): string {\n  return s\n    .replace(/([a-z])([A-Z])/g, '$1_$2')\n    .replace(/[-\\s.]+/g, '_')\n    .toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// Hint types — consumer-provided overrides for operation resolution\n// ---------------------------------------------------------------------------\n\n/** Per-operation override keyed by \"METHOD /path\" (e.g. \"POST /auth/token\"). */\nexport interface OperationHint {\n  /** Override the algorithm-derived method name. */\n  name?: string;\n  /** Remount this operation to a different service/namespace (PascalCase). */\n  mountOn?: string;\n  /** Split a union-body operation into N typed wrapper methods. */\n  split?: SplitHint[];\n  /** Inject constant body defaults (e.g. { grant_type: 'password' }). */\n  defaults?: Record<string, string | number | boolean>;\n  /** Fields the SDK reads from client config at runtime (e.g. ['client_id']). */\n  inferFromClient?: string[];\n  /**\n   * Marks this operation as a URL builder rather than a real HTTP call. Emitters\n   * should generate a method that returns the constructed URL (typically as a\n   * string) without performing any I/O. Used for OAuth-style redirect endpoints\n   * such as /auth/authorize and /accounts/sessions/logout.\n   */\n  urlBuilder?: boolean;\n}\n\nexport interface SplitHint {\n  /** Wrapper method name (snake_case). */\n  name: string;\n  /** The discriminated union variant model name (e.g. 'PasswordSessionAuthenticateRequest'). */\n  targetVariant: string;\n  /** Constant body fields injected by the wrapper. */\n  defaults?: Record<string, string | number | boolean>;\n  /** Fields the SDK reads from client config at runtime. */\n  inferFromClient?: string[];\n  /** Only these body fields are exposed as method params. If omitted, all non-default/non-inferred fields are exposed. */\n  exposedParams?: string[];\n  /**\n   * Subset of exposedParams that should be emitted as optional even when the\n   * variant model would otherwise mark them required (or when the variant has\n   * no addressable model, as happens for inline oneOf branches).\n   */\n  optionalParams?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Resolved output — consumed by emitters\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedOperation {\n  /** The original IR operation (preserves description, params, types, etc.). */\n  operation: Operation;\n  /** The original IR service that owns this operation. */\n  service: Service;\n  /** Resolved snake_case method name (emitters convert to their convention). */\n  methodName: string;\n  /** Resolved target service/namespace (PascalCase). */\n  mountOn: string;\n  /** For split operations: one wrapper per union variant. */\n  wrappers?: ResolvedWrapper[];\n  /** Constant defaults injected into query/body at runtime (from operation-level hint). */\n  defaults: Record<string, string | number | boolean>;\n  /** Fields the SDK reads from client config at runtime (from operation-level hint). */\n  inferFromClient: string[];\n  /** Marks this operation as a URL builder; emitters should not generate an HTTP call. */\n  urlBuilder: boolean;\n}\n\nexport interface ResolvedWrapper {\n  /** Wrapper method name (snake_case). */\n  name: string;\n  /** The discriminated union variant model name. */\n  targetVariant: string;\n  /** Constant body defaults injected by the wrapper. */\n  defaults: Record<string, string | number | boolean>;\n  /** Fields read from client config at runtime. */\n  inferFromClient: string[];\n  /** Body fields exposed as method params. */\n  exposedParams: string[];\n  /** Optional body fields (not required in the variant). */\n  optionalParams: string[];\n  /** Response model name (if any). */\n  responseModelName: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Algorithm\n// ---------------------------------------------------------------------------\n\n/**\n * Action verbs recognised at the terminal path segment.\n * When a path ends with one of these, we use it as the verb instead of\n * deriving a CRUD verb from the HTTP method.\n */\nconst ACTION_VERBS = new Set([\n  'accept',\n  'activate',\n  'authorize',\n  'challenge',\n  'check',\n  'complete',\n  'confirm',\n  'deactivate',\n  'disable',\n  'enable',\n  'enroll',\n  'generate',\n  'reactivate',\n  'resend',\n  'revoke',\n  'send',\n  'verify',\n]);\n\n/** Map HTTP method → default CRUD verb. */\nconst CRUD_VERB: Record<HttpMethod, string> = {\n  get: 'list',\n  post: 'create',\n  put: 'update',\n  patch: 'update',\n  delete: 'delete',\n  head: 'get',\n  options: 'list',\n  trace: 'list',\n};\n\n/**\n * Naive singularization: strips trailing \"s\" with common-sense exceptions.\n * Good enough for API resource nouns; not a general-purpose English stemmer.\n */\nfunction singularize(word: string): string {\n  if (word.length <= 2) return word;\n  if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\n  if (\n    word.endsWith('ses') ||\n    word.endsWith('zes') ||\n    word.endsWith('xes') ||\n    word.endsWith('ches') ||\n    word.endsWith('shes')\n  ) {\n    return word.slice(0, -2);\n  }\n  if (word.endsWith('ss') || word.endsWith('us') || word.endsWith('is')) return word;\n  if (word.endsWith('s')) return word.slice(0, -1);\n  return word;\n}\n\n/**\n * Derive a snake_case method name from an operation's HTTP method and path.\n *\n * Rules:\n * 1. Strip path-param segments (`{id}`, `{slug}`, etc.)\n * 2. If the terminal segment is an action verb, use it as the verb\n * 3. Otherwise, use the CRUD verb for the HTTP method\n * 4. For GET on a collection (no trailing {id}), use \"list\"; with {id}, use \"get\"\n * 5. For POST on a resource path, if only one path param, use \"create\" singular\n * 6. Singularize the resource noun for single-resource operations\n */\nexport function deriveMethodName(op: Operation, _service: Service): string {\n  const segments = op.path.split('/').filter(Boolean);\n\n  // Separate static segments from param segments\n  const staticSegments: string[] = [];\n  let trailingParam = false;\n  for (const seg of segments) {\n    if (seg.startsWith('{') && seg.endsWith('}')) {\n      trailingParam = true;\n    } else {\n      staticSegments.push(seg);\n      trailingParam = false;\n    }\n  }\n\n  if (staticSegments.length === 0) {\n    return `${CRUD_VERB[op.httpMethod] ?? 'get'}_root`;\n  }\n\n  const terminal = toSnake(staticSegments[staticSegments.length - 1]);\n\n  // Check if terminal is an action verb\n  if (ACTION_VERBS.has(terminal)) {\n    // Resource context from preceding segments\n    const context = staticSegments.slice(0, -1).filter((s) => !s.startsWith('{'));\n    const resource = context.length > 0 ? toSnake(singularize(context[context.length - 1])) : '';\n    if (resource) {\n      return `${terminal}_${resource}`;\n    }\n    return terminal;\n  }\n\n  // Determine verb from HTTP method\n  let verb = CRUD_VERB[op.httpMethod] ?? 'get';\n\n  // GET with trailing {id} → \"get\" instead of \"list\"\n  if (op.httpMethod === 'get' && trailingParam) {\n    verb = 'get';\n  }\n\n  // Build resource name from static segments.\n  // When path params separate static segments, include the penultimate static\n  // segment (singularized) as a parent-context prefix to disambiguate nested paths.\n  // e.g. /projects/{id}/roles → \"project_roles\"\n  let resource = toSnake(terminal);\n  if (staticSegments.length >= 2) {\n    const penultimate = staticSegments[staticSegments.length - 2];\n    // Check if a path param appears between the penultimate and terminal segments\n    // in the original path by finding both positions and looking for {…} between them.\n    const penIdx = segments.lastIndexOf(penultimate);\n    const termIdx = segments.lastIndexOf(staticSegments[staticSegments.length - 1]);\n    const hasParamBetween = segments.slice(penIdx + 1, termIdx).some((s) => s.startsWith('{'));\n    if (hasParamBetween) {\n      const prefix = toSnake(singularize(penultimate));\n      resource = `${prefix}_${resource}`;\n    }\n  }\n\n  // Singularize when:\n  //   * there's a trailing path param (single-resource read/update/delete), or\n  //   * the verb itself implies a single-resource operation (e.g. POST → create\n  //     always creates one item even when posted to a collection endpoint).\n  const isSingleResource = trailingParam || verb === 'create';\n  const noun = isSingleResource ? singularize(resource) : resource;\n\n  // For \"list\" verb, keep plural\n  const finalNoun = verb === 'list' ? resource : noun;\n\n  return `${verb}_${finalNoun}`;\n}\n\n/**\n * Resolve all operations in the spec, applying hints and mount rules.\n *\n * @param spec - The parsed API spec\n * @param hints - Per-operation overrides keyed by \"METHOD /path\"\n * @param mountRules - Service name → target service mappings\n * @returns Resolved operations ready for emitter consumption\n */\nexport function resolveOperations(\n  spec: ApiSpec,\n  hints?: Record<string, OperationHint>,\n  mountRules?: Record<string, string>,\n): ResolvedOperation[] {\n  const resolved: ResolvedOperation[] = [];\n  const hintMap = hints ?? {};\n  const mounts = mountRules ?? {};\n\n  for (const service of spec.services) {\n    for (const op of service.operations) {\n      const key = `${op.httpMethod.toUpperCase()} ${op.path}`;\n      const hint = hintMap[key];\n\n      // Resolve method name: hint > algorithm\n      const methodName = hint?.name ?? deriveMethodName(op, service);\n\n      // Resolve mount target: per-op hint > service mount rule > original service\n      const mountOn = hint?.mountOn ?? mounts[service.name] ?? service.name;\n\n      // Build wrappers for split operations\n      let wrappers: ResolvedWrapper[] | undefined;\n      if (hint?.split) {\n        wrappers = hint.split.map((sh) => ({\n          name: sh.name,\n          targetVariant: sh.targetVariant,\n          defaults: sh.defaults ?? {},\n          inferFromClient: sh.inferFromClient ?? [],\n          exposedParams: sh.exposedParams ?? [],\n          optionalParams: sh.optionalParams ?? [],\n          responseModelName: resolveResponseModelName(op),\n        }));\n      }\n\n      resolved.push({\n        operation: op,\n        service,\n        methodName,\n        mountOn,\n        wrappers,\n        defaults: hint?.defaults ?? {},\n        inferFromClient: hint?.inferFromClient ?? [],\n        urlBuilder: hint?.urlBuilder ?? false,\n      });\n    }\n  }\n\n  return resolved;\n}\n\n/** Extract the response model name from an operation (for wrapper metadata). */\nfunction resolveResponseModelName(op: Operation): string | null {\n  if (op.httpMethod === 'delete') return null;\n  const ref = op.response;\n  if (ref.kind === 'model') return ref.name;\n  if (ref.kind === 'nullable' && ref.inner.kind === 'model') return ref.inner.name;\n  return null;\n}\n","import type { ApiSpec, Model, TypeRef, Service } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport type { Emitter, EmitterContext, GeneratedFile, OperationsMap } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { toSnakeCase } from '../utils/naming.js';\n\nexport function buildEmitterContext(\n  spec: ApiSpec,\n  options: {\n    namespace: string;\n    outputDir: string;\n    apiSurface?: ApiSurface;\n    overlayLookup?: OverlayLookup;\n    operationHints?: Record<string, OperationHint>;\n    mountRules?: Record<string, string>;\n    modelHints?: Record<string, string>;\n    emitterOptions?: Record<string, unknown>;\n    target?: string;\n    priorTargetManifestPaths?: Set<string>;\n    scopedServices?: Set<string>;\n  },\n): EmitterContext {\n  const resolvedOperations = resolveOperations(spec, options.operationHints, options.mountRules);\n\n  // In a scoped run, derive the model/enum allow-lists = names reachable\n  // from the SELECTED source services (those whose post-mount target is selected).\n  // Emitters write a model/enum FILE only when it is in these sets, so a\n  // non-selected service's exclusive models are left untouched (no leak) while\n  // shared models reachable from the selection still emit. Barrels stay full.\n  let scopedModelNames: Set<string> | undefined;\n  let scopedEnumNames: Set<string> | undefined;\n  if (options.scopedServices && options.scopedServices.size > 0) {\n    const selected = options.scopedServices;\n    const selectedSourceServices = spec.services.filter((s) =>\n      resolvedOperations.some((r) => r.service.name === s.name && selected.has(r.mountOn)),\n    );\n    const reachable = collectReferencedNames(selectedSourceServices, spec.models, { preserveAllDiscriminated: false });\n    scopedModelNames = reachable.models;\n    scopedEnumNames = reachable.enums;\n  }\n\n  return {\n    namespace: toSnakeCase(options.namespace),\n    namespacePascal: options.namespace,\n    spec,\n    outputDir: options.outputDir,\n    apiSurface: options.apiSurface,\n    overlayLookup: options.overlayLookup,\n    resolvedOperations,\n    modelHints: options.modelHints,\n    emitterOptions: options.emitterOptions,\n    targetDir: options.target,\n    priorTargetManifestPaths: options.priorTargetManifestPaths,\n    scopedServices: options.scopedServices,\n    scopedModelNames,\n    scopedEnumNames,\n  };\n}\n\n/**\n * Collect model and enum names transitively referenced by service operations.\n * Walks operation parameters, request bodies, responses, and pagination item\n * types, then chases model field references until the set stabilizes.\n */\nexport function collectReferencedNames(\n  services: Service[],\n  models: Model[],\n  opts: { preserveAllDiscriminated?: boolean } = {},\n): { models: Set<string>; enums: Set<string> } {\n  // Default: preserve EVERY discriminated/event model as public surface (full\n  // emission). Strict mode (`preserveAllDiscriminated: false`, used to compute a\n  // scoped run's reachable set) skips that blanket and instead chases the mapping\n  // variants of discriminated models that are actually reached — so a scoped\n  // service doesn't pull in the entire unrelated event tree.\n  const preserveAllDiscriminated = opts.preserveAllDiscriminated !== false;\n  const referencedModels = new Set<string>();\n  const referencedEnums = new Set<string>();\n\n  const collectFromTypeRef = (ref: TypeRef): void => {\n    walkTypeRef(ref, {\n      model: (r) => referencedModels.add(r.name),\n      enum: (r) => referencedEnums.add(r.name),\n    });\n  };\n\n  // Seed: walk every operation's params, request body, response, errors, and pagination\n  for (const service of services) {\n    for (const op of service.operations) {\n      for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n        collectFromTypeRef(p.type);\n      }\n      if (op.requestBody) collectFromTypeRef(op.requestBody);\n      collectFromTypeRef(op.response);\n      if (op.pagination) collectFromTypeRef(op.pagination.itemType);\n      for (const err of op.errors) {\n        if (err.type) collectFromTypeRef(err.type);\n      }\n      if (op.successResponses) {\n        for (const sr of op.successResponses) {\n          collectFromTypeRef(sr.type);\n        }\n      }\n    }\n  }\n\n  // Preserve discriminated models as public SDK types even when no operation\n  // returns them directly. This matters for event/webhook unions where the base\n  // operation references a generic envelope but the variant structs are still\n  // useful public surface.\n  //\n  // Also preserve the variants mapped from an `allOf [base, oneOf […]]` base\n  // (carried as `Model.discriminator.mapping`). The base model is reached\n  // through the operation; without explicitly chasing its mapping, the\n  // variant structs would be unreachable and the dispatcher would dangle\n  // imports.\n  if (preserveAllDiscriminated) {\n    for (const model of models) {\n      if (isDiscriminatedModel(model)) {\n        referencedModels.add(model.name);\n      }\n      const disc = model.discriminator;\n      if (disc?.mapping) {\n        for (const variantName of Object.values(disc.mapping)) {\n          referencedModels.add(variantName);\n        }\n      }\n    }\n  }\n\n  // Chase: transitively resolve model field references until stable\n  const modelsByName = new Map(models.map((m) => [m.name, m]));\n  const visited = new Set<string>();\n  const queue = [...referencedModels];\n  while (queue.length > 0) {\n    const name = queue.pop()!;\n    if (visited.has(name)) continue;\n    visited.add(name);\n    const model = modelsByName.get(name);\n    if (!model) continue;\n    // A reached discriminated base pulls in its mapping variants (the dispatcher\n    // would otherwise dangle). In full mode this is redundant with the blanket\n    // pass above; in strict mode it is the only path that includes variants.\n    const disc = model.discriminator;\n    if (disc?.mapping) {\n      for (const variantName of Object.values(disc.mapping)) {\n        if (!referencedModels.has(variantName)) {\n          referencedModels.add(variantName);\n          queue.push(variantName);\n        }\n      }\n    }\n    for (const field of model.fields) {\n      collectFromTypeRef(field.type);\n      // If new models were discovered, enqueue them\n      for (const m of referencedModels) {\n        if (!visited.has(m)) queue.push(m);\n      }\n    }\n  }\n\n  return { models: referencedModels, enums: referencedEnums };\n}\n\nfunction isDiscriminatedModel(model: Model): boolean {\n  return model.fields.some(\n    (field) =>\n      (field.name === 'event' || field.name === 'type' || field.name === 'object') && field.type.kind === 'literal',\n  );\n}\n\n/**\n * Collect all generated files from an emitter (no headers, no path prefixes).\n *\n * In a scoped (`--services`) run the spec is NOT filtered: every generator runs\n * over the full spec so model placement, dedup, the root client, and all\n * aggregate/barrel files are byte-identical to a full run (and a brand-new\n * selected service is wired into the client automatically). The emitters\n * themselves consult `ctx.scopedServices` to emit only the selected services'\n * per-service resource/test files.\n */\nexport function generateAllFiles(spec: ApiSpec, emitter: Emitter, ctx: EmitterContext): GeneratedFile[] {\n  const referenced = collectReferencedNames(spec.services, spec.models);\n  const reachableModels = spec.models.filter((m) => referenced.models.has(m.name));\n  const reachableEnums = spec.enums.filter((e) => referenced.enums.has(e.name));\n  const reachableSpec: ApiSpec = { ...spec, models: reachableModels, enums: reachableEnums };\n\n  return [\n    ...emitter.generateModels(reachableModels, ctx),\n    ...emitter.generateEnums(reachableEnums, ctx),\n    ...emitter.generateResources(spec.services, ctx),\n    ...emitter.generateClient(spec, ctx),\n    ...emitter.generateErrors(ctx),\n    ...(emitter.generateTypeSignatures?.(reachableSpec, ctx) ?? []),\n    ...emitter.generateTests(reachableSpec, ctx),\n  ];\n}\n\n/** Apply file header to generated files, respecting headerPlacement and JSON files. */\nexport function applyFileHeaders(files: GeneratedFile[], header: string): GeneratedFile[] {\n  return files.map((f) => ({\n    ...f,\n    content:\n      !header || f.path.endsWith('.json') || f.headerPlacement === 'skip' ? f.content : header + '\\n\\n' + f.content,\n    skipIfExists: f.skipIfExists ?? false,\n  }));\n}\n\nexport function generateFiles(\n  spec: ApiSpec,\n  emitter: Emitter,\n  options: {\n    namespace: string;\n    outputDir: string;\n    apiSurface?: ApiSurface;\n    overlayLookup?: OverlayLookup;\n    operationHints?: Record<string, OperationHint>;\n    mountRules?: Record<string, string>;\n    modelHints?: Record<string, string>;\n    emitterOptions?: Record<string, unknown>;\n    target?: string;\n    priorTargetManifestPaths?: Set<string>;\n    /** Scoped-generation signal (POST-MOUNT names); set on ctx for emitters to gate per-service emission. */\n    scopedServices?: Set<string>;\n  },\n): { files: GeneratedFile[]; ctx: EmitterContext; header: string; operations?: OperationsMap } {\n  const ctx = buildEmitterContext(spec, options);\n  const files = generateAllFiles(spec, emitter, ctx);\n  const operations = emitter.buildOperationsMap?.(spec, ctx);\n  const header = emitter.fileHeader();\n  return { files: applyFileHeaders(files, header), ctx, header, operations };\n}\n","import type { ApiSpec } from '../ir/types.js';\n\n/**\n * Validate a `--services` selection and return it as a set of POST-MOUNT service\n * names for emitters to scope on.\n *\n * Scoped generation does NOT filter the IR: model placement, dedup/aliasing, and\n * shared-schema decisions are global computations over the full service/model set\n * (filtering them churns shared `common/` files). Instead the full spec flows to\n * the emitters unchanged and this set is passed as `ctx.scopedServices`; each\n * emitter gates only its per-service resource/test emission on it.\n *\n * Matching is on the POST-MOUNT name. Mount resolution never mutates\n * `spec.services` — the post-mount target lives on `ResolvedOperation.mountOn`\n * (`mountOn = hint?.mountOn ?? mountRules[service.name] ?? service.name`) — so the\n * post-mount name of a source service is derived here as\n * `mountRules[service.name] ?? service.name`. Selecting a target (e.g.\n * `DirectorySync`) is valid because every source tag that mounts into it\n * (`DirectoryUsers`, `DirectoryGroups`, …) shares that post-mount name, and the\n * emitters group resources by mount, so all siblings emit together.\n *\n * @param spec - The parsed API spec (never mutated; never filtered).\n * @param selected - Post-mount service names from `--services` (normalized/trimmed).\n * @param mountRules - Source-service-name → post-mount-target mappings.\n * @returns The validated selection as a `Set` of post-mount names.\n * @throws A `ConfigError` listing valid post-mount names when a selection is\n *   unknown — scoped generation never silently emits the wrong set.\n */\nexport function resolveScopedServices(\n  spec: ApiSpec,\n  selected: string[],\n  mountRules?: Record<string, string>,\n): Set<string> {\n  const mounts = mountRules ?? {};\n  const postMountName = (name: string): string => mounts[name] ?? name;\n  const validPostMount = new Set(spec.services.map((s) => postMountName(s.name)));\n  const selectedSet = new Set(selected);\n\n  const unknown = [...selectedSet].filter((s) => !validPostMount.has(s));\n  if (unknown.length > 0) {\n    const err = new Error(\n      `Unknown --services: ${unknown.sort().join(', ')}. ` +\n        `Valid post-mount services: ${[...validPostMount].sort().join(', ')}`,\n    );\n    err.name = 'ConfigError';\n    throw err;\n  }\n\n  return selectedSet;\n}\n","import * as fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { writeFiles, type WriteResult } from './writer.js';\nimport { extractStatements } from './merger.js';\nimport { hasGrammar } from './merger.js';\n\n/**\n * Resolve a relative import path against a source file path to get the\n * target file path.  Handles implicit .ts extensions and /index.ts.\n */\nfunction resolveImportPath(\n  fromFilePath: string,\n  importModulePath: string,\n  knownPaths: Set<string>,\n): string | undefined {\n  // Strip quotes from module path key (tree-sitter keeps them)\n  const cleaned = importModulePath.replace(/^['\"]|['\"]$/g, '');\n  // Skip non-relative imports (node_modules, bare specifiers)\n  if (!cleaned.startsWith('.')) return undefined;\n\n  const dir = path.dirname(fromFilePath);\n  const resolved = path.normalize(path.join(dir, cleaned));\n\n  // Try exact match, .ts, /index.ts\n  for (const candidate of [resolved, `${resolved}.ts`, `${resolved}/index.ts`]) {\n    if (knownPaths.has(candidate)) return candidate;\n  }\n  return undefined;\n}\n\n/**\n * Determine whether a generated file is a \"root\" — a file that should always\n * be integrated into the target.  Roots are entry points from which we trace\n * the import graph.  Everything else must be reachable from a root.\n *\n * Roots: resource classes, client, config, errors, enums, barrel index files.\n * Non-roots: serializers, fixtures, standalone interfaces, test files.\n */\nfunction isRootFile(filePath: string): boolean {\n  // Fixtures are never roots (and should be filtered by integrateTarget already)\n  if (filePath.includes('/fixtures/')) return false;\n  // Test files are roots — they are standalone entry points that belong in the\n  // target repo even though nothing imports them.\n  if (filePath.endsWith('.spec.ts') || filePath.endsWith('.test.ts')) return true;\n  // Serializer files\n  if (filePath.includes('/serializers/')) return false;\n  // Standalone interface files (not barrel/index)\n  if (filePath.includes('/interfaces/') && !filePath.endsWith('/index.ts')) return false;\n  // Everything else is a root: resource classes, client, config, errors, enums, barrel files\n  return true;\n}\n\n/**\n * Build a file-level dependency graph from generated files and return only\n * files reachable from root entry points.  Uses tree-sitter to parse imports.\n */\nexport async function treeShakeFiles(files: GeneratedFile[], language: string): Promise<GeneratedFile[]> {\n  if (!hasGrammar(language)) return files;\n\n  const knownPaths = new Set(files.map((f) => f.path));\n\n  // Build dependency graph: file → set of files it imports\n  const deps = new Map<string, Set<string>>();\n  for (const file of files) {\n    // Only parse .ts/.js files (skip JSON, etc.)\n    if (!file.path.endsWith('.ts') && !file.path.endsWith('.js')) {\n      deps.set(file.path, new Set());\n      continue;\n    }\n    const parsed = await extractStatements(file.content, language);\n    const fileDeps = new Set<string>();\n    for (const imp of parsed.imports) {\n      const resolved = resolveImportPath(file.path, imp.key, knownPaths);\n      if (resolved) fileDeps.add(resolved);\n    }\n    // Also check re-export statements (export * from './foo')\n    for (const stmt of parsed.statements) {\n      if (stmt.kind === 'reexport') {\n        // Extract module path from \"export * from './foo'\" or \"export { X } from './foo'\"\n        const match = stmt.text.match(/from\\s+['\"]([^'\"]+)['\"]/);\n        if (match) {\n          const resolved = resolveImportPath(file.path, match[1], knownPaths);\n          if (resolved) fileDeps.add(resolved);\n        }\n      }\n    }\n    deps.set(file.path, fileDeps);\n  }\n\n  // Determine which file extensions are source code for this language\n  const codeExtensions = new Set([\n    '.ts',\n    '.js',\n    '.tsx',\n    '.jsx',\n    '.py',\n    '.rb',\n    '.go',\n    '.rs',\n    '.kt',\n    '.cs',\n    '.ex',\n    '.exs',\n    '.php',\n  ]);\n\n  // BFS from roots\n  const reachable = new Set<string>();\n  const queue: string[] = [];\n  for (const file of files) {\n    const ext = file.path.slice(file.path.lastIndexOf('.'));\n    // Non-code files (JSON, etc.) are always reachable — they can't participate\n    // in the import graph and are loaded at runtime (e.g. test fixtures).\n    if (!codeExtensions.has(ext)) {\n      reachable.add(file.path);\n      continue;\n    }\n    if (isRootFile(file.path)) {\n      reachable.add(file.path);\n      queue.push(file.path);\n    }\n  }\n  while (queue.length > 0) {\n    const current = queue.pop()!;\n    const fileDeps = deps.get(current);\n    if (!fileDeps) continue;\n    for (const dep of fileDeps) {\n      if (!reachable.has(dep)) {\n        reachable.add(dep);\n        queue.push(dep);\n      }\n    }\n  }\n\n  return files.filter((f) => reachable.has(f.path));\n}\n\nexport function mapFilesForTargetIntegration(files: GeneratedFile[], language: string): GeneratedFile[] {\n  const langPrefix = `${language}/`;\n  return files\n    .filter((f) => f.integrateTarget !== false) // integrateTarget: false files are standalone-only\n    .map((f) => {\n      const stripped = f.path.startsWith(langPrefix) ? f.path.replace(langPrefix, '') : f.path;\n      return {\n        ...f,\n        skipIfExists: false, // Always merge in target — never hard-skip\n        path: stripped,\n      };\n    });\n}\n\n/**\n * Resolve file-to-directory conflicts in the target.\n *\n * When a generated file creates a package directory (e.g., `api_keys/__init__.py`)\n * that would shadow an existing module file (e.g., `api_keys.py`), move the\n * module file's content into `_compat.py` inside the package and add a\n * re-export from `__init__.py`.  This preserves backward-compatible imports\n * (e.g., `from acme.api_keys import ApiKeysModule`) while the package directory\n * provides the generated models and resource classes.\n */\nasync function resolveFileToDirectoryConflicts(\n  files: GeneratedFile[],\n  targetDir: string,\n): Promise<{ files: GeneratedFile[]; removals: string[] }> {\n  const result = [...files];\n  const removals: string[] = [];\n\n  for (let i = 0; i < result.length; i++) {\n    const file = result[i];\n    // Match package init files: e.g., src/acme/api_keys/__init__.py\n    const match = file.path.match(/^(.+)\\/__init__\\.py$/);\n    if (!match) continue;\n\n    const dirPath = match[1]; // e.g., src/acme/api_keys\n    const moduleFilePath = `${dirPath}.py`; // e.g., src/acme/api_keys.py\n    const fullModulePath = path.join(targetDir, moduleFilePath);\n\n    let moduleContent: string;\n    try {\n      moduleContent = await fs.readFile(fullModulePath, 'utf-8');\n    } catch {\n      continue; // Module file doesn't exist — no conflict\n    }\n\n    // Create a compat shim inside the package with the old module's content\n    const compatPath = `${dirPath}/_compat.py`;\n    result.push({\n      path: compatPath,\n      content: moduleContent,\n      overwriteExisting: true,\n    });\n\n    // Append re-export from _compat to __init__.py so existing imports work.\n    // Compat must come AFTER generated models so hand-written types take\n    // precedence over generated types with the same name.\n    const compatImport = 'from ._compat import *  # noqa: F401,F403  # pyright: ignore[reportUnusedImport]';\n    const existingContent = file.content.endsWith('\\n') ? file.content : file.content + '\\n';\n    result[i] = {\n      ...file,\n      content: existingContent + compatImport + '\\n',\n    };\n\n    // Schedule the shadowed module file for removal\n    removals.push(fullModulePath);\n  }\n\n  return { files: result, removals };\n}\n\nexport interface IntegrateResult extends WriteResult {\n  /** Final set of paths this run claims ownership of in the target (post tree-shake + conflict resolution). */\n  emittedPaths: string[];\n}\n\nexport async function integrateGeneratedFiles(opts: {\n  files: GeneratedFile[];\n  language: string;\n  targetDir: string;\n  header: string;\n}): Promise<IntegrateResult> {\n  const mapped = mapFilesForTargetIntegration(opts.files, opts.language);\n  const shaken = await treeShakeFiles(mapped, opts.language);\n\n  // Handle file-to-directory conflicts before writing\n  const { files: resolved, removals } = await resolveFileToDirectoryConflicts(shaken, opts.targetDir);\n\n  const result = await writeFiles(resolved, opts.targetDir, {\n    language: opts.language,\n    header: opts.header,\n  });\n\n  // Remove shadowed module files after integration\n  for (const filePath of removals) {\n    try {\n      await fs.unlink(filePath);\n    } catch {\n      // File may already be gone\n    }\n  }\n\n  // The manifest tracks ALL files oagen owns, including tree-shaken ones.\n  // Tree-shaking decides what to write, but shaken files are still oagen-managed\n  // and must not be pruned from the target on subsequent runs.\n  return { ...result, emittedPaths: mapped.map((f) => f.path) };\n}\n","/**\n * Post-integration formatter.\n *\n * After generating and merging files into a target directory, runs the\n * emitter-provided format command on all written/merged files so that\n * generated code matches the target project's style conventions.\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport * as path from 'node:path';\nimport type { Emitter } from './types.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Run the emitter's format command on the given target files.\n * Silently skips if the emitter has no formatCommand or returns null.\n */\nexport async function formatTargetFiles(emitter: Emitter, targetDir: string, filePaths: string[]): Promise<void> {\n  if (filePaths.length === 0) return;\n  if (!emitter.formatCommand) return;\n\n  const formatCmd = emitter.formatCommand(targetDir);\n  if (!formatCmd) return;\n\n  const absolutePaths = filePaths.map((f) => path.resolve(targetDir, f));\n  const batchSize = formatCmd.batchSize ?? 100;\n\n  process.stderr.write(\n    `[oagen] formatting ${absolutePaths.length} file(s) with ${formatCmd.cmd} (batch ${batchSize})\\n`,\n  );\n\n  for (let i = 0; i < absolutePaths.length; i += batchSize) {\n    const batch = absolutePaths.slice(i, i + batchSize);\n    try {\n      await execFileAsync(formatCmd.cmd, [...formatCmd.args, ...batch], {\n        cwd: targetDir,\n        maxBuffer: 10 * 1024 * 1024,\n        timeout: 120_000,\n      });\n    } catch (err) {\n      // Formatter failed on this batch — continue with remaining batches.\n      // Surface the failure on stderr so misconfigured commands don't silently\n      // leave generated code unformatted every regen.\n      const msg = err instanceof Error ? err.message : String(err);\n      process.stderr.write(`[oagen] formatter batch failed: ${msg}\\n`);\n    }\n  }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n/**\n * Prune-manifest support for `oagen generate`.\n *\n * The manifest records every auto-generated file emitted on the previous run,\n * relative to the directory it lives in (either the `--output` standalone dir\n * or the `--target` integration dir).  On the next run we diff the previous\n * list against the current emission set and delete anything that's no longer\n * produced — preventing stale-file accumulation across regens.\n *\n * Design notes:\n *  - The manifest is versioned so future format changes can be handled safely.\n *  - Paths are stored sorted for deterministic diffs in git.\n *  - Deletion is gated on a header guard when one is available: we only remove\n *    files whose contents start with the auto-generated header.  This protects\n *    a hand-maintained file that happens to share a name with a previously\n *    generated one (extremely rare, but worth catching).\n *  - On first adoption (no previous manifest), pruning is skipped and a\n *    one-line notice is printed — no surprise deletions.\n */\n\nexport const MANIFEST_FILENAME = '.oagen-manifest.json';\nconst MANIFEST_VERSION = 2;\n\nexport interface Manifest {\n  /** Schema version.  Bump when the format changes incompatibly. */\n  version: number;\n  /** Emitter language (e.g. \"python\").  Used only as a consistency hint. */\n  language: string;\n  /** Human-readable or package-level SDK identity (e.g. \"acme-php\"). */\n  sdkName?: string;\n  /** ISO-8601 timestamp of the run that produced the current manifest contents. */\n  generatedAt: string;\n  /** SHA-256 hash of the source OpenAPI spec used for generation. */\n  specSha?: string;\n  /** Path or reference to the source spec. */\n  specPath?: string;\n  /** Git SHA or version of the emitter code used. */\n  emitterSha?: string;\n  /** Emitter version string if available. */\n  emitterVersion?: string;\n  /** SHA-256 hash of the effective oagen.config.ts after resolution. */\n  configSha?: string;\n  /** Version of the compat snapshot/report schema expected by this generation. */\n  compatSchemaVersion?: string;\n  /** Sorted list of paths, relative to the manifest's containing directory. */\n  files: string[];\n  /** Maps \"METHOD /path\" to SDK method + service property name. */\n  operations?: Record<string, unknown>;\n}\n\nexport interface PruneResult {\n  /** Paths actually deleted. */\n  pruned: string[];\n  /** Paths skipped because the header guard didn't match (preserved). */\n  preserved: string[];\n  /** Paths already absent on disk (nothing to do). */\n  missing: string[];\n}\n\n/** Read `.oagen-manifest.json` from a directory.  Returns null if absent or malformed. */\nexport async function readManifest(dir: string): Promise<Manifest | null> {\n  const manifestPath = path.join(dir, MANIFEST_FILENAME);\n  let raw: string;\n  try {\n    raw = await fs.readFile(manifestPath, 'utf-8');\n  } catch {\n    return null;\n  }\n  try {\n    const parsed = JSON.parse(raw) as Partial<Manifest>;\n    if (\n      typeof parsed.version !== 'number' ||\n      typeof parsed.language !== 'string' ||\n      typeof parsed.generatedAt !== 'string' ||\n      !Array.isArray(parsed.files) ||\n      !parsed.files.every((p): p is string => typeof p === 'string')\n    ) {\n      return null;\n    }\n    if (parsed.version > MANIFEST_VERSION) {\n      console.warn(\n        `[oagen] ${MANIFEST_FILENAME} schema version ${parsed.version} is newer than supported (${MANIFEST_VERSION}); ignoring for pruning.`,\n      );\n      return null;\n    }\n    // v1 manifests are forward-compatible — new fields are simply absent\n    return parsed as Manifest;\n  } catch {\n    return null;\n  }\n}\n\n/** Options for writing a manifest. */\nexport interface WriteManifestOpts {\n  language: string;\n  files: Iterable<string>;\n  sdkName?: string;\n  specSha?: string;\n  specPath?: string;\n  emitterSha?: string;\n  emitterVersion?: string;\n  configSha?: string;\n  compatSchemaVersion?: string;\n  operations?: Record<string, unknown>;\n}\n\n/** Write `.oagen-manifest.json` to a directory with sorted paths. */\nexport async function writeManifest(dir: string, opts: WriteManifestOpts): Promise<void> {\n  const manifestPath = path.join(dir, MANIFEST_FILENAME);\n  const manifest: Manifest = {\n    version: MANIFEST_VERSION,\n    language: opts.language,\n    ...(opts.sdkName !== undefined ? { sdkName: opts.sdkName } : {}),\n    generatedAt: new Date().toISOString(),\n    ...(opts.specSha !== undefined ? { specSha: opts.specSha } : {}),\n    ...(opts.specPath !== undefined ? { specPath: opts.specPath } : {}),\n    ...(opts.emitterSha !== undefined ? { emitterSha: opts.emitterSha } : {}),\n    ...(opts.emitterVersion !== undefined ? { emitterVersion: opts.emitterVersion } : {}),\n    ...(opts.configSha !== undefined ? { configSha: opts.configSha } : {}),\n    ...(opts.compatSchemaVersion !== undefined ? { compatSchemaVersion: opts.compatSchemaVersion } : {}),\n    files: [...new Set(opts.files)].sort(),\n    ...(opts.operations !== undefined ? { operations: opts.operations } : {}),\n  };\n  const previous = await readManifest(dir);\n  if (previous && sameManifestExceptGeneratedAt(previous, manifest)) {\n    manifest.generatedAt = previous.generatedAt;\n  }\n  await fs.mkdir(dir, { recursive: true });\n  await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8');\n}\n\nfunction sameManifestExceptGeneratedAt(a: Manifest, b: Manifest): boolean {\n  const { generatedAt: _aGeneratedAt, ...aComparable } = a;\n  const { generatedAt: _bGeneratedAt, ...bComparable } = b;\n  return JSON.stringify(aComparable) === JSON.stringify(bComparable);\n}\n\n/** Return the set of previous paths no longer present in the current emission. */\nexport function computeStalePaths(prev: Manifest, currentPaths: Iterable<string>): string[] {\n  const current = new Set(currentPaths);\n  return prev.files.filter((p) => !current.has(p)).sort();\n}\n\n/**\n * Merge a scoped run's emitted records into the prior manifest's records.\n *\n * A scoped (`--services`) run only emits files for the selected services, but it\n * must NOT discard the prior manifest's record of unselected services' files\n * records. The result unions prior + scoped file paths and shallow-merges the\n * operations maps, with scoped operations overriding prior entries for the same\n * \"METHOD /path\" key (a re-emission updates that operation's record).\n *\n * When `prev` is null (the first-ever run is scoped) there is nothing to\n * preserve, so the scoped subset is returned unchanged — matching the\n * first-adoption behavior of a full run.\n */\nexport function mergeScopedManifestRecords(\n  prev: Manifest | null,\n  scopedFiles: Iterable<string>,\n  scopedOperations?: Record<string, unknown>,\n): { files: string[]; operations?: Record<string, unknown> } {\n  const scopedFileList = [...scopedFiles];\n  if (!prev) {\n    return { files: scopedFileList, operations: scopedOperations };\n  }\n  const files = [...new Set([...prev.files, ...scopedFileList])].sort();\n  const priorOps = prev.operations;\n  const operations = priorOps || scopedOperations ? { ...priorOps, ...scopedOperations } : undefined;\n  return { files, operations };\n}\n\n/**\n * Delete stale files from `dir`.\n *\n * When `header` is provided, a file is only deleted if its contents start with\n * that header — so hand-maintained files that somehow collide with a previously\n * generated path can't be clobbered.  When `header` is omitted, the guard is\n * skipped (useful for non-source artifacts like fixture JSON).\n *\n * Returns lists for reporting.  Empty parent directories are removed after\n * deletion, up to (but not including) `dir` itself.\n */\nexport async function pruneStaleFiles(\n  dir: string,\n  paths: string[],\n  opts: { header?: string } = {},\n): Promise<PruneResult> {\n  const pruned: string[] = [];\n  const preserved: string[] = [];\n  const missing: string[] = [];\n\n  for (const relPath of paths) {\n    const fullPath = path.join(dir, relPath);\n    let content: string;\n    try {\n      content = await fs.readFile(fullPath, 'utf-8');\n    } catch {\n      missing.push(relPath);\n      continue;\n    }\n    if (opts.header && !content.startsWith(opts.header)) {\n      preserved.push(relPath);\n      continue;\n    }\n    try {\n      await fs.unlink(fullPath);\n      pruned.push(relPath);\n    } catch {\n      // Racing deletion or permission issue — treat as missing rather than fatal.\n      missing.push(relPath);\n      continue;\n    }\n    await removeEmptyParents(path.dirname(fullPath), dir);\n  }\n\n  return { pruned, preserved, missing };\n}\n\n/**\n * Walk up from `startDir` removing empty directories until we hit `stopDir`\n * (exclusive) or a non-empty directory.  Silently ignores errors.\n */\nasync function removeEmptyParents(startDir: string, stopDir: string): Promise<void> {\n  let current = path.resolve(startDir);\n  const stop = path.resolve(stopDir);\n  while (current.startsWith(stop + path.sep) && current !== stop) {\n    let entries: string[];\n    try {\n      entries = await fs.readdir(current);\n    } catch {\n      return;\n    }\n    if (entries.length > 0) return;\n    try {\n      await fs.rmdir(current);\n    } catch {\n      return;\n    }\n    current = path.dirname(current);\n  }\n}\n","import type { ApiSpec } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Emitter, GeneratedFile } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { writeFiles } from './writer.js';\nimport { generateFiles } from './generate-files.js';\nimport { resolveScopedServices } from './scoped-services.js';\nimport { integrateGeneratedFiles } from './integrate.js';\nimport { formatTargetFiles } from './formatter.js';\nimport {\n  computeStalePaths,\n  MANIFEST_FILENAME,\n  mergeScopedManifestRecords,\n  pruneStaleFiles,\n  readManifest,\n  writeManifest,\n} from './manifest.js';\n\nexport async function generate(\n  spec: ApiSpec,\n  emitter: Emitter,\n  options: {\n    namespace: string;\n    dryRun?: boolean;\n    outputDir: string;\n    target?: string;\n    apiSurface?: ApiSurface;\n    overlayLookup?: OverlayLookup;\n    operationHints?: Record<string, OperationHint>;\n    mountRules?: Record<string, string>;\n    modelHints?: Record<string, string>;\n    emitterOptions?: Record<string, unknown>;\n    /** When true, skip deletion of files recorded in the previous manifest but not in the current emission. */\n    noPrune?: boolean;\n    /**\n     * Post-mount service names to generate (a `--services` run). When non-empty,\n     * the FULL spec is still emitted for models/enums/client/barrels (so shared\n     * files stay byte-identical and a brand-new selected service is wired into the\n     * client automatically); only per-service resource/test emission is gated to\n     * the selection (via `ctx.scopedServices`). Pruning is disabled and the\n     * manifest is merged so unselected services' records survive.\n     */\n    services?: string[];\n  },\n): Promise<GeneratedFile[]> {\n  // Scoped generation: validate + expand the selection to POST-MOUNT names. The\n  // spec is NOT filtered — placement/dedup/shared-schemas are computed over the\n  // full spec so shared files stay byte-identical; emitters gate only per-service\n  // resource/test emission on this set.\n  const scopedServices =\n    options.services && options.services.length > 0\n      ? resolveScopedServices(spec, options.services, options.mountRules)\n      : undefined;\n  const scoped = scopedServices !== undefined;\n  // Scoped mode implies no-prune so unselected services' files survive.\n  const noPrune = options.noPrune === true || scoped;\n\n  // Read previous manifests up front so emitters can mark files the prior run\n  // wrote as safe-to-overwrite (vs files a human hand-maintains), and so scoped\n  // runs can merge prior records. Skipped only when --no-prune is set on a\n  // non-scoped run (opting out of lifecycle tracking). Scoped runs always read,\n  // even though they force no-prune, because the merge needs the prior records.\n  const skipManifestRead = options.noPrune === true && !scoped;\n  const outputPrevManifestForCtx = skipManifestRead ? null : await readManifest(options.outputDir);\n  const targetManifestForCtx = options.target && !skipManifestRead ? await readManifest(options.target) : null;\n  const priorTargetManifestPaths = targetManifestForCtx\n    ? new Set(targetManifestForCtx.files)\n    : outputPrevManifestForCtx\n      ? new Set(outputPrevManifestForCtx.files)\n      : undefined;\n\n  const {\n    files: withHeaders,\n    header,\n    operations,\n  } = generateFiles(spec, emitter, {\n    ...options,\n    priorTargetManifestPaths,\n    scopedServices,\n  });\n\n  if (options.dryRun) {\n    if (options.target) {\n      console.log(`\\nTarget integration (${options.target}):`);\n      for (const f of withHeaders) {\n        console.log(`  ${f.path}`);\n      }\n    }\n    return withHeaders;\n  }\n\n  // Reuse the manifest read before generation; nothing above writes it.\n  const outputPrevManifest = outputPrevManifestForCtx;\n\n  const writeResult = await writeFiles(withHeaders, options.outputDir, {\n    language: emitter.language,\n    header,\n  });\n\n  if (writeResult.merged.length > 0) {\n    console.log(`Merged into ${writeResult.merged.length} existing files (additive only)`);\n  }\n  if (writeResult.ignored.length > 0) {\n    console.log(`Ignored ${writeResult.ignored.length} files (@oagen-ignore-file)`);\n  }\n\n  const outputEmittedPaths = withHeaders.map((f) => f.path);\n  await applyManifestPrune({\n    dir: options.outputDir,\n    label: 'Output',\n    prevManifest: outputPrevManifest,\n    currentPaths: outputEmittedPaths,\n    language: emitter.language,\n    header,\n    noPrune,\n    operations,\n    scoped,\n  });\n\n  // Format output files so the emitter's formatter runs even without --target.\n  const allOutputFiles = [...writeResult.written, ...writeResult.merged];\n  if (allOutputFiles.length > 0) {\n    await formatTargetFiles(emitter, options.outputDir, allOutputFiles);\n  }\n\n  // Target integration pass\n  if (options.target) {\n    // Reuse the manifest we already read to build the emitter context.  This\n    // is correct because nothing between the two reads writes the manifest.\n    const targetPrevManifest = targetManifestForCtx;\n\n    const targetResult = await integrateGeneratedFiles({\n      files: withHeaders,\n      language: emitter.language,\n      targetDir: options.target,\n      header,\n    });\n\n    if (targetResult.written.length > 0) {\n      console.log(`Target: created ${targetResult.written.length} new files`);\n    }\n    if (targetResult.merged.length > 0) {\n      console.log(`Target: merged into ${targetResult.merged.length} existing files (additive only)`);\n    }\n    if (targetResult.skipped.length > 0) {\n      console.log(`Target: skipped ${targetResult.skipped.length} files (excluded or no grammar)`);\n    }\n\n    await applyManifestPrune({\n      dir: options.target,\n      label: 'Target',\n      prevManifest: targetPrevManifest,\n      currentPaths: targetResult.emittedPaths,\n      language: emitter.language,\n      header,\n      noPrune,\n      operations,\n      scoped,\n    });\n\n    // Run the emitter's formatter on all written/merged/identical files\n    const allTargetFiles = [...targetResult.written, ...targetResult.merged, ...targetResult.identical];\n    if (allTargetFiles.length > 0) {\n      await formatTargetFiles(emitter, options.target, allTargetFiles);\n    }\n  }\n\n  return withHeaders;\n}\n\n/**\n * Prune files recorded in the previous manifest but absent from the current emission,\n * then write the fresh manifest.  Safe on first adoption (no previous manifest).\n */\nasync function applyManifestPrune(opts: {\n  dir: string;\n  label: string;\n  prevManifest: Awaited<ReturnType<typeof readManifest>>;\n  currentPaths: string[];\n  language: string;\n  header: string;\n  noPrune?: boolean;\n  operations?: Record<string, unknown>;\n  /** When true, union this scoped run's records with the prior manifest. */\n  scoped?: boolean;\n}): Promise<void> {\n  // A scoped run only emits the selected services' files, so the manifest is\n  // merged with the prior records rather than replaced — otherwise unselected\n  // services would be dropped from the manifest and mis-pruned on the next run.\n  const records = opts.scoped\n    ? mergeScopedManifestRecords(opts.prevManifest, opts.currentPaths, opts.operations)\n    : { files: opts.currentPaths, operations: opts.operations };\n  const manifestOpts = { language: opts.language, files: records.files, operations: records.operations };\n  if (opts.noPrune) {\n    // Still refresh the manifest so future runs with pruning enabled have a baseline.\n    await writeManifest(opts.dir, manifestOpts);\n    return;\n  }\n\n  if (!opts.prevManifest) {\n    console.log(\n      `${opts.label}: no ${MANIFEST_FILENAME} found — skipping prune (this baseline manifest will be written now).`,\n    );\n    await writeManifest(opts.dir, manifestOpts);\n    return;\n  }\n\n  const stale = computeStalePaths(opts.prevManifest, opts.currentPaths);\n  if (stale.length > 0) {\n    const { pruned, preserved } = await pruneStaleFiles(opts.dir, stale, { header: opts.header });\n    if (pruned.length > 0) {\n      console.log(`${opts.label}: pruned ${pruned.length} stale file${pruned.length === 1 ? '' : 's'}`);\n    }\n    if (preserved.length > 0) {\n      console.log(\n        `${opts.label}: preserved ${preserved.length} file${preserved.length === 1 ? '' : 's'} in previous manifest but lacking the auto-generated header (possibly hand-edited).`,\n      );\n      for (const p of preserved) console.log(`  ${p}`);\n    }\n  }\n\n  await writeManifest(opts.dir, manifestOpts);\n}\n","import { RegistryError } from '../errors.js';\nimport type { Emitter } from './types.js';\n\nconst emitters = new Map<string, Emitter>();\n\nexport function registerEmitter(emitter: Emitter): void {\n  emitters.set(emitter.language, emitter);\n}\n\nexport function getEmitter(language: string): Emitter {\n  const emitter = emitters.get(language);\n  if (!emitter) {\n    const available = [...emitters.keys()].join(', ') || '(none)';\n    throw new RegistryError(\n      `Unknown language: ${language}. Available: ${available}`,\n      `Register an emitter for \"${language}\" via registerEmitter() or check your oagen.config.ts plugin configuration.`,\n    );\n  }\n  return emitter;\n}\n","import type { ApiSurface, LanguageHints } from './types.js';\nimport { splitWords } from '../utils/naming.js';\n\n/** Untyped map patterns — hoisted to avoid allocation on every isTypeEquivalent call. */\nconst UNTYPED_MAP_PATTERNS = new Set([\n  'Record<string, unknown>',\n  'Record<string, any>',\n  '{ [key: string]: any; }',\n  '{ [key: string]: unknown; }',\n  'any',\n]);\n\nexport const NAMED_TYPE_RE = /^[A-Z][a-zA-Z0-9]*$/;\n\n/** Check whether a type name exists as an interface, class, or enum in a surface. */\nexport function typeExistsInSurface(name: string, surface: ApiSurface): boolean {\n  return !!(surface.interfaces[name] || surface.classes[name] || surface.enums[name]);\n}\n\n/** Split a PascalCase string into words, keeping only words > 2 chars. */\nfunction splitPascalWords(s: string): string[] {\n  return splitWords(s).filter((w) => w.length > 2);\n}\n\n/**\n * Check whether two named types share enough PascalCase word components to\n * be considered equivalent (handles name reordering from Json merges, etc.).\n * Both names have `Response$` stripped before comparison.\n */\nexport function namedTypeWordsOverlap(a: string, b: string, minOverlap = 1): boolean {\n  const aNoResp = a.replace(/Response$/, '');\n  const bNoResp = b.replace(/Response$/, '');\n  const aWords = new Set(splitPascalWords(aNoResp).map((w) => w.toLowerCase()));\n  const bWords = new Set(splitPascalWords(bNoResp).map((w) => w.toLowerCase()));\n  const overlap = [...aWords].filter((w) => bWords.has(w));\n  return overlap.length >= minOverlap && overlap.length >= Math.min(aWords.size, bWords.size) - 1;\n}\n\n/** Split a pipe-delimited union string into trimmed, non-empty members. */\nfunction parseUnionMembers(s: string): string[] {\n  return s\n    .split('|')\n    .map((p) => p.trim())\n    .filter(Boolean);\n}\n\n/**\n * Default implementation of isNullableOnlyDifference — shared across extractors.\n * Returns true when stripping nullable wrappers from both sides yields the same\n * type, but the original types differ (i.e., the only difference is nullability).\n */\nexport function defaultIsNullableOnlyDifference(\n  hints: Pick<LanguageHints, 'stripNullable'>,\n  a: string,\n  b: string,\n): boolean {\n  return (hints.stripNullable(a) ?? a) === (hints.stripNullable(b) ?? b) && a !== b;\n}\n\n/**\n * Node/TypeScript language hints — reference implementation.\n * Extracted from the hardcoded logic previously in differ.ts and overlay.ts.\n */\nexport const nodeHints: LanguageHints = {\n  stripNullable(type: string): string | null {\n    const members = parseUnionMembers(type);\n    const stripped = members.filter((p) => p !== 'null');\n    if (stripped.length === members.length) {\n      return null; // no null member found\n    }\n    return stripped.join(' | ');\n  },\n\n  isNullableOnlyDifference(a: string, b: string): boolean {\n    return (nodeHints.stripNullable(a) ?? a) === (nodeHints.stripNullable(b) ?? b) && a !== b;\n  },\n\n  isUnionReorder(a: string, b: string): boolean {\n    const membersA = parseUnionMembers(a).sort();\n    const membersB = parseUnionMembers(b).sort();\n    if (membersA.length !== membersB.length || membersA.length < 2) return false;\n    return membersA.every((m, i) => m === membersB[i]);\n  },\n\n  isGenericTypeParam(type: string): boolean {\n    if (/^[A-Z]$/.test(type)) return true;\n    if (/^T[A-Z][a-zA-Z]*$/.test(type)) return true;\n    if (/^[A-Z]\\[\\]$/.test(type) || /^T[A-Z][a-zA-Z]*\\[\\]$/.test(type)) return true;\n    return false;\n  },\n\n  isExtractionArtifact(type: string): boolean {\n    return type === 'any' || type === 'Record<string, unknown>';\n  },\n\n  tolerateCategoryMismatch: true,\n\n  extractReturnTypeName(returnType: string): string | null {\n    let inner = returnType;\n    while (inner.startsWith('Promise<') && inner.endsWith('>')) {\n      inner = inner.slice(8, -1);\n    }\n    const genericMatch = inner.match(/^[A-Za-z]+<(.+)>$/);\n    if (genericMatch) {\n      inner = genericMatch[1];\n    }\n    inner = inner.replace(/\\[\\]$/, '');\n    if (['void', 'string', 'number', 'boolean', 'any', 'unknown', 'null', 'undefined'].includes(inner)) {\n      return null;\n    }\n    return inner;\n  },\n\n  extractParamTypeName(paramType: string): string | null {\n    if (['string', 'number', 'boolean', 'any', 'unknown'].includes(paramType)) {\n      return null;\n    }\n    return paramType;\n  },\n\n  propertyMatchesClass(propertyName: string, className: string): boolean {\n    // Support both camelCase and snake_case properties matching PascalCase classes\n    // e.g., \"organizations\" ≡ \"Organizations\", \"api_keys\" ≡ \"ApiKeys\"\n    const normalizedProp = propertyName.replace(/[-_]/g, '').toLowerCase();\n    return normalizedProp === className.toLowerCase();\n  },\n\n  derivedModelNames(modelName: string): string[] {\n    return [`${modelName}Response`, `Serialized${modelName}`];\n  },\n\n  isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n    // Check if one side is a named enum and the other is an inline union\n    // of that enum's string literal values.\n    // e.g., baseline: '\"active\" | \"inactive\"', candidate: 'ConnectionState'\n    //    or baseline: 'ConnectionState', candidate: '\"active\" | \"inactive\"'\n\n    // Try: candidate is enum name, baseline is inline union of string literals.\n    // The generated enum may have MORE members than the baseline (new spec values),\n    // so check that all baseline members exist in the enum (subset match).\n    const candEnum = candidateSurface.enums[candidateType];\n    if (candEnum) {\n      const enumValuesSet = new Set(Object.values(candEnum.members).flatMap((v) => [`\"${v}\"`, `'${v}'`]));\n      const baseMembers = parseUnionMembers(baselineType);\n      if (baseMembers.length > 0 && baseMembers.every((m) => enumValuesSet.has(m))) {\n        return true;\n      }\n    }\n\n    // Tolerate untyped-map equivalences:\n    // { [key: string]: any; } ≡ Record<string, unknown> ≡ Record<string, any>\n    if (UNTYPED_MAP_PATTERNS.has(baselineType) && UNTYPED_MAP_PATTERNS.has(candidateType)) {\n      return true;\n    }\n\n    // Tolerate inline object literal vs named model in candidate.\n    // e.g., baseline: '{ type: \"organization\"; id: string; }', candidate: 'ApiKeyOwner'\n    // The named model is more structured but semantically equivalent.\n    if (baselineType.startsWith('{') && baselineType.endsWith('}')) {\n      if (typeExistsInSurface(candidateType, candidateSurface)) {\n        return true;\n      }\n    }\n\n    // Tolerate named-type-to-named-type mismatches when both types exist\n    // as models/interfaces/enums in their respective surfaces. This handles\n    // cases where the parser qualifies inline types with parent names while\n    // the live SDK uses shared types:\n    //   baseline: RoleResponse, candidate: OrganizationMembershipRole\n    //   baseline: ConnectionType, candidate: ProfileConnectionType\n    //   baseline: AuditLogTargetSchema[], candidate: AuditLogSchemaJsonTarget[]\n    const baseClean = baselineType.replace(/\\[\\]$/, '');\n    const candClean = candidateType.replace(/\\[\\]$/, '');\n    const sameArrayness = baselineType.endsWith('[]') === candidateType.endsWith('[]');\n\n    // Response suffix equivalence (both directions)\n    if (sameArrayness) {\n      if (candClean === baseClean + 'Response' || baseClean === candClean + 'Response') {\n        return true;\n      }\n    }\n\n    // Both are named types (PascalCase, no operators) — check if candidate\n    // is a known model/interface/enum, and baseline looks like a named type too.\n    // This tolerates the parser's qualified naming vs the live SDK's shared naming.\n    if (sameArrayness && NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n      if (typeExistsInSurface(candClean, candidateSurface)) {\n        // One name contains the other (e.g., ProfileConnectionType contains ConnectionType)\n        if (candClean.includes(baseClean) || baseClean.includes(candClean)) {\n          return true;\n        }\n        // Strip Response suffix and check containment\n        const baseNoResp = baseClean.replace(/Response$/, '');\n        const candNoResp = candClean.replace(/Response$/, '');\n        if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) {\n          return true;\n        }\n        // Word-component overlap: split PascalCase into words and check\n        // if they share enough meaningful words (handles name reordering\n        // from Json merges: AuditLogTargetSchema vs AuditLogSchemaJsonTarget)\n        if (namedTypeWordsOverlap(baseClean, candClean, 2)) {\n          return true;\n        }\n      }\n    }\n\n    return false;\n  },\n};\n\n/**\n * Merge partial language hint overrides over nodeHints defaults.\n * Any hint not provided falls back to the Node/TypeScript implementation.\n */\nexport function resolveHints(overrides: Partial<LanguageHints>): LanguageHints {\n  return { ...nodeHints, ...overrides };\n}\n","import type { ApiSurface, ApiInterface, ApiMethod, OverlayLookup, LanguageHints } from './types.js';\nimport type { ClassifiedChange } from './classify.js';\nimport type { ApiSpec, Model } from '../ir/types.js';\nimport { toSnakeCase, splitWords } from '../utils/naming.js';\nimport { nodeHints as defaultNodeHints } from './language-hints.js';\n\nexport type { MethodOverlay, OverlayLookup } from './types.js';\n\nexport interface ManifestEntry {\n  operationId: string;\n  sdkResourceProperty: string;\n  sdkMethodName: string;\n  httpMethod: string;\n  path: string;\n  pathParams: string[];\n  bodyFields: string[];\n  queryFields: string[];\n}\n\n/**\n * Find the class name that owns a given SDK resource property.\n * E.g. if the surface has a class \"Organizations\" with property \"organizations\",\n * and sdkResourceProperty is \"organizations\", return \"Organizations\".\n */\nfunction findClassForProperty(\n  surface: ApiSurface,\n  sdkResourceProperty: string,\n  hints: LanguageHints,\n): string | undefined {\n  for (const [className, cls] of Object.entries(surface.classes)) {\n    // Check if the class itself maps to this property (language-specific match)\n    if (hints.propertyMatchesClass(sdkResourceProperty, className)) {\n      return className;\n    }\n    // Check properties — resolve to the property's type class, not the parent.\n    // This prevents generic parent classes (e.g., Client) from being returned\n    // when the actual resource class (e.g., ApiKeys) should be used.\n    for (const [propName, prop] of Object.entries(cls.properties)) {\n      if (propName === sdkResourceProperty) {\n        const propType = (prop as { type?: string }).type;\n        if (propType && surface.classes[propType]) {\n          return propType;\n        }\n        // Property type not in surface — skip rather than return the parent\n        return undefined;\n      }\n    }\n  }\n\n  // Strategy 3: Word-suffix fallback\n  // \"adminPortal\" → [\"admin\",\"portal\"]; class \"Portal\" → [\"portal\"]\n  // [\"portal\"] is a suffix of [\"admin\",\"portal\"] → match\n  const propWords = splitWords(sdkResourceProperty).map((w) => w.toLowerCase());\n  if (propWords.length > 1) {\n    for (const [className] of Object.entries(surface.classes)) {\n      const classWords = splitWords(className).map((w) => w.toLowerCase());\n      if (classWords.length > 0 && classWords.length < propWords.length) {\n        const suffix = propWords.slice(propWords.length - classWords.length);\n        if (classWords.every((w, i) => w === suffix[i])) {\n          return className;\n        }\n      }\n    }\n  }\n\n  return undefined;\n}\n\nexport function buildOverlayLookup(\n  surface: ApiSurface,\n  manifest?: ManifestEntry[],\n  spec?: ApiSpec,\n  hints?: LanguageHints,\n  options?: { strictModelMatch?: boolean },\n): OverlayLookup {\n  const resolvedHints = hints ?? defaultNodeHints;\n  const lookup: OverlayLookup = {\n    methodByOperation: new Map(),\n    httpKeyByMethod: new Map(),\n    interfaceByName: new Map(),\n    typeAliasByName: new Map(),\n    requiredExports: new Map(),\n    modelNameByIR: new Map(),\n    fileBySymbol: new Map(),\n  };\n\n  // If manifest available, map operationId → HTTP method + path → existing method\n  if (manifest) {\n    for (const entry of manifest) {\n      const key = `${entry.httpMethod.toUpperCase()} ${entry.path}`;\n      const className = findClassForProperty(surface, entry.sdkResourceProperty, resolvedHints);\n      if (className) {\n        let resolvedMethodName = entry.sdkMethodName;\n        let methods = surface.classes[className]?.methods[resolvedMethodName];\n\n        // Exact match failed — try prefix match on the resolved class.\n        // Handles cases where the generated name is shorter than the existing name\n        // (e.g., manifest says \"delete\" but existing SDK has \"deleteApiKey\").\n        // Only accept when exactly one candidate matches — ambiguous matches are worse than no match.\n        if (!methods) {\n          const classMethods = surface.classes[className]?.methods ?? {};\n          const prefix = resolvedMethodName.toLowerCase();\n          const candidates: [string, ApiMethod[]][] = [];\n          for (const [name, overloads] of Object.entries(classMethods)) {\n            if (name.toLowerCase().startsWith(prefix) && name !== resolvedMethodName) {\n              candidates.push([name, overloads]);\n            }\n          }\n          if (candidates.length === 1) {\n            methods = candidates[0][1];\n            resolvedMethodName = candidates[0][0];\n          } else if (candidates.length > 1) {\n            // Disambiguate: prefer the candidate whose name is <prefix><pathSegment>\n            // derived from the FIRST segment of the operation path. This avoids\n            // mismatching when a class combines operations from multiple path groups\n            // (e.g., /organizations and /organization_domains both in Organizations).\n            const firstSegment =\n              entry.path\n                .split('/')\n                .filter(Boolean)[0]\n                ?.replace(/[{}_-]/g, '') ?? '';\n            if (firstSegment) {\n              const segLower = firstSegment.toLowerCase();\n              // Try the path segment as-is and as singular\n              const segSingular = segLower.endsWith('s') ? segLower.slice(0, -1) : segLower;\n              const best = candidates.find(([name]) => {\n                const lower = name.toLowerCase();\n                return lower === prefix + segLower || lower === prefix + segSingular;\n              });\n              if (best) {\n                methods = best[1];\n                resolvedMethodName = best[0];\n              }\n            }\n\n            // HTTP verb disambiguation: when path disambiguation fails, use the\n            // HTTP method to prefer method names that match the verb semantics.\n            // E.g., GET → list/get, POST → create, PUT → set/update, DELETE → delete/remove.\n            if (!methods) {\n              const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n              if (verbMatch) {\n                methods = verbMatch[1];\n                resolvedMethodName = verbMatch[0];\n              }\n            }\n          }\n        }\n\n        // Suffix match: the existing SDK may use a longer controller-prefixed\n        // method name that ends with the transformed name.\n        // (e.g., manifest says \"validate_api_key\" but existing SDK has\n        // \"api_keys_controller_validate_api_key\").\n        // Only accept when exactly one candidate matches — ambiguous matches are worse than no match.\n        if (!methods) {\n          const classMethods = surface.classes[className]?.methods ?? {};\n          const suffix = resolvedMethodName.toLowerCase();\n          const candidates: [string, ApiMethod[]][] = [];\n          for (const [name, overloads] of Object.entries(classMethods)) {\n            if (name.toLowerCase().endsWith(suffix) && name !== resolvedMethodName) {\n              candidates.push([name, overloads]);\n            }\n          }\n          if (candidates.length === 1) {\n            methods = candidates[0][1];\n            resolvedMethodName = candidates[0][0];\n          }\n        }\n\n        // Word-part subsequence match: the surface method may have extra words\n        // inserted into the manifest method name. For example:\n        //   \"disableFlag\" → \"disableFeatureFlag\" ([\"disable\",\"Flag\"] ⊂ [\"disable\",\"Feature\",\"Flag\"])\n        //   \"getByExternalId\" → \"getOrganizationByExternalId\"\n        // Only accept when exactly one candidate matches, or use HTTP verb disambiguation.\n        if (!methods) {\n          const manifestWords = splitCamelCase(resolvedMethodName);\n          if (manifestWords.length >= 2) {\n            const classMethods = surface.classes[className]?.methods ?? {};\n            const candidates: [string, ApiMethod[]][] = [];\n            for (const [name, overloads] of Object.entries(classMethods)) {\n              if (name === resolvedMethodName) continue;\n              const surfaceWords = splitCamelCase(name);\n              if (surfaceWords.length > manifestWords.length && isSubsequence(manifestWords, surfaceWords)) {\n                candidates.push([name, overloads]);\n              }\n            }\n            if (candidates.length === 1) {\n              methods = candidates[0][1];\n              resolvedMethodName = candidates[0][0];\n            } else if (candidates.length > 1) {\n              const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n              if (verbMatch) {\n                methods = verbMatch[1];\n                resolvedMethodName = verbMatch[0];\n              }\n            }\n          }\n        }\n\n        // Reverse prefix match: the manifest name may be LONGER than the surface\n        // name (e.g., \"createResources\" → \"createResource\", \"removeRoleByCriteria\" → \"removeRole\").\n        // Check if the manifest name starts with a surface name. Only accept unique matches.\n        if (!methods) {\n          const classMethods = surface.classes[className]?.methods ?? {};\n          const manifestLower = resolvedMethodName.toLowerCase();\n          const candidates: [string, ApiMethod[]][] = [];\n          for (const [name, overloads] of Object.entries(classMethods)) {\n            if (name === resolvedMethodName) continue;\n            if (manifestLower.startsWith(name.toLowerCase()) && name.length >= 3) {\n              candidates.push([name, overloads]);\n            }\n          }\n          if (candidates.length === 1) {\n            methods = candidates[0][1];\n            resolvedMethodName = candidates[0][0];\n          } else if (candidates.length > 1) {\n            const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n            if (verbMatch) {\n              methods = verbMatch[1];\n              resolvedMethodName = verbMatch[0];\n            }\n          }\n        }\n\n        const method = methods?.[0];\n        if (method) {\n          lookup.methodByOperation.set(key, {\n            className,\n            methodName: resolvedMethodName,\n            params: method.params,\n            returnType: method.returnType,\n          });\n          lookup.httpKeyByMethod.set(`${className}.${resolvedMethodName}`, key);\n        }\n      }\n    }\n  }\n\n  // Map interface and type alias names\n  for (const name of Object.keys(surface.interfaces)) {\n    lookup.interfaceByName.set(name, name);\n  }\n  for (const name of Object.keys(surface.typeAliases)) {\n    lookup.typeAliasByName.set(name, name);\n  }\n\n  // Map barrel exports\n  for (const [path, symbols] of Object.entries(surface.exports)) {\n    lookup.requiredExports.set(path, new Set(symbols));\n  }\n\n  // Populate fileBySymbol from enriched surface\n  for (const record of [surface.classes, surface.interfaces, surface.typeAliases, surface.enums] as Record<\n    string,\n    { sourceFile?: string }\n  >[]) {\n    for (const [name, item] of Object.entries(record)) {\n      if (item.sourceFile) lookup.fileBySymbol.set(name, item.sourceFile);\n    }\n  }\n\n  // Auto-infer IR model name → SDK interface name mappings\n  if (spec) {\n    buildModelNameMap(surface, spec, lookup, resolvedHints, options);\n\n    // Remap fileBySymbol so IR model names point to the SDK symbol's file\n    for (const [irName, sdkName] of lookup.modelNameByIR) {\n      const filePath = lookup.fileBySymbol.get(sdkName);\n      if (filePath) {\n        lookup.fileBySymbol.set(irName, filePath);\n      }\n    }\n  }\n\n  return lookup;\n}\n\n// ---------------------------------------------------------------------------\n// HTTP verb disambiguation\n// ---------------------------------------------------------------------------\n\n/** Map HTTP methods to preferred method name prefixes for disambiguation. */\nconst HTTP_VERB_PREFIXES: Record<string, string[]> = {\n  GET: ['list', 'get', 'fetch', 'retrieve', 'find'],\n  POST: ['create', 'add', 'insert', 'send'],\n  PUT: ['set', 'update', 'replace', 'put'],\n  PATCH: ['update', 'patch', 'modify'],\n  DELETE: ['delete', 'remove', 'revoke'],\n};\n\n/**\n * Disambiguate multiple method candidates using HTTP verb semantics.\n * Returns the best match or undefined if no unique match is found.\n */\nfunction disambiguateByHttpVerb<T>(candidates: [string, T][], httpMethod: string): [string, T] | undefined {\n  const prefixes = HTTP_VERB_PREFIXES[httpMethod.toUpperCase()];\n  if (!prefixes) return undefined;\n\n  const verbCandidates = candidates.filter(([name]) => {\n    const lower = name.toLowerCase();\n    return prefixes.some((p) => lower.startsWith(p));\n  });\n\n  if (verbCandidates.length === 1) return verbCandidates[0];\n  return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Word-part matching helpers\n// ---------------------------------------------------------------------------\n\n/** Split a camelCase identifier into its word parts (e.g., \"getByExternalId\" → [\"get\",\"By\",\"External\",\"Id\"]). */\nfunction splitCamelCase(name: string): string[] {\n  const parts: string[] = [];\n  let start = 0;\n  for (let i = 1; i < name.length; i++) {\n    if (name[i] >= 'A' && name[i] <= 'Z') {\n      parts.push(name.slice(start, i));\n      start = i;\n    }\n  }\n  parts.push(name.slice(start));\n  return parts;\n}\n\n/** Check if `needle` words form a subsequence of `haystack` words (case-insensitive). */\nfunction isSubsequence(needle: string[], haystack: string[]): boolean {\n  let ni = 0;\n  for (let hi = 0; hi < haystack.length && ni < needle.length; hi++) {\n    if (needle[ni].toLowerCase() === haystack[hi].toLowerCase()) ni++;\n  }\n  return ni === needle.length;\n}\n\n// ---------------------------------------------------------------------------\n// Automatic model name inference\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize a field name to a canonical form for comparison.\n * Handles camelCase → snake_case so \"createdAt\" and \"created_at\" match.\n */\nfunction normalizeFieldName(name: string): string {\n  return toSnakeCase(name);\n}\n\n/**\n * Compute the Jaccard similarity between two sets of normalized field names.\n * Returns score (0–1) and raw intersection count.\n */\nfunction jaccardSimilarity(a: Set<string>, b: Set<string>): { score: number; intersection: number } {\n  if (a.size === 0 && b.size === 0) return { score: 0, intersection: 0 };\n  let intersection = 0;\n  for (const item of a) {\n    if (b.has(item)) intersection++;\n  }\n  const union = a.size + b.size - intersection;\n  return { score: union === 0 ? 0 : intersection / union, intersection };\n}\n\n/**\n * Build a set of normalized field names from an IR model.\n */\nfunction irModelFieldSignature(model: Model): Set<string> {\n  return new Set(model.fields.map((f) => normalizeFieldName(f.name)));\n}\n\n/**\n * Build a set of normalized field names from an SDK interface.\n */\nfunction sdkInterfaceFieldSignature(iface: ApiInterface): Set<string> {\n  return new Set(Object.keys(iface.fields).map(normalizeFieldName));\n}\n\n/**\n * Populate the modelNameByIR map using two strategies:\n *\n * 1. Operation-based matching (high confidence):\n *    When a manifest maps an HTTP operation to an SDK method, extract the\n *    method's return type and parameter types. Match them against the IR\n *    operation's response model and request body model.\n *\n * 2. Field-structure matching (fallback):\n *    For IR models not matched by operations, compare their field names\n *    against all SDK interfaces using Jaccard similarity. A match requires\n *    ≥60% field overlap with ≥3 fields in common.\n */\nfunction buildModelNameMap(\n  surface: ApiSurface,\n  spec: ApiSpec,\n  lookup: OverlayLookup,\n  hints: LanguageHints,\n  options?: { strictModelMatch?: boolean },\n): void {\n  const mapped = new Set<string>(); // IR model names already mapped\n  const usedSdkNames = new Set<string>(); // SDK names already claimed\n\n  // --- Strategy 1: Operation-based matching ---\n  if (lookup.methodByOperation.size > 0) {\n    for (const service of spec.services) {\n      for (const op of service.operations) {\n        const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n        const methodOverlay = lookup.methodByOperation.get(httpKey);\n        if (!methodOverlay) continue;\n\n        // Match response model → SDK return type\n        if (op.response.kind === 'model' && !mapped.has(op.response.name)) {\n          const sdkTypeName = hints.extractReturnTypeName(methodOverlay.returnType);\n          if (sdkTypeName && surface.interfaces[sdkTypeName]) {\n            lookup.modelNameByIR.set(op.response.name, sdkTypeName);\n            mapped.add(op.response.name);\n            usedSdkNames.add(sdkTypeName);\n          }\n        }\n\n        // Match request body model → SDK param type\n        if (op.requestBody?.kind === 'model' && !mapped.has(op.requestBody.name)) {\n          for (const param of methodOverlay.params) {\n            const sdkTypeName = hints.extractParamTypeName(param.type);\n            if (sdkTypeName && surface.interfaces[sdkTypeName]) {\n              lookup.modelNameByIR.set(op.requestBody.name, sdkTypeName);\n              mapped.add(op.requestBody.name);\n              usedSdkNames.add(sdkTypeName);\n              break;\n            }\n          }\n        }\n      }\n    }\n  }\n\n  // --- Strategy 2: Field-structure matching ---\n  // Pre-compute SDK interface field signatures\n  const sdkSignatures: { name: string; fields: Set<string>; fieldCount: number }[] = [];\n  for (const [name, iface] of Object.entries(surface.interfaces)) {\n    if (usedSdkNames.has(name)) continue;\n    const fields = sdkInterfaceFieldSignature(iface);\n    if (fields.size >= 2) {\n      sdkSignatures.push({ name, fields, fieldCount: fields.size });\n    }\n  }\n\n  const sdkSignatureNames = new Set(sdkSignatures.map((s) => s.name));\n\n  for (const model of spec.models) {\n    if (mapped.has(model.name)) continue;\n    if (model.fields.length < 2) continue;\n\n    // Strategy 2a: Prefer exact name match — if the IR model name matches an SDK\n    // interface name exactly, use it without Jaccard scoring. This prevents\n    // false positives when a superset interface (e.g., DirectoryUserWithGroups)\n    // scores higher than the exact match (DirectoryUser).\n    if (sdkSignatureNames.has(model.name) && !usedSdkNames.has(model.name)) {\n      lookup.modelNameByIR.set(model.name, model.name);\n      mapped.add(model.name);\n      usedSdkNames.add(model.name);\n      continue;\n    }\n\n    // Strategy 2a+: Try derived model names before falling back to Jaccard\n    const derivedNames = hints.derivedModelNames(model.name);\n    for (const derived of derivedNames) {\n      if (sdkSignatureNames.has(derived) && !usedSdkNames.has(derived)) {\n        lookup.modelNameByIR.set(model.name, derived);\n        mapped.add(model.name);\n        usedSdkNames.add(derived);\n        break;\n      }\n    }\n    if (mapped.has(model.name)) continue;\n\n    // In strict mode, skip Jaccard entirely\n    if (options?.strictModelMatch) continue;\n\n    // Strategy 2b: Fall back to Jaccard field-similarity matching\n    const irFields = irModelFieldSignature(model);\n    let bestMatch: string | null = null;\n    let bestScore = 0;\n\n    for (const sdk of sdkSignatures) {\n      if (usedSdkNames.has(sdk.name)) continue;\n\n      const { score, intersection } = jaccardSimilarity(irFields, sdk.fields);\n\n      // Require ≥60% Jaccard AND enough fields in common (scaled by model size)\n      const minIntersection = Math.max(3, Math.ceil(irFields.size * 0.5));\n      if (score > bestScore && score >= 0.6 && intersection >= minIntersection) {\n        bestScore = score;\n        bestMatch = sdk.name;\n      }\n    }\n\n    if (bestMatch) {\n      lookup.modelNameByIR.set(model.name, bestMatch);\n      mapped.add(model.name);\n      usedSdkNames.add(bestMatch);\n    }\n  }\n}\n\n/** Categories that can be patched by the overlay retry loop. */\nconst PATCHABLE_CATEGORIES = new Set(['symbol_removed', 'symbol_renamed']);\n\n/** Check if a classified change is patchable by the overlay loop. */\nexport function isPatchableChange(change: ClassifiedChange): boolean {\n  return PATCHABLE_CATEGORIES.has(change.category);\n}\n\n/**\n * Patch overlay with classified changes from a failed verification.\n * Adds explicit name mappings for symbols that were generated with wrong names.\n * Returns a new OverlayLookup (immutable).\n */\nexport function patchOverlay(overlay: OverlayLookup, changes: ClassifiedChange[], baseline: ApiSurface): OverlayLookup {\n  const patched: OverlayLookup = {\n    methodByOperation: new Map(overlay.methodByOperation),\n    httpKeyByMethod: new Map(overlay.httpKeyByMethod),\n    interfaceByName: new Map(overlay.interfaceByName),\n    typeAliasByName: new Map(overlay.typeAliasByName),\n    requiredExports: new Map(Array.from(overlay.requiredExports.entries()).map(([k, v]) => [k, new Set(v)])),\n    modelNameByIR: new Map(overlay.modelNameByIR),\n    fileBySymbol: new Map(overlay.fileBySymbol),\n  };\n\n  let warnedManifest = false;\n\n  for (const c of changes) {\n    if (!isPatchableChange(c)) continue;\n\n    // symbol is the fqName, e.g. \"ClassName.methodName\" or \"ClassName\"\n    const parts = c.symbol.split('.');\n    if (parts.length === 2) {\n      const [className, methodName] = parts;\n      const baseClass = baseline.classes[className];\n      if (baseClass && baseClass.methods[methodName]?.length > 0) {\n        const httpKey = overlay.httpKeyByMethod.get(`${className}.${methodName}`);\n        if (!httpKey && overlay.httpKeyByMethod.size === 0 && !warnedManifest) {\n          console.warn(\n            'Warning: No operations map in .oagen-manifest.json. Method-level violations cannot be auto-patched. ' +\n              'Implement buildOperationsMap in your emitter for the self-correcting loop to resolve these.',\n          );\n          warnedManifest = true;\n        }\n        if (httpKey) {\n          const method = baseClass.methods[methodName][0];\n          patched.methodByOperation.set(httpKey, {\n            className,\n            methodName,\n            params: method.params,\n            returnType: method.returnType,\n          });\n        }\n      }\n      const baseIface = baseline.interfaces[className];\n      if (baseIface) {\n        patched.interfaceByName.set(className, className);\n      }\n    } else if (parts.length === 1) {\n      const name = parts[0];\n      if (baseline.interfaces[name]) {\n        patched.interfaceByName.set(name, name);\n      }\n      if (baseline.typeAliases[name]) {\n        patched.typeAliasByName.set(name, name);\n      }\n    }\n  }\n\n  return patched;\n}\n","import { RegistryError } from '../errors.js';\nimport type { Extractor } from './types.js';\n\nconst extractors = new Map<string, Extractor>();\n\nexport function registerExtractor(extractor: Extractor): void {\n  extractors.set(extractor.language, extractor);\n}\n\nexport function getExtractor(language: string): Extractor {\n  const extractor = extractors.get(language);\n  if (!extractor) {\n    const available = [...extractors.keys()].join(', ') || '(none)';\n    throw new RegistryError(\n      `No extractor registered for language: ${language}. Available: ${available}`,\n      `Register an extractor for \"${language}\" via registerExtractor() or add one in your oagen.config.ts plugin.`,\n    );\n  }\n  return extractor;\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { MANIFEST_FILENAME } from './manifest.js';\n\n/** Minimal shape matching compat/overlay.ts ManifestEntry for cross-layer use. */\ninterface ManifestEntry {\n  operationId: string;\n  sdkResourceProperty: string;\n  sdkMethodName: string;\n  httpMethod: string;\n  path: string;\n  pathParams: string[];\n  bodyFields: string[];\n  queryFields: string[];\n}\n\n/**\n * Read the operations map from `.oagen-manifest.json` in the given directory\n * and convert it to `ManifestEntry[]` for the overlay builder.\n *\n * Returns undefined if the manifest is absent or has no operations field.\n */\nexport function readManifestSync(dir: string): ManifestEntry[] | undefined {\n  const manifestPath = path.join(dir, MANIFEST_FILENAME);\n  if (!existsSync(manifestPath)) return undefined;\n  try {\n    const parsed = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n    const operations = parsed?.operations;\n    if (!operations || typeof operations !== 'object') return undefined;\n    return convertOperationsToManifestEntries(operations);\n  } catch {\n    return undefined;\n  }\n}\n\n/** Convert the operations map from .oagen-manifest.json into ManifestEntry[]. */\nfunction convertOperationsToManifestEntries(operations: Record<string, unknown>): ManifestEntry[] {\n  const entries: ManifestEntry[] = [];\n  for (const [httpKey, value] of Object.entries(operations)) {\n    const spaceIdx = httpKey.indexOf(' ');\n    const httpMethod = httpKey.slice(0, spaceIdx);\n    const httpPath = httpKey.slice(spaceIdx + 1);\n\n    const values = Array.isArray(value) ? value : [value];\n    for (const v of values) {\n      const entry = v as { sdkMethod?: string; service?: string };\n      entries.push({\n        operationId: '',\n        sdkResourceProperty: entry.service ?? '',\n        sdkMethodName: entry.sdkMethod ?? '',\n        httpMethod,\n        path: httpPath,\n        pathParams: [],\n        bodyFields: [],\n        queryFields: [],\n      });\n    }\n  }\n  return entries;\n}\n","import { readFileSync } from 'node:fs';\nimport { ConfigError } from '../errors.js';\nimport { buildOverlayLookup } from '../compat/overlay.js';\nimport type { ApiSurface, LanguageHints, OverlayLookup } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { nodeHints } from '../compat/language-hints.js';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport { readManifestSync } from '../engine/manifest-reader.js';\n\nexport interface OverlayContext {\n  apiSurface: ApiSurface;\n  overlayLookup: OverlayLookup;\n}\n\n/**\n * Load an API surface from disk, discover/load the manifest, resolve\n * language hints, and build the overlay lookup. Shared by diff and generate.\n */\nexport function loadOverlayContext(opts: {\n  apiSurfacePath: string;\n  outputDir: string;\n  lang: string;\n  spec?: ApiSpec;\n}): OverlayContext {\n  let raw: string;\n  try {\n    raw = readFileSync(opts.apiSurfacePath, 'utf-8');\n  } catch {\n    throw new ConfigError(\n      `API surface file not found: ${opts.apiSurfacePath}. Run \\`oagen extract\\` first.`,\n      `Generate the API surface file by running \\`oagen extract --lang ${opts.lang} --sdk-path <path-to-sdk>\\` before running this command.`,\n    );\n  }\n  let apiSurface: ApiSurface;\n  try {\n    apiSurface = JSON.parse(raw) as ApiSurface;\n  } catch (err) {\n    throw new ConfigError(\n      `Failed to parse API surface JSON: ${err instanceof Error ? err.message : String(err)}`,\n      `Ensure \"${opts.apiSurfacePath}\" contains valid JSON. Re-run \\`oagen extract\\` to regenerate it.`,\n    );\n  }\n\n  // Load operations from .oagen-manifest.json in output directory\n  const manifest = readManifestSync(opts.outputDir);\n\n  let hints: LanguageHints = nodeHints;\n  try {\n    hints = getExtractor(opts.lang).hints;\n  } catch {\n    // no extractor registered — use nodeHints fallback\n  }\n\n  const overlayLookup = buildOverlayLookup(apiSurface, manifest, opts.spec, hints);\n  return { apiSurface, overlayLookup };\n}\n","import type { ApiSpec } from '../ir/types.js';\n\n/**\n * Walk all description fields in the IR and expand relative URL paths\n * (e.g. `/reference/users/user`) into full URLs using the given base.\n *\n * Matches markdown-style links: `[text](/path)` → `[text](https://example.com/path)`\n * and bare parenthetical refs: `(/path)` → `(https://example.com/path)`\n */\nexport function expandDocUrls(spec: ApiSpec, docUrl: string): ApiSpec {\n  // Normalize: strip trailing slash so joins are clean\n  const base = docUrl.replace(/\\/+$/, '');\n\n  function expand(description: string | undefined): string | undefined {\n    if (!description) return description;\n    // Match markdown links and bare parenthetical paths with a leading slash\n    return description.replace(/\\(\\/([^)]*)\\)/g, `(${base}/$1)`);\n  }\n\n  return {\n    ...spec,\n    description: expand(spec.description),\n    services: spec.services.map((service) => ({\n      ...service,\n      description: expand(service.description),\n      operations: service.operations.map((op) => ({\n        ...op,\n        description: expand(op.description),\n        pathParams: op.pathParams.map((p) => ({ ...p, description: expand(p.description) })),\n        queryParams: op.queryParams.map((p) => ({ ...p, description: expand(p.description) })),\n        headerParams: op.headerParams.map((p) => ({ ...p, description: expand(p.description) })),\n      })),\n    })),\n    models: spec.models.map((model) => ({\n      ...model,\n      description: expand(model.description),\n      fields: model.fields.map((f) => ({ ...f, description: expand(f.description) })),\n    })),\n    enums: spec.enums.map((e) => ({\n      ...e,\n      values: e.values.map((v) => ({ ...v, description: expand(v.description) })),\n    })),\n  };\n}\n","import { parseSpec, type OpenApiDocument } from '../parser/parse.js';\nimport { generate } from '../engine/orchestrator.js';\nimport { getEmitter } from '../engine/registry.js';\nimport { loadOverlayContext } from './overlay-loader.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\n\nexport async function generateCommand(opts: {\n  spec: string;\n  lang: string;\n  output: string;\n  target?: string;\n  namespace?: string;\n  dryRun?: boolean;\n  apiSurface?: string;\n  compatCheck?: boolean;\n  /** From `--no-prune`. When false, manifest-driven stale-file pruning is skipped. */\n  prune?: boolean;\n  /**\n   * Post-mount service names to generate (from `--services`, a CSV string, or an\n   * array via config). When set, only these services + their mount-siblings +\n   * reachable shared models are emitted; the rest of the SDK tree is left intact.\n   */\n  services?: string | string[];\n  operationIdTransform?: (id: string) => string;\n  schemaNameTransform?: (name: string) => string;\n  transformSpec?: (spec: OpenApiDocument) => OpenApiDocument;\n  docUrl?: string;\n  operationHints?: Record<string, OperationHint>;\n  mountRules?: Record<string, string>;\n  modelHints?: Record<string, string>;\n  fieldHints?: Record<string, Record<string, string>>;\n  emitterOptions?: Record<string, unknown>;\n}): Promise<void> {\n  let ir = await parseSpec(opts.spec, {\n    operationIdTransform: opts.operationIdTransform,\n    schemaNameTransform: opts.schemaNameTransform,\n    transformSpec: opts.transformSpec,\n    fieldHints: opts.fieldHints,\n  });\n  if (opts.docUrl) {\n    ir = expandDocUrls(ir, opts.docUrl);\n  }\n  const emitter = getEmitter(opts.lang);\n  const namespace = opts.namespace ?? ir.name;\n\n  // Normalize the scoped-service selection. Accept a CSV string (CLI) or an\n  // array (config); trim and drop empties so a blank `--services` is treated as\n  // a full generation rather than \"match nothing\".\n  const rawServices = Array.isArray(opts.services) ? opts.services : opts.services?.split(',');\n  const services = rawServices?.map((s) => s.trim()).filter(Boolean);\n\n  // Build overlay from API surface if provided and not disabled\n  let apiSurface;\n  let overlayLookup;\n  if (opts.apiSurface && opts.compatCheck !== false) {\n    const ctx = loadOverlayContext({\n      apiSurfacePath: opts.apiSurface,\n      outputDir: opts.output,\n      lang: opts.lang,\n      spec: ir,\n    });\n    apiSurface = ctx.apiSurface;\n    overlayLookup = ctx.overlayLookup;\n  }\n\n  const files = await generate(ir, emitter, {\n    namespace,\n    dryRun: opts.dryRun,\n    outputDir: opts.output,\n    target: opts.target,\n    apiSurface,\n    overlayLookup,\n    operationHints: opts.operationHints,\n    mountRules: opts.mountRules,\n    modelHints: opts.modelHints,\n    emitterOptions: opts.emitterOptions,\n    noPrune: opts.prune === false,\n    services: services && services.length > 0 ? services : undefined,\n  });\n\n  if (opts.dryRun) {\n    for (const f of files) {\n      console.log(f.path);\n    }\n  } else {\n    console.log(`Generated ${files.length} files in ${opts.output}`);\n    if (opts.target) {\n      console.log(`Integrated into ${opts.target}`);\n    }\n  }\n}\n","import type { FieldChange, ParamChange } from './types.js';\n\nexport function classifyFieldChange(kind: FieldChange['kind'], fieldName: string, isRequired?: boolean): FieldChange {\n  switch (kind) {\n    case 'field-added':\n      return {\n        kind,\n        fieldName,\n        classification: isRequired ? 'breaking' : 'additive',\n      };\n    case 'field-removed':\n      return { kind, fieldName, classification: 'breaking' };\n    case 'field-type-changed':\n      return { kind, fieldName, classification: 'breaking' };\n    case 'field-format-changed':\n      // A primitive's `format` changing (e.g., string → string format=email)\n      // is classified additive at the IR level: the wire-format base type is\n      // unchanged, so callers' deserialization keeps working. Per-emitter\n      // compat checks catch any source-level break a specific language layers\n      // on top (e.g., a typed Email value object in TypeScript).\n      return { kind, fieldName, classification: 'additive' };\n    case 'field-required-changed':\n      return {\n        kind,\n        fieldName,\n        classification: isRequired ? 'breaking' : 'additive',\n        details: isRequired ? 'optional → required' : 'required → optional',\n      };\n    case 'field-access-changed':\n      return { kind, fieldName, classification: 'breaking' };\n  }\n}\n\nexport function classifyParamChange(kind: ParamChange['kind'], paramName: string, isRequired?: boolean): ParamChange {\n  switch (kind) {\n    case 'param-added':\n      return {\n        kind,\n        paramName,\n        classification: isRequired ? 'breaking' : 'additive',\n      };\n    case 'param-removed':\n      return { kind, paramName, classification: 'breaking' };\n    case 'param-type-changed':\n      return { kind, paramName, classification: 'breaking' };\n    case 'param-format-changed':\n      // See `field-format-changed`: format-only diffs are additive at the IR\n      // layer.\n      return { kind, paramName, classification: 'additive' };\n    case 'param-required-changed':\n      return {\n        kind,\n        paramName,\n        classification: isRequired ? 'breaking' : 'additive',\n      };\n    case 'param-default-changed':\n      // Removing or changing a default that callers may have implicitly relied on\n      // changes runtime behavior for clients who never set the param explicitly.\n      // We treat this as breaking so it surfaces as a major bump rather than\n      // sliding through as a silent regression.\n      return { kind, paramName, classification: 'breaking' };\n  }\n}\n","import type { Model, TypeRef } from '../ir/types.js';\nimport { assertNever } from '../ir/types.js';\nimport type { Change, FieldChange } from './types.js';\nimport { classifyFieldChange } from './classify.js';\n\nexport function diffModels(oldModels: Model[], newModels: Model[]): Change[] {\n  const changes: Change[] = [];\n  const oldByName = new Map(oldModels.map((m) => [m.name, m]));\n  const newByName = new Map(newModels.map((m) => [m.name, m]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({ kind: 'model-added', name, classification: 'additive' });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({ kind: 'model-removed', name, classification: 'breaking' });\n    }\n  }\n\n  for (const [name, newModel] of newByName) {\n    const oldModel = oldByName.get(name);\n    if (!oldModel) continue;\n\n    const fieldChanges = diffFields(oldModel, newModel);\n    if (fieldChanges.length > 0) {\n      const hasBreaking = fieldChanges.some((fc) => fc.classification === 'breaking');\n      changes.push({\n        kind: 'model-modified',\n        name,\n        fieldChanges,\n        classification: hasBreaking ? 'breaking' : 'additive',\n      });\n    }\n  }\n\n  return changes;\n}\n\nfunction diffFields(oldModel: Model, newModel: Model): FieldChange[] {\n  const changes: FieldChange[] = [];\n  const oldByName = new Map(oldModel.fields.map((f) => [f.name, f]));\n  const newByName = new Map(newModel.fields.map((f) => [f.name, f]));\n\n  for (const [name, field] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push(classifyFieldChange('field-added', name, field.required));\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push(classifyFieldChange('field-removed', name));\n    }\n  }\n\n  for (const [name, newField] of newByName) {\n    const oldField = oldByName.get(name);\n    if (!oldField) continue;\n\n    if (!typeRefsEqual(oldField.type, newField.type)) {\n      if (primitivesDifferOnlyByFormat(oldField.type, newField.type)) {\n        changes.push({\n          ...classifyFieldChange('field-format-changed', name),\n          details: formatChangeDetails(oldField.type, newField.type),\n        });\n      } else {\n        changes.push({\n          kind: 'field-type-changed',\n          fieldName: name,\n          classification: 'breaking',\n          details: `type changed`,\n        });\n      }\n    }\n\n    if (oldField.required !== newField.required) {\n      changes.push(classifyFieldChange('field-required-changed', name, newField.required));\n    }\n\n    if (!!oldField.readOnly !== !!newField.readOnly || !!oldField.writeOnly !== !!newField.writeOnly) {\n      changes.push(classifyFieldChange('field-access-changed', name));\n    }\n  }\n\n  return changes;\n}\n\n/**\n * True when both refs are primitives with the same base `type` but different\n * `format`. Used to downgrade format-only diffs from breaking type changes to\n * additive `field-format-changed` / `param-format-changed` events: the wire\n * base type is unchanged, so the diff is a hint to language emitters rather\n * than a source-level break.\n */\nexport function primitivesDifferOnlyByFormat(a: TypeRef, b: TypeRef): boolean {\n  if (a.kind !== 'primitive' || b.kind !== 'primitive') return false;\n  if (a.type !== b.type) return false;\n  return (a.format ?? '') !== (b.format ?? '');\n}\n\nexport function formatChangeDetails(a: TypeRef, b: TypeRef): string {\n  const oldFmt = a.kind === 'primitive' ? a.format : undefined;\n  const newFmt = b.kind === 'primitive' ? b.format : undefined;\n  return `format ${oldFmt ?? '<unset>'} → ${newFmt ?? '<unset>'}`;\n}\n\nexport function typeRefsEqual(a: TypeRef, b: TypeRef): boolean {\n  if (a.kind !== b.kind) return false;\n\n  switch (a.kind) {\n    case 'primitive':\n      return b.kind === 'primitive' && a.type === b.type && (a.format ?? '') === ((b as typeof a).format ?? '');\n    case 'array':\n      return b.kind === 'array' && typeRefsEqual(a.items, b.items);\n    case 'model':\n      return b.kind === 'model' && a.name === b.name;\n    case 'enum':\n      return b.kind === 'enum' && a.name === b.name;\n    case 'literal':\n      return b.kind === 'literal' && a.value === b.value;\n    case 'nullable':\n      return b.kind === 'nullable' && typeRefsEqual(a.inner, b.inner);\n    case 'union': {\n      if (b.kind !== 'union') return false;\n      if (a.variants.length !== b.variants.length) return false;\n      if (!a.variants.every((v, i) => typeRefsEqual(v, b.variants[i]))) return false;\n      // Compare discriminator\n      if (!a.discriminator && !b.discriminator) return true;\n      if (!a.discriminator || !b.discriminator) return false;\n      if (a.discriminator.property !== b.discriminator.property) return false;\n      const aKeys = Object.keys(a.discriminator.mapping).sort();\n      const bKeys = Object.keys(b.discriminator.mapping).sort();\n      if (aKeys.length !== bKeys.length) return false;\n      return aKeys.every((k, i) => k === bKeys[i] && a.discriminator!.mapping[k] === b.discriminator!.mapping[k]);\n    }\n    case 'map':\n      return b.kind === 'map' && typeRefsEqual(a.valueType, b.valueType);\n  }\n  return assertNever(a);\n}\n","import type { ErrorResponse, Operation } from '../ir/types.js';\nimport type { Change, ParamChange } from './types.js';\nimport { classifyParamChange } from './classify.js';\nimport { formatChangeDetails, primitivesDifferOnlyByFormat, typeRefsEqual } from './models.js';\n\nexport function diffOperations(serviceName: string, oldOps: Operation[], newOps: Operation[]): Change[] {\n  const changes: Change[] = [];\n  const oldByName = new Map(oldOps.map((o) => [o.name, o]));\n  const newByName = new Map(newOps.map((o) => [o.name, o]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({\n        kind: 'operation-added',\n        serviceName,\n        operationName: name,\n        classification: 'additive',\n      });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({\n        kind: 'operation-removed',\n        serviceName,\n        operationName: name,\n        classification: 'breaking',\n      });\n    }\n  }\n\n  for (const [name, newOp] of newByName) {\n    const oldOp = oldByName.get(name);\n    if (!oldOp) continue;\n\n    const paramChanges = diffParams(oldOp, newOp);\n    const responseChanged = !typeRefsEqual(oldOp.response, newOp.response);\n    const requestBodyChanged = !requestBodiesEqual(oldOp.requestBody, newOp.requestBody);\n    const httpMethodChanged = oldOp.httpMethod !== newOp.httpMethod;\n    const pathChanged = oldOp.path !== newOp.path;\n    const paginatedChanged = !!oldOp.pagination !== !!newOp.pagination;\n    const injectIdempotencyKeyChanged = oldOp.injectIdempotencyKey !== newOp.injectIdempotencyKey;\n    const errorsDiff = classifyErrorsChange(oldOp.errors, newOp.errors);\n    const errorsChanged = errorsDiff !== 'none';\n\n    const hasChanges =\n      paramChanges.length > 0 ||\n      responseChanged ||\n      requestBodyChanged ||\n      httpMethodChanged ||\n      pathChanged ||\n      paginatedChanged ||\n      injectIdempotencyKeyChanged ||\n      errorsChanged;\n\n    if (hasChanges) {\n      // paginated: false→true is additive (SDK gains pagination helper)\n      // paginated: true→false is breaking (SDK loses pagination helper)\n      const paginatedBreaking = paginatedChanged && !newOp.pagination;\n      // injectIdempotencyKey: false→true is additive (SDK gains idempotency key)\n      // injectIdempotencyKey: true→false is breaking (SDK loses idempotency key)\n      const injectIdempotencyKeyBreaking = injectIdempotencyKeyChanged && !newOp.injectIdempotencyKey;\n      const errorsBreaking = errorsDiff === 'breaking';\n\n      const hasBreaking =\n        responseChanged ||\n        requestBodyChanged ||\n        httpMethodChanged ||\n        pathChanged ||\n        paginatedBreaking ||\n        injectIdempotencyKeyBreaking ||\n        errorsBreaking ||\n        paramChanges.some((pc) => pc.classification === 'breaking');\n      changes.push({\n        kind: 'operation-modified',\n        serviceName,\n        operationName: name,\n        paramChanges,\n        responseChanged,\n        requestBodyChanged,\n        httpMethodChanged,\n        pathChanged,\n        paginatedChanged,\n        injectIdempotencyKeyChanged,\n        errorsChanged,\n        classification: hasBreaking ? 'breaking' : 'additive',\n      });\n    }\n  }\n\n  return changes;\n}\n\nfunction requestBodiesEqual(a: Operation['requestBody'], b: Operation['requestBody']): boolean {\n  if (!a && !b) return true;\n  if (!a || !b) return false;\n  return typeRefsEqual(a, b);\n}\n\nfunction classifyErrorsChange(\n  oldErrors: ErrorResponse[],\n  newErrors: ErrorResponse[],\n): 'none' | 'additive' | 'breaking' {\n  const oldByCode = new Map(oldErrors.map((e) => [e.statusCode, e]));\n  const newByCode = new Map(newErrors.map((e) => [e.statusCode, e]));\n\n  let hasAdditive = false;\n  let hasBreaking = false;\n\n  // New error codes added → additive (SDK gains new error classes)\n  for (const code of newByCode.keys()) {\n    if (!oldByCode.has(code)) hasAdditive = true;\n  }\n\n  // Old error codes removed → breaking (SDK loses error classes)\n  for (const code of oldByCode.keys()) {\n    if (!newByCode.has(code)) hasBreaking = true;\n  }\n\n  // Shared error codes with changed types → breaking\n  for (const [code, newErr] of newByCode) {\n    const oldErr = oldByCode.get(code);\n    if (!oldErr) continue;\n    if (!oldErr.type && !newErr.type) continue;\n    if (!oldErr.type || !newErr.type || !typeRefsEqual(oldErr.type, newErr.type)) {\n      hasBreaking = true;\n    }\n  }\n\n  if (hasBreaking) return 'breaking';\n  if (hasAdditive) return 'additive';\n  return 'none';\n}\n\nfunction diffParams(oldOp: Operation, newOp: Operation): ParamChange[] {\n  const changes: ParamChange[] = [];\n  const tagged = (loc: 'path' | 'query' | 'header', params: typeof oldOp.queryParams) =>\n    params.map((p) => ({ p, loc }));\n  const allOldParams = [\n    ...tagged('path', oldOp.pathParams),\n    ...tagged('query', oldOp.queryParams),\n    ...tagged('header', oldOp.headerParams),\n  ];\n  const allNewParams = [\n    ...tagged('path', newOp.pathParams),\n    ...tagged('query', newOp.queryParams),\n    ...tagged('header', newOp.headerParams),\n  ];\n  const oldByName = new Map(allOldParams.map((e) => [e.p.name, e]));\n  const newByName = new Map(allNewParams.map((e) => [e.p.name, e]));\n\n  for (const [name, entry] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push(classifyParamChange('param-added', name, entry.p.required));\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push(classifyParamChange('param-removed', name));\n    }\n  }\n\n  for (const [name, newEntry] of newByName) {\n    const oldEntry = oldByName.get(name);\n    if (!oldEntry) continue;\n\n    if (!typeRefsEqual(oldEntry.p.type, newEntry.p.type)) {\n      if (primitivesDifferOnlyByFormat(oldEntry.p.type, newEntry.p.type)) {\n        const change = classifyParamChange('param-format-changed', name);\n        change.details = formatChangeDetails(oldEntry.p.type, newEntry.p.type);\n        changes.push(change);\n      } else {\n        changes.push(classifyParamChange('param-type-changed', name));\n      }\n    }\n\n    if (oldEntry.p.required !== newEntry.p.required) {\n      changes.push(classifyParamChange('param-required-changed', name, newEntry.p.required));\n    }\n\n    const oldDefault = serializeDefault(oldEntry.p.default);\n    const newDefault = serializeDefault(newEntry.p.default);\n    if (oldDefault !== newDefault) {\n      const change = classifyParamChange('param-default-changed', name);\n      change.oldDefault = oldDefault;\n      change.newDefault = newDefault;\n      change.paramLocation = newEntry.loc;\n      change.details = `default ${oldDefault ?? '<unset>'} → ${newDefault ?? '<unset>'}`;\n      changes.push(change);\n    }\n  }\n\n  return changes;\n}\n\nfunction serializeDefault(value: unknown): string | null {\n  if (value === undefined) return null;\n  if (value === null) return 'null';\n  if (typeof value === 'string') return value;\n  if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n  // Objects/arrays: stable JSON. Stringification of equal-valued objects is\n  // deterministic enough for this comparison since callers typically pass\n  // primitives; complex defaults are rare.\n  try {\n    return JSON.stringify(value);\n  } catch {\n    return String(value);\n  }\n}\n","import type { Service } from '../ir/types.js';\nimport type { Change } from './types.js';\nimport { diffOperations } from './operations.js';\n\nexport function diffServices(oldServices: Service[], newServices: Service[]): Change[] {\n  const changes: Change[] = [];\n  const oldByName = new Map(oldServices.map((s) => [s.name, s]));\n  const newByName = new Map(newServices.map((s) => [s.name, s]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({ kind: 'service-added', name, classification: 'additive' });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({ kind: 'service-removed', name, classification: 'breaking' });\n    }\n  }\n\n  for (const [name, newService] of newByName) {\n    const oldService = oldByName.get(name);\n    if (!oldService) continue;\n\n    changes.push(...diffOperations(name, oldService.operations, newService.operations));\n  }\n\n  return changes;\n}\n","import type { ApiSpec, Enum } from '../ir/types.js';\nimport type { BehaviorChange, Change, DiffReport, EnumValueChange } from './types.js';\nimport { diffModels } from './models.js';\nimport { diffServices } from './services.js';\n\nexport function diffSpecs(oldSpec: ApiSpec, newSpec: ApiSpec): DiffReport {\n  const changes: Change[] = [\n    ...diffModels(oldSpec.models, newSpec.models),\n    ...diffEnums(oldSpec.enums, newSpec.enums),\n    ...diffServices(oldSpec.services, newSpec.services),\n  ];\n\n  const behaviorChanges = collectBehaviorChanges(changes);\n\n  return {\n    oldVersion: oldSpec.version,\n    newVersion: newSpec.version,\n    changes,\n    behaviorChanges,\n    summary: { ...summarize(changes), behaviorChanges: behaviorChanges.length },\n  };\n}\n\nfunction collectBehaviorChanges(changes: Change[]): BehaviorChange[] {\n  const out: BehaviorChange[] = [];\n  for (const c of changes) {\n    if (c.kind !== 'operation-modified') continue;\n    for (const pc of c.paramChanges) {\n      if (pc.kind !== 'param-default-changed') continue;\n      out.push({\n        kind: 'param-default-changed',\n        serviceName: c.serviceName,\n        operationName: c.operationName,\n        paramName: pc.paramName,\n        paramLocation: pc.paramLocation ?? 'query',\n        oldDefault: pc.oldDefault ?? null,\n        newDefault: pc.newDefault ?? null,\n        classification: 'breaking',\n      });\n    }\n  }\n  return out;\n}\n\nfunction diffEnums(oldEnums: Enum[], newEnums: Enum[]): Change[] {\n  const changes: Change[] = [];\n  const oldByName = new Map(oldEnums.map((e) => [e.name, e]));\n  const newByName = new Map(newEnums.map((e) => [e.name, e]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({ kind: 'enum-added', name, classification: 'additive' });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({ kind: 'enum-removed', name, classification: 'breaking' });\n    }\n  }\n\n  for (const [name, newEnum] of newByName) {\n    const oldEnum = oldByName.get(name);\n    if (!oldEnum) continue;\n\n    const valueChanges = diffEnumValues(oldEnum, newEnum);\n    if (valueChanges.length > 0) {\n      const hasBreaking = valueChanges.some((vc) => vc.classification === 'breaking');\n      changes.push({\n        kind: 'enum-modified',\n        name,\n        valueChanges,\n        classification: hasBreaking ? 'breaking' : 'additive',\n      });\n    }\n  }\n\n  return changes;\n}\n\nfunction diffEnumValues(oldEnum: Enum, newEnum: Enum): EnumValueChange[] {\n  const changes: EnumValueChange[] = [];\n  const oldByName = new Map(oldEnum.values.map((v) => [v.name, v]));\n  const newByName = new Map(newEnum.values.map((v) => [v.name, v]));\n\n  for (const [name] of newByName) {\n    if (!oldByName.has(name)) {\n      changes.push({ kind: 'value-added', valueName: name, classification: 'additive' });\n    }\n  }\n\n  for (const [name] of oldByName) {\n    if (!newByName.has(name)) {\n      changes.push({ kind: 'value-removed', valueName: name, classification: 'breaking' });\n    }\n  }\n\n  for (const [name, newVal] of newByName) {\n    const oldVal = oldByName.get(name);\n    if (!oldVal) continue;\n\n    if (oldVal.value !== newVal.value) {\n      changes.push({\n        kind: 'value-changed',\n        valueName: name,\n        classification: 'breaking',\n        details: `value changed from '${oldVal.value}' to '${newVal.value}'`,\n      });\n    }\n  }\n\n  return changes;\n}\n\nfunction summarize(changes: Change[]) {\n  let added = 0;\n  let removed = 0;\n  let modified = 0;\n  let breaking = 0;\n  let additive = 0;\n\n  for (const c of changes) {\n    if (c.kind.endsWith('-added')) added++;\n    else if (c.kind.endsWith('-removed')) removed++;\n    else if (c.kind.endsWith('-modified')) modified++;\n\n    if (c.classification === 'breaking') breaking++;\n    else additive++;\n  }\n\n  return { added, removed, modified, breaking, additive };\n}\n","import { parseSpec, type OpenApiDocument } from '../parser/parse.js';\nimport { diffSpecs } from '../differ/diff.js';\nimport { CommandError } from '../errors.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\n\nexport async function diffCommand(opts: {\n  old: string;\n  new: string;\n  operationIdTransform?: (id: string) => string;\n  schemaNameTransform?: (name: string) => string;\n  transformSpec?: (spec: OpenApiDocument) => OpenApiDocument;\n  docUrl?: string;\n}): Promise<void> {\n  const parseOptions = {\n    operationIdTransform: opts.operationIdTransform,\n    schemaNameTransform: opts.schemaNameTransform,\n    transformSpec: opts.transformSpec,\n  };\n  let [oldSpec, newSpec] = await Promise.all([parseSpec(opts.old, parseOptions), parseSpec(opts.new, parseOptions)]);\n  if (opts.docUrl) {\n    oldSpec = expandDocUrls(oldSpec, opts.docUrl);\n    newSpec = expandDocUrls(newSpec, opts.docUrl);\n  }\n\n  const diff = diffSpecs(oldSpec, newSpec);\n  console.log(JSON.stringify(diff, null, 2));\n  throw new CommandError(\n    '',\n    '',\n    diff.summary.breaking > 0\n      ? 2\n      : diff.summary.modified > 0 || diff.summary.removed > 0\n        ? 1\n        : diff.summary.added > 0\n          ? 1\n          : 0,\n  );\n}\n","import { writeFileSync } from 'node:fs';\nimport { getExtractor } from '../compat/extractor-registry.js';\n\nexport async function extractCommand(opts: { sdkPath: string; lang: string; output: string }): Promise<void> {\n  const extractor = getExtractor(opts.lang);\n  console.log(`Extracting ${opts.lang} API surface from ${opts.sdkPath}...`);\n  const surface = await extractor.extract(opts.sdkPath);\n  writeFileSync(opts.output, JSON.stringify(surface, null, 2));\n  const symbolCount =\n    Object.keys(surface.classes).length +\n    Object.keys(surface.interfaces).length +\n    Object.keys(surface.typeAliases).length +\n    Object.keys(surface.enums).length;\n  console.log(`Extracted ${symbolCount} symbols → ${opts.output}`);\n}\n","/**\n * Language-aware compatibility policy.\n *\n * Defines which aspects of the public API surface are breaking in each\n * language. Built-in defaults capture language semantics (e.g., PHP has\n * named arguments, Go does not). Config overrides allow per-SDK divergence.\n */\n\nimport type { LanguageId } from './ir.js';\n\n/** Policy hints that determine what constitutes a breaking change. */\nexport interface CompatPolicyHints {\n  /** Callers reference parameter names at the call site (PHP named args, Python/Ruby keyword args, Kotlin/C# named args). */\n  callerUsesParamNames: boolean;\n  /** Constructor positional order is part of the public API. */\n  constructorOrderMatters: boolean;\n  /** Method parameter names are visible to callers. */\n  methodParameterNamesArePublicApi: boolean;\n  /** Constructor parameter names are visible to callers. */\n  constructorParameterNamesArePublicApi: boolean;\n  /** Method overload sets are part of the public API (Kotlin, C#). */\n  overloadsArePublicApi: boolean;\n  /** Function arity is part of the public API (Elixir, Go). */\n  arityIsPublicApi: boolean;\n}\n\n/** Built-in language defaults. */\nconst LANGUAGE_DEFAULTS: Record<LanguageId, CompatPolicyHints> = {\n  php: {\n    callerUsesParamNames: true,\n    constructorOrderMatters: true,\n    methodParameterNamesArePublicApi: true,\n    constructorParameterNamesArePublicApi: true,\n    overloadsArePublicApi: false,\n    arityIsPublicApi: false,\n  },\n  python: {\n    callerUsesParamNames: true,\n    constructorOrderMatters: true,\n    methodParameterNamesArePublicApi: true,\n    constructorParameterNamesArePublicApi: true,\n    overloadsArePublicApi: false,\n    arityIsPublicApi: false,\n  },\n  ruby: {\n    callerUsesParamNames: true,\n    constructorOrderMatters: true,\n    methodParameterNamesArePublicApi: true,\n    constructorParameterNamesArePublicApi: true,\n    overloadsArePublicApi: false,\n    arityIsPublicApi: false,\n  },\n  go: {\n    callerUsesParamNames: false,\n    constructorOrderMatters: true,\n    methodParameterNamesArePublicApi: false,\n    constructorParameterNamesArePublicApi: false,\n    overloadsArePublicApi: false,\n    arityIsPublicApi: true,\n  },\n  kotlin: {\n    callerUsesParamNames: true,\n    constructorOrderMatters: false,\n    methodParameterNamesArePublicApi: true,\n    constructorParameterNamesArePublicApi: true,\n    overloadsArePublicApi: true,\n    arityIsPublicApi: false,\n  },\n  dotnet: {\n    callerUsesParamNames: true,\n    constructorOrderMatters: false,\n    methodParameterNamesArePublicApi: true,\n    constructorParameterNamesArePublicApi: true,\n    overloadsArePublicApi: true,\n    arityIsPublicApi: false,\n  },\n  elixir: {\n    callerUsesParamNames: true,\n    constructorOrderMatters: false,\n    methodParameterNamesArePublicApi: true,\n    constructorParameterNamesArePublicApi: false,\n    overloadsArePublicApi: false,\n    arityIsPublicApi: true,\n  },\n  rust: {\n    callerUsesParamNames: false,\n    constructorOrderMatters: true,\n    methodParameterNamesArePublicApi: false,\n    constructorParameterNamesArePublicApi: false,\n    overloadsArePublicApi: false,\n    arityIsPublicApi: true,\n  },\n  node: {\n    callerUsesParamNames: false,\n    constructorOrderMatters: false,\n    methodParameterNamesArePublicApi: false,\n    constructorParameterNamesArePublicApi: false,\n    overloadsArePublicApi: false,\n    arityIsPublicApi: false,\n  },\n};\n\n/** Get the built-in default policy for a language. */\nexport function getDefaultPolicy(language: LanguageId): CompatPolicyHints {\n  return { ...LANGUAGE_DEFAULTS[language] };\n}\n\n/** Merge user overrides onto language defaults. Only provided keys are overridden. */\nexport function mergePolicy(defaults: CompatPolicyHints, overrides: Partial<CompatPolicyHints>): CompatPolicyHints {\n  return { ...defaults, ...overrides };\n}\n\n/** All supported language IDs. */\nexport const ALL_LANGUAGE_IDS: readonly LanguageId[] = Object.keys(LANGUAGE_DEFAULTS) as LanguageId[];\n","/**\n * Schema versioning for compatibility snapshots.\n *\n * Snapshots are versioned so consumers can detect format changes and\n * apply migration logic if needed.\n */\n\nimport type { CompatSnapshot } from './ir.js';\n\n/** Current schema version for compatibility snapshots. */\nexport const COMPAT_SCHEMA_VERSION = '1';\n\n/** Validate that a parsed snapshot has a compatible schema version. */\nexport function isCompatibleSchemaVersion(snapshot: { schemaVersion?: string }): boolean {\n  return snapshot.schemaVersion === COMPAT_SCHEMA_VERSION;\n}\n\n/** Validate the basic structure of a parsed compat snapshot. */\nexport function validateSnapshot(data: unknown): data is CompatSnapshot {\n  if (typeof data !== 'object' || data === null) return false;\n  const obj = data as Record<string, unknown>;\n  return (\n    typeof obj.schemaVersion === 'string' &&\n    typeof obj.source === 'object' &&\n    obj.source !== null &&\n    typeof obj.policies === 'object' &&\n    obj.policies !== null &&\n    Array.isArray(obj.symbols)\n  );\n}\n","/**\n * Rich compatibility IR for cross-language compatibility verification.\n *\n * These types represent the public API surface of an SDK in a language-aware,\n * machine-readable format. They extend the basic ApiSurface with richer\n * parameter semantics, sensitivity flags, and provenance metadata.\n */\n\nimport type { CompatPolicyHints } from './policy.js';\n\n/** Language identifier for emitter targets. */\nexport type LanguageId = 'node' | 'php' | 'python' | 'ruby' | 'go' | 'kotlin' | 'dotnet' | 'elixir' | 'rust';\n\n/** A full compatibility snapshot of an SDK's public API surface. */\nexport interface CompatSnapshot {\n  schemaVersion: string;\n  source: {\n    specSha?: string;\n    extractedAt: string;\n  };\n  policies: CompatPolicyHints;\n  symbols: CompatSymbol[];\n}\n\n/** Kind of public API symbol. */\nexport type CompatSymbolKind =\n  | 'service_accessor'\n  | 'callable'\n  | 'constructor'\n  | 'field'\n  | 'property'\n  | 'enum'\n  | 'enum_member'\n  | 'alias';\n\n/** Visibility level of a symbol. */\nexport type CompatVisibility = 'public' | 'protected' | 'internal';\n\n/** Stability classification of a symbol. */\nexport type CompatStability = 'stable' | 'unstable' | 'deprecated';\n\n/** How the symbol was generated. */\nexport type CompatSourceKind =\n  | 'generated_service_wrapper'\n  | 'generated_model_constructor'\n  | 'generated_resource_constructor'\n  | 'generated_enum'\n  | 'compat_alias';\n\n/** A single public API symbol with its full metadata. */\nexport interface CompatSymbol {\n  id: string;\n  kind: CompatSymbolKind;\n  fqName: string;\n  ownerFqName?: string;\n  displayName: string;\n  visibility: CompatVisibility;\n  stability: CompatStability;\n  sourceKind: CompatSourceKind;\n  operationId?: string;\n  schemaName?: string;\n  route?: {\n    method: string;\n    path: string;\n  };\n  parameters?: CompatParameter[];\n  returns?: CompatTypeRef;\n  /** Type reference for field/property symbols. */\n  typeRef?: CompatTypeRef;\n  /** Value for enum member symbols. */\n  value?: string | number;\n  /** Relative path to the source file where this symbol is defined. */\n  sourceFile?: string;\n}\n\n/** How a parameter is passed at the call site. */\nexport type CompatPassingStyle =\n  | 'positional'\n  | 'keyword'\n  | 'named'\n  | 'keyword_or_positional'\n  | 'options_object'\n  | 'builder';\n\n/** A parameter on a callable or constructor symbol. */\nexport interface CompatParameter {\n  publicName: string;\n  wireName?: string;\n  position: number;\n  required: boolean;\n  nullable: boolean;\n  hasDefault: boolean;\n  passing: CompatPassingStyle;\n  type: CompatTypeRef;\n  sensitivity: ParameterSensitivity;\n}\n\n/** Which aspects of this parameter are part of the public API contract. */\nexport interface ParameterSensitivity {\n  order: boolean;\n  publicName: boolean;\n  requiredness: boolean;\n  type: boolean;\n}\n\n/** A type reference — either a named type or an inline description. */\nexport interface CompatTypeRef {\n  name: string;\n  nullable?: boolean;\n  array?: boolean;\n  generic?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Bridge: ApiSurface → CompatSnapshot\n// ---------------------------------------------------------------------------\n\nimport type { ApiSurface, ApiParam } from './types.js';\nimport { getDefaultPolicy } from './policy.js';\nimport { COMPAT_SCHEMA_VERSION } from './schema.js';\n\n/**\n * Convert a legacy ApiSurface to a CompatSnapshot.\n *\n * This bridge allows existing extractors (which produce ApiSurface) to feed\n * into the new classified diff engine without requiring immediate migration.\n */\nexport function apiSurfaceToSnapshot(surface: ApiSurface): CompatSnapshot {\n  const language = (surface.language || 'node') as LanguageId;\n  const symbols: CompatSymbol[] = [];\n\n  // Convert classes → service_accessor symbols + callable/constructor children\n  for (const [className, cls] of Object.entries(surface.classes)) {\n    symbols.push({\n      id: `class:${className}`,\n      kind: 'service_accessor',\n      fqName: className,\n      displayName: className,\n      visibility: 'public',\n      stability: cls.deprecationMessage ? 'deprecated' : 'stable',\n      sourceKind: 'generated_service_wrapper',\n      ...(cls.sourceFile ? { sourceFile: cls.sourceFile } : {}),\n    });\n\n    // Constructor\n    if (cls.constructorParams.length > 0) {\n      symbols.push({\n        id: `ctor:${className}`,\n        kind: 'constructor',\n        fqName: `${className}.constructor`,\n        ownerFqName: className,\n        displayName: `new ${className}`,\n        visibility: 'public',\n        stability: 'stable',\n        sourceKind: 'generated_resource_constructor',\n        parameters: cls.constructorParams.map((p, i) => apiParamToCompatParam(p, i, language)),\n        ...(cls.sourceFile ? { sourceFile: cls.sourceFile } : {}),\n      });\n    }\n\n    // Methods\n    for (const [methodName, overloads] of Object.entries(cls.methods)) {\n      for (let oi = 0; oi < overloads.length; oi++) {\n        const method = overloads[oi];\n        const suffix = overloads.length > 1 ? `#${oi}` : '';\n        symbols.push({\n          id: `method:${className}.${methodName}${suffix}`,\n          kind: 'callable',\n          fqName: `${className}.${methodName}`,\n          ownerFqName: className,\n          displayName: `${className}.${methodName}`,\n          visibility: 'public',\n          stability: 'stable',\n          sourceKind: 'generated_service_wrapper',\n          parameters: method.params.map((p, i) => apiParamToCompatParam(p, i, language)),\n          returns: { name: method.returnType },\n          ...(cls.sourceFile ? { sourceFile: cls.sourceFile } : {}),\n        });\n      }\n    }\n\n    // Properties\n    for (const [propName, prop] of Object.entries(cls.properties)) {\n      symbols.push({\n        id: `prop:${className}.${propName}`,\n        kind: 'property',\n        fqName: `${className}.${propName}`,\n        ownerFqName: className,\n        displayName: `${className}.${propName}`,\n        visibility: 'public',\n        stability: 'stable',\n        sourceKind: 'generated_service_wrapper',\n        typeRef: { name: prop.type },\n        ...(cls.sourceFile ? { sourceFile: cls.sourceFile } : {}),\n      });\n    }\n  }\n\n  // Convert interfaces → field symbols\n  for (const [ifaceName, iface] of Object.entries(surface.interfaces)) {\n    symbols.push({\n      id: `iface:${ifaceName}`,\n      kind: 'alias',\n      fqName: ifaceName,\n      displayName: ifaceName,\n      visibility: 'public',\n      stability: 'stable',\n      sourceKind: 'generated_resource_constructor',\n      ...(iface.sourceFile ? { sourceFile: iface.sourceFile } : {}),\n    });\n\n    for (const [fieldName, field] of Object.entries(iface.fields)) {\n      symbols.push({\n        id: `field:${ifaceName}.${fieldName}`,\n        kind: 'field',\n        fqName: `${ifaceName}.${fieldName}`,\n        ownerFqName: ifaceName,\n        displayName: `${ifaceName}.${fieldName}`,\n        visibility: 'public',\n        stability: 'stable',\n        sourceKind: 'generated_resource_constructor',\n        typeRef: { name: field.type },\n        ...(iface.sourceFile ? { sourceFile: iface.sourceFile } : {}),\n      });\n    }\n\n    // Constructor if interface has one\n    if (iface.hasCustomConstructor) {\n      symbols.push({\n        id: `ctor:${ifaceName}`,\n        kind: 'constructor',\n        fqName: `${ifaceName}.constructor`,\n        ownerFqName: ifaceName,\n        displayName: `new ${ifaceName}`,\n        visibility: 'public',\n        stability: 'stable',\n        sourceKind: 'generated_resource_constructor',\n        ...(iface.sourceFile ? { sourceFile: iface.sourceFile } : {}),\n      });\n    }\n  }\n\n  // Convert type aliases\n  for (const [aliasName, alias] of Object.entries(surface.typeAliases)) {\n    symbols.push({\n      id: `alias:${aliasName}`,\n      kind: 'alias',\n      fqName: aliasName,\n      displayName: aliasName,\n      visibility: 'public',\n      stability: 'stable',\n      sourceKind: 'generated_resource_constructor',\n      ...(alias.sourceFile ? { sourceFile: alias.sourceFile } : {}),\n    });\n  }\n\n  // Convert enums\n  for (const [enumName, enumDef] of Object.entries(surface.enums)) {\n    symbols.push({\n      id: `enum:${enumName}`,\n      kind: 'enum',\n      fqName: enumName,\n      displayName: enumName,\n      visibility: 'public',\n      stability: 'stable',\n      sourceKind: 'generated_enum',\n      ...(enumDef.sourceFile ? { sourceFile: enumDef.sourceFile } : {}),\n    });\n\n    for (const [memberName, memberValue] of Object.entries(enumDef.members)) {\n      symbols.push({\n        id: `enum_member:${enumName}.${memberName}`,\n        kind: 'enum_member',\n        fqName: `${enumName}.${memberName}`,\n        ownerFqName: enumName,\n        displayName: `${enumName}.${memberName}`,\n        visibility: 'public',\n        stability: 'stable',\n        sourceKind: 'generated_enum',\n        value: memberValue,\n        ...(enumDef.sourceFile ? { sourceFile: enumDef.sourceFile } : {}),\n      });\n    }\n  }\n\n  return {\n    schemaVersion: COMPAT_SCHEMA_VERSION,\n    source: { extractedAt: surface.extractedAt },\n    policies: getDefaultPolicy(language),\n    symbols,\n  };\n}\n\n/** Convert a legacy ApiParam to a CompatParameter. */\nfunction apiParamToCompatParam(param: ApiParam, position: number, language: LanguageId): CompatParameter {\n  const policy = getDefaultPolicy(language);\n  const passing = param.passingStyle ?? inferPassingStyle(language);\n  return {\n    publicName: param.name,\n    position,\n    required: !param.optional,\n    nullable: false,\n    hasDefault: param.optional,\n    passing,\n    type: { name: param.type },\n    sensitivity: {\n      // Method-call order matters only when callers pass positionally. keyword\n      // (Ruby/Python/Elixir) and options_object (Node) hide position entirely;\n      // named (PHP/Kotlin/C#) is handled as soft-risk in classify.\n      order: passing === 'positional',\n      publicName: policy.methodParameterNamesArePublicApi,\n      requiredness: true,\n      type: true,\n    },\n  };\n}\n\n/** Infer the default parameter passing style for a language. */\nfunction inferPassingStyle(language: LanguageId): CompatPassingStyle {\n  switch (language) {\n    case 'python':\n    case 'ruby':\n    case 'elixir':\n      return 'keyword';\n    case 'php':\n    case 'kotlin':\n    case 'dotnet':\n      return 'named';\n    case 'node':\n      return 'options_object';\n    default:\n      return 'positional';\n  }\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { resolve } from 'node:path';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport { parseSpec, type OpenApiDocument } from '../parser/parse.js';\nimport { apiSurfaceToSnapshot } from '../compat/ir.js';\nimport { readManifest } from '../engine/manifest.js';\nimport type { Manifest } from '../engine/manifest.js';\nimport type { CompatSnapshot } from '../compat/ir.js';\nimport type { ApiSurface, ApiClass } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\n\nconst SNAPSHOT_FILENAME = '.oagen-compat-snapshot.json';\n\n/** Normalize a name for case-insensitive matching: strip underscores and lowercase. */\nfunction normalize(name: string): string {\n  return name.replace(/_/g, '').toLowerCase();\n}\n\n/**\n * Build a map of normalized service name → Set of generated method names\n * from the manifest's operations record.\n */\nfunction buildServiceMethodMap(operations: Record<string, unknown>): Map<string, Set<string>> {\n  const result = new Map<string, Set<string>>();\n  for (const value of Object.values(operations)) {\n    if (typeof value !== 'object' || value === null) continue;\n    const { sdkMethod, service } = value as { sdkMethod?: string; service?: string };\n    if (typeof sdkMethod !== 'string' || typeof service !== 'string') continue;\n    const key = normalize(service);\n    if (!result.has(key)) result.set(key, new Set());\n    result.get(key)!.add(sdkMethod);\n  }\n  return result;\n}\n\n/**\n * Filter an ApiSurface to only include generated symbols based on the manifest.\n *\n * Two levels of filtering:\n *  1. File-level: classes/interfaces/enums from files not in the manifest are\n *     dropped entirely (they are wholly hand-written).\n *  2. Method-level: for service classes (those whose name matches a manifest\n *     service), only methods listed in the manifest operations are kept.\n *     Constructors and properties are always preserved since they are structural.\n *     Non-service classes (models, enums, etc.) keep all their symbols.\n */\nfunction filterSurfaceByManifest(\n  surface: ApiSurface,\n  manifest: Manifest,\n): {\n  filtered: ApiSurface;\n  filesExcluded: number;\n  methodsExcluded: number;\n} {\n  const manifestFiles = new Set(manifest.files);\n  const serviceMethodMap = manifest.operations\n    ? buildServiceMethodMap(manifest.operations)\n    : new Map<string, Set<string>>();\n\n  let filesExcluded = 0;\n  let methodsExcluded = 0;\n\n  // Filter a record by manifest files, counting exclusions\n  const filterByFile = <T extends { sourceFile?: string }>(record: Record<string, T>): Record<string, T> => {\n    const result: Record<string, T> = {};\n    for (const [name, entry] of Object.entries(record)) {\n      if (entry.sourceFile && manifestFiles.has(entry.sourceFile)) {\n        result[name] = entry;\n      } else {\n        filesExcluded++;\n      }\n    }\n    return result;\n  };\n\n  // Filter classes: file-level first, then method-level for service classes\n  const filteredClasses: Record<string, ApiClass> = {};\n  for (const [name, cls] of Object.entries(surface.classes)) {\n    if (cls.sourceFile && !manifestFiles.has(cls.sourceFile)) {\n      filesExcluded++;\n      continue;\n    }\n\n    // Check if this class is a service with known operations\n    const generatedMethods = serviceMethodMap.get(normalize(name));\n    if (generatedMethods) {\n      // Service class from a generated file — keep all methods.\n      // File-level filtering already ensures this is a generated file;\n      // method-level filtering was dropping wrapper methods (e.g.\n      // createM2MApplication) and utility methods (e.g. verify_event)\n      // that aren't tracked as HTTP operations in the manifest.\n      // Clear constructorParams: service constructors are internal DI\n      // wiring (e.g. __construct($client)), not user-facing API.\n      filteredClasses[name] = { ...cls, constructorParams: [] };\n    } else {\n      // Model / utility class — keep all symbols\n      filteredClasses[name] = cls;\n    }\n  }\n\n  // Filter exports to only include files in the manifest\n  const filteredExports: Record<string, string[]> = {};\n  for (const [filePath, symbols] of Object.entries(surface.exports)) {\n    if (manifestFiles.has(filePath)) {\n      filteredExports[filePath] = symbols;\n    }\n  }\n\n  return {\n    filtered: {\n      ...surface,\n      classes: filteredClasses,\n      interfaces: filterByFile(surface.interfaces),\n      typeAliases: filterByFile(surface.typeAliases),\n      enums: filterByFile(surface.enums),\n      exports: filteredExports,\n    },\n    filesExcluded,\n    methodsExcluded,\n  };\n}\n\nexport async function compatExtractCommand(opts: {\n  sdkPath: string;\n  lang: string;\n  output: string;\n  spec?: string;\n  schemaNameTransform?: (name: string) => string;\n  transformSpec?: (spec: OpenApiDocument) => OpenApiDocument;\n}): Promise<void> {\n  const extractor = getExtractor(opts.lang);\n  console.log(`Extracting ${opts.lang} compat snapshot from ${opts.sdkPath}...`);\n\n  let surface = await extractor.extract(opts.sdkPath);\n\n  // If the SDK has a manifest, scope extraction to only generated symbols.\n  // File-level: excludes wholly hand-written files.\n  const manifest = await readManifest(opts.sdkPath);\n  if (manifest) {\n    const { filtered, filesExcluded } = filterSurfaceByManifest(surface, manifest);\n    surface = filtered;\n    if (filesExcluded > 0) {\n      console.log(`Manifest filter: excluded ${filesExcluded} hand-written file(s)`);\n    }\n  }\n\n  const snapshot = apiSurfaceToSnapshot(surface);\n\n  // Enrich with spec context if provided\n  if (opts.spec) {\n    const specContent = readFileSync(opts.spec, 'utf-8');\n    snapshot.source.specSha = createHash('sha256').update(specContent).digest('hex');\n\n    const parsedSpec = await parseSpec(opts.spec, {\n      schemaNameTransform: opts.schemaNameTransform,\n      transformSpec: opts.transformSpec,\n    });\n    enrichWithSpecContext(snapshot, parsedSpec);\n  }\n\n  const outputPath = resolve(opts.output, SNAPSHOT_FILENAME);\n  writeFileSync(outputPath, JSON.stringify(snapshot, null, 2));\n  console.log(`Extracted ${snapshot.symbols.length} symbols → ${outputPath}`);\n}\n\n/**\n * Enrich snapshot symbols with spec-level identity.\n *\n * - Callable symbols get `operationId` and `route` from spec operations.\n * - Property/field/constructor/service_accessor symbols get `schemaName`\n *   from spec models, enabling cross-language grouping in reports.\n *\n * The `schemaName` uses the spec-level identity (e.g. \"GenerateLinkBody.admin_emails\")\n * which is the same regardless of the language's naming conventions.\n */\nfunction enrichWithSpecContext(snapshot: CompatSnapshot, spec: ApiSpec): void {\n  // Build lookup: \"ServiceName.methodName\" → { operationId, method, path }\n  const opLookup = new Map<string, { operationId: string; method: string; path: string }>();\n  for (const service of spec.services) {\n    for (const op of service.operations) {\n      const key = `${service.name}.${op.name}`;\n      opLookup.set(key, {\n        operationId: op.name,\n        method: op.httpMethod,\n        path: op.path,\n      });\n    }\n  }\n\n  // Build model field lookup for schema-level identity.\n  // Normalized class name → { specModelName, fields: Map<normalizedFieldName, specFieldName> }\n  const norm = (s: string) => s.replace(/_/g, '').toLowerCase();\n  const modelLookup = new Map<string, { specName: string; fields: Map<string, string> }>();\n  for (const model of spec.models) {\n    const fieldMap = new Map<string, string>();\n    for (const field of model.fields) {\n      fieldMap.set(norm(field.name), field.name);\n    }\n    modelLookup.set(norm(model.name), { specName: model.name, fields: fieldMap });\n  }\n\n  for (const sym of snapshot.symbols) {\n    // Enrich callables with operation identity\n    if (sym.kind === 'callable') {\n      const match = opLookup.get(sym.fqName);\n      if (match) {\n        sym.operationId = match.operationId;\n        sym.route = { method: match.method, path: match.path };\n      }\n    }\n\n    // Enrich all symbols with schema-level identity\n    if (sym.ownerFqName) {\n      // This symbol belongs to a class — try to match the class to a spec model\n      const modelMatch = modelLookup.get(norm(sym.ownerFqName));\n      if (modelMatch) {\n        // Extract the local name (part after the dot)\n        const localName = sym.fqName.includes('.') ? sym.fqName.split('.').pop()! : sym.fqName;\n        const fieldMatch = modelMatch.fields.get(norm(localName));\n        if (fieldMatch) {\n          sym.schemaName = `${modelMatch.specName}.${fieldMatch}`;\n        } else {\n          // Class-level symbol (constructor, etc.) — use just the model name\n          sym.schemaName = modelMatch.specName;\n        }\n      }\n    } else {\n      // Top-level symbol (class itself) — try to match to a spec model\n      const modelMatch = modelLookup.get(norm(sym.fqName));\n      if (modelMatch) {\n        sym.schemaName = modelMatch.specName;\n      }\n    }\n  }\n}\n","/**\n * Compat configuration types for `oagen.config.ts`.\n *\n * The `compat` section of the config holds human-authored policy:\n * fail thresholds, language overrides, and intentional break approvals.\n * Generated state (manifests, snapshots, reports) lives elsewhere.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\n\n// ---------------------------------------------------------------------------\n// Change categories\n// ---------------------------------------------------------------------------\n\n/** Breaking change categories — changes that break callers. */\nexport type BreakingChangeCategory =\n  | 'symbol_removed'\n  | 'symbol_renamed'\n  | 'parameter_removed'\n  | 'parameter_renamed'\n  | 'parameter_requiredness_increased'\n  | 'parameter_type_narrowed'\n  | 'parameter_position_changed_order_sensitive'\n  | 'constructor_position_changed_order_sensitive'\n  | 'named_arg_name_removed'\n  | 'keyword_name_removed'\n  | 'overload_removed'\n  | 'union_wrapper_migration_without_compat_alias'\n  | 'field_type_changed'\n  | 'return_type_changed'\n  | 'enum_member_value_changed';\n\n/** Soft-risk change categories — may affect callers depending on usage. */\nexport type SoftRiskChangeCategory =\n  | 'parameter_added_non_terminal_optional'\n  | 'constructor_reordered_named_friendly'\n  | 'default_value_changed'\n  | 'wrapper_stricter_than_previous_sdk_but_matches_spec'\n  | 'doc_surface_drift';\n\n/** Additive change categories — safe to ship. */\nexport type AdditiveChangeCategory =\n  | 'symbol_added'\n  | 'parameter_added_optional_terminal'\n  | 'new_constructor_overload_added'\n  | 'new_wrapper_alias_added';\n\n/** All change categories. */\nexport type CompatChangeCategory = BreakingChangeCategory | SoftRiskChangeCategory | AdditiveChangeCategory;\n\n/** Change severity levels. */\nexport type CompatChangeSeverity = 'breaking' | 'soft-risk' | 'additive';\n\n/** Provenance bucket — where the drift originated. */\nexport type CompatProvenance =\n  | 'spec_shape_change'\n  | 'spec_ordering_change'\n  | 'emitter_template_change'\n  | 'compat_extractor_change'\n  | 'operation_hint_change'\n  | 'manual_override_change'\n  | 'normalization_change'\n  | 'unknown';\n\n// ---------------------------------------------------------------------------\n// Fail threshold\n// ---------------------------------------------------------------------------\n\n/** Level at which `verify` should fail. */\nexport type CompatFailLevel = 'none' | 'breaking' | 'soft-risk';\n\n// ---------------------------------------------------------------------------\n// Approvals\n// ---------------------------------------------------------------------------\n\n/** A single intentional-break approval in `oagen.config.ts`. */\nexport interface CompatApproval {\n  /** Fully-qualified symbol (e.g., \"Acme\\\\Service\\\\Users::createUser\"). */\n  symbol: string;\n  /** The kind of change being approved. */\n  category: CompatChangeCategory;\n  /** Languages this approval applies to. Omit for all impacted languages. */\n  appliesTo?: LanguageId[] | 'all-impacted-languages';\n  /** Optional narrowing criteria. */\n  match?: {\n    parameter?: string;\n    member?: string;\n    oldName?: string;\n    newName?: string;\n  };\n  /** Minimum release level required for this break. */\n  allowedReleaseLevel?: 'major' | 'minor' | 'patch';\n  /** Human-readable reason for this approval. */\n  reason: string;\n  /** Issue tracker reference (e.g., \"SDK-1234\"). */\n  issue?: string;\n  /** Auto-expire this approval after a version is released. */\n  expiresAfterVersion?: string;\n  /** Whether this approval is currently active. */\n  approved?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Config section\n// ---------------------------------------------------------------------------\n\n/** The `compat` section of `oagen.config.ts`. */\nexport interface CompatConfig {\n  /** Level at which `oagen verify` should fail. Default: 'breaking'. */\n  failOn?: CompatFailLevel;\n  /** Path to write the machine-readable compat report. */\n  reportPath?: string;\n  /** Include provenance explanations in reports. */\n  explain?: boolean;\n  /** Path to the baseline compatibility snapshot. */\n  baselinePath?: string;\n  /** Per-language policy overrides. Sparse — only override what diverges. */\n  languagePolicy?: Partial<Record<LanguageId, Partial<CompatPolicyHints>>>;\n  /** Intentional break approvals. */\n  allow?: CompatApproval[];\n}\n\n// ---------------------------------------------------------------------------\n// Category → severity mapping\n// ---------------------------------------------------------------------------\n\nconst BREAKING_CATEGORIES: ReadonlySet<BreakingChangeCategory> = new Set<BreakingChangeCategory>([\n  'symbol_removed',\n  'symbol_renamed',\n  'parameter_removed',\n  'parameter_renamed',\n  'parameter_requiredness_increased',\n  'parameter_type_narrowed',\n  'parameter_position_changed_order_sensitive',\n  'constructor_position_changed_order_sensitive',\n  'named_arg_name_removed',\n  'keyword_name_removed',\n  'overload_removed',\n  'union_wrapper_migration_without_compat_alias',\n  'field_type_changed',\n  'return_type_changed',\n  'enum_member_value_changed',\n]);\n\nconst SOFT_RISK_CATEGORIES: ReadonlySet<SoftRiskChangeCategory> = new Set<SoftRiskChangeCategory>([\n  'parameter_added_non_terminal_optional',\n  'constructor_reordered_named_friendly',\n  'default_value_changed',\n  'wrapper_stricter_than_previous_sdk_but_matches_spec',\n  'doc_surface_drift',\n]);\n\n/** Get the default severity for a change category. */\nexport function defaultSeverityForCategory(category: CompatChangeCategory): CompatChangeSeverity {\n  if (BREAKING_CATEGORIES.has(category as BreakingChangeCategory)) return 'breaking';\n  if (SOFT_RISK_CATEGORIES.has(category as SoftRiskChangeCategory)) return 'soft-risk';\n  return 'additive';\n}\n\n/** Check whether a severity meets or exceeds a fail threshold. */\nexport function severityMeetsThreshold(severity: CompatChangeSeverity, threshold: CompatFailLevel): boolean {\n  if (threshold === 'none') return false;\n  if (threshold === 'soft-risk') return severity === 'breaking' || severity === 'soft-risk';\n  return severity === 'breaking';\n}\n","/**\n * Change classifier for compatibility verification.\n *\n * Takes raw diffs between baseline and candidate compat snapshots and\n * classifies each change into a specific category with policy-aware severity.\n */\n\nimport type { CompatSymbol, CompatParameter } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\nimport type { CompatChangeCategory, CompatChangeSeverity, CompatProvenance } from './config.js';\nimport { defaultSeverityForCategory } from './config.js';\n\n/** A single classified compatibility change. */\nexport interface ClassifiedChange {\n  /** Specific change category. */\n  category: CompatChangeCategory;\n  /** Policy-aware severity (may differ from defaultSeverityForCategory). */\n  severity: CompatChangeSeverity;\n  /** Fully-qualified symbol path. */\n  symbol: string;\n  /** Deterministic ID for grouping related changes across languages. */\n  conceptualChangeId: string;\n  /** Where the drift originated. */\n  provenance: CompatProvenance;\n  /** Description of the old state. */\n  old: Record<string, string>;\n  /** Description of the new state. */\n  new: Record<string, string>;\n  /** Human-readable explanation. */\n  message: string;\n  /**\n   * Optional spec-level remediation hint. Set by post-classification rules\n   * (see `detectForkedSchemas` in differ.ts) when a change has a recognized\n   * upstream root cause that the spec author can fix. Surfaces in both the\n   * machine-readable report and the human-readable summary.\n   */\n  remediation?: string;\n}\n\n/** Result of classifying all changes between two snapshots. */\nexport interface ClassificationResult {\n  changes: ClassifiedChange[];\n  summary: {\n    breaking: number;\n    softRisk: number;\n    additive: number;\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Classification engine\n// ---------------------------------------------------------------------------\n\n/**\n * Classify changes between a baseline and candidate symbol.\n * Returns one or more classified changes for the diff.\n */\nexport function classifySymbolChanges(\n  baseline: CompatSymbol,\n  candidate: CompatSymbol | undefined,\n  policy: CompatPolicyHints,\n): ClassifiedChange[] {\n  const changes: ClassifiedChange[] = [];\n\n  // Build spec-level ref for cross-language grouping.\n  // Prefer schemaName from either symbol (baseline for removals, candidate for adds).\n  const specRef = baseline.schemaName ?? candidate?.schemaName;\n\n  // Symbol removed\n  if (!candidate) {\n    changes.push(\n      makeChange({\n        category: 'symbol_removed',\n        symbol: baseline.fqName,\n        old: { symbol: baseline.fqName },\n        new: { symbol: '(removed)' },\n        message: `Symbol \"${baseline.displayName}\" was removed`,\n        policy,\n        specRef,\n      }),\n    );\n    return changes;\n  }\n\n  // Symbol renamed\n  if (baseline.fqName !== candidate.fqName && baseline.id === candidate.id) {\n    changes.push(\n      makeChange({\n        category: 'symbol_renamed',\n        symbol: baseline.fqName,\n        old: { name: baseline.fqName },\n        new: { name: candidate.fqName },\n        message: `Symbol renamed from \"${baseline.displayName}\" to \"${candidate.displayName}\"`,\n        policy,\n        specRef,\n      }),\n    );\n  }\n\n  // Parameter-level changes (for callables and constructors)\n  if (baseline.parameters && candidate.parameters) {\n    changes.push(...classifyParameterChanges(baseline, candidate, policy, specRef));\n  }\n\n  // Return type changes (for callables)\n  if (baseline.returns && candidate.returns && baseline.returns.name !== candidate.returns.name) {\n    changes.push(\n      makeChange({\n        category: 'return_type_changed',\n        symbol: baseline.fqName,\n        old: { returnType: baseline.returns.name },\n        new: { returnType: candidate.returns.name },\n        message: `Return type changed for \"${baseline.displayName}\" from \"${baseline.returns.name}\" to \"${candidate.returns.name}\"`,\n        policy,\n        specRef,\n      }),\n    );\n  }\n\n  // Field/property type changes\n  if (baseline.typeRef && candidate.typeRef && baseline.typeRef.name !== candidate.typeRef.name) {\n    changes.push(\n      makeChange({\n        category: 'field_type_changed',\n        symbol: baseline.fqName,\n        old: { type: baseline.typeRef.name },\n        new: { type: candidate.typeRef.name },\n        message: `Type changed for \"${baseline.displayName}\" from \"${baseline.typeRef.name}\" to \"${candidate.typeRef.name}\"`,\n        policy,\n        specRef,\n      }),\n    );\n  }\n\n  // Enum member value changes\n  if (\n    baseline.kind === 'enum_member' &&\n    candidate.kind === 'enum_member' &&\n    baseline.value !== undefined &&\n    candidate.value !== undefined &&\n    baseline.value !== candidate.value\n  ) {\n    changes.push(\n      makeChange({\n        category: 'enum_member_value_changed',\n        symbol: baseline.fqName,\n        old: { value: String(baseline.value) },\n        new: { value: String(candidate.value) },\n        message: `Enum value changed for \"${baseline.displayName}\" from \"${baseline.value}\" to \"${candidate.value}\"`,\n        policy,\n      }),\n    );\n  }\n\n  return changes;\n}\n\n/**\n * Classify parameter-level changes between two symbol versions.\n */\nfunction classifyParameterChanges(\n  baseline: CompatSymbol,\n  candidate: CompatSymbol,\n  policy: CompatPolicyHints,\n  specRef?: string,\n): ClassifiedChange[] {\n  const changes: ClassifiedChange[] = [];\n  const baseParams = baseline.parameters ?? [];\n  const candParams = candidate.parameters ?? [];\n\n  const baseByName = new Map(baseParams.map((p) => [p.publicName, p]));\n  const candByName = new Map(candParams.map((p) => [p.publicName, p]));\n  const isConstructor = baseline.kind === 'constructor';\n\n  // Check each baseline parameter\n  for (const baseParam of baseParams) {\n    const candParam = candByName.get(baseParam.publicName);\n\n    if (!candParam) {\n      // Parameter removed — check if it was renamed\n      const positionalMatch = candParams[baseParam.position];\n      if (positionalMatch && !baseByName.has(positionalMatch.publicName)) {\n        // Position preserved but name changed → rename\n        const isBreakingRename = parameterNameIsPublicApi(baseParam, policy, isConstructor);\n        changes.push(\n          makeChange({\n            category: 'parameter_renamed',\n            symbol: baseline.fqName,\n            old: { parameter: baseParam.publicName },\n            new: { parameter: positionalMatch.publicName },\n            message: `Parameter \"${baseParam.publicName}\" renamed to \"${positionalMatch.publicName}\" on \"${baseline.displayName}\"`,\n            policy,\n            specRef,\n            severityOverride: isBreakingRename ? undefined : 'soft-risk',\n          }),\n        );\n      } else {\n        // Truly removed\n        changes.push(\n          makeChange({\n            category: 'parameter_removed',\n            symbol: baseline.fqName,\n            old: { parameter: baseParam.publicName },\n            new: { parameter: '(removed)' },\n            message: `Parameter \"${baseParam.publicName}\" removed from \"${baseline.displayName}\"`,\n            policy,\n            specRef,\n          }),\n        );\n      }\n      continue;\n    }\n\n    // Requiredness increased (optional → required)\n    if (!baseParam.required && candParam.required) {\n      changes.push(\n        makeChange({\n          category: 'parameter_requiredness_increased',\n          symbol: baseline.fqName,\n          old: { parameter: baseParam.publicName, required: 'false' },\n          new: { parameter: candParam.publicName, required: 'true' },\n          message: `Parameter \"${baseParam.publicName}\" became required on \"${baseline.displayName}\"`,\n          policy,\n          specRef,\n        }),\n      );\n    }\n\n    // Type narrowed\n    if (baseParam.type.name !== candParam.type.name) {\n      changes.push(\n        makeChange({\n          category: 'parameter_type_narrowed',\n          symbol: baseline.fqName,\n          old: { parameter: baseParam.publicName, type: baseParam.type.name },\n          new: { parameter: candParam.publicName, type: candParam.type.name },\n          message: `Parameter type changed for \"${baseParam.publicName}\" on \"${baseline.displayName}\"`,\n          policy,\n          specRef,\n        }),\n      );\n    }\n\n    // Position changed.\n    //\n    // Constructors are governed by `policy.constructorOrderMatters` — some\n    // languages treat ctor positional order as part of the public API even\n    // when method args are named.\n    //\n    // For methods, the parameter's `passing` style decides:\n    //   - 'positional'     → callers reference by index; reorder is breaking\n    //   - 'named'          → both styles work; reorder is soft-risk (positional callers exist)\n    //   - 'keyword'        → callers MUST use names (Ruby kwargs, Python kw-only, Elixir); position invisible\n    //   - 'options_object' → callers pass a single object literal (Node); position invisible\n    if (baseParam.position !== candParam.position) {\n      if (isConstructor) {\n        if (policy.constructorOrderMatters) {\n          changes.push(\n            makeChange({\n              category: 'constructor_position_changed_order_sensitive',\n              symbol: baseline.fqName,\n              old: { parameter: baseParam.publicName, position: String(baseParam.position) },\n              new: { parameter: candParam.publicName, position: String(candParam.position) },\n              message: `Parameter \"${baseParam.publicName}\" moved from position ${baseParam.position} to ${candParam.position} on \"${baseline.displayName}\"`,\n              policy,\n              specRef,\n            }),\n          );\n        } else {\n          changes.push(\n            makeChange({\n              category: 'constructor_reordered_named_friendly',\n              symbol: baseline.fqName,\n              old: { parameter: baseParam.publicName, position: String(baseParam.position) },\n              new: { parameter: candParam.publicName, position: String(candParam.position) },\n              message: `Parameter \"${baseParam.publicName}\" reordered on \"${baseline.displayName}\" (named-friendly language)`,\n              policy,\n              specRef,\n            }),\n          );\n        }\n      } else if (baseParam.passing === 'positional') {\n        changes.push(\n          makeChange({\n            category: 'parameter_position_changed_order_sensitive',\n            symbol: baseline.fqName,\n            old: { parameter: baseParam.publicName, position: String(baseParam.position) },\n            new: { parameter: candParam.publicName, position: String(candParam.position) },\n            message: `Parameter \"${baseParam.publicName}\" moved from position ${baseParam.position} to ${candParam.position} on \"${baseline.displayName}\"`,\n            policy,\n            specRef,\n          }),\n        );\n      } else if (baseParam.passing === 'named') {\n        changes.push(\n          makeChange({\n            category: 'constructor_reordered_named_friendly',\n            symbol: baseline.fqName,\n            old: { parameter: baseParam.publicName, position: String(baseParam.position) },\n            new: { parameter: candParam.publicName, position: String(candParam.position) },\n            message: `Parameter \"${baseParam.publicName}\" reordered on \"${baseline.displayName}\" (named-friendly language)`,\n            policy,\n            specRef,\n          }),\n        );\n      }\n      // keyword / options_object: position is invisible to callers — no change emitted.\n    }\n  }\n\n  // Check for new parameters in candidate\n  for (const candParam of candParams) {\n    if (!baseByName.has(candParam.publicName)) {\n      // Check if this was already captured as a rename\n      const isRename = changes.some(\n        (c) => c.category === 'parameter_renamed' && c.new.parameter === candParam.publicName,\n      );\n      if (isRename) continue;\n\n      const isTerminal = candParam.position === candParams.length - 1;\n      const category: CompatChangeCategory = candParam.required\n        ? 'parameter_requiredness_increased'\n        : isTerminal\n          ? 'parameter_added_optional_terminal'\n          : 'parameter_added_non_terminal_optional';\n\n      if (candParam.required) {\n        changes.push(\n          makeChange({\n            category,\n            symbol: baseline.fqName,\n            old: { parameter: '(absent)' },\n            new: { parameter: candParam.publicName, required: 'true' },\n            message: `Required parameter \"${candParam.publicName}\" added to \"${baseline.displayName}\"`,\n            policy,\n            specRef,\n          }),\n        );\n      } else {\n        changes.push(\n          makeChange({\n            category,\n            symbol: baseline.fqName,\n            old: { parameter: '(absent)' },\n            new: { parameter: candParam.publicName },\n            message: `Optional parameter \"${candParam.publicName}\" added to \"${baseline.displayName}\"`,\n            policy,\n            specRef,\n          }),\n        );\n      }\n    }\n  }\n\n  return changes;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction parameterNameIsPublicApi(param: CompatParameter, policy: CompatPolicyHints, isConstructor: boolean): boolean {\n  if (param.sensitivity.publicName) return true;\n  if (isConstructor) return policy.constructorParameterNamesArePublicApi;\n  return policy.methodParameterNamesArePublicApi;\n}\n\n/**\n * Build a deterministic conceptual change ID.\n *\n * When `specRef` is provided (e.g. \"GenerateLinkBody.admin_emails\"), it is\n * used instead of the language-specific symbol name.  This ensures the same\n * spec entity produces the same ID across all languages, enabling cross-\n * language rollup in reports.\n */\nfunction buildConceptualChangeId(\n  category: CompatChangeCategory,\n  symbol: string,\n  match: Record<string, string>,\n  specRef?: string,\n): string {\n  const identity = specRef ?? symbol;\n  const parts = ['chg', category, identity.replace(/[^a-zA-Z0-9_.]/g, '_')];\n  if (match.parameter) parts.push(match.parameter);\n  if (match.member) parts.push(match.member);\n  return parts.join('_').toLowerCase();\n}\n\nfunction makeChange(opts: {\n  category: CompatChangeCategory;\n  symbol: string;\n  old: Record<string, string>;\n  new: Record<string, string>;\n  message: string;\n  policy: CompatPolicyHints;\n  provenance?: CompatProvenance;\n  severityOverride?: CompatChangeSeverity;\n  specRef?: string;\n}): ClassifiedChange {\n  return {\n    category: opts.category,\n    severity: opts.severityOverride ?? defaultSeverityForCategory(opts.category),\n    symbol: opts.symbol,\n    conceptualChangeId: buildConceptualChangeId(opts.category, opts.symbol, opts.old, opts.specRef),\n    provenance: opts.provenance ?? 'unknown',\n    old: opts.old,\n    new: opts.new,\n    message: opts.message,\n  };\n}\n\n/**\n * Classify a new symbol as additive.\n */\nexport function classifyAddedSymbol(symbol: CompatSymbol): ClassifiedChange {\n  return {\n    category: 'symbol_added',\n    severity: 'additive',\n    symbol: symbol.fqName,\n    conceptualChangeId: buildConceptualChangeId('symbol_added', symbol.fqName, {}, symbol.schemaName),\n    provenance: 'unknown',\n    old: { symbol: '(absent)' },\n    new: { symbol: symbol.fqName },\n    message: `Symbol \"${symbol.displayName}\" was added`,\n  };\n}\n\n/** Summarize a list of classified changes by severity. */\nexport function summarizeChanges(changes: ClassifiedChange[]): ClassificationResult['summary'] {\n  let breaking = 0;\n  let softRisk = 0;\n  let additive = 0;\n  for (const c of changes) {\n    if (c.severity === 'breaking') breaking++;\n    else if (c.severity === 'soft-risk') softRisk++;\n    else additive++;\n  }\n  return { breaking, softRisk, additive };\n}\n","import type { ApiSpec, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { ApiSurface, LanguageHints } from './types.js';\n\n/**\n * Compute the set of symbol names that are derivable from the OpenAPI spec.\n * Only these names should be compared during compat verification — everything\n * else in the baseline is hand-written and out of scope for generation.\n */\nexport function specDerivedNames(spec: ApiSpec, hints: LanguageHints): Set<string> {\n  const names = new Set<string>();\n\n  // Build set of top-level enum names for filtering inline enums\n  const topLevelEnumNames = new Set(spec.enums.map((e) => e.name));\n\n  // Service classes\n  for (const service of spec.services) {\n    names.add(service.name);\n    for (const op of service.operations) {\n      // Operation methods are matched by the class diff, not by name here\n      collectTypeRefNames(op.response, names, hints, topLevelEnumNames);\n      if (op.requestBody) collectTypeRefNames(op.requestBody, names, hints, topLevelEnumNames);\n      for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n        collectTypeRefNames(p.type, names, hints, topLevelEnumNames);\n      }\n    }\n  }\n\n  // Models → domain interface + language-specific derived names\n  for (const model of spec.models) {\n    names.add(model.name);\n    for (const derived of hints.derivedModelNames(model.name)) {\n      names.add(derived);\n    }\n    for (const field of model.fields) {\n      collectTypeRefNames(field.type, names, hints, topLevelEnumNames);\n    }\n  }\n\n  // Enums → type aliases\n  for (const e of spec.enums) {\n    names.add(e.name);\n  }\n\n  return names;\n}\n\n/**\n * Compute a map of enum name → set of wire values that appear in the spec.\n * Used by filterSurface to exclude hand-added enum members that aren't in the spec.\n */\nexport function specDerivedEnumValues(spec: ApiSpec): Map<string, Set<string | number>> {\n  const result = new Map<string, Set<string | number>>();\n  for (const e of spec.enums) {\n    result.set(e.name, new Set(e.values.map((v) => v.value)));\n  }\n  return result;\n}\n\n/**\n * Compute the set of field paths (e.g., \"Organization.name\") that are defined\n * in the OpenAPI spec's model schemas. Used by filterSurface to exclude\n * hand-added SDK fields that reference spec-derived types.\n */\nexport function specDerivedFieldPaths(spec: ApiSpec, hints: LanguageHints): Set<string> {\n  const paths = new Set<string>();\n  for (const model of spec.models) {\n    for (const field of model.fields) {\n      paths.add(`${model.name}.${field.name}`);\n    }\n    // Also add field paths for derived model names (e.g., OrganizationResponse.name)\n    for (const derived of hints.derivedModelNames(model.name)) {\n      for (const field of model.fields) {\n        paths.add(`${derived}.${field.name}`);\n      }\n    }\n  }\n  return paths;\n}\n\n/**\n * Compute the set of method paths (e.g., \"Auth.authorize\") that are defined\n * as operations in the OpenAPI spec's services. Used by filterSurface to\n * exclude hand-written SDK methods that don't correspond to spec operations.\n */\nexport function specDerivedMethodPaths(spec: ApiSpec): Set<string> {\n  const paths = new Set<string>();\n  for (const service of spec.services) {\n    for (const op of service.operations) {\n      paths.add(`${service.name}.${op.name}`);\n    }\n  }\n  return paths;\n}\n\n/**\n * Compute the set of HTTP operation keys (e.g., \"GET /auth/authorize\") that\n * exist in the spec. Used for overlay-based method matching.\n */\nexport function specDerivedHttpKeys(spec: ApiSpec): Set<string> {\n  const keys = new Set<string>();\n  for (const service of spec.services) {\n    for (const op of service.operations) {\n      keys.add(`${op.httpMethod.toUpperCase()} ${op.path}`);\n    }\n  }\n  return keys;\n}\n\nfunction collectTypeRefNames(ref: TypeRef, out: Set<string>, hints: LanguageHints, topLevelEnums?: Set<string>): void {\n  walkTypeRef(ref, {\n    model: (r) => {\n      out.add(r.name);\n      for (const derived of hints.derivedModelNames(r.name)) {\n        out.add(derived);\n      }\n    },\n    enum: (r) => {\n      // Only include enums that are top-level (in spec.enums). Inline enums\n      // embedded in TypeRefs (e.g., query parameter enums) may not be emitted\n      // by all emitters, so they should not create false-positive violations.\n      if (!topLevelEnums || topLevelEnums.has(r.name)) {\n        out.add(r.name);\n      }\n    },\n  });\n}\n\nfunction filterRecord<T>(record: Record<string, T>, allowed: Set<string>): Record<string, T> {\n  const result: Record<string, T> = {};\n  for (const [name, value] of Object.entries(record)) {\n    if (allowed.has(name)) result[name] = value;\n  }\n  return result;\n}\n\n/**\n * Filter an ApiSurface to only include symbols whose names appear in the\n * allowed set. Symbols not in the set are dropped entirely — they won't\n * count toward the total or produce violations.\n *\n * For interfaces: when fieldPaths is provided, only keeps fields that appear\n * in the spec-derived field paths. This prevents false positives from hand-added\n * SDK fields that reference spec-derived types but aren't defined in the spec.\n *\n * For classes: when methodPaths is provided, only keeps methods whose names\n * appear in the spec-derived method paths. This prevents false positives from\n * hand-written SDK methods (e.g., Auth.authorization_url, Webhooks.construct_event)\n * that don't correspond to spec operations. Properties on service classes are\n * also filtered: only UPPER_CASE constants that are spec-derivable are kept.\n */\nexport function filterSurface(\n  surface: ApiSurface,\n  allowedNames: Set<string>,\n  opts?: {\n    fieldPaths?: Set<string>;\n    methodPaths?: Set<string>;\n    enumValues?: Map<string, Set<string | number>>;\n  },\n): ApiSurface {\n  const { fieldPaths, methodPaths, enumValues } = opts ?? {};\n  const filteredInterfaces = filterRecord(surface.interfaces, allowedNames);\n\n  // Filter interface fields by spec-derived field paths if provided\n  if (fieldPaths) {\n    for (const [name, iface] of Object.entries(filteredInterfaces)) {\n      const filteredFields: Record<string, (typeof iface.fields)[string]> = {};\n      for (const [fieldName, field] of Object.entries(iface.fields)) {\n        // Keep the field if its path is spec-derived\n        if (fieldPaths.has(`${name}.${fieldName}`)) {\n          filteredFields[fieldName] = field;\n        }\n      }\n      filteredInterfaces[name] = { ...iface, fields: filteredFields };\n    }\n  }\n\n  let filteredClasses = filterRecord(surface.classes, allowedNames);\n\n  // Filter class methods and properties by spec-derived method paths if provided\n  if (methodPaths) {\n    // Build a set of service-class names that have spec-derived methods.\n    // Only filter methods on these classes; non-service model classes keep all members.\n    const serviceClassNames = new Set<string>();\n    for (const path of methodPaths) {\n      const dot = path.indexOf('.');\n      if (dot !== -1) serviceClassNames.add(path.slice(0, dot));\n    }\n\n    const newClasses: Record<string, (typeof filteredClasses)[string]> = {};\n    for (const [name, cls] of Object.entries(filteredClasses)) {\n      if (serviceClassNames.has(name)) {\n        // Service class — filter methods and properties by spec-derived method paths\n        const filteredMethods: typeof cls.methods = {};\n        for (const [methodName, overloads] of Object.entries(cls.methods)) {\n          if (methodPaths.has(`${name}.${methodName}`)) {\n            filteredMethods[methodName] = overloads;\n          }\n        }\n\n        // Filter properties: only keep properties that are spec-derivable.\n        // Hand-written constants (PROVIDERS, DEFAULT_TOLERANCE, WIDGET_SCOPES)\n        // are not derivable from the spec and should be excluded.\n        const filteredProperties: typeof cls.properties = {};\n        for (const [propName, prop] of Object.entries(cls.properties)) {\n          if (methodPaths.has(`${name}.${propName}`)) {\n            filteredProperties[propName] = prop;\n          }\n        }\n\n        newClasses[name] = {\n          ...cls,\n          methods: filteredMethods,\n          properties: filteredProperties,\n        };\n      } else if (fieldPaths) {\n        // Non-service (model) class — filter properties by spec-derived field paths.\n        // In some languages (Ruby, PHP), models are represented as classes with\n        // properties rather than interfaces with fields. Apply the same field-level\n        // filtering used for interfaces to exclude hand-added SDK fields.\n        const filteredProperties: typeof cls.properties = {};\n        for (const [propName, prop] of Object.entries(cls.properties)) {\n          if (fieldPaths.has(`${name}.${propName}`)) {\n            filteredProperties[propName] = prop;\n          }\n        }\n\n        // Also filter methods on model classes: convenience methods like\n        // `primary_email` are hand-written and not spec-derivable.\n        // Keep utility methods (from_json, to_json, etc.) if they appear in fieldPaths,\n        // otherwise drop non-spec methods.\n        const filteredMethods: typeof cls.methods = {};\n        for (const [methodName, overloads] of Object.entries(cls.methods)) {\n          if (fieldPaths.has(`${name}.${methodName}`) || methodPaths.has(`${name}.${methodName}`)) {\n            filteredMethods[methodName] = overloads;\n          }\n        }\n\n        newClasses[name] = {\n          ...cls,\n          methods: filteredMethods,\n          properties: filteredProperties,\n        };\n      } else {\n        // No filtering available — keep as-is\n        newClasses[name] = cls;\n      }\n    }\n    filteredClasses = newClasses;\n  }\n\n  // Filter enum members by spec-derived values if provided\n  let filteredEnums = filterRecord(surface.enums, allowedNames);\n  if (enumValues) {\n    const newEnums: Record<string, (typeof filteredEnums)[string]> = {};\n    for (const [name, enumDef] of Object.entries(filteredEnums)) {\n      const specValues = enumValues.get(name);\n      if (!specValues) {\n        // Enum not in spec values map — keep as-is\n        newEnums[name] = enumDef;\n        continue;\n      }\n      // Filter members: keep only those whose wire value is in the spec.\n      // Use case-insensitive comparison since some extractors produce\n      // PascalCase values (e.g., \"Pending\") while the spec has lowercase.\n      const specValuesLower = new Set([...specValues].map((v) => String(v).toLowerCase()));\n      const filteredMembers: typeof enumDef.members = {};\n      for (const [member, value] of Object.entries(enumDef.members)) {\n        if (specValues.has(value) || specValuesLower.has(String(value).toLowerCase())) {\n          filteredMembers[member] = value;\n        }\n      }\n      newEnums[name] = { ...enumDef, members: filteredMembers };\n    }\n    filteredEnums = newEnums;\n  }\n\n  return {\n    ...surface,\n    classes: filteredClasses,\n    interfaces: filteredInterfaces,\n    typeAliases: filterRecord(surface.typeAliases, allowedNames),\n    enums: filteredEnums,\n    exports: {}, // exports are structural, not symbol-level — skip for scoped comparison\n  };\n}\n","/**\n * Compatibility diff engine.\n *\n * Compares two API surfaces (or compat snapshots) and produces classified\n * changes with policy-aware severity, provenance, and conceptual change IDs.\n *\n * This replaces the previous unclassified diff engine with a richer model\n * that supports cross-language severity analysis and approval matching.\n */\n\nimport type { ApiSurface, ApiMethod, LanguageHints, DiffResult, Violation, Addition } from './types.js';\nimport type { CompatSnapshot, CompatSymbol } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\nimport type { ClassifiedChange, ClassificationResult } from './classify.js';\nimport { classifySymbolChanges, classifyAddedSymbol, summarizeChanges } from './classify.js';\nimport { NAMED_TYPE_RE, typeExistsInSurface } from './language-hints.js';\n\nexport {\n  specDerivedNames,\n  specDerivedFieldPaths,\n  specDerivedMethodPaths,\n  specDerivedHttpKeys,\n  specDerivedEnumValues,\n  filterSurface,\n} from './spec-filter.js';\n\n// ---------------------------------------------------------------------------\n// New: CompatSnapshot-based diff\n// ---------------------------------------------------------------------------\n\n/** Result of diffing two compat snapshots. */\nexport interface CompatDiffResult {\n  changes: ClassifiedChange[];\n  summary: ClassificationResult['summary'];\n}\n\n/**\n * Diff two compat snapshots, producing classified changes with\n * policy-aware severity.\n */\nexport function diffSnapshots(\n  baseline: CompatSnapshot,\n  candidate: CompatSnapshot,\n  policy?: CompatPolicyHints,\n): CompatDiffResult {\n  const effectivePolicy = policy ?? baseline.policies;\n  const changes: ClassifiedChange[] = [];\n\n  // Build set of service wrapper fqNames from both snapshots so we can\n  // suppress constructor noise — users never instantiate service classes\n  // directly, so their constructor changes are not public-API breaking.\n  const serviceAccessors = new Set<string>();\n  for (const sym of baseline.symbols) {\n    if (sym.kind === 'service_accessor') serviceAccessors.add(sym.fqName);\n  }\n  for (const sym of candidate.symbols) {\n    if (sym.kind === 'service_accessor') serviceAccessors.add(sym.fqName);\n  }\n\n  // Index candidate symbols by ID and fqName for lookup\n  const candById = new Map<string, CompatSymbol>();\n  const candByFqName = new Map<string, CompatSymbol>();\n  for (const sym of candidate.symbols) {\n    candById.set(sym.id, sym);\n    candByFqName.set(sym.fqName, sym);\n  }\n\n  // Index baseline symbols by fqName\n  const baseByFqName = new Set<string>();\n  for (const sym of baseline.symbols) {\n    baseByFqName.add(sym.fqName);\n  }\n\n  // Compare each baseline symbol against candidate\n  for (const baseSym of baseline.symbols) {\n    if (isServiceWrapperConstructor(baseSym, serviceAccessors)) continue;\n    const candSym = candById.get(baseSym.id) ?? candByFqName.get(baseSym.fqName);\n    changes.push(...classifySymbolChanges(baseSym, candSym, effectivePolicy));\n  }\n\n  // Detect added symbols\n  for (const candSym of candidate.symbols) {\n    if (!baseByFqName.has(candSym.fqName)) {\n      if (isServiceWrapperConstructor(candSym, serviceAccessors)) continue;\n      changes.push(classifyAddedSymbol(candSym));\n    }\n  }\n\n  // Post-pass: attach spec-level remediation hints when recognized upstream\n  // patterns are detected. Currently flags the \"schema fork\" antipattern —\n  // a path's response type was redirected to a brand-new schema whose field\n  // set is a superset of the prior schema, which forces a breaking SDK\n  // signature change instead of an additive field on the existing schema.\n  detectForkedSchemas(changes, baseline, candidate);\n\n  // Post-pass: detect type and enum *renames* — cases where a baseline\n  // symbol disappears and a structurally-equivalent symbol takes its place\n  // in the candidate. These are reported as `symbol_removed` (breaking) by\n  // the symbol-level walker because the fqName is gone, but consumer code\n  // that uses the type's fields/methods or the enum's wire values continues\n  // to work — only explicit type annotations and (in dotnet) un-aliased\n  // enum class references actually need to migrate. Downgrade these to\n  // soft-risk so CI gates default-pass while the change stays visible.\n  //\n  // Ordered after detectForkedSchemas so the fork detector's remediation\n  // hint is preserved on the typed cases it owns; renames operate on\n  // pure removals where no fork hint applies.\n  const typeRenames = detectTypeRenames(changes, baseline, candidate);\n  const enumRenames = detectEnumRenames(changes, baseline, candidate);\n  // Transitive pass: when a typed field on a renamed parent points at an\n  // alias type that has no extractable children of its own (common for\n  // discriminated-union owner types — e.g. Go's `APIKeyWithValueOwner`,\n  // generated alongside its parent type), the structural detector can't\n  // pair them on its own. Use the recorded parent rename + the field\n  // typeRefs to derive the secondary rename.\n  inferTransitiveTypeRenames(typeRenames, baseline, candidate, changes);\n  cascadeRenameDowngrades(changes, typeRenames, enumRenames, baseline, candidate);\n\n  return {\n    changes,\n    summary: summarizeChanges(changes),\n  };\n}\n\n/**\n * Detect \"schema fork\" antipattern and attach a remediation hint.\n *\n * Fires when:\n *  1. A return type or field type changed from `OldType` → `NewType`.\n *  2. `NewType` is newly added in the candidate snapshot.\n *  3. `NewType.fields ⊇ OldType.fields` (every field on the old type still\n *     exists on the new one — the new schema is a strict superset, so the\n *     same fields could have been added to the existing schema additively).\n *\n * Mutates `changes` in place: sets `remediation` on the matching change.\n * Leaves the original category and severity alone — this is just a hint.\n *\n * Identity match is by `displayName` of the type symbol, which corresponds\n * to the type name as it appears in `change.old.returnType` / `.type` and\n * `change.new.returnType` / `.type`.\n */\nfunction detectForkedSchemas(changes: ClassifiedChange[], baseline: CompatSnapshot, candidate: CompatSnapshot): void {\n  // Build name → field-name set maps from each snapshot. A \"type\" here is any\n  // symbol that owns field/property children (alias, service_accessor, enum).\n  const baselineTypeFields = collectTypeFieldSets(baseline);\n  const candidateTypeFields = collectTypeFieldSets(candidate);\n  const baselineTypeNames = new Set(baselineTypeFields.keys());\n\n  for (const change of changes) {\n    if (change.remediation) continue;\n\n    let oldType: string | undefined;\n    let newType: string | undefined;\n    if (change.category === 'return_type_changed') {\n      oldType = change.old.returnType;\n      newType = change.new.returnType;\n    } else if (change.category === 'field_type_changed') {\n      oldType = change.old.type;\n      newType = change.new.type;\n    } else {\n      continue;\n    }\n    if (!oldType || !newType || oldType === newType) continue;\n\n    // Strip array/nullable decorations so we compare bare type names. This\n    // covers e.g. `FooList` vs `BarList`, plus simple `Foo[]` vs `Bar[]`.\n    const oldTypeBare = bareTypeName(oldType);\n    const newTypeBare = bareTypeName(newType);\n\n    // The new type must be newly introduced.\n    if (baselineTypeNames.has(newTypeBare)) continue;\n\n    const oldFields = baselineTypeFields.get(oldTypeBare);\n    const newFields = candidateTypeFields.get(newTypeBare);\n    if (!oldFields || !newFields) continue;\n    if (oldFields.size === 0) continue;\n\n    // newFields must be a (non-strict) superset of oldFields.\n    let isSuperset = true;\n    for (const f of oldFields) {\n      if (!newFields.has(f)) {\n        isSuperset = false;\n        break;\n      }\n    }\n    if (!isSuperset) continue;\n\n    change.remediation =\n      `Schema \"${newTypeBare}\" looks like \"${oldTypeBare}\" with additional fields. ` +\n      `Consider adding the new fields to \"${oldTypeBare}\" instead of forking a new schema — ` +\n      `forking forces a breaking type-name change in typed SDKs, while extending the existing ` +\n      `schema is additive.`;\n  }\n}\n\n/**\n * Build a map from type fqName → set of (lowercased) child field names.\n * Used by `detectForkedSchemas` for superset comparison.\n */\nfunction collectTypeFieldSets(snapshot: CompatSnapshot): Map<string, Set<string>> {\n  const result = new Map<string, Set<string>>();\n  for (const sym of snapshot.symbols) {\n    if (sym.kind !== 'field' && sym.kind !== 'property') continue;\n    if (!sym.ownerFqName) continue;\n    const localName = sym.fqName.includes('.') ? sym.fqName.slice(sym.fqName.lastIndexOf('.') + 1) : sym.fqName;\n    let set = result.get(sym.ownerFqName);\n    if (!set) {\n      set = new Set<string>();\n      result.set(sym.ownerFqName, set);\n    }\n    set.add(localName.toLowerCase());\n  }\n  return result;\n}\n\n/**\n * Detect type renames: a baseline type symbol disappears and a candidate\n * type symbol with the same (or superset) field set takes its place.\n *\n * Common when an upstream spec promotes a single schema into multiple\n * (e.g. `ApiKey` → `OrganizationApiKey` + `UserApiKey`). The wire shape\n * returned by individual endpoints is unchanged — `OrganizationApiKey`\n * has the same fields `ApiKey` had — so consumer code accessing those\n * fields *through a return value* keeps working. The parent symbol\n * itself, however, is gone: callers who referenced it by name (Sorbet\n * annotations, `is_a?` checks, pattern matches, deserialization targets)\n * will fail at runtime. The parent removal therefore stays `breaking`;\n * we only attach a remediation hint pointing at the new name.\n *\n * Identity criteria (must all hold):\n *   1. The removed symbol owns ≥ 1 field/property in the baseline (i.e.\n *      it's a type-shaped symbol — model/interface/class — not a plain\n *      function or constant).\n *   2. Some candidate type that did *not* exist in the baseline has a\n *      field set that is a non-strict superset of the removed type's\n *      fields. (Strict-subset would mean fields were lost — a real break.)\n *   3. The candidate type is the alphabetically-first such match, so\n *      pairing is deterministic when multiple candidates fit (e.g. both\n *      `OrganizationApiKey` and `UserApiKey` share the original fields).\n *\n * Returns a `removedName -> newName` map so a downstream cascade pass\n * can downgrade owned-field removals and `*_type_changed` pointing at\n * the same pair — those *are* downgraded to `soft-risk`, since values\n * flowing through the new type continue to expose the same fields.\n *\n * Mutates matching `symbol_removed` entries in `changes`: attaches a\n * `remediation` describing the rename. Severity is left at `breaking`.\n */\nfunction detectTypeRenames(\n  changes: ClassifiedChange[],\n  baseline: CompatSnapshot,\n  candidate: CompatSnapshot,\n): Map<string, string> {\n  const renameMap = new Map<string, string>();\n  const baselineTypeFields = collectTypeFieldSets(baseline);\n  const candidateTypeFields = collectTypeFieldSets(candidate);\n  const baselineTypeNames = new Set(baselineTypeFields.keys());\n  const candidateTypesSorted = [...candidateTypeFields.entries()].sort((a, b) => a[0].localeCompare(b[0]));\n\n  // Index parent `symbol_removed` changes by fqName so we can downgrade\n  // them when a rename is detected. Some languages (Go's enum-alias path\n  // for ordering enums; emitters that emit `type Old = New`) preserve the\n  // old fqName as a candidate alias and never report a removal — that's\n  // fine, the rename map is still populated for the cascade pass.\n  const parentRemovalByName = new Map<string, ClassifiedChange>();\n  for (const change of changes) {\n    if (change.category === 'symbol_removed' && change.severity === 'breaking') {\n      parentRemovalByName.set(change.old.symbol ?? '', change);\n    }\n  }\n\n  // Walk every baseline type *directly*, not via `symbol_removed` events.\n  // The parent-removal path alone misses rename-as-alias cases (e.g. Go\n  // emits `type ApiKey = OrganizationApiKey` to preserve the old name)\n  // because no `symbol_removed` fires for the old name. The structural\n  // match (field-set superset) is what matters, regardless of whether\n  // the old fqName persists as an alias.\n  for (const [baselineTypeName, baselineFields] of baselineTypeFields) {\n    if (baselineFields.size === 0) continue;\n\n    // No-op: same name, same fields still in candidate.\n    const sameNameFields = candidateTypeFields.get(baselineTypeName);\n    if (sameNameFields && setEquals(baselineFields, sameNameFields)) continue;\n\n    // Find a newly-added candidate type (not in baseline) whose field set\n    // is a non-strict superset of the baseline type's fields.\n    const match = candidateTypesSorted.find(([candName, candFields]) => {\n      if (baselineTypeNames.has(candName)) return false;\n      for (const f of baselineFields) {\n        if (!candFields.has(f)) return false;\n      }\n      return true;\n    });\n    if (!match) continue;\n    const [newName] = match;\n\n    renameMap.set(baselineTypeName, newName);\n\n    // Attach a remediation hint to the parent removal so reviewers can see\n    // where the symbol moved. Severity stays `breaking`: the symbol's name\n    // is gone, and callers who referenced it directly (Sorbet annotations,\n    // `is_a?` checks, pattern matches, deserialization targets) will fail\n    // at runtime. Languages that emit a `type Old = New` alias keep the\n    // parent symbol alive, so this branch may not fire — but the rename is\n    // still recorded for the cascade pass to use on field/return-type swaps.\n    const parentRemoval = parentRemovalByName.get(baselineTypeName);\n    if (parentRemoval) {\n      parentRemoval.remediation =\n        `Type \"${baselineTypeName}\" appears to have been renamed to \"${newName}\" — ` +\n        `the new type has every field of the old (a non-strict superset). ` +\n        `Field accesses and method calls on values of type \"${newName}\" continue to work; ` +\n        `only explicit \"${baselineTypeName}\" type annotations need to migrate. ` +\n        `Consider emitting a deprecated alias \\`type ${baselineTypeName} = ${newName}\\` in languages that support it.`;\n    }\n  }\n\n  return renameMap;\n}\n\n/**\n * Transitive rename inference. After `detectTypeRenames` records direct\n * structural matches (e.g. `ApiKeyWithValue → OrganizationApiKeyWithValue`),\n * walk the parent's fields and follow the `typeRef.name` of each: if the\n * baseline parent's field references an alias-type `OldOwner` and the new\n * parent's same-named field references a different alias `NewOwner`, the\n * pair is the same type-concept under a renamed name. Record the\n * secondary rename so the cascade can downgrade any `field_type_changed`\n * pointing at the pair, and attach a remediation hint to `OldOwner`'s\n * `symbol_removed` (which stays `breaking` — see `detectTypeRenames`).\n *\n * Why this is necessary: discriminated-union owner types (Go's\n * `APIKeyWithValueOwner`, PHP/Python's nested constructor params) are\n * frequently emitted as `kind: 'alias'` symbols with no extractable\n * field children — so `collectTypeFieldSets` returns empty for them and\n * the structural matcher can't pair them directly. The transitive\n * lookup gives us a deterministic, conservative way to propagate the\n * rename: it only fires when the parent rename has already been\n * positively identified, and only follows fields that share the same\n * wire name across baseline and candidate.\n */\nfunction inferTransitiveTypeRenames(\n  typeRenames: Map<string, string>,\n  baseline: CompatSnapshot,\n  candidate: CompatSnapshot,\n  changes: ClassifiedChange[],\n): void {\n  if (typeRenames.size === 0) return;\n\n  // Index field/property symbols by `${ownerFqName}.${localName}` so we\n  // can read the typeRef both sides of the rename.\n  const baselineFieldType = new Map<string, string>();\n  for (const sym of baseline.symbols) {\n    if (sym.kind !== 'field' && sym.kind !== 'property') continue;\n    if (!sym.ownerFqName || !sym.typeRef) continue;\n    const localName = sym.fqName.includes('.') ? sym.fqName.slice(sym.fqName.lastIndexOf('.') + 1) : sym.fqName;\n    baselineFieldType.set(`${sym.ownerFqName}.${localName.toLowerCase()}`, sym.typeRef.name);\n  }\n  const candidateFieldType = new Map<string, string>();\n  for (const sym of candidate.symbols) {\n    if (sym.kind !== 'field' && sym.kind !== 'property') continue;\n    if (!sym.ownerFqName || !sym.typeRef) continue;\n    const localName = sym.fqName.includes('.') ? sym.fqName.slice(sym.fqName.lastIndexOf('.') + 1) : sym.fqName;\n    candidateFieldType.set(`${sym.ownerFqName}.${localName.toLowerCase()}`, sym.typeRef.name);\n  }\n\n  // Index parent `symbol_removed` changes for downgrade.\n  const parentRemovalByName = new Map<string, ClassifiedChange>();\n  for (const change of changes) {\n    if (change.category === 'symbol_removed' && change.severity === 'breaking') {\n      parentRemovalByName.set(change.old.symbol ?? '', change);\n    }\n  }\n\n  // Walk a snapshot of the rename map — we may mutate it inside the loop\n  // but only via `set`, never `delete`, and we don't re-iterate on the\n  // additions in the same pass (one transitive hop is enough; deeper\n  // chains can be handled by re-running, which we don't need today).\n  const initialEntries = [...typeRenames.entries()];\n  for (const [oldOwner, newOwner] of initialEntries) {\n    // Find every baseline field on the renamed owner whose typeRef points\n    // at a *different* type than the same-named field on the new owner.\n    for (const [baselineKey, baselineFieldTypeRef] of baselineFieldType) {\n      if (!baselineKey.startsWith(`${oldOwner}.`)) continue;\n      const localName = baselineKey.slice(oldOwner.length + 1);\n      const candidateKey = `${newOwner}.${localName}`;\n      const candidateFieldTypeRef = candidateFieldType.get(candidateKey);\n      if (!candidateFieldTypeRef) continue;\n\n      const oldT = bareTypeName(baselineFieldTypeRef);\n      const newT = bareTypeName(candidateFieldTypeRef);\n      if (!oldT || !newT || oldT === newT) continue;\n      if (typeRenames.has(oldT)) continue; // already recorded\n\n      typeRenames.set(oldT, newT);\n      const removal = parentRemovalByName.get(oldT);\n      if (removal) {\n        // Severity stays `breaking` — see `detectTypeRenames` for the\n        // rationale. We only attach a remediation hint here.\n        removal.remediation =\n          `Type \"${oldT}\" appears to have been renamed to \"${newT}\" — ` +\n          `inferred transitively because the renamed parent \"${oldOwner}\" → \"${newOwner}\" ` +\n          `has a \"${localName}\" field whose type swapped from \"${oldT}\" to \"${newT}\". ` +\n          `Consider emitting a deprecated alias \\`type ${oldT} = ${newT}\\` in languages that support it.`;\n      }\n    }\n  }\n}\n\n/**\n * Detect enum canonical-flips: a baseline enum disappears and a candidate\n * enum with the **same wire-value set** takes its place.\n *\n * Caused by the emitter's enum-dedup heuristic picking a different\n * canonical name when a new same-shape enum joins the spec. Languages\n * that emit type aliases (Go, Ruby, Python, PHP, Kotlin) handle this\n * transparently via `type Old = New`; languages without first-class\n * aliases (dotnet) report the old enum as removed. The wire values are\n * unchanged — every legal value still serializes to the same JSON — so\n * consumer code constructing or matching on these enum values keeps\n * working. Only references to the typed enum class need migration.\n *\n * Identity criterion: a removed enum's value set is *exactly* equal to\n * a newly-added enum's value set (not superset — narrowing the value\n * set would be a real break for consumers expecting the dropped values).\n */\nfunction detectEnumRenames(\n  changes: ClassifiedChange[],\n  baseline: CompatSnapshot,\n  candidate: CompatSnapshot,\n): Map<string, string> {\n  const renameMap = new Map<string, string>();\n  const baselineEnumValues = collectEnumValueSets(baseline);\n  const candidateEnumValues = collectEnumValueSets(candidate);\n  const baselineEnumNames = new Set(baselineEnumValues.keys());\n\n  const candidateEnumsSorted = [...candidateEnumValues.entries()].sort((a, b) => a[0].localeCompare(b[0]));\n\n  // Index `symbol_removed` changes by fqName for O(1) lookup when downgrading\n  // a parent removal (only some languages report one; others alias).\n  const parentRemovalByName = new Map<string, ClassifiedChange>();\n  for (const change of changes) {\n    if (change.category === 'symbol_removed' && change.severity === 'breaking') {\n      parentRemovalByName.set(change.old.symbol ?? '', change);\n    }\n  }\n\n  // Walk every baseline enum *directly*, not via `symbol_removed` events.\n  // The parent-removal path alone misses canonical-flips in languages that\n  // alias non-canonical enums (Go, Ruby, Python, PHP, Kotlin): the old\n  // fqName persists as `type ApplicationsOrder = APIKeysOrder`, no parent\n  // `symbol_removed` fires, and the rename map stays empty — so the\n  // member-removal cascade never runs. Iterating baseline enums fixes this\n  // by deciding \"did this enum's value set move to a different owner?\"\n  // independent of whether the parent symbol survived.\n  for (const [baselineEnumName, baselineValues] of baselineEnumValues) {\n    if (baselineValues.size === 0) continue;\n\n    // No-op case: same name, same value set still present in candidate.\n    const sameNameValues = candidateEnumValues.get(baselineEnumName);\n    if (sameNameValues && setEquals(baselineValues, sameNameValues)) continue;\n\n    // Find a newly-added candidate enum (not present under that name in\n    // the baseline) with an exactly-equal wire-value set.\n    const match = candidateEnumsSorted.find(\n      ([candName, candValues]) => !baselineEnumNames.has(candName) && setEquals(baselineValues, candValues),\n    );\n    if (!match) continue;\n    const [newName] = match;\n\n    renameMap.set(baselineEnumName, newName);\n\n    // Attach a remediation hint to the parent removal if one was reported\n    // (dotnet path). Severity stays `breaking`: even though the wire values\n    // are unchanged, the typed enum class is gone, so callers referencing\n    // it by name will fail to compile or resolve. See `detectTypeRenames`\n    // for the full rationale.\n    const parentRemoval = parentRemovalByName.get(baselineEnumName);\n    if (parentRemoval) {\n      parentRemoval.remediation =\n        `Enum \"${baselineEnumName}\" appears to have been renamed to \"${newName}\" — ` +\n        `both enums have identical wire values, so on-the-wire serialization is unchanged. ` +\n        `This is typically the emitter's dedup canonical-flip after a new same-shape enum joined the spec. ` +\n        `Consider emitting a deprecated alias in languages that support it, or pinning the canonical via emitter config.`;\n    }\n  }\n\n  return renameMap;\n}\n\n/**\n * Cascade rename downgrades to changes whose meaning depends on a renamed\n * symbol. Walks every change and:\n *\n *   - Downgrades child removals (`Owner.field` removed where `Owner` was\n *     renamed) — the field still exists, just under a new owner fqName.\n *     Same logic for enum members under a renamed enum.\n *   - Downgrades `return_type_changed` / `field_type_changed` whose\n *     old → new pair matches a recorded rename — the type swap is the\n *     rename itself, not a meaningful signature break.\n *\n * Each cascaded change gets a remediation pointing at the parent rename\n * so the reviewer can find the explanation in the report.\n */\nfunction cascadeRenameDowngrades(\n  changes: ClassifiedChange[],\n  typeRenames: Map<string, string>,\n  enumRenames: Map<string, string>,\n  baseline: CompatSnapshot,\n  candidate: CompatSnapshot,\n): void {\n  // Lazy-built field-set maps for the structural-equivalence fallback used\n  // by `*_type_changed`. Both maps are needed even when no renames were\n  // recorded — the structural test handles cases where both old and new\n  // types coexist (e.g. a method's return type was redirected from an\n  // existing schema to a structurally-equivalent newly-added schema, the\n  // canonical fork antipattern).\n  let baselineTypeFields: Map<string, Set<string>> | undefined;\n  let candidateTypeFields: Map<string, Set<string>> | undefined;\n  const getBaselineFields = (): Map<string, Set<string>> => {\n    if (!baselineTypeFields) baselineTypeFields = collectTypeFieldSets(baseline);\n    return baselineTypeFields;\n  };\n  const getCandidateFields = (): Map<string, Set<string>> => {\n    if (!candidateTypeFields) candidateTypeFields = collectTypeFieldSets(candidate);\n    return candidateTypeFields;\n  };\n\n  /**\n   * Structural equivalence: candidate type's field set is a non-strict\n   * superset of baseline type's field set, AND the candidate type was\n   * newly added in this diff (not a swap to a pre-existing type, which\n   * is a real signature break the consumer chose). When `New ⊇ Old` and\n   * `New` is new, every field the consumer accessed on the old type\n   * still exists on the value they receive — so the swap is non-breaking\n   * at the value level even though the declared type changed. This is\n   * the fork-detector's positive signal, applied as a severity\n   * downgrade in addition to the existing remediation hint.\n   */\n  const isStructurallyEquivalent = (oldT: string, newT: string): boolean => {\n    if (!oldT || !newT || oldT === newT) return false;\n    const baselineFields = getBaselineFields();\n    const candidateFields = getCandidateFields();\n    // The new type must be newly introduced — a swap to an existing type\n    // is a real signature change the consumer chose, not a rename.\n    if (baselineFields.has(newT)) return false;\n    const oldFields = baselineFields.get(oldT);\n    const newFields = candidateFields.get(newT);\n    if (!oldFields || !newFields) return false;\n    if (oldFields.size === 0) return false;\n    for (const f of oldFields) {\n      if (!newFields.has(f)) return false;\n    }\n    return true;\n  };\n\n  for (const change of changes) {\n    if (change.severity !== 'breaking') continue;\n\n    if (change.category === 'symbol_removed') {\n      const removed = change.old.symbol ?? '';\n      const dotIdx = removed.indexOf('.');\n      if (dotIdx <= 0) continue;\n      const ownerName = removed.slice(0, dotIdx);\n      const renamedTo = typeRenames.get(ownerName) ?? enumRenames.get(ownerName);\n      if (!renamedTo) continue;\n      change.severity = 'soft-risk';\n      change.remediation =\n        `Owned by renamed symbol \"${ownerName}\" (now \"${renamedTo}\"). ` +\n        `The same member exists on the new symbol under \"${renamedTo}.${removed.slice(dotIdx + 1)}\".`;\n      continue;\n    }\n\n    if (change.category === 'return_type_changed') {\n      const oldT = bareTypeName(change.old.returnType ?? '');\n      const newT = bareTypeName(change.new.returnType ?? '');\n      if (typeRenames.get(oldT) === newT) {\n        change.severity = 'soft-risk';\n        change.remediation =\n          `Return type swap matches recorded rename \"${oldT}\" → \"${newT}\". ` +\n          `The underlying field set is preserved (see the rename advisory on \"${oldT}\").`;\n      } else if (isStructurallyEquivalent(oldT, newT)) {\n        // Downgrade severity for the structural-equivalence case (the\n        // fork-detector's positive signal). Preserve any remediation\n        // already attached by `detectForkedSchemas` — its message\n        // already explains the situation; we only need to flip severity.\n        change.severity = 'soft-risk';\n        if (!change.remediation) {\n          change.remediation =\n            `Return type swap from \"${oldT}\" to \"${newT}\" is structurally equivalent — ` +\n            `every field on \"${oldT}\" still exists on \"${newT}\". ` +\n            `Consumer code accessing fields on the returned value continues to work; ` +\n            `only explicit \"${oldT}\" type annotations need to migrate.`;\n        }\n      }\n      continue;\n    }\n\n    if (change.category === 'field_type_changed') {\n      const oldT = bareTypeName(change.old.type ?? '');\n      const newT = bareTypeName(change.new.type ?? '');\n      const renamedTo = typeRenames.get(oldT) ?? enumRenames.get(oldT);\n      if (renamedTo === newT) {\n        change.severity = 'soft-risk';\n        change.remediation =\n          `Field type swap matches recorded rename \"${oldT}\" → \"${newT}\". ` +\n          `On-the-wire shape is unchanged (see the rename advisory on \"${oldT}\").`;\n      } else if (isStructurallyEquivalent(oldT, newT)) {\n        change.severity = 'soft-risk';\n        if (!change.remediation) {\n          change.remediation =\n            `Field type swap from \"${oldT}\" to \"${newT}\" is structurally equivalent — ` +\n            `every field on \"${oldT}\" still exists on \"${newT}\".`;\n        }\n      }\n    }\n  }\n}\n\n/**\n * Build a map from enum fqName → set of wire values. Used by\n * `detectEnumRenames` to find structurally-identical enums across\n * baseline and candidate. Wire values come from `enum_member.value`\n * (the JSON-level value) — not the member names, which are\n * language-specific PascalCase forms.\n *\n * Members whose `value` is undefined are skipped — they contribute no\n * identity information.\n */\nfunction collectEnumValueSets(snapshot: CompatSnapshot): Map<string, Set<string>> {\n  const result = new Map<string, Set<string>>();\n  for (const sym of snapshot.symbols) {\n    if (sym.kind !== 'enum_member') continue;\n    if (!sym.ownerFqName) continue;\n    if (sym.value === undefined) continue;\n    let set = result.get(sym.ownerFqName);\n    if (!set) {\n      set = new Set<string>();\n      result.set(sym.ownerFqName, set);\n    }\n    set.add(String(sym.value));\n  }\n  return result;\n}\n\n/** Set equality for the small string sets used by rename detection. */\nfunction setEquals(a: Set<string>, b: Set<string>): boolean {\n  if (a.size !== b.size) return false;\n  for (const v of a) {\n    if (!b.has(v)) return false;\n  }\n  return true;\n}\n\n/**\n * Strip array/nullable suffixes so we compare bare type names. Languages\n * encode these differently (`Foo[]`, `Foo | null`, `Foo?`, `List<Foo>`,\n * `Optional[Foo]`); this is a best-effort common-case stripper, not an\n * exhaustive parser.\n */\nfunction bareTypeName(t: string): string {\n  let s = t.trim();\n  // Go pointer prefix: `*Foo` → `Foo`. Strip first because the rest of the\n  // patterns expect a leading identifier character.\n  s = s.replace(/^\\*/, '');\n  // PHP namespace prefix: `\\Vendor\\Pkg\\Foo` → `Foo`. PHP fully-qualified\n  // type references in generated method signatures lead with a backslash\n  // and use backslash-separated segments. Split on the last segment to\n  // preserve nested generics inside the path.\n  if (s.startsWith('\\\\')) {\n    const lastBackslash = s.lastIndexOf('\\\\');\n    s = s.slice(lastBackslash + 1);\n  }\n  // Nullable suffixes: `Foo | null`, `Foo?`.\n  s = s.replace(/\\s*\\|\\s*null$/, '').replace(/\\?$/, '');\n  // Array suffix: `Foo[]`.\n  s = s.replace(/\\[\\]$/, '');\n  // Single-arg generic. Two encodings to support:\n  //   - angle brackets: `Iterator<Foo>`, `Optional<Foo>`, `List<Foo>`\n  //   - square brackets: `Iterator[Foo]` (Go iterator returns from the\n  //     emitter, e.g. `*Iterator[APIKey]`)\n  const angleGeneric = s.match(/^[A-Za-z_][A-Za-z0-9_.]*<\\s*([A-Za-z_*][A-Za-z0-9_.*]*)\\s*>$/);\n  if (angleGeneric) return bareTypeName(angleGeneric[1]);\n  const bracketGeneric = s.match(/^[A-Za-z_][A-Za-z0-9_.]*\\[\\s*([A-Za-z_*][A-Za-z0-9_.*]*)\\s*\\]$/);\n  if (bracketGeneric) return bareTypeName(bracketGeneric[1]);\n  return s;\n}\n\n/**\n * Check if a symbol is a constructor belonging to a service wrapper class.\n *\n * Service wrapper constructors are internal plumbing (taking a client/config\n * object) — users interact with services via `client.admin_portal`, not\n * `new AdminPortal(...)`.  Changes to these constructors should not be\n * reported as breaking.\n *\n * Catches two patterns:\n *  - Ruby: kind === 'constructor', ownerFqName is a service_accessor\n *  - PHP:  kind === 'callable' with fqName ending in '.__construct'\n */\nfunction isServiceWrapperConstructor(sym: CompatSymbol, serviceAccessors: Set<string>): boolean {\n  if (!sym.ownerFqName || !serviceAccessors.has(sym.ownerFqName)) return false;\n  if (sym.kind === 'constructor') return true;\n  if (sym.kind === 'callable' && sym.fqName.endsWith('.__construct')) return true;\n  return false;\n}\n\n// ---------------------------------------------------------------------------\n// Legacy: ApiSurface-based diff (delegates to existing logic)\n// ---------------------------------------------------------------------------\n\n/**\n * Compare two ApiSurface objects and return a DiffResult.\n *\n * This preserves the existing diffing behavior used by the overlay retry loop,\n * compat check, and all existing tests. The internal implementation uses the\n * same algorithms as before to maintain full backward compatibility with\n * overlay patching and verification workflows.\n */\nexport function diffSurfaces(baseline: ApiSurface, candidate: ApiSurface, hints: LanguageHints): DiffResult {\n  const violations: Violation[] = [];\n  const additions: Addition[] = [];\n  let totalBaseline = 0;\n  let preserved = 0;\n\n  // Diff classes\n  for (const [name, baseClass] of Object.entries(baseline.classes)) {\n    totalBaseline++;\n    const candClass = candidate.classes[name];\n    if (!candClass) {\n      violations.push({\n        category: 'public-api',\n        severity: 'breaking',\n        symbolPath: name,\n        baseline: name,\n        candidate: '(missing)',\n        message: `Class \"${name}\" exists in baseline but not in generated output`,\n      });\n      totalBaseline += Object.values(baseClass.methods).reduce((sum, overloads) => sum + overloads.length, 0);\n      totalBaseline += Object.keys(baseClass.properties).length;\n      continue;\n    }\n    preserved++;\n\n    // Diff methods (each method name maps to an array of overloads)\n    for (const [methodName, baseOverloads] of Object.entries(baseClass.methods)) {\n      const candOverloads = candClass.methods[methodName];\n      for (const baseMethod of baseOverloads) {\n        totalBaseline++;\n        if (!candOverloads || candOverloads.length === 0) {\n          violations.push({\n            category: 'public-api',\n            severity: 'breaking',\n            symbolPath: `${name}.${methodName}`,\n            baseline: methodName,\n            candidate: '(missing)',\n            message: `Method \"${name}.${methodName}\" exists in baseline but not in generated output`,\n          });\n          continue;\n        }\n        const candMethod = candOverloads.find((c) => signaturesMatch(baseMethod, c));\n        if (!candMethod) {\n          // Fallback: check language-specific signature equivalence\n          const equivalentMethod = hints.isSignatureEquivalent\n            ? candOverloads.find((c) => hints.isSignatureEquivalent!(baseMethod, c, candidate))\n            : undefined;\n          if (equivalentMethod) {\n            preserved++;\n            continue;\n          }\n          violations.push({\n            category: 'signature',\n            severity: 'breaking',\n            symbolPath: `${name}.${methodName}`,\n            baseline: formatSignature(baseMethod),\n            candidate: formatSignature(candOverloads[0]),\n            message: `Signature mismatch for \"${name}.${methodName}\"`,\n          });\n          continue;\n        }\n        preserved++;\n      }\n    }\n\n    // Check for new methods (additions)\n    for (const methodName of Object.keys(candClass.methods)) {\n      if (!baseClass.methods[methodName]) {\n        additions.push({ symbolPath: `${name}.${methodName}`, symbolType: 'method' });\n      }\n    }\n\n    // Diff properties\n    for (const [propName, baseProp] of Object.entries(baseClass.properties)) {\n      totalBaseline++;\n      const candProp = candClass.properties[propName];\n      if (!candProp) {\n        violations.push({\n          category: 'public-api',\n          severity: 'breaking',\n          symbolPath: `${name}.${propName}`,\n          baseline: baseProp.type,\n          candidate: '(missing)',\n          message: `Property \"${name}.${propName}\" exists in baseline but not in generated output`,\n        });\n        continue;\n      }\n      if (baseProp.type !== candProp.type) {\n        const nullableOnly = hints.isNullableOnlyDifference(baseProp.type, candProp.type);\n        violations.push({\n          category: 'signature',\n          severity: nullableOnly ? 'warning' : 'breaking',\n          symbolPath: `${name}.${propName}`,\n          baseline: baseProp.type,\n          candidate: candProp.type,\n          message: `Property type mismatch for \"${name}.${propName}\"`,\n        });\n        if (nullableOnly) preserved++;\n        continue;\n      }\n      preserved++;\n    }\n\n    // Check for new properties (additions)\n    for (const propName of Object.keys(candClass.properties)) {\n      if (!baseClass.properties[propName]) {\n        additions.push({ symbolPath: `${name}.${propName}`, symbolType: 'property' });\n      }\n    }\n  }\n\n  // Check for new classes (additions)\n  for (const name of Object.keys(candidate.classes)) {\n    if (!baseline.classes[name]) {\n      additions.push({ symbolPath: name, symbolType: 'class' });\n    }\n  }\n\n  // Precompute lowercased field/property name sets for field-structure matching\n  const candIfaceFieldSets = new Map<string, Set<string>>();\n  for (const [n, iface] of Object.entries(candidate.interfaces)) {\n    candIfaceFieldSets.set(n, new Set(Object.keys(iface.fields).map((f) => f.toLowerCase())));\n  }\n  const candClassPropSets = new Map<string, Set<string>>();\n  for (const [n, cls] of Object.entries(candidate.classes)) {\n    candClassPropSets.set(n, new Set(Object.keys(cls.properties).map((f) => f.toLowerCase())));\n  }\n\n  // Diff interfaces\n  for (const [name, baseIface] of Object.entries(baseline.interfaces)) {\n    totalBaseline++;\n    const candIface = candidate.interfaces[name];\n    if (!candIface) {\n      let tolerated = false;\n      if (hints.tolerateCategoryMismatch && name.startsWith('Serialized')) {\n        const baseName = name.slice('Serialized'.length);\n        if (candidate.interfaces[baseName] || candidate.classes[baseName]) {\n          tolerated = true;\n        }\n      }\n      if (tolerated) {\n        preserved++;\n        totalBaseline += Object.keys(baseIface.fields).length;\n        preserved += Object.keys(baseIface.fields).length;\n        continue;\n      }\n      if (!tolerated) {\n        const baseFieldNamesLower = new Set(Object.keys(baseIface.fields).map((f) => f.toLowerCase()));\n        if (baseFieldNamesLower.size > 0) {\n          for (const [, candFieldNamesLower] of candIfaceFieldSets) {\n            if (\n              candFieldNamesLower.size === baseFieldNamesLower.size &&\n              [...baseFieldNamesLower].every((f) => candFieldNamesLower.has(f))\n            ) {\n              tolerated = true;\n              break;\n            }\n          }\n          if (!tolerated) {\n            for (const [, candPropNamesLower] of candClassPropSets) {\n              if (\n                candPropNamesLower.size === baseFieldNamesLower.size &&\n                [...baseFieldNamesLower].every((f) => candPropNamesLower.has(f))\n              ) {\n                tolerated = true;\n                break;\n              }\n            }\n          }\n        } else {\n          tolerated = true;\n        }\n      }\n      if (tolerated) {\n        preserved++;\n        totalBaseline += Object.keys(baseIface.fields).length;\n        preserved += Object.keys(baseIface.fields).length;\n        continue;\n      }\n      violations.push({\n        category: 'public-api',\n        severity: 'breaking',\n        symbolPath: name,\n        baseline: name,\n        candidate: '(missing)',\n        message: `Interface \"${name}\" exists in baseline but not in generated output`,\n      });\n      totalBaseline += Object.keys(baseIface.fields).length;\n      continue;\n    }\n    preserved++;\n\n    for (const [fieldName, baseField] of Object.entries(baseIface.fields)) {\n      totalBaseline++;\n      const candField = candIface.fields[fieldName];\n      if (!candField) {\n        const baseTypeClean = baseField.type.replace(/\\[\\]$/, '').replace(/ \\| null$/, '');\n        const typeIsUnresolvable = NAMED_TYPE_RE.test(baseTypeClean) && !typeExistsInSurface(baseTypeClean, candidate);\n        violations.push({\n          category: 'public-api',\n          severity: typeIsUnresolvable ? 'warning' : 'breaking',\n          symbolPath: `${name}.${fieldName}`,\n          baseline: baseField.type,\n          candidate: '(missing)',\n          message: `Field \"${name}.${fieldName}\" exists in baseline but not in generated output`,\n        });\n        if (typeIsUnresolvable) preserved++;\n        continue;\n      }\n      if (baseField.type !== candField.type) {\n        if (hints.isUnionReorder(baseField.type, candField.type)) {\n          preserved++;\n          continue;\n        }\n        if (hints.isTypeEquivalent?.(baseField.type, candField.type, candidate)) {\n          preserved++;\n          continue;\n        }\n        const nullableOnly = hints.isNullableOnlyDifference(baseField.type, candField.type);\n        const genericParam = hints.isGenericTypeParam(baseField.type);\n        const extractionArtifact = hints.isExtractionArtifact(candField.type);\n        const isWarning = nullableOnly || genericParam || extractionArtifact;\n        violations.push({\n          category: 'signature',\n          severity: isWarning ? 'warning' : 'breaking',\n          symbolPath: `${name}.${fieldName}`,\n          baseline: baseField.type,\n          candidate: candField.type,\n          message: `Field type mismatch for \"${name}.${fieldName}\"`,\n        });\n        if (isWarning) preserved++;\n        continue;\n      }\n      preserved++;\n    }\n\n    for (const fieldName of Object.keys(candIface.fields)) {\n      if (!baseIface.fields[fieldName]) {\n        additions.push({ symbolPath: `${name}.${fieldName}`, symbolType: 'property' });\n      }\n    }\n  }\n\n  // Check for new interfaces (additions)\n  for (const name of Object.keys(candidate.interfaces)) {\n    if (!baseline.interfaces[name]) {\n      additions.push({ symbolPath: name, symbolType: 'interface' });\n    }\n  }\n\n  // Diff type aliases\n  for (const [name, baseAlias] of Object.entries(baseline.typeAliases)) {\n    totalBaseline++;\n    const candAlias = candidate.typeAliases[name];\n    if (!candAlias) {\n      if (hints.tolerateCategoryMismatch && typeExistsInSurface(name, candidate)) {\n        preserved++;\n        continue;\n      }\n      violations.push({\n        category: 'public-api',\n        severity: 'breaking',\n        symbolPath: name,\n        baseline: baseAlias.value,\n        candidate: '(missing)',\n        message: `Type alias \"${name}\" exists in baseline but not in generated output`,\n      });\n      continue;\n    }\n    if (baseAlias.value !== candAlias.value) {\n      if (hints.isUnionReorder(baseAlias.value, candAlias.value)) {\n        preserved++;\n        continue;\n      }\n      const nullableOnly = hints.isNullableOnlyDifference(baseAlias.value, candAlias.value);\n      violations.push({\n        category: 'signature',\n        severity: nullableOnly ? 'warning' : 'breaking',\n        symbolPath: name,\n        baseline: baseAlias.value,\n        candidate: candAlias.value,\n        message: `Type alias value mismatch for \"${name}\"`,\n      });\n      if (nullableOnly) preserved++;\n      continue;\n    }\n    preserved++;\n  }\n\n  // Check for new type aliases (additions)\n  for (const name of Object.keys(candidate.typeAliases)) {\n    if (!baseline.typeAliases[name]) {\n      additions.push({ symbolPath: name, symbolType: 'type-alias' });\n    }\n  }\n\n  // Diff enums\n  for (const [name, baseEnum] of Object.entries(baseline.enums)) {\n    totalBaseline++;\n    const candEnum = candidate.enums[name];\n    if (!candEnum) {\n      violations.push({\n        category: 'public-api',\n        severity: 'breaking',\n        symbolPath: name,\n        baseline: name,\n        candidate: '(missing)',\n        message: `Enum \"${name}\" exists in baseline but not in generated output`,\n      });\n      continue;\n    }\n\n    const candValueToMembers = new Map<string | number, string[]>();\n    for (const [candMember, candValue] of Object.entries(candEnum.members)) {\n      const existing = candValueToMembers.get(candValue);\n      if (existing) {\n        existing.push(candMember);\n      } else {\n        candValueToMembers.set(candValue, [candMember]);\n      }\n    }\n\n    let enumMatch = true;\n    for (const [member, value] of Object.entries(baseEnum.members)) {\n      if (candEnum.members[member] === value) {\n        continue;\n      }\n\n      const valueMatches = candValueToMembers.get(value);\n      if (valueMatches && valueMatches.length > 0) {\n        violations.push({\n          category: 'signature',\n          severity: 'warning',\n          symbolPath: `${name}.${member}`,\n          baseline: `${member}=${String(value)}`,\n          candidate: `${valueMatches[0]}=${String(value)}`,\n          message: `Enum member name differs for \"${name}.${member}\" (value \"${value}\" preserved as \"${valueMatches[0]}\")`,\n        });\n        continue;\n      }\n\n      const lowerValue = String(value).toLowerCase();\n      const caseInsensitiveMatch = [...candValueToMembers.entries()].find(\n        ([candVal]) => String(candVal).toLowerCase() === lowerValue,\n      );\n      if (caseInsensitiveMatch) {\n        violations.push({\n          category: 'signature',\n          severity: 'warning',\n          symbolPath: `${name}.${member}`,\n          baseline: `${member}=${String(value)}`,\n          candidate: `${caseInsensitiveMatch[1][0]}=${String(caseInsensitiveMatch[0])}`,\n          message: `Enum member value case differs for \"${name}.${member}\" (baseline \"${value}\" vs candidate \"${caseInsensitiveMatch[0]}\")`,\n        });\n        continue;\n      }\n\n      const isExtractionArtifact =\n        String(value) === member || member === 'JsonEnumDefaultValue' || member === 'JsonProperty';\n      if (isExtractionArtifact) {\n        violations.push({\n          category: 'signature',\n          severity: 'warning',\n          symbolPath: `${name}.${member}`,\n          baseline: String(value),\n          candidate: '(extraction artifact)',\n          message: `Enum member \"${name}.${member}\" appears to be an extraction artifact`,\n        });\n        continue;\n      }\n\n      violations.push({\n        category: 'signature',\n        severity: 'breaking',\n        symbolPath: `${name}.${member}`,\n        baseline: String(value),\n        candidate: member in candEnum.members ? String(candEnum.members[member]) : '(missing)',\n        message: `Enum member mismatch for \"${name}.${member}\"`,\n      });\n      enumMatch = false;\n    }\n    if (enumMatch) {\n      preserved++;\n    }\n  }\n\n  // Check for new enums (additions)\n  for (const name of Object.keys(candidate.enums)) {\n    if (!baseline.enums[name]) {\n      additions.push({ symbolPath: name, symbolType: 'enum' });\n    }\n  }\n\n  // Diff barrel exports\n  for (const [path, baseExports] of Object.entries(baseline.exports)) {\n    const candExports = candidate.exports[path];\n    if (!candExports) {\n      for (const exp of baseExports) {\n        violations.push({\n          category: 'export-structure',\n          severity: 'warning',\n          symbolPath: `exports[${path}].${exp}`,\n          baseline: exp,\n          candidate: '(missing)',\n          message: `Export \"${exp}\" from \"${path}\" not found in generated output`,\n        });\n      }\n      continue;\n    }\n    const candSet = new Set(candExports);\n    for (const exp of baseExports) {\n      if (!candSet.has(exp)) {\n        violations.push({\n          category: 'export-structure',\n          severity: 'warning',\n          symbolPath: `exports[${path}].${exp}`,\n          baseline: exp,\n          candidate: '(missing)',\n          message: `Export \"${exp}\" from \"${path}\" not found in generated output`,\n        });\n      }\n    }\n  }\n\n  return {\n    preservationScore: totalBaseline > 0 ? Math.round((preserved / totalBaseline) * 100) : 100,\n    totalBaselineSymbols: totalBaseline,\n    preservedSymbols: preserved,\n    violations,\n    additions,\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers (legacy)\n// ---------------------------------------------------------------------------\n\nfunction signaturesMatch(baseline: ApiMethod, candidate: ApiMethod): boolean {\n  if (baseline.returnType !== candidate.returnType) return false;\n  for (let i = 0; i < baseline.params.length; i++) {\n    const baseParam = baseline.params[i];\n    const candParam = candidate.params[i];\n    if (!candParam) return false;\n    if (baseParam.type !== candParam.type) return false;\n    if (baseParam.name !== candParam.name) return false;\n  }\n  for (let i = baseline.params.length; i < candidate.params.length; i++) {\n    if (!candidate.params[i].optional) return false;\n  }\n  return true;\n}\n\nfunction formatSignature(method: ApiMethod): string {\n  const params = method.params.map((p) => `${p.name}${p.optional ? '?' : ''}: ${p.type}`).join(', ');\n  return `(${params}) => ${method.returnType}`;\n}\n","/**\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","import { readFileSync, writeFileSync } from 'node:fs';\nimport { validateSnapshot } from '../compat/schema.js';\nimport { diffSnapshots } from '../compat/differ.js';\nimport { generateReport, formatHumanSummary } from '../compat/report.js';\nimport { severityMeetsThreshold } from '../compat/config.js';\nimport type { CompatFailLevel } from '../compat/config.js';\nimport type { CompatSnapshot } from '../compat/ir.js';\n\nexport async function compatDiffCommand(opts: {\n  baseline: string;\n  candidate: string;\n  output?: string;\n  failOn?: string;\n  explain?: boolean;\n}): Promise<void> {\n  const baselineData = JSON.parse(readFileSync(opts.baseline, 'utf-8'));\n  const candidateData = JSON.parse(readFileSync(opts.candidate, 'utf-8'));\n\n  if (!validateSnapshot(baselineData)) {\n    throw new Error(`Invalid baseline snapshot: ${opts.baseline}`);\n  }\n  if (!validateSnapshot(candidateData)) {\n    throw new Error(`Invalid candidate snapshot: ${opts.candidate}`);\n  }\n\n  const baseline = baselineData as CompatSnapshot;\n  const candidate = candidateData as CompatSnapshot;\n\n  const diff = diffSnapshots(baseline, candidate);\n\n  // Human-readable output to terminal\n  console.log(formatHumanSummary(diff, { explain: opts.explain }));\n\n  // Machine-readable output to file\n  if (opts.output) {\n    const report = generateReport(diff);\n    writeFileSync(opts.output, JSON.stringify(report, null, 2));\n    console.log(`Report written to ${opts.output}`);\n  }\n\n  // Fail if threshold exceeded\n  const failOn = (opts.failOn ?? 'breaking') as CompatFailLevel;\n  const hasFailure = diff.changes.some((c) => severityMeetsThreshold(c.severity, failOn));\n  if (hasFailure) {\n    process.exitCode = 1;\n  }\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport type { CompatReport, CompatReportChange } from '../compat/report.js';\nimport type { CompatDiffResult } from '../compat/differ.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport type { CompatChangeSeverity } from '../compat/config.js';\nimport { buildConceptualRollup, highestSeverity, summarizeConceptualChanges } from '../compat/concepts.js';\n\n/**\n * Format compat report(s) as a markdown PR comment.\n *\n * Single report:\n *   oagen compat-summary --report node-report.json | gh pr comment --body-file -\n *\n * Multiple reports (cross-language rollup):\n *   oagen compat-summary --report php.json --report python.json --report go.json\n */\nexport async function compatSummaryCommand(opts: { report: string | string[]; output?: string }): Promise<void> {\n  const paths = Array.isArray(opts.report) ? opts.report : [opts.report];\n  const reports = paths.map((p) => JSON.parse(readFileSync(p, 'utf-8')) as CompatReport);\n\n  const md = reports.length === 1 ? formatSingleReport(reports[0]) : formatCrossLanguageRollup(reports);\n\n  if (opts.output) {\n    writeFileSync(opts.output, md);\n    console.log(`Summary written to ${opts.output}`);\n  } else {\n    process.stdout.write(md);\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Single-language report\n// ---------------------------------------------------------------------------\n\nfunction formatSingleReport(report: CompatReport): string {\n  const lines: string[] = [];\n  const { breaking, softRisk, additive } = report.summary;\n  const total = breaking + softRisk + additive;\n\n  if (breaking > 0) {\n    lines.push(`## :x: Compat check failed — ${report.language}`);\n  } else if (softRisk > 0) {\n    lines.push(`## :warning: Compat check has warnings — ${report.language}`);\n  } else {\n    lines.push(`## :white_check_mark: Compat check passed — ${report.language}`);\n  }\n\n  lines.push('');\n  lines.push('| Severity | Count |');\n  lines.push('| --- | --- |');\n  lines.push(`| Breaking | ${breaking} |`);\n  lines.push(`| Soft-risk | ${softRisk} |`);\n  lines.push(`| Additive | ${additive} |`);\n  lines.push(`| **Total** | **${total}** |`);\n\n  if (total === 0) {\n    lines.push('');\n    lines.push('No compatibility changes detected.');\n    return lines.join('\\n') + '\\n';\n  }\n\n  const breakingChanges = report.changes.filter((c) => c.severity === 'breaking');\n  if (breakingChanges.length > 0) {\n    lines.push('');\n    lines.push('### Breaking changes');\n    lines.push('');\n    lines.push(formatChangesTable(breakingChanges));\n  }\n\n  const softRiskChanges = report.changes.filter((c) => c.severity === 'soft-risk');\n  if (softRiskChanges.length > 0) {\n    lines.push('');\n    lines.push('<details>');\n    lines.push(`<summary>Soft-risk changes (${softRiskChanges.length})</summary>`);\n    lines.push('');\n    lines.push(formatChangesTable(softRiskChanges));\n    lines.push('</details>');\n  }\n\n  const additiveChanges = report.changes.filter((c) => c.severity === 'additive');\n  if (additiveChanges.length > 0) {\n    lines.push('');\n    lines.push('<details>');\n    lines.push(`<summary>Additive changes (${additiveChanges.length})</summary>`);\n    lines.push('');\n    lines.push(formatChangesTable(additiveChanges));\n    lines.push('</details>');\n  }\n\n  return lines.join('\\n') + '\\n';\n}\n\n// ---------------------------------------------------------------------------\n// Cross-language rollup\n// ---------------------------------------------------------------------------\n\nfunction formatCrossLanguageRollup(reports: CompatReport[]): string {\n  const languages = reports.map((r) => r.language);\n\n  // Convert reports to the shape buildConceptualRollup expects\n  const perLanguage = reports.map((r) => ({\n    diff: { changes: r.changes, summary: r.summary } as CompatDiffResult,\n    language: r.language as LanguageId,\n  }));\n  const rollup = buildConceptualRollup(perLanguage);\n  const summary = summarizeConceptualChanges(rollup);\n\n  const lines: string[] = [];\n\n  // Header\n  if (summary.breaking > 0) {\n    lines.push(`## :x: Compat check failed — ${summary.breaking} breaking across ${languages.length} languages`);\n  } else if (summary.softRisk > 0) {\n    lines.push(\n      `## :warning: Compat check has warnings — ${summary.softRisk} soft-risk across ${languages.length} languages`,\n    );\n  } else {\n    lines.push(`## :white_check_mark: Compat check passed — ${languages.length} languages`);\n  }\n\n  lines.push('');\n\n  // Per-language summary table\n  lines.push('| Language | Breaking | Soft-risk | Additive |');\n  lines.push('| --- | --- | --- | --- |');\n  for (const r of reports) {\n    lines.push(`| ${r.language} | ${r.summary.breaking} | ${r.summary.softRisk} | ${r.summary.additive} |`);\n  }\n\n  if (rollup.conceptualChanges.length === 0) {\n    lines.push('');\n    lines.push('No compatibility changes detected.');\n    return lines.join('\\n') + '\\n';\n  }\n\n  // Conceptual changes table with per-language severity\n  const breakingConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'breaking');\n  if (breakingConcepts.length > 0) {\n    lines.push('');\n    lines.push('### Breaking changes');\n    lines.push('');\n    lines.push(formatConceptualTable(breakingConcepts, languages));\n  }\n\n  const softRiskConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'soft-risk');\n  if (softRiskConcepts.length > 0) {\n    lines.push('');\n    lines.push('<details>');\n    lines.push(`<summary>Soft-risk changes (${softRiskConcepts.length})</summary>`);\n    lines.push('');\n    lines.push(formatConceptualTable(softRiskConcepts, languages));\n    lines.push('</details>');\n  }\n\n  const additiveConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'additive');\n  if (additiveConcepts.length > 0) {\n    lines.push('');\n    lines.push('<details>');\n    lines.push(`<summary>Additive changes (${additiveConcepts.length})</summary>`);\n    lines.push('');\n    lines.push(formatConceptualTable(additiveConcepts, languages));\n    lines.push('</details>');\n  }\n\n  return lines.join('\\n') + '\\n';\n}\n\nfunction formatConceptualTable(\n  concepts: Array<{ symbol: string; category: string; impact: Partial<Record<string, CompatChangeSeverity>> }>,\n  languages: string[],\n): string {\n  const lines: string[] = [];\n  const langHeaders = languages.map((l) => l).join(' | ');\n  lines.push(`| Symbol | Category | ${langHeaders} |`);\n  lines.push(`| --- | --- | ${languages.map(() => '---').join(' | ')} |`);\n  for (const c of concepts) {\n    const severities = languages.map((l) => severityIcon(c.impact[l])).join(' | ');\n    lines.push(`| \\`${c.symbol}\\` | \\`${c.category}\\` | ${severities} |`);\n  }\n  return lines.join('\\n');\n}\n\nfunction severityIcon(severity: CompatChangeSeverity | undefined): string {\n  if (!severity) return '—';\n  switch (severity) {\n    case 'breaking':\n      return ':x: breaking';\n    case 'soft-risk':\n      return ':warning: soft-risk';\n    case 'additive':\n      return ':white_check_mark: additive';\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction formatChangesTable(changes: CompatReportChange[]): string {\n  const lines: string[] = [];\n  lines.push('| Category | Symbol | Detail |');\n  lines.push('| --- | --- | --- |');\n  for (const c of changes) {\n    const detail = c.message ?? formatOldNew(c.old, c.new);\n    lines.push(`| \\`${c.category}\\` | \\`${c.symbol}\\` | ${escapeMarkdown(detail)} |`);\n  }\n  return lines.join('\\n');\n}\n\nfunction formatOldNew(old: Record<string, string>, updated: Record<string, string>): string {\n  const parts: string[] = [];\n  for (const key of Object.keys(old)) {\n    if (updated[key] && old[key] !== updated[key]) {\n      parts.push(`${key}: \\`${old[key]}\\` → \\`${updated[key]}\\``);\n    }\n  }\n  return parts.length > 0 ? parts.join(', ') : '';\n}\n\nfunction escapeMarkdown(text: string): string {\n  return text.replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\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","import { getExtractor } from '../compat/extractor-registry.js';\nimport {\n  diffSnapshots,\n  specDerivedNames,\n  specDerivedFieldPaths,\n  specDerivedMethodPaths,\n  specDerivedEnumValues,\n  filterSurface,\n} from '../compat/differ.js';\nimport { apiSurfaceToSnapshot } from '../compat/ir.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport { getDefaultPolicy, mergePolicy } from '../compat/policy.js';\nimport type { CompatPolicyHints } from '../compat/policy.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { CompatCheckResult } from './types.js';\n\nexport async function runCompatCheck(\n  baseline: ApiSurface,\n  outputDir: string,\n  lang: string,\n  spec?: ApiSpec,\n  policyOverrides?: Partial<CompatPolicyHints>,\n): Promise<CompatCheckResult> {\n  const extractor = getExtractor(lang);\n  const candidate = await extractor.extract(outputDir);\n\n  let scopedBaseline = baseline;\n  let scopedToSpec = false;\n  let scopedSymbolCount: number | undefined;\n  if (spec) {\n    const allowed = specDerivedNames(spec, extractor.hints);\n    const fieldPaths = specDerivedFieldPaths(spec, extractor.hints);\n    const methodPaths = specDerivedMethodPaths(spec);\n    const enumVals = specDerivedEnumValues(spec);\n    scopedBaseline = filterSurface(baseline, allowed, { fieldPaths, methodPaths, enumValues: enumVals });\n    scopedToSpec = true;\n    scopedSymbolCount =\n      Object.keys(scopedBaseline.interfaces).length +\n      Object.keys(scopedBaseline.classes).length +\n      Object.keys(scopedBaseline.typeAliases).length +\n      Object.keys(scopedBaseline.enums).length;\n  }\n\n  const baseSnap = apiSurfaceToSnapshot(scopedBaseline);\n  const candSnap = apiSurfaceToSnapshot(candidate);\n\n  const langId = lang as LanguageId;\n  const policy = policyOverrides ? mergePolicy(getDefaultPolicy(langId), policyOverrides) : getDefaultPolicy(langId);\n\n  const diff = diffSnapshots(baseSnap, candSnap, policy);\n  const passed = diff.changes.every((c) => c.severity !== 'breaking');\n\n  return { passed, diff, scopedToSpec, scopedSymbolCount };\n}\n","import { readdirSync, unlinkSync, statSync, openSync, readSync, closeSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { buildOverlayLookup, patchOverlay, isPatchableChange } from '../compat/overlay.js';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { getEmitter } from '../engine/registry.js';\nimport { generate } from '../engine/orchestrator.js';\nimport { runCompatCheck } from './run-compat-check.js';\nimport type { OverlayRetryResult } from './types.js';\nimport { readManifestSync } from '../engine/manifest-reader.js';\n\n/** Generated file header markers used by various emitters. */\nconst GENERATED_MARKERS = ['Code generated by oagen', 'auto-generated by oagen', 'This file is auto-generated'];\n\n/**\n * Delete oagen-generated source files so the retry loop can regenerate them\n * with overlay-corrected names. Only deletes files that contain an oagen\n * generation marker, preserving hand-written files.\n */\nfunction cleanGeneratedFiles(dir: string): void {\n  let entries: string[];\n  try {\n    entries = readdirSync(dir);\n  } catch {\n    return;\n  }\n  for (const entry of entries) {\n    const full = path.join(dir, entry);\n    let stat;\n    try {\n      stat = statSync(full);\n    } catch {\n      continue;\n    }\n    if (stat.isDirectory()) {\n      cleanGeneratedFiles(full);\n      continue;\n    }\n    // Skip non-source files and manifests\n    if (entry.endsWith('.json') || entry.endsWith('.lock')) continue;\n    // Read only the first 200 bytes to check for generation marker\n    try {\n      const buf = Buffer.alloc(200);\n      const fd = openSync(full, 'r');\n      try {\n        readSync(fd, buf, 0, 200, 0);\n      } finally {\n        closeSync(fd);\n      }\n      const header = buf.toString('utf-8');\n      if (GENERATED_MARKERS.some((m) => header.includes(m))) {\n        unlinkSync(full);\n      }\n    } catch {\n      // ignore read/delete errors\n    }\n  }\n}\n\nexport async function runOverlayRetryLoop(opts: {\n  baseline: ApiSurface;\n  parsedSpec: ApiSpec;\n  outputDir: string;\n  lang: string;\n  maxRetries: number;\n  namespace?: string;\n  onRetry?: (attemptNumber: number, maxRetries: number, patchableCount: number) => void;\n}): Promise<OverlayRetryResult> {\n  const { baseline, parsedSpec, outputDir, lang, maxRetries, namespace, onRetry } = opts;\n\n  const manifest = readManifestSync(outputDir);\n  // Pass language-specific hints so property-to-class matching works correctly\n  // (e.g., Ruby snake_case \"api_keys\" → PascalCase \"ApiKeys\").\n  const extractor = getExtractor(lang);\n  let overlay = buildOverlayLookup(baseline, manifest, parsedSpec, extractor.hints);\n  let prevPreserved = -1;\n  const patchedPerIteration: number[] = [];\n\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    const compatResult = await runCompatCheck(baseline, outputDir, lang, parsedSpec);\n    if (compatResult.passed) {\n      return {\n        status: 'passed',\n        attempts: attempt,\n        patchedPerIteration,\n        compatResult,\n      };\n    }\n\n    if (attempt === maxRetries) {\n      return {\n        status: 'max-retries',\n        attempts: attempt,\n        patchedPerIteration,\n        compatResult,\n      };\n    }\n\n    const patchable = compatResult.diff.changes.filter(isPatchableChange);\n    if (patchable.length === 0) {\n      return {\n        status: 'no-patchable',\n        attempts: attempt,\n        patchedPerIteration,\n        compatResult,\n      };\n    }\n\n    const currentBreaking = compatResult.diff.summary.breaking;\n    // Stall detection: if breaking count hasn't decreased, we're not making progress\n    if (attempt > 0 && currentBreaking >= prevPreserved) {\n      return {\n        status: 'stalled',\n        attempts: attempt,\n        patchedPerIteration,\n        compatResult,\n      };\n    }\n    prevPreserved = currentBreaking;\n    patchedPerIteration.push(patchable.length);\n    onRetry?.(attempt + 1, maxRetries, patchable.length);\n\n    overlay = patchOverlay(overlay, patchable, baseline);\n\n    // Pre-delete generated source files so the writer creates them fresh\n    // with overlay-corrected names. Without this, the AST merger would preserve\n    // old method/class names from the existing files.\n    // Only delete files that look like oagen-generated source files (have the header).\n    cleanGeneratedFiles(outputDir);\n\n    const emitter = getEmitter(lang);\n    await generate(parsedSpec, emitter, {\n      namespace: namespace ?? parsedSpec.name,\n      outputDir,\n      overlayLookup: overlay,\n      apiSurface: baseline,\n    });\n  }\n\n  const compatResult = await runCompatCheck(baseline, outputDir, lang, parsedSpec);\n  return {\n    status: 'max-retries',\n    attempts: maxRetries,\n    patchedPerIteration,\n    compatResult,\n  };\n}\n","import type { ApiSurface, LanguageHints, Violation } from './types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { specDerivedNames, specDerivedFieldPaths } from './spec-filter.js';\nimport { diffSpecs } from '../differ/diff.js';\n\n/**\n * Detect symbols that exist in the live SDK surface but are no longer defined\n * in the current OpenAPI spec. These are \"stale\" — they compile and run but\n * represent dead code from a previous spec version.\n *\n * Requires both the old and new spec so we can distinguish hand-written SDK\n * symbols (never in any spec) from genuinely removed spec symbols.\n */\nexport function detectStaleSymbols(\n  liveSurface: ApiSurface,\n  oldSpec: ApiSpec,\n  newSpec: ApiSpec,\n  hints: LanguageHints,\n): Violation[] {\n  const violations: Violation[] = [];\n\n  // Step 1-3: Name-set difference for top-level symbols\n  const oldNames = specDerivedNames(oldSpec, hints);\n  const newNames = specDerivedNames(newSpec, hints);\n\n  const removedNames = new Set<string>();\n  for (const name of oldNames) {\n    if (!newNames.has(name)) removedNames.add(name);\n  }\n\n  for (const name of removedNames) {\n    if (liveSurface.classes[name]) {\n      violations.push({\n        category: 'staleness',\n        severity: 'warning',\n        symbolPath: name,\n        baseline: name,\n        candidate: '(removed from spec)',\n        message: `Class \"${name}\" is no longer defined in the OpenAPI spec`,\n      });\n    }\n    if (liveSurface.interfaces[name]) {\n      violations.push({\n        category: 'staleness',\n        severity: 'warning',\n        symbolPath: name,\n        baseline: name,\n        candidate: '(removed from spec)',\n        message: `Interface \"${name}\" is no longer defined in the OpenAPI spec`,\n      });\n    }\n    if (liveSurface.typeAliases[name]) {\n      violations.push({\n        category: 'staleness',\n        severity: 'warning',\n        symbolPath: name,\n        baseline: name,\n        candidate: '(removed from spec)',\n        message: `Type alias \"${name}\" is no longer defined in the OpenAPI spec`,\n      });\n    }\n    if (liveSurface.enums[name]) {\n      violations.push({\n        category: 'staleness',\n        severity: 'warning',\n        symbolPath: name,\n        baseline: name,\n        candidate: '(removed from spec)',\n        message: `Enum \"${name}\" is no longer defined in the OpenAPI spec`,\n      });\n    }\n  }\n\n  // Step 4-6: Field-level staleness for models that still exist in new spec\n  const oldFieldPaths = specDerivedFieldPaths(oldSpec, hints);\n  const newFieldPaths = specDerivedFieldPaths(newSpec, hints);\n\n  for (const fieldPath of oldFieldPaths) {\n    if (newFieldPaths.has(fieldPath)) continue;\n\n    const [modelName, fieldName] = fieldPath.split('.');\n    // Only flag field-level staleness for models that still exist in the new spec\n    // (fully removed models are already caught above)\n    if (removedNames.has(modelName)) continue;\n\n    const iface = liveSurface.interfaces[modelName];\n    if (iface?.fields[fieldName]) {\n      violations.push({\n        category: 'staleness',\n        severity: 'warning',\n        symbolPath: fieldPath,\n        baseline: fieldName,\n        candidate: '(removed from spec)',\n        message: `Field \"${fieldPath}\" is no longer defined in the OpenAPI spec`,\n      });\n    }\n  }\n\n  // Step 7: Operation-level staleness via diffSpecs\n  const diff = diffSpecs(oldSpec, newSpec);\n  for (const change of diff.changes) {\n    if (change.kind === 'operation-removed') {\n      const cls = liveSurface.classes[change.serviceName];\n      if (cls?.methods[change.operationName]) {\n        violations.push({\n          category: 'staleness',\n          severity: 'warning',\n          symbolPath: `${change.serviceName}.${change.operationName}`,\n          baseline: change.operationName,\n          candidate: '(removed from spec)',\n          message: `Method \"${change.serviceName}.${change.operationName}\" is no longer defined in the OpenAPI spec`,\n        });\n      }\n    }\n  }\n\n  return violations;\n}\n","import { getExtractor } from '../compat/extractor-registry.js';\nimport { detectStaleSymbols } from '../compat/staleness.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { StalenessCheckResult } from './types.js';\n\nexport function runStalenessCheck(\n  baseline: ApiSurface,\n  oldSpec: ApiSpec,\n  newSpec: ApiSpec,\n  lang: string,\n): StalenessCheckResult {\n  const extractor = getExtractor(lang);\n  const violations = detectStaleSymbols(baseline, oldSpec, newSpec, extractor.hints);\n  return { violations };\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport * as path from 'node:path';\nimport { CommandError } from '../errors.js';\nimport type { SmokeCheckResult } from './types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nfunction resolveScript(scriptRelPath: string): { bin: string; script: string } {\n  const distScript = path.resolve(__dirname, '..', '..', 'dist', 'scripts', scriptRelPath.replace(/\\.ts$/, '.mjs'));\n  if (existsSync(distScript)) {\n    return { bin: 'node', script: distScript };\n  }\n  const srcScript = path.resolve(__dirname, '..', '..', 'scripts', scriptRelPath);\n  return { bin: 'npx', script: srcScript };\n}\n\nfunction runPackagedScript(scriptRelPath: string, args: string[]): void {\n  const { bin, script } = resolveScript(scriptRelPath);\n  const fullArgs = bin === 'npx' ? ['tsx', script, ...args] : [script, ...args];\n  execFileSync(bin, fullArgs, { stdio: 'inherit', env: process.env });\n}\n\nexport function runSmokeCheck(opts: {\n  spec?: string;\n  lang: string;\n  output: string;\n  rawResults?: string;\n  smokeConfig?: string;\n  smokeRunner?: string;\n}): SmokeCheckResult {\n  const { spec, lang, output, rawResults, smokeConfig, smokeRunner } = opts;\n\n  let baselinePath = rawResults ?? 'smoke-results-raw.json';\n  let generatedBaseline = false;\n\n  if (!rawResults && !existsSync('smoke-results-raw.json')) {\n    if (!spec) {\n      throw new CommandError(\n        'error: --spec <path> or OPENAPI_SPEC_PATH env var is required when no raw baseline exists',\n        '',\n        1,\n      );\n    }\n\n    try {\n      runPackagedScript('smoke/baseline.ts', ['--spec', spec]);\n    } catch {\n      throw new CommandError('Baseline generation failed', '', 1);\n    }\n    baselinePath = 'smoke-results-spec-baseline.json';\n    generatedBaseline = true;\n  }\n\n  const smokeArgs = ['--lang', lang, '--sdk-path', output, '--raw-results', baselinePath];\n  if (spec) smokeArgs.push('--spec', spec);\n  if (smokeConfig) smokeArgs.push('--smoke-config', smokeConfig);\n\n  try {\n    if (smokeRunner) {\n      const bin = smokeRunner.endsWith('.ts') ? 'npx' : 'node';\n      const fullArgs = bin === 'npx' ? ['tsx', smokeRunner, ...smokeArgs] : [smokeRunner, ...smokeArgs];\n      execFileSync(bin, fullArgs, { stdio: 'inherit', env: process.env });\n    } else {\n      runPackagedScript('smoke/sdk-test.ts', smokeArgs);\n    }\n\n    return { passed: true, baselinePath, generatedBaseline };\n  } catch {\n    if (existsSync('smoke-compile-errors.json')) {\n      return { passed: false, compileErrors: true, baselinePath, generatedBaseline };\n    }\n\n    const findingsCount = existsSync('smoke-diff-findings.json')\n      ? (JSON.parse(readFileSync('smoke-diff-findings.json', 'utf-8')) as unknown[]).length\n      : undefined;\n\n    return { passed: false, findingsCount, baselinePath, generatedBaseline };\n  }\n}\n","import { writeFileSync } from 'node:fs';\nimport type { VerifyDiagnostics, CompatCheckResult } from './types.js';\n\nexport function summarizeCompatCheck(result: CompatCheckResult): NonNullable<VerifyDiagnostics['compatCheck']> {\n  const violationsByCategory: Record<string, number> = {};\n  const violationsBySeverity: Record<string, number> = {};\n  for (const c of result.diff.changes) {\n    violationsByCategory[c.category] = (violationsByCategory[c.category] ?? 0) + 1;\n    violationsBySeverity[c.severity] = (violationsBySeverity[c.severity] ?? 0) + 1;\n  }\n\n  const { breaking, softRisk, additive } = result.diff.summary;\n  const totalChanges = breaking + softRisk + additive;\n  const totalBaselineSymbols = totalChanges + additive; // approximate; additive are new\n  const preservedSymbols = totalBaselineSymbols - breaking - softRisk;\n  const preservationScore =\n    totalBaselineSymbols > 0 ? Math.round((preservedSymbols / totalBaselineSymbols) * 100) : 100;\n\n  return {\n    totalBaselineSymbols,\n    preservedSymbols,\n    preservationScore,\n    violationsByCategory,\n    violationsBySeverity,\n    additions: additive,\n    scopedToSpec: result.scopedToSpec,\n    ...(result.scopedSymbolCount !== undefined ? { scopedSymbolCount: result.scopedSymbolCount } : {}),\n  };\n}\n\nexport function setRetryDiagnostics(\n  diagData: VerifyDiagnostics,\n  attempt: number,\n  converged: boolean,\n  finalScore: number,\n  patchedPerIteration: number[],\n): void {\n  diagData.retryLoop = { attempts: attempt, converged, finalScore, patchedPerIteration };\n}\n\nexport function writeDiagnostics(data: VerifyDiagnostics, filePath: string = 'verify-diagnostics.json'): void {\n  writeFileSync(filePath, JSON.stringify(data, null, 2) + '\\n');\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { CommandError } from '../errors.js';\nimport { parseSpec, type OpenApiDocument } from '../parser/parse.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { CompatConfig, CompatFailLevel } from '../compat/config.js';\nimport { severityMeetsThreshold } from '../compat/config.js';\nimport { generateReport, formatHumanSummary } from '../compat/report.js';\nimport { unapprovedChanges } from '../compat/approvals.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport { runCompatCheck } from '../verify/run-compat-check.js';\nimport { runOverlayRetryLoop } from '../verify/run-overlay-retry-loop.js';\nimport { runStalenessCheck } from '../verify/run-staleness-check.js';\nimport { runSmokeCheck } from '../verify/run-smoke-check.js';\nimport { summarizeCompatCheck, setRetryDiagnostics, writeDiagnostics } from '../verify/write-diagnostics.js';\nimport type { VerifyDiagnostics } from '../verify/types.js';\n\nexport type { VerifyDiagnostics } from '../verify/types.js';\n\nconst separator = '='.repeat(60);\n\nfunction printCompatResult(result: ReturnType<typeof summarizeCompatCheck>, baseline: ApiSurface): void {\n  if (result.scopedToSpec) {\n    const totalBefore =\n      Object.keys(baseline.interfaces).length +\n      Object.keys(baseline.classes).length +\n      Object.keys(baseline.typeAliases).length +\n      Object.keys(baseline.enums).length;\n    console.log(`(scoped to spec: ${result.scopedSymbolCount}/${totalBefore} baseline symbols in scope)`);\n  }\n\n  console.log(\n    `compat: ${result.preservationScore}% (${result.preservedSymbols}/${result.totalBaselineSymbols} symbols preserved)`,\n  );\n}\n\nexport async function verifyCommand(opts: {\n  spec?: string;\n  oldSpec?: string;\n  lang: string;\n  output: string;\n  apiSurface?: string;\n  rawResults?: string;\n  smokeConfig?: string;\n  smokeRunner?: string;\n  scope?: 'full' | 'spec-only';\n  diagnostics?: boolean;\n  maxRetries?: number;\n  operationIdTransform?: (id: string) => string;\n  schemaNameTransform?: (name: string) => string;\n  transformSpec?: (spec: OpenApiDocument) => OpenApiDocument;\n  namespace?: string;\n  compatConfig?: CompatConfig;\n  compatReport?: string;\n  compatFailOn?: string;\n  compatBaseline?: string;\n  compatExplain?: boolean;\n}): Promise<void> {\n  const {\n    spec,\n    oldSpec,\n    lang,\n    output,\n    apiSurface,\n    rawResults,\n    smokeConfig,\n    smokeRunner,\n    scope,\n    diagnostics,\n    operationIdTransform,\n    schemaNameTransform,\n    transformSpec,\n    compatConfig,\n    compatReport,\n    compatExplain,\n  } = opts;\n  const maxRetries = opts.maxRetries ?? 3;\n  const diagData: VerifyDiagnostics = {};\n\n  // Resolve compat options: CLI flags take precedence over config\n  const effectiveFailOn: CompatFailLevel =\n    (opts.compatFailOn as CompatFailLevel | undefined) ?? compatConfig?.failOn ?? 'breaking';\n  const effectiveReportPath = compatReport ?? compatConfig?.reportPath;\n  const effectiveExplain = compatExplain ?? compatConfig?.explain ?? false;\n\n  let stepNum = 1;\n  const baseline: ApiSurface | undefined = apiSurface\n    ? (JSON.parse(readFileSync(apiSurface, 'utf-8')) as ApiSurface)\n    : undefined;\n\n  if (apiSurface && baseline) {\n    console.log(`\\n${separator}`);\n    console.log(`Step ${stepNum}: Compat verification`);\n    console.log(separator);\n\n    const effectiveScope = scope ?? (spec ? 'spec-only' : 'full');\n    let parsedSpec;\n    if (effectiveScope === 'spec-only' && spec) {\n      parsedSpec = await parseSpec(spec, { operationIdTransform, schemaNameTransform, transformSpec });\n    } else if (effectiveScope === 'spec-only') {\n      throw new CommandError('error: --scope spec-only requires --spec <path>', '', 1);\n    }\n\n    const compatFlow =\n      parsedSpec && maxRetries > 0\n        ? await runOverlayRetryLoop({\n            baseline,\n            parsedSpec,\n            outputDir: output,\n            lang,\n            maxRetries,\n            namespace: opts.namespace,\n            onRetry: (attemptNumber, retryLimit, patchableCount) => {\n              console.log(`\\nRetry ${attemptNumber}/${retryLimit}: patching ${patchableCount} violation(s)...`);\n            },\n          })\n        : {\n            status: 'passed' as const,\n            attempts: 0,\n            patchedPerIteration: [],\n            compatResult: await runCompatCheck(baseline, output, lang, parsedSpec),\n          };\n\n    const compatSummary = summarizeCompatCheck(compatFlow.compatResult);\n    printCompatResult(compatSummary, baseline);\n    const classifiedDiff = compatFlow.compatResult.diff;\n    for (const c of classifiedDiff.changes) {\n      if (c.severity !== 'additive') {\n        console.log(`  [${c.category}] ${c.severity}: ${c.symbol} — ${c.message}`);\n      }\n    }\n    const additiveCount = classifiedDiff.summary.additive;\n    if (additiveCount > 0) {\n      console.log(`  + ${additiveCount} new symbols added`);\n    }\n\n    if (diagnostics) {\n      diagData.compatCheck = compatSummary;\n      if (parsedSpec && maxRetries > 0) {\n        setRetryDiagnostics(\n          diagData,\n          compatFlow.attempts,\n          compatFlow.status === 'passed',\n          compatSummary.preservationScore,\n          compatFlow.patchedPerIteration,\n        );\n      }\n    }\n\n    if (compatFlow.status === 'passed' && compatFlow.compatResult.passed) {\n      if (compatFlow.attempts > 0) {\n        console.log(`Compat: converged after ${compatFlow.attempts} retry iteration(s)`);\n      } else {\n        console.log('Compat: passed');\n      }\n    } else {\n      if (diagnostics) {\n        writeDiagnostics(diagData);\n        console.log('Diagnostics written to verify-diagnostics.json');\n      }\n\n      if (compatFlow.status === 'no-patchable') {\n        console.log(\n          'No patchable violations — cannot self-correct. Remaining violations require emitter code changes.',\n        );\n      } else if (compatFlow.status === 'stalled') {\n        console.log(`Stalled — overlay patching is not making progress.`);\n      }\n\n      throw new CommandError('\\nCompat violations found — fix the emitter and re-run `oagen verify`.', '', 1);\n    }\n\n    // Classified compat analysis — approvals, reports, and explanations\n    // The diff is already classified from runCompatCheck/runOverlayRetryLoop\n    if (effectiveReportPath || effectiveExplain || (compatConfig?.allow?.length ?? 0) > 0) {\n      const langId = lang as LanguageId;\n      const approvals = compatConfig?.allow ?? [];\n      const remaining = unapprovedChanges(classifiedDiff.changes, approvals, langId);\n      const hasFailure = remaining.some((c) => severityMeetsThreshold(c.severity, effectiveFailOn));\n\n      if (effectiveExplain) {\n        console.log('');\n        console.log(formatHumanSummary(classifiedDiff, { explain: true }));\n      }\n\n      if (effectiveReportPath) {\n        const report = generateReport(classifiedDiff);\n        writeFileSync(effectiveReportPath, JSON.stringify(report, null, 2) + '\\n');\n        console.log(`Compat report written to ${effectiveReportPath}`);\n      }\n\n      if (hasFailure && effectiveFailOn !== 'none') {\n        const unapprovedBreaking = remaining.filter((c) => severityMeetsThreshold(c.severity, effectiveFailOn));\n        console.log(`\\n${unapprovedBreaking.length} unapproved change(s) at or above '${effectiveFailOn}' threshold`);\n      }\n    }\n\n    stepNum++;\n  }\n\n  if (oldSpec && spec && apiSurface && baseline) {\n    console.log(`\\n${separator}`);\n    console.log(`Step ${stepNum}: Staleness detection`);\n    console.log(separator);\n\n    const oldParsedSpec = await parseSpec(oldSpec, { operationIdTransform, schemaNameTransform, transformSpec });\n    const newParsedSpec = await parseSpec(spec, { operationIdTransform, schemaNameTransform, transformSpec });\n    const stalenessResult = runStalenessCheck(baseline, oldParsedSpec, newParsedSpec, lang);\n\n    if (stalenessResult.violations.length > 0) {\n      console.log(`Found ${stalenessResult.violations.length} stale symbol(s):`);\n      for (const v of stalenessResult.violations) {\n        console.log(`  [${v.category}] ${v.severity}: ${v.symbolPath} — ${v.message}`);\n      }\n    } else {\n      console.log('No stale symbols detected.');\n    }\n\n    if (diagnostics) {\n      diagData.stalenessCheck = {\n        staleSymbolCount: stalenessResult.violations.length,\n        staleSymbols: stalenessResult.violations.map((v) => v.symbolPath),\n      };\n    }\n\n    stepNum++;\n  }\n\n  const needsBaselineStep = !rawResults && !existsSync('smoke-results-raw.json');\n  if (needsBaselineStep) {\n    console.log(`\\n${separator}`);\n    console.log(`Step ${stepNum}: Generating spec-only baseline (no raw baseline found)`);\n    console.log(separator);\n    stepNum++;\n  }\n\n  console.log(`\\n${separator}`);\n  console.log(`Step ${stepNum}: Smoke test + diff`);\n  console.log(separator);\n\n  const smokeResult = runSmokeCheck({\n    spec,\n    lang,\n    output,\n    rawResults,\n    smokeConfig,\n    smokeRunner,\n  });\n\n  if (diagnostics) {\n    diagData.smokeCheck = {\n      passed: smokeResult.passed,\n      ...(smokeResult.findingsCount !== undefined ? { findingsCount: smokeResult.findingsCount } : {}),\n      ...(smokeResult.compileErrors ? { compileErrors: true } : {}),\n    };\n    writeDiagnostics(diagData);\n    console.log('Diagnostics written to verify-diagnostics.json');\n  }\n\n  if (!smokeResult.passed) {\n    if (smokeResult.compileErrors) {\n      throw new CommandError('\\nSDK compile errors — read smoke-compile-errors.json for details', '', 2);\n    }\n\n    throw new CommandError(\n      '\\nSmoke test findings — read smoke-diff-findings.json for details\\n\\n' +\n        `Remediation guide (by finding type):\n  \"HTTP method differs\"               → fix ${lang} emitter resources.ts (in emitter project)\n  \"Request path structure differs\"     → fix ${lang} emitter resources.ts (in emitter project)\n  \"Query parameters differ\"            → fix ${lang} emitter resources.ts (in emitter project)\n  \"Request body key sets differ\"       → fix ${lang} emitter models.ts or resources.ts (in emitter project)\n  \"Skipped in SDK\"                     → fix smoke/sdk-${lang}.ts (in emitter project)\n  \"Missing from SDK\"                   → fix smoke/sdk-${lang}.ts (in emitter project)`,\n      '',\n      1,\n    );\n  }\n\n  console.log('\\nVerify: all checks passed');\n}\n","import { toCamelCase } from '../../utils/naming.js';\n\nexport function oagenScripts(lang: string): Record<string, string> {\n  return {\n    [`sdk:generate:${lang}`]: `oagen generate --lang ${lang} --output ./sdk --namespace my-api --spec open-api-spec.yaml --api-surface ./sdk-${lang}-surface.json --target ../your-${lang}-sdk`,\n    [`sdk:diff:${lang}`]: `oagen diff --old ./sdk/spec-snapshot.yaml --new open-api-spec.yaml --lang ${lang} --output ./sdk --target ../your-${lang}-sdk --api-surface ./sdk-${lang}-surface.json`,\n    [`sdk:verify:${lang}`]: `oagen verify --lang ${lang} --output ./sdk --spec open-api-spec.yaml --api-surface ./sdk-${lang}-surface.json`,\n    [`sdk:extract:${lang}`]: `oagen extract --lang ${lang} --sdk-path ../your-${lang}-sdk --output ./sdk-${lang}-surface.json`,\n  };\n}\n\nexport function packageJson(lang: string): string {\n  return JSON.stringify(\n    {\n      name: `custom-oagen-emitters`,\n      version: '0.0.1',\n      type: 'module',\n      main: 'dist/index.js',\n      types: 'dist/index.d.ts',\n      exports: {\n        '.': { types: './dist/index.d.ts', import: './dist/index.js' },\n        './plugin': { types: './dist/plugin.d.ts', import: './dist/plugin.js' },\n      },\n      scripts: {\n        build: 'tsup',\n        test: 'vitest run',\n        'test:watch': 'vitest',\n        typecheck: 'tsc --noEmit',\n        ...oagenScripts(lang),\n      },\n      dependencies: {\n        '@workos/oagen': '^0.0.1',\n      },\n      devDependencies: {\n        tsup: '^8.4.0',\n        tsx: '^4.19.0',\n        vitest: '^3.0.0',\n        '@types/node': '^25.3.3',\n      },\n    },\n    null,\n    2,\n  );\n}\n\nexport function tsconfigJson(): string {\n  return JSON.stringify(\n    {\n      compilerOptions: {\n        target: 'ES2022',\n        module: 'ESNext',\n        moduleResolution: 'bundler',\n        strict: true,\n        declaration: true,\n        declarationMap: true,\n        sourceMap: true,\n        outDir: 'dist',\n        rootDir: '.',\n        esModuleInterop: true,\n        skipLibCheck: true,\n        forceConsistentCasingInFileNames: true,\n        resolveJsonModule: true,\n        isolatedModules: true,\n      },\n      include: ['src', 'test'],\n      exclude: ['node_modules', 'dist'],\n    },\n    null,\n    2,\n  );\n}\n\nexport function vitestConfig(): string {\n  return `import { defineConfig } from 'vitest/config';\nexport default defineConfig({\n  test: { globals: true, include: ['test/**/*.test.ts'] },\n});\n`;\n}\n\nexport function tsupConfig(): string {\n  return `import { defineConfig } from 'tsup';\nexport default defineConfig({\n  entry: { index: 'src/index.ts', plugin: 'src/plugin.ts' },\n  format: ['esm'],\n  dts: true,\n  clean: true,\n  target: 'node20',\n});\n`;\n}\n\nexport function oagenConfig(): string {\n  return `import type { OagenConfig } from '@workos/oagen';\nimport { plugin } from './src/plugin.js';\n\n// Minimal config for local emitter development.\n// The canonical consumer config lives in the consumer project's oagen.config.ts,\n// which imports the plugin bundle from this package.\nconst config: OagenConfig = {\n  ...plugin,\n};\nexport default config;\n`;\n}\n\nexport function srcPlugin(lang: string): string {\n  const varName = `${toCamelCase(lang)}Emitter`;\n  return `import type { OagenConfig } from '@workos/oagen';\nimport { ${varName} } from './${lang}/index.js';\n\nexport const plugin: Pick<OagenConfig, 'emitters' | 'extractors' | 'smokeRunners'> = {\n  emitters: [${varName}],\n  extractors: [],\n  smokeRunners: {},\n};\n`;\n}\n\nexport function srcIndex(lang: string): string {\n  const varName = `${toCamelCase(lang)}Emitter`;\n  return `export { ${varName} } from './${lang}/index.js';\nexport { plugin } from './plugin.js';\n`;\n}\n\nexport function gitignore(): string {\n  return `node_modules/\ndist/\n.env\nsdk-*-surface.json\nsmoke-*.json\nsdk/\n`;\n}\n\nexport function stubEmitter(lang: string): string {\n  const varName = `${toCamelCase(lang)}Emitter`;\n  return `import type { Emitter, EmitterContext, GeneratedFile, ApiSpec, Model, Enum, Service } from '@workos/oagen';\n\nexport const ${varName}: Emitter = {\n  language: '${lang}',\n\n  generateModels(_models: Model[], _ctx: EmitterContext): GeneratedFile[] {\n    return [];\n  },\n\n  generateEnums(_enums: Enum[], _ctx: EmitterContext): GeneratedFile[] {\n    return [];\n  },\n\n  generateResources(_services: Service[], _ctx: EmitterContext): GeneratedFile[] {\n    return [];\n  },\n\n  generateClient(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n    return [];\n  },\n\n  generateErrors(_ctx: EmitterContext): GeneratedFile[] {\n    return [];\n  },\n\n  generateTypeSignatures(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n    return [];\n  },\n\n  generateTests(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n    return [];\n  },\n\n  buildOperationsMap(_spec: ApiSpec, _ctx: EmitterContext) {\n    return {};\n  },\n\n  fileHeader(): string {\n    return '// Auto-generated by oagen. Do not edit.';\n  },\n};\n`;\n}\n","import { resolve, relative } from 'node:path';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';\nimport {\n  packageJson,\n  tsconfigJson,\n  vitestConfig,\n  tsupConfig,\n  oagenConfig,\n  srcPlugin,\n  srcIndex,\n  gitignore,\n  stubEmitter,\n} from './templates/init.js';\n\nexport async function initCommand(opts: { lang: string; project?: string }): Promise<void> {\n  const projectDir = resolve(opts.project ?? '.');\n  const lang = opts.lang;\n\n  if (existsSync(resolve(projectDir, 'oagen.config.ts'))) {\n    throw new Error('Project already initialized — oagen.config.ts exists');\n  }\n\n  // Create directories\n  const dirs = [`src/${lang}`, 'test', 'smoke', 'docs/sdk-architecture'];\n  for (const dir of dirs) {\n    mkdirSync(resolve(projectDir, dir), { recursive: true });\n  }\n\n  // Write template files\n  const files: Array<[string, string]> = [\n    ['tsconfig.json', tsconfigJson()],\n    ['vitest.config.ts', vitestConfig()],\n    ['tsup.config.ts', tsupConfig()],\n    ['oagen.config.ts', oagenConfig()],\n    ['src/plugin.ts', srcPlugin(lang)],\n    ['src/index.ts', srcIndex(lang)],\n    [`src/${lang}/index.ts`, stubEmitter(lang)],\n  ];\n\n  // Handle package.json specially - merge if it exists\n  const packageJsonPath = resolve(projectDir, 'package.json');\n  let packageJsonContent: string;\n  if (existsSync(packageJsonPath)) {\n    const existingContent = readFileSync(packageJsonPath, 'utf-8');\n    const existingPkg = JSON.parse(existingContent);\n    const newPkg = JSON.parse(packageJson(lang));\n    // Merge: existing values take precedence, but append new scripts/devDependencies\n    existingPkg.scripts = { ...newPkg.scripts, ...existingPkg.scripts };\n    existingPkg.devDependencies = { ...newPkg.devDependencies, ...existingPkg.devDependencies };\n    existingPkg.dependencies = { ...newPkg.dependencies, ...existingPkg.dependencies };\n    // Only set exports if not already defined\n    if (!existingPkg.exports) {\n      existingPkg.exports = newPkg.exports;\n    }\n    // Only set type if not already defined\n    if (!existingPkg.type) {\n      existingPkg.type = newPkg.type;\n    }\n    // Only set main if not already defined\n    if (!existingPkg.main) {\n      existingPkg.main = newPkg.main;\n    }\n    // Only set types if not already defined\n    if (!existingPkg.types) {\n      existingPkg.types = newPkg.types;\n    }\n    packageJsonContent = JSON.stringify(existingPkg, null, 2);\n  } else {\n    packageJsonContent = packageJson(lang);\n  }\n\n  // Handle .gitignore specially - append if it exists\n  const gitignorePath = resolve(projectDir, '.gitignore');\n  let gitignoreContent: string;\n  if (existsSync(gitignorePath)) {\n    const existingContent = readFileSync(gitignorePath, 'utf-8');\n    const newContent = gitignore();\n    // Append new entries that don't already exist (filter out comments and empty lines for comparison)\n    const existingLines = new Set(\n      existingContent\n        .split('\\n')\n        .map((line) => line.trim())\n        .filter((line) => line && !line.startsWith('#')),\n    );\n    const newLines = newContent.split('\\n').filter((line) => {\n      const trimmed = line.trim();\n      return trimmed && !existingLines.has(trimmed);\n    });\n    gitignoreContent = existingContent + (existingContent.endsWith('\\n') ? '' : '\\n') + newLines.join('\\n');\n  } else {\n    gitignoreContent = gitignore();\n  }\n\n  for (const [filePath, content] of files) {\n    const fullPath = resolve(projectDir, filePath);\n    mkdirSync(resolve(fullPath, '..'), { recursive: true });\n    writeFileSync(fullPath, content, 'utf-8');\n  }\n\n  // Write package.json\n  writeFileSync(packageJsonPath, packageJsonContent, 'utf-8');\n\n  // Write .gitignore\n  writeFileSync(gitignorePath, gitignoreContent, 'utf-8');\n\n  // Print summary\n  console.log(`Initialized emitter project for \"${lang}\" in ${relative(process.cwd(), projectDir) || '.'}`);\n  console.log('');\n  console.log('Created:');\n  for (const [filePath] of files) {\n    console.log(`  ${filePath}`);\n  }\n  for (const dir of dirs) {\n    console.log(`  ${dir}/`);\n  }\n\n  // Print next steps\n  console.log('');\n  console.log('Next steps:');\n  console.log(`  - Implement your emitter in src/${lang}/index.ts`);\n  console.log('  - npm run sdk:generate -- --spec <path-to-spec> --namespace <Name>');\n  console.log('  - npm run sdk:verify -- --spec <path-to-spec>');\n}\n","import { parseSpec, type OpenApiDocument } from '../parser/parse.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\nimport type { OperationHint, ResolvedOperation } from '../ir/operation-hints.js';\n\nexport async function resolveCommand(opts: {\n  spec: string;\n  format?: 'table' | 'json';\n  operationIdTransform?: (id: string) => string;\n  schemaNameTransform?: (name: string) => string;\n  transformSpec?: (spec: OpenApiDocument) => OpenApiDocument;\n  docUrl?: string;\n  operationHints?: Record<string, OperationHint>;\n  mountRules?: Record<string, string>;\n}): Promise<void> {\n  let ir = await parseSpec(opts.spec, {\n    operationIdTransform: opts.operationIdTransform,\n    schemaNameTransform: opts.schemaNameTransform,\n    transformSpec: opts.transformSpec,\n  });\n  if (opts.docUrl) {\n    ir = expandDocUrls(ir, opts.docUrl);\n  }\n\n  const resolved = resolveOperations(ir, opts.operationHints, opts.mountRules);\n  const format = opts.format ?? 'table';\n\n  if (format === 'json') {\n    const output = resolved.map(toJsonRow);\n    console.log(JSON.stringify(output, null, 2));\n    return;\n  }\n\n  // Table format\n  printTable(resolved, opts.operationHints);\n}\n\ninterface JsonRow {\n  service: string;\n  method: string;\n  path: string;\n  derivedName: string;\n  hintApplied: boolean;\n  mountOn: string;\n  wrappers?: string[];\n}\n\nfunction toJsonRow(r: ResolvedOperation): JsonRow {\n  return {\n    service: r.service.name,\n    method: r.operation.httpMethod.toUpperCase(),\n    path: r.operation.path,\n    derivedName: r.methodName,\n    hintApplied: r.methodName !== r.operation.name,\n    mountOn: r.mountOn,\n    wrappers: r.wrappers?.map((w) => w.name),\n  };\n}\n\nfunction printTable(resolved: ResolvedOperation[], hints?: Record<string, OperationHint>): void {\n  const hintMap = hints ?? {};\n\n  // Header\n  console.log('| Service | Method | Path | Resolved Name | Hint | Mount On |');\n  console.log('|---|---|---|---|---|---|');\n\n  const unhinted: ResolvedOperation[] = [];\n\n  for (const r of resolved) {\n    const key = `${r.operation.httpMethod.toUpperCase()} ${r.operation.path}`;\n    const hasHint = key in hintMap;\n    const hintMarker = hasHint ? 'yes' : '';\n    const mountChanged = r.mountOn !== r.service.name;\n    const mountCol = mountChanged ? r.mountOn : '';\n\n    console.log(\n      `| ${r.service.name} | ${r.operation.httpMethod.toUpperCase()} | ${r.operation.path} | \\`${r.methodName}\\` | ${hintMarker} | ${mountCol} |`,\n    );\n\n    // Track wrappers\n    if (r.wrappers) {\n      for (const w of r.wrappers) {\n        console.log(`|  | | | \\`${w.name}\\` (wrapper) | yes | ${mountCol} |`);\n      }\n    }\n\n    if (!hasHint && !mountChanged) {\n      unhinted.push(r);\n    }\n  }\n\n  console.log('');\n  console.log(\n    `Total: ${resolved.length} operations, ${resolved.length - unhinted.length} with hints/mounts, ${unhinted.length} algorithm-only`,\n  );\n}\n","import * as path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport type { Emitter } from '../engine/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Extractor } from '../compat/types.js';\nimport type { CompatConfig } from '../compat/config.js';\nimport type { OpenApiDocument } from '../parser/parse.js';\nimport { ConfigLoadError } from '../errors.js';\n\nexport interface OagenConfig {\n  emitters?: Emitter[];\n  extractors?: Extractor[];\n  /** Compatibility verification policy. See docs/core/compatibility-policy.md. */\n  compat?: CompatConfig;\n  /** Path to the emitter project (where skills scaffold new emitters, tests, smoke runners). */\n  emitterProject?: string;\n  /** Map from language key to custom smoke runner script path. */\n  smokeRunners?: Record<string, string>;\n  /**\n   * Custom transform for operation IDs. When provided, replaces the default\n   * camelCase pass-through. Receives the raw operationId string; return the\n   * desired operation name (no additional conversion is applied).\n   *\n   */\n  operationIdTransform?: (id: string) => string;\n  /**\n   * Custom transform for schema (model/enum) names. Applied after the built-in\n   * cleanSchemaName normalization. Receives the cleaned PascalCase name; return\n   * the desired name. Collisions are detected automatically -- if a transform\n   * would produce a duplicate name, the original is kept.\n   */\n  schemaNameTransform?: (name: string) => string;\n  /** Base URL for documentation links. When set, relative paths in descriptions\n   *  (e.g. `/reference/users/user`) are expanded to full URLs. */\n  docUrl?: string;\n  /**\n   * Pre-IR overlay applied to the bundled OpenAPI document before any IR\n   * extraction. Use this when the upstream spec can't be changed but a quirk\n   * in it would otherwise emit a breaking SDK change — e.g. rewriting a\n   * path's response `$ref` back to its prior schema, merging the new fields\n   * onto the prior schema, and dropping the fork schema.\n   *\n   * The function may mutate the document in place and return it, or return a\n   * new object. Runs once, after `$ref` bundling and before schema/operation\n   * extraction. See `docs/advanced/transform-spec.md` for examples.\n   */\n  transformSpec?: (spec: OpenApiDocument) => OpenApiDocument;\n  /**\n   * Per-operation overrides keyed by \"METHOD /path\" (e.g. \"POST /auth/token\").\n   * Used by the operation resolver to override derived method names, mount\n   * targets, and to split union-body operations into typed wrappers.\n   */\n  operationHints?: Record<string, OperationHint>;\n  /**\n   * Service-level mount rules: maps an IR service name to a target\n   * service/namespace (PascalCase). All operations in the source service\n   * are mounted on the target. Per-operation mountOn in operationHints\n   * takes priority.\n   */\n  mountRules?: Record<string, string>;\n  /**\n   * Pin specific models to a specific IR service for placement, overriding the\n   * default \"first service to reference the model wins\" assignment.\n   *\n   * Maps IR model name → IR service name (both PascalCase). Useful when a model\n   * is shared across services and the natural ordering would place it in a\n   * service that's wrong for the public API.\n   *\n   * Both names must exist in the parsed spec; unknown names throw at generation\n   * time so typos fail loud. Note that keys are post-cleanSchemaName /\n   * post-schemaNameTransform model names (e.g. `User`, not `UserlandUser`).\n   */\n  modelHints?: Record<string, string>;\n  /**\n   * Domain-facing field-name overrides, keyed by IR model name then wire field\n   * name: `{ Connection: { connection_type: 'type' } }`. Sets `Field.domainName`\n   * so every emitter can expose the field under a friendlier domain name while\n   * keeping the wire key unchanged.\n   */\n  fieldHints?: Record<string, Record<string, string>>;\n  /**\n   * Language-specific emitter options. The CLI passes only the active\n   * language's option bag to that emitter.\n   */\n  emitterOptions?: Record<string, Record<string, unknown>>;\n}\n\nconst CONFIG_NAMES = ['oagen.config.ts', 'oagen.config.js', 'oagen.config.mjs'];\n\n/**\n * Load an oagen config file.\n *\n * @param configPath - Explicit path to a config file. When provided, only that\n *   file is attempted (no fallback search).\n * @param cwd - Directory to search when `configPath` is omitted. Defaults to\n *   `process.cwd()`. The loader tries each name in `CONFIG_NAMES` in order.\n */\nexport async function loadConfig(configPath?: string, cwd: string = process.cwd()): Promise<OagenConfig | null> {\n  if (configPath) {\n    const resolved = path.resolve(cwd, configPath);\n    if (!existsSync(resolved)) {\n      throw new ConfigLoadError(`Config file not found: ${resolved}`, 'Check that the path passed to --config exists.');\n    }\n    try {\n      const mod = await import(pathToFileURL(resolved).href);\n      return (mod.default ?? mod) as OagenConfig;\n    } catch (err) {\n      const message = err instanceof Error ? err.message : String(err);\n      throw new ConfigLoadError(\n        `Failed to load ${resolved}: ${message}`,\n        resolved.endsWith('.ts')\n          ? 'TypeScript config files require tsx or ts-node. Use .mjs instead, or run via `npx tsx`.'\n          : 'Check that the config file is valid ESM.',\n      );\n    }\n  }\n\n  for (const name of CONFIG_NAMES) {\n    const resolved = path.resolve(cwd, name);\n    if (!existsSync(resolved)) continue;\n    try {\n      const mod = await import(pathToFileURL(resolved).href);\n      const config = (mod.default ?? mod) as OagenConfig;\n      return config;\n    } catch (err) {\n      const message = err instanceof Error ? err.message : String(err);\n      throw new ConfigLoadError(\n        `Failed to load ${name}: ${message}`,\n        name.endsWith('.ts')\n          ? 'TypeScript config files require tsx or ts-node. Use .mjs instead, or run via `npx tsx`.'\n          : 'Check that the config file is valid ESM.',\n      );\n    }\n  }\n  return null;\n}\n","import { registerEmitter } from '../engine/registry.js';\nimport { registerExtractor } from '../compat/extractor-registry.js';\nimport type { OagenConfig } from './config-loader.js';\n\nexport function applyConfig(config: OagenConfig): void {\n  for (const emitter of config.emitters ?? []) {\n    registerEmitter(emitter);\n  }\n  for (const extractor of config.extractors ?? []) {\n    registerExtractor(extractor);\n  }\n}\n","import 'dotenv/config';\nimport { Command } from 'commander';\nimport { parseCommand } from './parse.js';\nimport { generateCommand } from './generate.js';\nimport { diffCommand } from './diff.js';\nimport { extractCommand } from './extract.js';\nimport { compatExtractCommand } from './compat-extract.js';\nimport { compatDiffCommand } from './compat-diff.js';\nimport { compatSummaryCommand } from './compat-summary.js';\nimport { verifyCommand } from './verify.js';\nimport { initCommand } from './init.js';\nimport { resolveCommand } from './resolve.js';\nimport { loadConfig } from './config-loader.js';\nimport { applyConfig } from './plugin-loader.js';\nimport { CommandError } from '../errors.js';\n\nfunction handleError(err: unknown): never {\n  const exitCode = err instanceof CommandError ? err.exitCode : 1;\n  const message = err instanceof Error ? err.message : String(err);\n  if (message) console.error(message);\n  process.exit(exitCode);\n}\n\n// Parse --config before Commander runs so we can load the right config file\n// at startup. Commander's parseOptions isn't available before .parse(), so we\n// do a simple argv scan.\nconst configArgIdx = process.argv.indexOf('--config');\nconst explicitConfigPath = configArgIdx !== -1 ? process.argv[configArgIdx + 1] : undefined;\n\n// Load config at startup so user-provided emitters/extractors are registered\n// before any command runs. loadConfig is async (dynamic import), so we use\n// top-level await.\nlet configSmokeRunners: Record<string, string> | undefined;\nlet configOperationIdTransform: ((id: string) => string) | undefined;\nlet configSchemaNameTransform: ((name: string) => string) | undefined;\nlet configTransformSpec:\n  | ((spec: import('../parser/parse.js').OpenApiDocument) => import('../parser/parse.js').OpenApiDocument)\n  | undefined;\nlet configDocUrl: string | undefined;\nlet configOperationHints: Record<string, import('../ir/operation-hints.js').OperationHint> | undefined;\nlet configMountRules: Record<string, string> | undefined;\nlet configModelHints: Record<string, string> | undefined;\nlet configFieldHints: Record<string, Record<string, string>> | undefined;\nlet configEmitterOptions: Record<string, Record<string, unknown>> | undefined;\nlet configCompat: import('../compat/config.js').CompatConfig | undefined;\ntry {\n  const config = await loadConfig(explicitConfigPath);\n  if (config) {\n    applyConfig(config);\n    configSmokeRunners = config.smokeRunners;\n    configOperationIdTransform = config.operationIdTransform;\n    configSchemaNameTransform = config.schemaNameTransform;\n    configTransformSpec = config.transformSpec;\n    configDocUrl = config.docUrl;\n    configOperationHints = config.operationHints;\n    configMountRules = config.mountRules;\n    configModelHints = config.modelHints;\n    configFieldHints = config.fieldHints;\n    configEmitterOptions = config.emitterOptions;\n    configCompat = config.compat;\n  }\n} catch (err) {\n  handleError(err);\n}\n\nconst program = new Command()\n  .name('oagen')\n  .description('Framework for building OpenAPI SDK emitters')\n  .version('0.0.1')\n  .option('--config <path>', 'Path to oagen config file (default: oagen.config.ts in cwd)');\n\nprogram\n  .command('parse')\n  .description('Parse an OpenAPI spec and output IR as JSON')\n  .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n  .action((opts) => {\n    opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n    if (!opts.spec) {\n      console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n      process.exit(1);\n    }\n    return parseCommand({\n      ...opts,\n      operationIdTransform: configOperationIdTransform,\n      schemaNameTransform: configSchemaNameTransform,\n      transformSpec: configTransformSpec,\n    });\n  });\n\nprogram\n  .command('generate')\n  .description('Run a registered emitter against an OpenAPI spec')\n  .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n  .requiredOption('--lang <language>', 'Target language')\n  .requiredOption('--output <dir>', 'Output directory')\n  .option('--target <dir>', 'Target directory for live SDK integration (merged output)')\n  .option('--namespace <name>', 'SDK namespace/package name')\n  .option('--dry-run', 'Preview files without writing')\n  .option('--api-surface <path>', 'Path to baseline API surface JSON for compat overlay')\n  .option('--no-compat-check', 'Skip compat overlay even if --api-surface is provided')\n  .option('--no-prune', 'Skip deletion of stale files recorded in the previous .oagen-manifest.json')\n  .option('--services <list>', 'Comma-separated post-mount service names to generate (default: all)')\n  .action((opts) => {\n    opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n    if (!opts.spec) {\n      console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n      process.exit(1);\n    }\n    generateCommand({\n      ...opts,\n      operationIdTransform: configOperationIdTransform,\n      schemaNameTransform: configSchemaNameTransform,\n      transformSpec: configTransformSpec,\n      docUrl: configDocUrl,\n      operationHints: configOperationHints,\n      mountRules: configMountRules,\n      modelHints: configModelHints,\n      fieldHints: configFieldHints,\n      emitterOptions: configEmitterOptions?.[opts.lang],\n    }).catch(handleError);\n  });\n\nprogram\n  .command('diff')\n  .description('Compare two OpenAPI specs and output a diff report')\n  .requiredOption('--old <path>', 'Path to old spec')\n  .requiredOption('--new <path>', 'Path to new spec')\n  .action((opts) => {\n    diffCommand({\n      ...opts,\n      operationIdTransform: configOperationIdTransform,\n      schemaNameTransform: configSchemaNameTransform,\n      transformSpec: configTransformSpec,\n      docUrl: configDocUrl,\n    }).catch(handleError);\n  });\n\nprogram\n  .command('extract')\n  .description('Extract public API surface from a live SDK')\n  .requiredOption('--sdk-path <path>', 'Path to the live SDK')\n  .requiredOption('--lang <language>', 'Target language')\n  .option('--output <path>', 'Output file path')\n  .action((opts) => {\n    opts.output ??= `sdk-${opts.lang}-surface.json`;\n    extractCommand(opts).catch(handleError);\n  });\n\nprogram\n  .command('compat-extract')\n  .description('Extract a compat snapshot from a live SDK and write .oagen-compat-snapshot.json')\n  .requiredOption('--sdk-path <path>', 'Path to the live SDK')\n  .requiredOption('--lang <language>', 'Target language')\n  .requiredOption('--output <dir>', 'Directory to write .oagen-compat-snapshot.json into')\n  .option('--spec <path>', 'Path to OpenAPI spec — enriches symbols with operationId, route, and specSha')\n  .action((opts) => {\n    opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n    compatExtractCommand({\n      ...opts,\n      schemaNameTransform: configSchemaNameTransform,\n      transformSpec: configTransformSpec,\n    }).catch(handleError);\n  });\n\nprogram\n  .command('compat-diff')\n  .description('Diff two compat snapshot files and produce a classified change report')\n  .requiredOption('--baseline <path>', 'Path to the baseline compat snapshot JSON')\n  .requiredOption('--candidate <path>', 'Path to the candidate compat snapshot JSON')\n  .option('--output <path>', 'Write machine-readable report to this path')\n  .option('--fail-on <level>', 'Fail threshold: none, breaking, or soft-risk', 'breaking')\n  .option('--explain', 'Include provenance explanations in output')\n  .action((opts) => {\n    compatDiffCommand(opts).catch(handleError);\n  });\n\nprogram\n  .command('compat-summary')\n  .description('Format compat report(s) as a markdown PR comment')\n  .requiredOption('--report <path...>', 'Path(s) to compat report JSON(s) — pass multiple for cross-language rollup')\n  .option('--output <path>', 'Write markdown to this file instead of stdout')\n  .action((opts) => {\n    compatSummaryCommand(opts).catch(handleError);\n  });\n\nprogram\n  .command('verify')\n  .description('Run smoke tests (and optional compat check) against an already-generated SDK')\n  .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n  .requiredOption('--lang <language>', 'Target language')\n  .requiredOption('--output <dir>', 'Path to the generated SDK')\n  .option('--api-surface <path>', 'Baseline API surface JSON — enables compat verification')\n  .option('--raw-results <path>', 'Path to an existing smoke baseline file to diff against')\n  .option('--smoke-config <path>', 'Path to smoke config JSON for skip lists and service mappings')\n  .option('--smoke-runner <path>', 'Path to a custom smoke runner script (overrides built-in sdk-test.ts)')\n  .option(\n    '--scope <mode>',\n    'Compat scope: \"full\" compares all baseline symbols, \"spec-only\" compares only symbols derivable from the OpenAPI spec (default: spec-only when --spec is provided)',\n  )\n  .option('--old-spec <path>', 'Previous OpenAPI spec — enables staleness detection for removed/renamed symbols')\n  .option('--namespace <name>', 'SDK namespace/package name (used by retry loop for regeneration)')\n  .option('--diagnostics', 'Output verify-diagnostics.json with structured violation breakdown')\n  .option('--max-retries <n>', 'Max retry iterations for self-correcting overlay loop (default: 3)', '3')\n  .option('--compat-report <path>', 'Write machine-readable compat report to this path')\n  .option('--compat-fail-on <level>', 'Fail threshold: none, breaking, or soft-risk')\n  .option('--compat-baseline <path>', 'Path to baseline compatibility snapshot')\n  .option('--compat-explain', 'Include provenance explanations in compat output')\n  .action((opts) => {\n    opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n    // --spec is only required when we need to generate a baseline (no --raw-results\n    // and no existing smoke-results-raw.json). Defer the check to verifyCommand.\n    // CLI --smoke-runner takes precedence, then per-language smokeRunners map from config\n    opts.smokeRunner ??= configSmokeRunners?.[opts.lang];\n    verifyCommand({\n      ...opts,\n      maxRetries: parseInt(opts.maxRetries, 10),\n      operationIdTransform: configOperationIdTransform,\n      schemaNameTransform: configSchemaNameTransform,\n      transformSpec: configTransformSpec,\n      compatConfig: configCompat,\n      compatReport: opts.compatReport,\n      compatFailOn: opts.compatFailOn,\n      compatBaseline: opts.compatBaseline,\n      compatExplain: opts.compatExplain,\n    }).catch(handleError);\n  });\n\nprogram\n  .command('resolve')\n  .description('Resolve operation names from spec and output a review table')\n  .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n  .option('--format <format>', 'Output format: table or json', 'table')\n  .action((opts) => {\n    opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n    if (!opts.spec) {\n      console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n      process.exit(1);\n    }\n    resolveCommand({\n      ...opts,\n      operationIdTransform: configOperationIdTransform,\n      schemaNameTransform: configSchemaNameTransform,\n      transformSpec: configTransformSpec,\n      docUrl: configDocUrl,\n      operationHints: configOperationHints,\n      mountRules: configMountRules,\n    }).catch(handleError);\n  });\n\nprogram\n  .command('init')\n  .description('Scaffold a new emitter project')\n  .requiredOption('--lang <language>', 'Target language')\n  .option('--project <dir>', 'Project directory', '.')\n  .action((opts) => {\n    initCommand(opts).catch(handleError);\n  });\n\nprogram.parse();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqLA,SAAgB,qBAAkC;AAChD,QAAO;EACL,OAAO;GACL,sBAAsB;IAAC;IAAK;IAAK;IAAK;IAAK;IAAI;GAC/C,YAAY;GACZ,wBAAwB;GACxB,gBAAgB;GAChB,SAAS;IACP,cAAc;IACd,YAAY;IACZ,UAAU;IACV,cAAc;IACf;GACF;EACD,QAAQ;GACN,eAAe;IACb,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACN;GACD,iBAAiB;GACjB,iBAAiB;GAClB;EACD,WAAW;GACT,kBAAkB;GAClB,YAAY;GACZ,iBAAiB;GAClB;EACD,YAAY,EACV,iBAAiB,GAClB;EACD,aAAa;GACX,YAAY;GACZ,qBAAqB;GACtB;EACD,SAAS;GACP,SAAS;GACT,QAAQ;IACN;IACA;IACA;IACA;IACA;IACA;IACD;GACF;EACD,WAAW;GACT,uBAAuB;GACvB,uBAAuB;GACvB,cAAc;GACd,gBAAgB;IACd;KAAE,QAAQ;KAAe,WAAW;KAAc;IAClD;KAAE,QAAQ;KAAgB,WAAW;KAAU;IAC/C;KAAE,QAAQ;KAAgB,WAAW;KAAS;IAC9C;KAAE,QAAQ;KAAmB,WAAW;KAAY;IACpD;KAAE,QAAQ;KAAiB,WAAW;KAAW;IAClD;GACF;EACD,cAAc,EACZ,YAAY;GACV;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,EACF;EACD,SAAS,EACP,uBAAuB,IACxB;EACF;;;;;;;;;;;AC5PH,IAAa,aAAb,cAAgC,MAAM;CACpC;CAEA,YAAY,SAAiB,MAAc;EACzC,MAAM,cAAc,OAAO,GAAG,QAAQ,UAAU,SAAS;AACzD,QAAM,YAAY;AAClB,OAAK,OAAO;AACZ,OAAK,OAAO;;;;AAKhB,IAAa,eAAb,cAAkC,WAAW;CAC3C;CAEA,YAAY,SAAiB,MAAc,UAAkB;AAC3D,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;AACZ,OAAK,WAAW;;;;AAKpB,IAAa,iBAAb,cAAoC,WAAW;CAC7C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAKhB,IAAa,cAAb,cAAiC,WAAW;CAC1C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAKhB,IAAa,kBAAb,cAAqC,YAAY;CAC/C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAqBhB,IAAa,gBAAb,cAAmC,WAAW;CAC5C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;;AC/DhB,eAAsB,kBAAkB,UAAwC;CAC9E,MAAM,eAAe,QAAQ,SAAS;CAOtC,MAAM,SAAS,MAAM,eAAe;EAClC,UANe,uBADD,MAAM,SAAS,cAAc,QAAQ,EACJ,cAAc,aAAa,CAAC,KAAK;EAOhF,QALa,MAAM,aAAa,EAAE,CAAC;EAMnC,OAAO;EACP,qBANe,IAAI,cAAc;EAOjC,aAAa;EACd,CAAC;AAEF,KAAI,OAAO,SAAS,MAAM,MAAM,EAAE,aAAa,QAAQ,CAKrD,OAAM,IAAI,eACR,yBALa,OAAO,SACnB,QAAQ,MAAM,EAAE,aAAa,QAAQ,CACrC,KAAK,MAAM,EAAE,QAAQ,CACrB,KAAK,KAAK,IAGX,8BAA8B,aAAa,oEAAoE,SAAS,wBACzH;AAGH,QAAO;EACL,QAAQ,OAAO,OAAO;EACtB,UAAU;EACX;;;;;;;;;;;;;;;;;ACoNH,SAAgB,YAAY,GAAiB;CAE3C,MAAM,OAAQ,EAAc;CAC5B,MAAM,sBAAM,IAAI,MACd,4BAA4B,KAAK,oGAClC;AACD,KAAI,OAAO;AACX,OAAM;;;;;;;;AASR,SAAgB,YACd,KACA,SAMM;AACN,SAAQ,IAAI,MAAZ;EACE,KAAK;AACH,WAAQ,QAAQ,IAAI;AACpB;EACF,KAAK;AACH,WAAQ,OAAO,IAAI;AACnB;EACF,KAAK;AACH,eAAY,IAAI,OAAO,QAAQ;AAC/B;EACF,KAAK;AACH,eAAY,IAAI,OAAO,QAAQ;AAC/B;EACF,KAAK;AACH,QAAK,MAAM,KAAK,IAAI,SAAU,aAAY,GAAG,QAAQ;AACrD;EACF,KAAK;AACH,OAAI,IAAI,QAAS,aAAY,IAAI,SAAS,QAAQ;AAClD,eAAY,IAAI,WAAW,QAAQ;AACnC;EACF,KAAK;AACH,WAAQ,UAAU,IAAI;AACtB;EACF,KAAK;AACH,WAAQ,YAAY,IAAI;AACxB;EACF,QACE,aAAY,IAAI;;;;;;;;;;AC5StB,MAAM,iBAAuC,CAC3C,CAAC;CAAC;CAAK;CAAK;CAAI,EAAE,MAAM,EACxB,CAAC,CAAC,KAAK,OAAO,EAAE,QAAQ,CACzB;;;;AAKD,SAAS,mBAAmB,OAA2B;CACrD,MAAM,SAAmB,EAAE;CAC3B,IAAI,IAAI;AACR,QAAO,IAAI,MAAM,QAAQ;EACvB,IAAI,UAAU;AACd,OAAK,MAAM,CAAC,SAAS,cAAc,eACjC,KAAI,IAAI,QAAQ,UAAU,MAAM;OACd,QAAQ,OAAO,GAAG,MAAM,MAAM,IAAI,GAAG,aAAa,KAAK,EAAE,EAC5D;AACX,WAAO,KAAK,UAAU;AACtB,SAAK,QAAQ;AACb,cAAU;AACV;;;AAIN,MAAI,CAAC,SAAS;AACZ,UAAO,KAAK,MAAM,GAAG;AACrB;;;AAGJ,QAAO;;;;;;;;;;AAWT,SAAgB,WAAW,GAAqB;AAC9C,KAAI,CAAC,EAAG,QAAO,EAAE;AAWjB,QAAO,mBATO,EACX,QAAQ,uBAAuB,IAAI,CACnC,QAAQ,mBAAmB,SAAS,CACpC,QAAQ,yBAAyB,SAAS,CAC1C,QAAQ,mBAAmB,SAAS,CACpC,QAAQ,mBAAmB,SAAS,CACpC,MAAM,cAAc,CACpB,QAAQ,MAAM,EAAE,SAAS,EAAE,CAEE;;AAGlC,MAAa,cAAc,IAAI,IAAI;CAAC;CAAO;CAAO;CAAQ;CAAQ;CAAO;CAAQ;CAAM,CAAC;AAExF,SAAgB,aAAa,GAAW,UAAgC;CACtE,MAAM,SAAS,WAAW,IAAI,IAAI,CAAC,GAAG,aAAa,GAAG,SAAS,CAAC,GAAG;AACnE,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM;EACV,MAAM,QAAQ,EAAE,aAAa;AAC7B,MAAI,OAAO,IAAI,MAAM,CAAE,QAAO;AAE9B,MAAI,UAAU,QAAS,QAAO;AAC9B,SAAO,EAAE,OAAO,EAAE,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE,CAAC,aAAa;GAC3D,CACD,KAAK,GAAG;;AAGb,SAAgB,YAAY,GAAW,UAAgC;CACrE,MAAM,SAAS,WAAW,IAAI,IAAI,CAAC,GAAG,aAAa,GAAG,SAAS,CAAC,GAAG;CACnE,MAAM,QAAQ,WAAW,EAAE;AAC3B,KAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAO,MACJ,KAAK,GAAG,MAAM;AACb,MAAI,MAAM,EAAG,QAAO,EAAE,aAAa;EACnC,MAAM,QAAQ,EAAE,aAAa;AAC7B,MAAI,OAAO,IAAI,MAAM,CAAE,QAAO;AAC9B,MAAI,UAAU,QAAS,QAAO;AAC9B,SAAO,EAAE,OAAO,EAAE,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE,CAAC,aAAa;GAC3D,CACD,KAAK,GAAG;;AAGb,SAAgB,YAAY,GAAmB;AAC7C,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM,EAAE,aAAa,CAAC,CAC3B,KAAK,IAAI;;AASd,SAAgB,iBAAiB,GAAmB;AAClD,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM,EAAE,aAAa,CAAC,CAC3B,KAAK,IAAI;;AAGd,MAAM,mBAAmB,CAAC,aAAa;AAEvC,SAAgB,qBAAqB,MAAsB;AACzD,MAAK,MAAM,UAAU,iBACnB,KAAI,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,OAAO,OAChD,QAAO,KAAK,MAAM,GAAG,CAAC,OAAO,OAAO;AAGxC,QAAO;;AAGT,SAAgB,qBAAqB,MAAsB;AACzD,QAAO,KAAK,QAAQ,aAAa,GAAG,CAAC,QAAQ,eAAe,GAAG;;;;;;AAOjE,SAAgB,qBAAqB,MAAsB;AACzD,QAAO,KACJ,QAAQ,aAAa,GAAG,CACxB,QAAQ,iBAAiB,GAAG,CAC5B,QAAQ,iBAAiB,GAAG,CAC5B,QAAQ,gBAAgB,GAAG;;;AAIhC,MAAM,qBAAqB,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;AASF,SAAgBA,cAAY,MAAsB;AAChD,KAAI,mBAAmB,IAAI,KAAK,CAAE,QAAO;AACzC,KAAI,KAAK,SAAS,MAAM,IAAI,KAAK,SAAS,EACxC,QAAO,KAAK,MAAM,GAAG,GAAG,GAAG;AAE7B,KAAI,KAAK,SAAS,MAAM,IAAI,KAAK,SAAS,EAExC,QAAO,KAAK,MAAM,GAAG,GAAG;AAE1B,KAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,EAC9D,QAAO,KAAK,MAAM,GAAG,GAAG;AAE1B,QAAO;;;;;;;;;;;;AAaT,SAAgB,qBAAqB,MAAsB;AACzD,QAAO,KAAK,QAAQ,eAAe,KAAK;;AAG1C,SAAgB,gBAAgB,MAAsB;CACpD,IAAI,SAAS,qBAAqB,qBAAqB,KAAK,CAAC;AAC7D,UAAS,qBAAqB,OAAO;CAGrC,MAAM,QAAQ,OAAO,MAAM,iBAAiB;AAC5C,KAAI,OAAO;EACT,MAAM,WAAW,MAAM;EACvB,MAAM,WAAWA,cAAY,SAAS;AACtC,MAAI,aAAa,SACf,UAAS,WAAW,OAAO,MAAM,SAAS,OAAO;;AAIrD,QAAO;;;;;;;;;;AC/LT,SAAgB,uBAAuB,UAAkB,YAA6B;AACpF,KAAI,CAAC,WAAY,QAAO;CAIxB,MAAM,cAAc,qBAAqB,WAAW;AACpD,KAAI,SAAS,WAAW,YAAY,CAAE,QAAO;CAG7C,MAAM,gBAAgB,SAAS,MAAM,uBAAuB;AAC5D,KAAI,eAAe;EACjB,MAAM,GAAG,QAAQ,gBAAgB;AAEjC,SAAO,GAAG,cAAc,SADPC,cAAY,aAAa;;AAG5C,QAAO,GAAG,cAAc;;;;;;;AAQ1B,SAAgB,+BAA+B,SAA4D;AACzG,KAAI,CAAC,QAAS,QAAO,EAAE;CAEvB,MAAM,eAAwB,EAAE;AAEhC,MAAK,MAAM,CAAC,YAAY,WAAW,OAAO,QAAQ,QAAQ,CAExD,mCAAkC,QAAQ,cADvB,kBAAkB,WAAW,CACmB;AAGrE,QAAO;;AAGT,SAAS,kCAAkC,QAAsB,SAAkB,YAA2B;CAC5G,MAAM,aAAa,OAAO,cAAc,EAAE;CAC1C,MAAM,eAAe,OAAO,SAAS,EAAE;AAEvC,MAAK,MAAM,OAAO,aAChB,KAAI,IAAI,WACN,mCAAkC,KAAK,SAAS,WAAW;AAI/D,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,WAAW,EAAE;AACjE,MAAI,CAAC,YAAa;AAElB,MAAI,YAAY,eAAe,YAAY,SAAS,YAAY,CAAC,YAAY,OAAO;GAElF,MAAM,YAAY,uBADD,aAAa,UAAU,EACW,WAAW;AAC9D,WAAQ,KAAK,iBAAiB,WAAW,YAAY,CAAC;AACtD,qCAAkC,aAAa,SAAS,UAAU;;AAIpE,MAAI,YAAY,SAAS,WAAW,YAAY,OAAO;GACrD,MAAM,QAAQ,YAAY;AAC1B,OAAI,MAAM,eAAe,MAAM,SAAS,YAAY,CAAC,MAAM,OAAO;IAEhE,MAAM,YAAY,uBADD,aAAa,UAAU,EACW,WAAW;AAC9D,YAAQ,KAAK,iBAAiB,WAAW,MAAM,CAAC;AAChD,sCAAkC,OAAO,SAAS,UAAU;;;AAYhE,MAAI,YAAY,OAAO;GACrB,MAAM,uBAAuB,YAAY,MAAM,QAC5C,MAAM,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,YAAY,CAAC,EAAE,MAC9D;AACD,OAAI,qBAAqB,SAAS,GAAG;IAEnC,MAAM,YAAY,uBADD,aAAa,UAAU,EACW,WAAW;IAC9D,MAAM,gBAAgB,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,KAAK,CAAC;IACzD,MAAM,iBAAiB,+BAA+B,qBAAqB;IAC3E,MAAM,eAAyB,EAAE;AACjC,SAAK,MAAM,WAAW,sBAAsB;KAC1C,MAAM,cAAc,iBAAiB,SAAS,WAAW,cAAc,eAAe;AACtF,kBAAa,KAAK,YAAY;AAC9B,SAAI,CAAC,cAAc,IAAI,YAAY,EAAE;AACnC,oBAAc,IAAI,YAAY;AAC9B,cAAQ,KAAK,iBAAiB,aAAa,QAAQ,CAAC;AACpD,wCAAkC,SAAS,SAAS,YAAY;;;;;;;;;;AAW5E,SAAS,+BAA+B,UAAyC;AAC/E,KAAI,SAAS,SAAS,EAAG,QAAO;CAChC,MAAM,aAAa,OAAO,KAAK,SAAS,IAAI,cAAc,EAAE,CAAC;AAC7D,MAAK,MAAM,YAAY,YAAY;EACjC,MAAM,SAAS,SAAS,KAAK,MAAM,gBAAgB,EAAE,aAAa,UAAU,CAAC;AAC7E,MAAI,OAAO,MAAM,MAAM,MAAM,KAAK,CAAE;AACpC,MAAI,IAAI,IAAI,OAAO,CAAC,SAAS,OAAO,OAAQ;AAC5C,SAAO;;AAET,QAAO;;AAGT,SAAS,gBAAgB,MAA+C;AACtE,KAAI,CAAC,KAAM,QAAO;AAClB,KAAI,OAAO,KAAK,UAAU,SAAU,QAAO,KAAK;AAChD,KAAI,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,KAAK,WAAW,KAAK,OAAO,KAAK,KAAK,OAAO,SAChF,QAAO,KAAK,KAAK;AAEnB,QAAO;;;;;;;AAQT,SAAS,iBACP,SACA,YACA,gBACA,uBACQ;AACR,KAAI,eAAe,WAAW,EAAG,QAAO;AACxC,KAAI,uBAAuB;EACzB,MAAM,aAAa,gBAAgB,QAAQ,aAAa,uBAAuB;AAC/E,MAAI,YAAY;GACd,MAAM,SAAS,aAAa,WAAW;AACvC,OAAI,QAAQ;IACV,MAAM,YAAY,WAAW,WAAW,OAAO,GAAG,aAAa,GAAG,SAAS;AAE3E,QAAI,EADc,cAAc,cAAc,eAAe,SAAS,UAAU,EAChE,QAAO;;;;AAI7B,QAAO,GAAG,aAAa,eAAe,SAAS;;AAGjD,SAAS,iBAAiB,MAAc,QAA6B;CACnE,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;CAClD,MAAM,SAAkB,EAAE;AAE1B,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,OAAO,cAAc,EAAE,CAAC,EAAE;AAC9E,MAAI,CAAC,YAAa;AAClB,SAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,YAAY,CAAC;;AAG9E,QAAO;EAAE;EAAM,aAAa,OAAO;EAAa;EAAQ;;;;;;;;AC1J1D,IAAI,4BAA+D;;;;;;;;AASnE,IAAI,wCAAqC,IAAI,KAAK;;AAGlD,SAAgB,kBAAkB,SAAyB;CACzD,IAAI,OAAO,gBAAgB,aAAa,QAAQ,CAAC;AACjD,KAAI,0BAA2B,QAAO,0BAA0B,KAAK;AACrE,QAAO;;AAqCT,SAAgB,eACd,SACA,SACkB;CAClB,MAAM,QAAgB,EAAE;AAExB,KAAI,CAAC,QAAS,QAAO;EAAE,QAAQ,EAAE;EAAE;EAAO;AAG1C,KAAI,SAAS,qBAAqB;EAChC,MAAM,YAAY,QAAQ;EAE1B,MAAM,eADW,OAAO,KAAK,QAAQ,CACP,KAAK,MAAM,gBAAgB,aAAa,EAAE,CAAC,CAAC;EAC1E,MAAM,yCAAyB,IAAI,KAAuB;AAC1D,OAAK,MAAM,WAAW,cAAc;GAClC,MAAM,cAAc,UAAU,QAAQ;AACtC,OAAI,CAAC,uBAAuB,IAAI,YAAY,CAAE,wBAAuB,IAAI,aAAa,EAAE,CAAC;AACzF,0BAAuB,IAAI,YAAY,CAAE,KAAK,QAAQ;;EAExD,MAAM,oCAAoB,IAAI,KAAa;AAC3C,OAAK,MAAM,GAAG,cAAc,uBAC1B,KAAI,UAAU,SAAS,EACrB,MAAK,MAAM,KAAK,UAAW,mBAAkB,IAAI,EAAE;AAGvD,+BAA6B,SAAkB,kBAAkB,IAAI,KAAK,GAAG,OAAO,UAAU,KAAK;OAEnG,6BAA4B;AAQ9B,yCAAwB,IAAI,KAAK;AACjC,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,QAAQ,CAClD,KAAI,OAAO,KAAM,uBAAsB,IAAI,kBAAkB,KAAK,CAAC;CAGrE,MAAM,oCAAoB,IAAI,KAAoB;AAElD,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,QAAQ,EAAE;EACpD,MAAM,aAAa,kBAAkB,KAAK;AAE1C,MAAI,OAAO,KACT,OAAM,KAAK,YAAY,YAAY,OAAO,CAAC;OACtC;GACL,MAAM,QAAQ,aAAa,YAAY,QAAQ,QAAQ;GACvD,MAAM,WAAW,kBAAkB,IAAI,WAAW;AAClD,OAAI;QAEE,MAAM,OAAO,SAAS,SAAS,OAAO,OACxC,mBAAkB,IAAI,YAAY,MAAM;SAG1C,mBAAkB,IAAI,YAAY,MAAM;AAG1C,QAAK,MAAM,eAAe,uCAAuC,QAAQ,WAAW,EAAE;IACpF,MAAM,iBAAiB,kBAAkB,IAAI,YAAY,KAAK;AAC9D,QAAI;SACE,YAAY,OAAO,SAAS,eAAe,OAAO,OACpD,mBAAkB,IAAI,YAAY,MAAM,YAAY;UAGtD,mBAAkB,IAAI,YAAY,MAAM,YAAY;;;;CAM5D,MAAM,SAAS,CAAC,GAAG,kBAAkB,QAAQ,CAAC;CAI9C,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;CACrD,MAAM,cAAuB,CAAC,GAAG,OAAO;AACxC,QAAO,YAAY,SAAS,GAAG;EAC7B,MAAM,QAAQ,YAAY,KAAK;AAC/B,OAAK,MAAM,SAAS,MAAM,OACxB,2BAA0B,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,WAAW,EAAE,EAAE,QAAQ,YAAY,YAAY;;AAKjH,MAAK,MAAM,SAAS,OAClB,oBAAmB,MAAM,QAAQ,MAAM;AAOzC,QAAO;EAAE;EAAQ;EAAO;;;AAI1B,SAAgB,2BAAiC;AAC/C,6BAA4B;AAC5B,yCAAwB,IAAI,KAAK;;;;;;AAOnC,SAAgB,yBAAyB,KAAc,OAAe,MAAyB;AAC7F,aAAY,KAAK,EACf,OAAO,MAAM;AACX,MAAI,EAAE,UAAU,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE;AACjC,QAAK,IAAI,EAAE,KAAK;AAChB,SAAM,KAAK;IACT,MAAM,EAAE;IACR,QAAQ,EAAE,OAAO,KAAK,OAAO;KAC3B,MAAM,iBAAiB,OAAO,EAAE,CAAC;KACjC,OAAO;KACP,aAAa,KAAA;KACd,EAAE;IACJ,CAAC;;IAGP,CAAC;;;;;;AAOJ,SAAS,mBAAmB,QAAiB,OAAqB;CAChE,MAAM,OAAO,IAAI,IAAI,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC;AAC9C,MAAK,MAAM,SAAS,OAClB,0BAAyB,MAAM,MAAM,OAAO,KAAK;;;;;;;;AAUrD,SAAS,0BACP,KACA,WACA,iBACA,SACA,QACA,YACA,OACM;AACN,aAAY,KAAK,EACf,QAAQ,aAAa;AACnB,MAAI,WAAW,IAAI,SAAS,KAAK,CAAE;AAInC,MADoB,OAAO,KAAK,QAAQ,CAAC,MAAM,MAAM,kBAAkB,EAAE,KAAK,SAAS,KAAK,CAC3E;EAIjB,MAAM,eAAe,iBAAiB,iBAAiB,QAAQ;AAC/D,MAAI,CAAC,aAAc;EAEnB,MAAM,cAAc,sBAAsB,WAAW,cAAc,QAAQ;AAC3E,MAAI,CAAC,YAAa;EAGlB,MAAM,YAAY,oBAAoB,SAAS,MAAM,YAAY;AACjE,OAAK,MAAM,KAAK,UACd,KAAI,CAAC,WAAW,IAAI,EAAE,KAAK,EAAE;AAC3B,UAAO,KAAK,EAAE;AACd,cAAW,IAAI,EAAE,KAAK;AACtB,SAAM,KAAK,EAAE;;IAIpB,CAAC;;;AAIJ,SAAS,iBAAiB,YAAoB,SAA4D;AACxG,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,QAAQ,CAC1C,KAAI,kBAAkB,EAAE,KAAK,WAAY,QAAO;AAElD,QAAO;;;AAIT,SAAS,sBACP,WACA,cACA,SACqB;AACrB,KAAI,aAAa,aAAa,WAC5B,QAAO,aAAa,WAAW;AAEjC,KAAI,aAAa,MACf,MAAK,MAAM,OAAO,aAAa,OAAO;EACpC,IAAI,WAAW;AACf,MAAI,IAAI,MAAM;GACZ,MAAM,WAAW,IAAI,KAAK,MAAM,IAAI;GACpC,MAAM,UAAU,SAAS,SAAS,SAAS;AAC3C,OAAI,WAAW,QAAQ,SAAU,YAAW,QAAQ;;AAEtD,MAAI,SAAS,aAAa,WACxB,QAAO,SAAS,WAAW;;AAMjC,MAAK,MAAM,WAAW,CAAC,GAAI,aAAa,SAAS,EAAE,EAAG,GAAI,aAAa,SAAS,EAAE,CAAE,EAAE;EACpF,IAAI,WAAW;AACf,MAAI,QAAQ,MAAM;GAChB,MAAM,WAAW,QAAQ,KAAK,MAAM,IAAI;GACxC,MAAM,UAAU,SAAS,SAAS,SAAS;AAC3C,OAAI,WAAW,QAAQ,SAAU,YAAW,QAAQ;;AAEtD,MAAI,SAAS,aAAa,WACxB,QAAO,SAAS,WAAW;;AAG/B,QAAO;;;AAIT,SAAS,oBAAoB,MAAc,QAA+B;AAExE,KAAI,OAAO,OAAO;EAChB,MAAM,SAAkB,EAAE;EAS1B,MAAM,2BAA2B,+BAHY,OAAO,MAAM,QACvD,MAAM,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,YAAY,CAAC,EAAE,MAC9D,CACoF;AAErF,OAAK,MAAM,WAAW,OAAO,OAAO;AAClC,OAAI,QAAQ,KAAM;AAClB,OAAI,QAAQ,eAAe,QAAQ,SAAS,YAAY,CAAC,QAAQ,OAAO;IACtE,MAAM,cAAc,IAAI,IAAI,QAAQ,YAAY,EAAE,CAAC;IACnD,MAAM,SAAkB,EAAE;AAC1B,SAAK,MAAM,CAAC,IAAI,OAAO,OAAO,QAAQ,QAAQ,WAAW,EAAE;AACzD,SAAI,CAAC,GAAI;AACT,YAAO,KAAK,qBAAqB,IAAI,IAAI,MAAM,YAAY,CAAC;;IAE9D,MAAM,cAAc,iBAAiB,SAAS,MAAM,QAAQ,yBAAyB;AACrF,WAAO,KAAK;KAAE,MAAM;KAAa,aAAa,QAAQ;KAAa;KAAQ,CAAC;;;AAGhF,SAAO;;AAIT,KAAI,OAAO,eAAe,OAAO,SAAS,YAAY,CAAC,OAAO,OAAO;EACnE,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;EAClD,MAAM,SAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,IAAI,OAAO,OAAO,QAAQ,OAAO,WAAW,EAAE;AACxD,OAAI,CAAC,GAAI;AACT,UAAO,KAAK,qBAAqB,IAAI,IAAI,MAAM,YAAY,CAAC;;AAE9D,SAAO,CAAC;GAAE;GAAM,aAAa,OAAO;GAAa;GAAQ,CAAC;;AAI5D,KAAI,OAAO,SAAS,WAAW,OAAO,OAAO,YAAY;EACvD,MAAM,cAAc,IAAI,IAAI,OAAO,MAAM,YAAY,EAAE,CAAC;EACxD,MAAM,SAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,IAAI,OAAO,OAAO,QAAQ,OAAO,MAAM,WAAW,EAAE;AAC9D,OAAI,CAAC,GAAI;AACT,UAAO,KAAK,qBAAqB,IAAI,IAAI,MAAM,YAAY,CAAC;;AAE9D,SAAO,CAAC;GAAE;GAAM,aAAa,OAAO,MAAM;GAAa;GAAQ,CAAC;;AAGlE,QAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BX,SAAS,iBACP,SACA,YACA,gBACA,eACQ;AAGR,KAAI,eAAe,WAAW,EAAG,QAAO;AAExC,KAAI,eAAe;EACjB,MAAM,aAAa,sBAAsB,SAAS,cAAc,SAAS;AACzE,MAAI,YAAY;GACd,MAAM,SAAS,aAAa,WAAW;AACvC,OAAI,QAAQ;IACV,MAAM,YAAY,WAAW,WAAW,OAAO,GAAG,aAAa,GAAG,SAAS;AAE3E,QAAI,EADc,cAAc,cAAc,eAAe,MAAM,MAAM,EAAE,SAAS,UAAU,EAC9E,QAAO;;;;AAI7B,QAAO,GAAG,aAAa,eAAe,SAAS;;;;;;;;;;;;;AAcjD,SAAS,+BAA+B,UAAuD;AAC7F,KAAI,SAAS,SAAS,EAAG,QAAO;CAChC,MAAM,aAAa,OAAO,KAAK,SAAS,IAAI,cAAc,EAAE,CAAC;AAC7D,MAAK,MAAM,YAAY,YAAY;EACjC,MAAM,SAAS,SAAS,KAAK,MAAM,sBAAsB,GAAG,SAAS,CAAC;AACtE,MAAI,OAAO,MAAM,MAAM,MAAM,KAAK,CAAE;AACpC,MAAI,IAAI,IAAI,OAAO,CAAC,SAAS,OAAO,OAAQ;AAC5C,SAAO,EAAE,UAAU,UAAU;;AAE/B,QAAO;;;AAIT,SAAgB,qBACd,WACA,aACA,aACA,aACO;AACP,QAAO;EACL,MAAM;EACN,MAAM,gBAAgB,aAAa,WAAW,YAAY;EAC1D,UAAU,YAAY,IAAI,UAAU;EACpC,aAAa,YAAY;EACzB,UAAU,YAAY,YAAY,KAAA;EAClC,WAAW,YAAY,aAAa,KAAA;EACpC,YAAY,YAAY,cAAc,KAAA;EACtC,SAAS,YAAY;EACrB,SAAS,YAAY;EACtB;;;;;;;;AASH,SAAS,2BAA2B,UAA2C;AAC7E,KAAI,SAAS,WAAW,EAAG,QAAO;CAClC,MAAM,SAAmB,EAAE;AAC3B,MAAK,MAAM,KAAK,UAAU;AAExB,MAAI,OAAO,EAAE,UAAU,UAAU;AAC/B,UAAO,KAAK,EAAE,MAAM;AACpB;;AAEF,MAAI,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,WAAW,KAAK,OAAO,EAAE,KAAK,OAAO,UAAU;AACjF,UAAO,KAAK,EAAE,KAAK,GAAG;AACtB;;AAEF,SAAO;;AAET,QAAO;;;AAIT,SAAS,sBACP,QACA,aACA,iBACS;CACT,MAAM,WAAW,aAAa,eAAe,cAAc;CAC3D,MAAM,cAAc,kBAAkB,qBAAqB,gBAAgB,GAAG,KAAA;CAC9E,MAAM,gBAAgB,eAAe,CAAC,SAAS,WAAW,YAAY,GAAG,GAAG,cAAc,aAAa;AAKvG,QAAO;EAAE,MAAM;EAAQ,MADL,4BAA4B,0BAA0B,cAAc,GAAG;EACjD;EAAQ;;;;;;;;;;;;;;;AAgBlD,SAAS,iCACP,UAC8D;AAC9D,KAAI,SAAS,SAAS,EAAG,QAAO;CAGhC,IAAI,oBAAmC;CACvC,MAAM,aAAa,OAAO,KAAK,SAAS,IAAI,cAAc,EAAE,CAAC;AAC7D,MAAK,MAAM,YAAY,WACrB,KAAI,SAAS,OAAO,MAAM,sBAAsB,GAAG,SAAS,KAAK,KAAK,EAAE;AACtE,sBAAoB;AACpB;;AAIJ,KAAI,CAAC,kBAAmB,QAAO;CAE/B,MAAM,UAAkC,EAAE;AAC1C,MAAK,MAAM,KAAK,UAAU;EACxB,MAAM,QAAQ,sBAAsB,GAAG,kBAAkB;AACzD,MAAI,UAAU,KAAM,QAAO;EAE3B,MAAM,cAAc,wBAAwB,EAAE;AAC9C,MAAI,CAAC,YAAa,QAAO;AACzB,UAAQ,SAAS;;AAGnB,QAAO;EAAE,UAAU;EAAmB;EAAS;;AAGjD,SAAS,sBAAsB,QAAsB,UAAiC;CACpF,MAAM,OAAO,OAAO,aAAa;AACjC,KAAI,CAAC,KAAM,QAAO;AAClB,KAAI,OAAO,KAAK,UAAU,SAAU,QAAO,KAAK;AAChD,KAAI,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,KAAK,WAAW,KAAK,OAAO,KAAK,KAAK,OAAO,SAChF,QAAO,KAAK,KAAK;AAEnB,QAAO;;AAGT,SAAS,wBAAwB,QAAqC;AACpE,KAAI,OAAO,KACT,QAAO,kBAAkB,OAAO,KAAK,QAAQ,6BAA6B,GAAG,CAAC;CAEhF,MAAM,QAAQ,OAAO,OAAO,aAAa,WAAY,OAAO,WAAsB;AAClF,KAAI,MAAO,QAAO,kBAAkB,MAAM;AAC1C,QAAO;;;;;;AAOT,SAAS,+BACP,SACA,eACe;CACf,MAAM,QAAQ,sBAAsB,SAAS,cAAc,SAAS;AACpE,KAAI,UAAU,KAAM,QAAO;AAC3B,QAAO,cAAc,QAAQ,UAAU;;;;;;;;;;;;;;;;;;AAmBzC,SAAS,2BACP,UACA,uBACA,aACA,iBAC+B;AAC/B,KAAI,SAAS,WAAW,KAAK,CAAC,YAAa,QAAO;CAClD,MAAM,uBAAuB,SAAS,QAAQ,MAAM,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,YAAY,CAAC,EAAE,MAAM;AAChH,KAAI,qBAAqB,WAAW,SAAS,OAAQ,QAAO;CAE5D,MAAM,iBAAiB,uBAAuB,aAAa,YAAY,EAAE,gBAAgB;CACzF,MAAM,sBAAsB,EAAE,UAAU,uBAAuB;CAC/D,MAAM,UAAkC,EAAE;CAC1C,MAAM,eAAwB,EAAE;AAChC,MAAK,MAAM,WAAW,sBAAsB;EAC1C,MAAM,aAAa,sBAAsB,SAAS,sBAAsB;AACxE,MAAI,eAAe,KAAM,QAAO;EAChC,MAAM,cAAc,iBAAiB,SAAS,gBAAgB,cAAc,oBAAoB;AAChG,UAAQ,cAAc;AACtB,eAAa,KAAK;GAAE,MAAM;GAAa,QAAQ,EAAE;GAAE,CAAC;;AAEtD,QAAO;;AAGT,SAAS,YAAY,MAAc,QAA4B;CAC7D,MAAM,UAAuB,OAAO,QAAQ,EAAE,EAAE,KAAK,OAAO;EAC1D,MAAM,iBAAiB,OAAO,EAAE,CAAC;EACjC,OAAO,OAAO,MAAM,WAAW,IAAI,OAAO,EAAE;EAC5C,aAAa,KAAA;EACd,EAAE;CAEH,MAAM,aAAa,OAAO;AAM1B,QAAO;EAAE;EAAM;EAAQ,SAJrB,eAAe,KAAA,KAAa,OAAO,MAAM,MAAM,EAAE,UAAU,WAAW,GACjE,aACD,KAAA;EAE+B;;AAEvC,SAAS,aAAa,MAAc,QAAsB,SAA+C;AACvG,KAAI,OAAO,MACT,QAAO,kBAAkB,MAAM,QAAQ,QAAQ;CAGjD,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;CAClD,MAAM,SAAkB,EAAE;AAE1B,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,OAAO,cAAc,EAAE,CAAC,EAAE;AAC9E,MAAI,CAAC,YAAa;AAClB,SAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,YAAY,CAAC;;AAM9E,KAAI,OAAO,WAAW,MAAM,OAAO,SAAS,OAAO,QAAQ;EACzD,MAAM,WAAW,OAAO,SAAS,OAAO,SAAS,EAAE;EACnD,MAAM,gCAAgB,IAAI,KAAa;EACvC,MAAM,iCAAiB,IAAI,KAAa;AACxC,OAAK,MAAM,WAAW,UAAU;AAC9B,OAAI,CAAC,QAAQ,WAAY;AACzB,QAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,QAAQ,WAAW,EAAE;AACzE,QAAI,CAAC,eAAe,eAAe,IAAI,UAAU,CAAE;AACnD,mBAAe,IAAI,UAAU;AAC7B,WAAO,KAAK,qBAAqB,WAAW,aAA6B,MAAM,cAAc,CAAC;;;;AAOpG,KAAI,OAAO,wBAAwB,OAAO,OAAO,yBAAyB,YAAY,OAAO;MAC5E,OAAO,KAAK,OAAO,qBAAqB,CAC5C,SAAS,GAAG;GACrB,MAAM,YAAY,gBAAgB,OAAO,sBAAsC,wBAAwB,KAAK;AAC5G,UAAO,KAAK;IACV,MAAM;IACN,MAAM;KAAE,MAAM;KAAO;KAAW;IAChC,UAAU;IACV,aAAa;IACd,CAAC;;;AAIN,QAAO;EAAE;EAAM,aAAa,OAAO;EAAa;EAAQ;;AAG1D,SAAS,kBAAkB,MAAc,QAAsB,SAA+C;CAC5G,MAAM,SAAkB,EAAE;CAC1B,MAAM,8BAAc,IAAI,KAAa;CACrC,IAAI;AAEJ,MAAK,MAAM,aAAa,OAAO,SAAS,EAAE,EAAE;EAE1C,IAAI,WAAW;AACf,MAAI,UAAU,QAAQ,SAAS;GAC7B,MAAM,WAAW,UAAU,KAAK,MAAM,IAAI;GAC1C,MAAM,UAAU,SAAS,SAAS,SAAS;AAC3C,OAAI,WAAW,QAAQ,SACrB,YAAW,QAAQ;;AAKvB,MAAI,SAAS,OAAO;GAClB,MAAM,SAAS,kBAAkB,MAAM,UAAU,QAAQ;AACzD,QAAK,MAAM,KAAK,OAAO,QAAQ;AAC7B,WAAO,KAAK;KAAE,GAAG;KAAG,UAAU;KAAO,CAAC;AACtC,QAAI,EAAE,SAAU,aAAY,IAAI,EAAE,KAAK;;aAEhC,SAAS,SAAS,SAAS,OAAO;GAC3C,MAAM,WAAW,SAAS,SAAS,SAAS,SAAS,EAAE;GAKvD,MAAM,oBAAoB,gCAAgC,UAAU,KAAK;AACzE,OAAI,kBACF,uBAAsB;QACjB;IAIL,MAAM,gCAAgB,IAAI,KAAa;IACvC,MAAM,iBAAiB,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;AACzD,SAAK,MAAM,WAAW,UAAU;AAC9B,SAAI,CAAC,QAAQ,WAAY;AACzB,UAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,QAAQ,WAAW,EAAE;AACzE,UAAI,CAAC,eAAe,eAAe,IAAI,UAAU,CAAE;AACnD,qBAAe,IAAI,UAAU;AAC7B,aAAO,KAAK,qBAAqB,WAAW,aAA6B,MAAM,cAAc,CAAC;;;;SAO/F;AACL,OAAI,SAAS,SACX,MAAK,MAAM,KAAK,SAAS,SAAU,aAAY,IAAI,EAAE;AAEvD,OAAI,SAAS,YAAY;IAEvB,MAAM,gCAAgB,IAAI,KAAa;AACvC,SAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,SAAS,WAAW,EAAE;AAC1E,SAAI,CAAC,YAAa;AAClB,YAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,cAAc,CAAC;;;;;AAOtF,KAAI,OAAO,SACT,MAAK,MAAM,KAAK,OAAO,SAAU,aAAY,IAAI,EAAE;AAIrD,MAAK,MAAM,KAAK,OACd,GAAE,WAAW,YAAY,IAAI,EAAE,KAAK;AAGtC,QAAO;EACL;EACA,aAAa,OAAO;EACpB;EACA,GAAI,sBAAsB,EAAE,eAAe,qBAAqB,GAAG,EAAE;EACtE;;;;;;;;;;;;AAaH,SAAS,uBAAuB,QAAoD;CAClF,MAAM,QAAsC,EAAE;CAC9C,MAAM,SAAS,MAA0B;AACvC,MAAI,EAAE;QACC,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,EAAE,WAAW,CAC/C,KAAI,EAAE,KAAK,UAAU,EAAG,OAAM,KAAK;;AAGvC,MAAI,EAAE,MACJ,MAAK,MAAM,OAAO,EAAE,MAAO,OAAM,IAAI;;AAKzC,OAAM,OAAO;AACb,QAAO;;AAGT,SAAS,+BAA+B,QAAsB,UAAiC;CAC7F,MAAM,SAAS,sBAAsB,QAAQ,SAAS;AACtD,KAAI,WAAW,KAAM,QAAO;CAC5B,MAAM,YAAY,uBAAuB,OAAO,CAAC;AACjD,KAAI,CAAC,UAAW,QAAO;AACvB,KAAI,OAAO,UAAU,UAAU,SAAU,QAAO,UAAU;AAC1D,KAAI,MAAM,QAAQ,UAAU,KAAK,IAAI,UAAU,KAAK,WAAW,KAAK,OAAO,UAAU,KAAK,OAAO,SAC/F,QAAO,UAAU,KAAK;AAExB,QAAO;;;;;;;;;;;;;;;;AAiBT,SAAS,gCACP,UACA,cAC8D;AAC9D,KAAI,SAAS,SAAS,EAAG,QAAO;CAIhC,MAAM,aAAa,uBAAuB,SAAS,MAAM,EAAE,CAAC;CAC5D,IAAI,oBAAmC;AACvC,MAAK,MAAM,YAAY,OAAO,KAAK,WAAW,CAC5C,KAAI,SAAS,OAAO,MAAM,+BAA+B,GAAG,SAAS,KAAK,KAAK,EAAE;AAC/E,sBAAoB;AACpB;;AAGJ,KAAI,CAAC,kBAAmB,QAAO;CAE/B,MAAM,UAAkC,EAAE;CAC1C,MAAM,iCAAiB,IAAI,KAAa;AACxC,MAAK,MAAM,KAAK,UAAU;EACxB,MAAM,QAAQ,+BAA+B,GAAG,kBAAkB;AAClE,MAAI,UAAU,KAAM,QAAO;EAC3B,MAAM,YAAY,+BAA+B,GAAG,aAAa;AAEjE,MAAI,eAAe,IAAI,UAAU,CAAE,QAAO;AAC1C,iBAAe,IAAI,UAAU;AAC7B,UAAQ,SAAS;;AAGnB,QAAO;EAAE,UAAU;EAAmB;EAAS;;AAGjD,SAAS,uCAAuC,QAAsB,cAA+B;CACnG,MAAM,SAAkB,EAAE;CAC1B,MAAM,4BAAY,IAAI,KAAa;CAQnC,MAAM,iBAA+C,EAAE;CACvD,MAAM,+BAAe,IAAI,KAAa;AACtC,MAAK,MAAM,aAAa,OAAO,SAAS,EAAE,EAAE;AAC1C,MAAI,UAAU,MAAO;EACrB,MAAM,OAAO,UAAU,QAAQ,4BAA4B,UAAU,GAAG;AACxE,MAAI,KAAK;QACF,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,WAAW,CAClD,KAAI,EAAE,KAAK,mBAAmB,EAAG,gBAAe,KAAK;;AAGzD,MAAI,KAAK,SAAU,MAAK,MAAM,KAAK,KAAK,SAAU,cAAa,IAAI,EAAE;;AAGvE,MAAK,MAAM,aAAa,OAAO,SAAS,EAAE,CACxC,MAAK,MAAM,WAAW,UAAU,SAAS,EAAE,EAAE;EAM3C,MAAM,OAAO,4BAA4B,QAAQ;AACjD,MAAI,CAAC,KAAK,cAAe,KAAK,SAAS,KAAA,KAAa,KAAK,SAAS,SAAW;EAK7E,MAAM,mBAAiD,EAAE,GAAG,gBAAgB;AAC5E,OAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,WAAW,CAClD,KAAI,EAAG,kBAAiB,KAAK;EAG/B,MAAM,SAAuB;GAC3B,MAAM;GACN,YAAY;GACZ,UAAU,CAAC,GAJU,IAAI,IAAY,CAAC,GAAG,cAAc,GAAI,KAAK,YAAY,EAAE,CAAE,CAAC,CAIpD;GAC9B;EAED,MAAM,cAAc,+BAA+B,SAAS,aAAa;AACzE,OAAK,MAAM,SAAS,uBAAuB,aAAa,OAAO,EAAE;AAC/D,OAAI,UAAU,IAAI,MAAM,KAAK,CAAE;AAC/B,aAAU,IAAI,MAAM,KAAK;AACzB,UAAO,KAAK,MAAM;;;AAKxB,QAAO;;;;;;;;;AAUT,SAAS,4BAA4B,SAAqC;AACxE,KAAI,CAAC,QAAQ,MAAO,QAAO;CAE3B,MAAM,mBAAiD,EAAE;CACzD,MAAM,iCAAiB,IAAI,KAAa;CACxC,MAAM,eAAiC,EAAE;CAEzC,MAAM,WAAW,MAA0B;AACzC,MAAI,EAAE;QACC,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,EAAE,WAAW,CAC/C,KAAI,EAAE,KAAK,qBAAqB,EAAG,kBAAiB,KAAK;;AAG7D,MAAI,EAAE,SACJ,MAAK,MAAM,KAAK,EAAE,SAAU,gBAAe,IAAI,EAAE;AAEnD,MAAI,EAAE,MACJ,MAAK,MAAM,OAAO,EAAE,MAAO,SAAQ,IAAI;AAEzC,MAAI,EAAE,MAAO,cAAa,KAAK,EAAE,MAAM;;AAEzC,SAAQ,QAAQ;AAOhB,MAAK,MAAM,YAAY,cAAc;EACnC,MAAM,eAAe,SAAS,IAAI,4BAA4B;EAC9D,MAAM,6BAAa,IAAI,KAAa;AACpC,OAAK,MAAM,KAAK,aACd,MAAK,MAAM,KAAK,OAAO,KAAK,EAAE,cAAc,EAAE,CAAC,CAAE,YAAW,IAAI,EAAE;AAEpE,OAAK,MAAM,OAAO,YAAY;GAC5B,MAAM,UAA0B,EAAE;AAClC,QAAK,MAAM,KAAK,cAAc;IAC5B,MAAM,IAAI,EAAE,aAAa;AACzB,QAAI,EAAG,SAAQ,KAAK,EAAE;;GAExB,MAAM,SAAS,2BAA2B,QAAQ;AAClD,OAAI,EAAE,OAAO,kBAAmB,kBAAiB,OAAO;AAGxD,OAFsB,aAAa,OAAO,MAAM,EAAE,cAAc,OAAO,EAAE,WAAW,IAC7C,aAAa,OAAO,OAAO,EAAE,YAAY,EAAE,EAAE,SAAS,IAAI,CAAC,CAC/E,gBAAe,IAAI,IAAI;;;AAI9C,QAAO;EACL,MAAM;EACN,YAAY;EACZ,UAAU,CAAC,GAAG,eAAe;EAC9B;;;;;;;;;AAUH,SAAS,2BAA2B,SAAuC;AACzE,KAAI,QAAQ,WAAW,EAAG,QAAO,EAAE;AACnC,KAAI,QAAQ,WAAW,EAAG,QAAO,QAAQ;AAGzC,KADqB,QAAQ,OAAO,MAAM,EAAE,SAAS,aAAa,OAAO,EAAE,UAAU,UAAU,CAE7F,QAAO;EAAE,MAAM;EAAW,aAAa,QAAQ,GAAG;EAAa;AAGjE,KADuB,QAAQ,OAAO,MAAM,EAAE,SAAS,YAAY,OAAO,EAAE,UAAU,SAAS,EAC3E;EAClB,MAAM,SAAS,QAAQ,KAAK,MAAM,EAAE,MAAgB;AACpD,MAAI,IAAI,IAAI,OAAO,CAAC,SAAS,EAAG,QAAO,QAAQ;AAC/C,SAAO;GAAE,MAAM;GAAU,aAAa,QAAQ,GAAG;GAAa;;AAEhE,QAAO,QAAQ;;AAGjB,SAAS,+BAA+B,QAAsB,cAA8B;CAI1F,MAAM,YAAY,uBAAuB,OAAO;AAChD,KAAI,OAAO,KAAK,UAAU,CAAC,WAAW,EAAG,QAAO;CAEhD,MAAM,aAAa,SAAgC;EACjD,MAAM,QAAQ,UAAU;AACxB,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,MAAM,UAAU,SAAU,QAAO,MAAM;AAClD,MAAI,MAAM,QAAQ,MAAM,KAAK,WAAW,KAAK,OAAO,MAAM,KAAK,OAAO,SACpE,QAAO,MAAM,KAAK;AAEpB,SAAO;;CAGT,IAAI,aAA4B;AAChC,MAAK,MAAM,aAAa;EAAC;EAAS;EAAQ;EAAS,EAAE;AACnD,eAAa,UAAU,UAAU;AACjC,MAAI,WAAY;;AAElB,KAAI,eAAe,KACjB,MAAK,MAAM,QAAQ,OAAO,KAAK,UAAU,EAAE;AACzC,eAAa,UAAU,KAAK;AAC5B,MAAI,WAAY;;AAGpB,KAAI,eAAe,KAAM,QAAO;CAEhC,MAAM,SAAS,aAAa,WAAW;AACvC,KAAI,CAAC,OAAQ,QAAO;AASpB,KADkB,WAAW,WAAW,CAAC,UACxB,EAAG,QAAO;AAC3B,KAAI,WAAW,aAAc,QAAO;AACpC,KAAI,aAAa,WAAW,OAAO,CAAE,QAAO;AAC5C,KAAI,OAAO,SAAS,aAAa,CAAE,QAAO;AAC1C,QAAO,GAAG,eAAe;;AAG3B,SAAS,uBAAuB,MAAc,QAA+B;CAC3E,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;CAClD,MAAM,SAAkB,EAAE;CAC1B,MAAM,aAAa,OAAO,cAAc,EAAE;CAC1C,MAAM,eAAwB,EAAE;AAEhC,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,WAAW,EAAE;AACjE,MAAI,CAAC,YAAa;AAClB,SAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,YAAY,CAAC;AAE5E,MAAI,YAAY,SAAS,YAAY,YAAY,WAC/C,cAAa,KAAK,GAAG,uBAAuB,wBAAwB,MAAM,UAAU,EAAE,YAAY,CAAC;AAGrG,MAAI,YAAY,SAAS,WAAW,YAAY,OAAO,WACrD,cAAa,KAAK,GAAG,uBAAuB,wBAAwB,MAAM,UAAU,EAAE,YAAY,MAAM,CAAC;AAG3G,MAAI,YAAY,OAAO;GACrB,MAAM,mBAA6D,EAAE;GACrE,MAAM,iBAA2B,EAAE;AACnC,QAAK,MAAM,OAAO,YAAY,OAAO;AACnC,QAAI,IAAI,WAAY,QAAO,OAAO,kBAAkB,IAAI,WAAW;AACnE,QAAI,IAAI,SAAU,gBAAe,KAAK,GAAG,IAAI,SAAS;;AAExD,OAAI,OAAO,KAAK,iBAAiB,CAAC,SAAS,EACzC,cAAa,KACX,GAAG,uBAAuB,wBAAwB,MAAM,UAAU,EAAE;IAClE,MAAM;IACN,YAAY;IACZ,UAAU;IACX,CAAC,CACH;;AAIL,MAAI,YAAY,OAAO;GACrB,MAAM,uBAAuB,YAAY,MAAM,QAC5C,MAAM,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,YAAY,CAAC,EAAE,MAC9D;AACD,OAAI,qBAAqB,SAAS,GAAG;IACnC,MAAM,gBAAgB,wBAAwB,MAAM,UAAU;IAC9D,MAAM,aAAa,+BAA+B,qBAAqB;IACvE,MAAM,UAAmB,EAAE;AAC3B,SAAK,MAAM,WAAW,sBAAsB;KAC1C,MAAM,cAAc,iBAAiB,SAAS,eAAe,SAAS,WAAW;AACjF,aAAQ,KAAK;MAAE,MAAM;MAAa,QAAQ,EAAE;MAAE,CAAC;AAC/C,kBAAa,KAAK,GAAG,uBAAuB,aAAa,QAAQ,CAAC;;;;;AAM1E,QAAO,CAAC;EAAE;EAAM,aAAa,OAAO;EAAa;EAAQ,EAAE,GAAG,aAAa;;AAG7E,SAAS,wBAAwB,YAAoB,WAA2B;CAC9E,MAAM,cAAc,aAAa,UAAU;AAC3C,KAAI,YAAY,WAAW,WAAW,CAAE,QAAO;CAG/C,MAAM,YAAY,GADE,qBAAqB,WAAW,GACjB;CACnC,MAAM,QAAQ,UAAU,MAAM,yBAAyB;AACvD,KAAI,SAAS,MAAM,GACjB,QAAO,MAAM,KAAKC,cAAY,MAAM,GAAG;AAEzC,QAAO;;AAGT,SAAgB,gBAAgB,QAAsB,aAAsB,iBAAmC;AAO7G,KAAI,OAAO,MAAM;EACf,MAAM,WAAW,OAAO,KAAK,MAAM,IAAI;EACvC,MAAM,UAAU,SAAS,SAAS,SAAS;EAC3C,MAAM,WAAW,kBAAkB,QAAQ;AAC3C,MAAI,sBAAsB,IAAI,SAAS,CACrC,QAAO;GAAE,MAAM;GAAQ,MAAM;GAAU;AAEzC,SAAO;GAAE,MAAM;GAAS,MAAM;GAAU;;AAI1C,KAAI,MAAM,QAAQ,OAAO,KAAK,EAAE;EAC9B,MAAM,eAAe,OAAO,KAAK,QAAQ,MAAc,MAAM,OAAO;AAEpE,MAAI,aAAa,WAAW,EAC1B,QAAO;GAAE,MAAM;GAAY,OAAO;IAAE,MAAM;IAAa,MAAM;IAAW;GAAE;AAE5E,MAAI,OAAO,KAAK,SAAS,OAAO,IAAI,aAAa,WAAW,EAC1D,QAAO;GACL,MAAM;GACN,OAAO,gBAAgB;IAAE,GAAG;IAAQ,MAAM,aAAa;IAAI,UAAU;IAAO,EAAE,YAAY;GAC3F;AAGH,MAAI,aAAa,SAAS,GAAG;GAE3B,MAAM,MAAe;IAAE,MAAM;IAAS,UADrB,aAAa,KAAK,MAAc,gBAAgB;KAAE,GAAG;KAAQ,MAAM;KAAG,EAAE,YAAY,CAAC;IACtD;AAChD,OAAI,OAAO,KAAK,SAAS,OAAO,CAC9B,QAAO;IAAE,MAAM;IAAY,OAAO;IAAK;AAEzC,UAAO;;;AAKX,KAAI,OAAO,YAAY,OAAO,KAC5B,QAAO;EACL,MAAM;EACN,OAAO,gBAAgB;GAAE,GAAG;GAAQ,UAAU;GAAO,EAAE,YAAY;EACpE;AAMH,KAAI,OAAO,OAAO;EAEhB,MAAM,UAAU,OAAO,MAAM,MAAM,MAAoB,EAAE,KAAK;AAC9D,MAAI,SAAS;AAIX,OADwB,OAAO,MAAM,MAAM,MAAoB,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,UAAU,CAG9G,QAAO;IAAE,MAAM;IAAS,MAAM,uBADb,aAAa,eAAe,eAAe,EACG,gBAAgB;IAAE;AAEnF,UAAO,gBAAgB,SAAS,aAAa,gBAAgB;;AAG/D,MAAI,OAAO,MAAM,WAAW,EAC1B,QAAO,gBAAgB,OAAO,MAAM,IAAI,aAAa,gBAAgB;AAIvE,MADsB,OAAO,MAAM,MAAM,MAAoB,EAAE,WAAW,CAGxE,QAAO;GACL,MAAM;GACN,MAAM,uBAHS,aAAa,eAAe,eAAe,EAGnB,gBAAgB;GACxD;;AAQL,KAAI,OAAO,SAAS,OAAO,OAAO;EAChC,MAAM,kBAAqC,OAAO,QAAQ,UAAU;EACpE,MAAM,cAA8B,OAAO,SAAS,OAAO,SAAS,EAAE;EAGtE,MAAM,cAAc,YAAY,MAC7B,MAAoB,EAAE,SAAS,UAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,WAAW,KAAK,EAAE,KAAK,OAAO,OAC1G;EACD,MAAM,kBAAkB,YAAY,QAAQ,MAAM,MAAM,YAAY;AAEpE,MAAI,eAAe,gBAAgB,WAAW,EAE5C,QAAO;GACL,MAAM;GACN,OAAO,gBAAgB,gBAAgB,IAAI,aAAa,gBAAgB;GACzE;EAQH,MAAM,iBAAiB,2BAA2B,gBAAgB;AAClE,MAAI,mBAAmB,QAAQ,eAAe,UAAU,GAAG;GACzD,MAAM,UAAU,sBAAsB,gBAAgB,aAAa,gBAAgB;AACnF,UAAO,cAAc;IAAE,MAAM;IAAY,OAAO;IAAS,GAAG;;EAoB9D,IAAI;AACJ,MAAI,OAAO,eAAe;GACxB,MAAM,WAAW,OAAO,cAAc;GACtC,MAAM,kBAAkB,OAAO,cAAc,WAAW,EAAE;GAC1D,IAAI,UAAkC,OAAO,YAC3C,OAAO,QAAQ,gBAAgB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,6BAA6B,GAAG,CAAC,CAAC,CACjG;AACD,OAAI,OAAO,KAAK,QAAQ,CAAC,WAAW,GAAG;IACrC,MAAM,gBAAgB,2BAA2B,iBAAiB,UAAU,aAAa,gBAAgB;AACzG,QAAI,cAAe,WAAU;;AAE/B,2BAAwB;IAAE;IAAU;IAAS;aACpC,oBAAoB,SAAS;GACtC,MAAM,YAAY,iCAAiC,gBAAgB;AACnE,OAAI,UACF,yBAAwB;QACnB;IACL,MAAM,aAAa,+BAA+B,gBAAgB;AAClE,QAAI,YAAY;KACd,MAAM,gBAAgB,2BACpB,iBACA,WAAW,UACX,aACA,gBACD;AACD,SAAI,cACF,yBAAwB;MAAE,UAAU,WAAW;MAAU,SAAS;MAAe;;;;EAYzF,MAAM,WAAsB,EAAE;AAC9B,OAAK,MAAM,KAAK,aAAa;AAC3B,OAAI,MAAM,YAAa;GACvB,MAAM,oBACJ,yBAAyB,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,YAAY,CAAC,EAAE,QAC3E,+BAA+B,GAAG,sBAAsB,GACxD;AACN,OAAI,kBACF,UAAS,KAAK;IAAE,MAAM;IAAS,MAAM;IAAmB,CAAC;OAEzD,UAAS,KAAK,gBAAgB,GAAG,aAAa,gBAAgB,CAAC;;EAGnE,MAAM,UAAU,CAAC,CAAC;EAElB,MAAM,QAAiB;GACrB,MAAM;GACN;GACA;GACA,GAAI,wBAAwB,EAAE,eAAe,uBAAuB,GAAG,EAAE;GAC1E;AACD,SAAO,UAAU;GAAE,MAAM;GAAY,OAAO;GAAO,GAAG;;AAIxD,KAAI,OAAO,UAAU,KAAA,GAAW;AAC9B,MAAI,OAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,UAClG,QAAO;GAAE,MAAM;GAAW,OAAO,OAAO;GAAO;AAGjD,MAAI,OAAO,UAAU,KACnB,QAAO;GAAE,MAAM;GAAY,OAAO;IAAE,MAAM;IAAa,MAAM;IAAW;GAAE;AAG5E,MAAI,OAAO,OAAO,UAAU,UAAU;AACpC,OAAI,MAAM,QAAQ,OAAO,MAAM,CAC7B,QAAO;IAAE,MAAM;IAAS,OAAO;KAAE,MAAM;KAAa,MAAM;KAAW;IAAE;AAEzE,UAAO;IAAE,MAAM;IAAO,WAAW;KAAE,MAAM;KAAa,MAAM;KAAW;IAAE;;;AAG7E,KAAI,OAAO,QAAQ,OAAO,KAAK,WAAW,GAAG;EAC3C,MAAM,IAAI,OAAO,KAAK;AACtB,SAAO;GAAE,MAAM;GAAW,OAAO,OAAO,MAAM,WAAW,IAAI,OAAO,EAAE;GAAE;;AAI1E,KAAI,OAAO,MAAM;EACf,MAAM,WAAW,aAAa,eAAe,cAAc;EAG3D,MAAM,cAAc,kBAAkB,qBAAqB,gBAAgB,GAAG,KAAA;EAE9E,MAAM,gBAAgB,eAAe,CAAC,SAAS,WAAW,YAAY,GAAG,GAAG,cAAc,aAAa;AAMvG,SAAO;GACL,MAAM;GACN,MAHgB,4BAA4B,0BAA0B,cAAc,GAAG;GAIvF,QAAQ,OAAO,KAAK,KAAK,MAAO,OAAO,MAAM,WAAW,IAAI,OAAO,EAAE,CAAE;GACxE;;AAIH,KAAI,OAAO,SAAS,WAAW,OAAO,MACpC,QAAO;EACL,MAAM;EACN,OAAO,gBAAgB,OAAO,OAAO,aAAa,gBAAgB;EACnE;AAGH,KAAI,CAAC,OAAO,QAAQ,OAAO,MACzB,QAAO;EACL,MAAM;EACN,OAAO,gBAAgB,OAAO,OAAO,aAAa,gBAAgB;EACnE;AAOH,KAAI,OAAO,SAAS,YAAY,OAAO,WAErC,QAAO;EACL,MAAM;EACN,MAAM,uBAHS,aAAa,eAAe,eAAe,EAGnB,gBAAgB;EACxD;AAIH,KAAI,OAAO,SAAS,YAAY,CAAC,OAAO,YAAY;EAClD,IAAI,YAAqB;GAAE,MAAM;GAAa,MAAM;GAAW;AAC/D,MAAI,OAAO,wBAAwB,OAAO,OAAO,yBAAyB;OAEzD,OAAO,KAAK,OAAO,qBAAqB,CAC5C,SAAS,EAClB,aAAY,gBAAgB,OAAO,sBAAsC,YAAY;aAE9E,OAAO,mBAAmB;GAEnC,MAAM,WAAW,OAAO,OAAO,OAAO,kBAAkB;AACxD,OAAI,SAAS,SAAS,EACpB,aAAY,gBAAgB,SAAS,IAAI,YAAY;;AAGzD,SAAO;GACL,MAAM;GACN;GACD;;CAIH,MAAM,eAA4E;EAChF,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,SAAS;EACV;CAED,MAAM,UAAU,MAAM,QAAQ,OAAO,KAAK,GAAG,OAAO,KAAK,KAAK,OAAO;AACrE,KAAI,WAAW,aAAa,SAC1B,QAAO;EACL,MAAM;EACN,MAAM,aAAa;EACnB,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,QAAQ,GAAG,EAAE;EACnD;AAIH,KAAI,CAAC,OAAO,QAAQ,OAAO,WAEzB,QAAO;EACL,MAAM;EACN,MAAM,uBAHS,aAAa,eAAe,eAAe,EAGnB,gBAAgB;EACxD;AAIH,KACE,CAAC,OAAO,QACR,CAAC,OAAO,QACR,CAAC,OAAO,SACR,CAAC,OAAO,SACR,CAAC,OAAO,SACR,CAAC,OAAO,QACR,CAAC,OAAO,cACR,CAAC,OAAO,MAER,QAAO;EAAE,MAAM;EAAa,MAAM;EAAW;AAI/C,KAAI,YACF,SAAQ,KAAK,sEAAsE,YAAY,GAAG;AAEpG,QAAO;EAAE,MAAM;EAAa,MAAM;EAAW;;;;ACz4C/C,MAAM,gBAAgB;CAAC;CAAU;CAAS;CAAU;CAAkB;CAAiB;CAAc;CAAa;AAElH,MAAM,gBAAgB;CAAC;CAAU;CAAQ;CAAe;CAAO;AAC/D,MAAM,eAAe;CAAC;CAAS;CAAa;CAAY;CAAQ;CAAQ;;;;;;;;;;;AAYxE,SAAgB,iBACd,UACA,aACA,UACuB;CAKvB,MAAM,cAAc,cAAc,KAAK,SAAS,YAAY,MAAM,MAAM,EAAE,SAAS,KAAK,CAAC,CAAC,MACvF,MAAsB,MAAM,KAAA,EAC9B;AAED,KAAI,aAAa;EACf,MAAM,WAAoB,SAAS,SAAS,UAAU,SAAS,QAAQ;AACvE,SAAO;GACL,UAAU;GACV,OAAO,YAAY;GACT;GACV;GACD;;CAIH,MAAM,cAAc,YAAY,MAAM,MAAM,cAAc,SAAS,EAAE,KAAK,CAAC;CAC3E,MAAM,aAAa,YAAY,MAAM,MAAM,aAAa,SAAS,EAAE,KAAK,CAAC;AAEzE,KAAI,eAAe,YAAY;EAC7B,MAAM,WAAoB,SAAS,SAAS,UAAU,SAAS,QAAQ;AACvE,SAAO;GACL,UAAU;GACV,OAAO,YAAY;GACnB,YAAY,WAAW;GACb;GACV;GACD;;AAGH,QAAO;;;;ACrCT,SAAgB,2BAA2B,QAAsB,aAA+C;AAE9G,KAAI,OAAO,KACT,QAAO;EAAE,UAAU,gBAAgB,QAAQ,YAAY;EAAE,cAAc,EAAE;EAAE,aAAa;EAAO;CAIjG,MAAM,WAAW,mBAAmB,OAAO;AAC3C,KAAI,SAAS,WACX,QAAO,oBAAoB,QAAQ,aAAa,SAAS,SAAU;AAIrE,KAAI,wBAAwB,OAAO,CACjC,QAAO,uBAAuB,QAAQ,YAAY;AAIpD,QAAO,sBAAsB,QAAQ,YAAY;;AAQnD,MAAM,mBAAmB,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAW;CAAW;CAAW;CAAU;CAAS;CAAQ,CAAC;AAEhH,MAAM,+BAA+B;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAS,mBAAmB,QAA0C;CAEpE,MAAM,cAA0D,EAAE;AAClE,KAAI,OAAO;OACJ,MAAM,OAAO,OAAO,MACvB,KAAI,IAAI,WAAY,aAAY,KAAK,IAAI,WAAW;;AAGxD,KAAI,OAAO,WACT,aAAY,KAAK,OAAO,WAAW;AAGrC,KAAI,YAAY,WAAW,EAAG,QAAO;EAAE,YAAY;EAAO,UAAU;EAAM;CAG1E,MAAM,cAAwD,EAAE;AAChE,MAAK,MAAM,UAAU,YACnB,QAAO,OAAO,aAAa,OAAO;CAIpC,MAAM,aAAuB,EAAE;CAC/B,MAAM,eAAyB,EAAE;AAEjC,MAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,YAAY,EAAE;AAC3D,MAAI,CAAC,WAAY;AACjB,MAAI,WAAW,SAAS,QACtB,YAAW,KAAK,IAAI;MAEpB,cAAa,KAAK,IAAI;;AAQ1B,KAAI,WAAW,WAAW,KAAK,aAAa,UAAU,GAAG;EACvD,MAAM,gBAAgB,WAAW;EAEjC,MAAM,yBAAyB,aAAa,MAAM,QAChD,6BAA6B,MAAM,YAAY,IAAI,aAAa,CAAC,SAAS,QAAQ,CAAC,CACpF;AAED,MAAI,iBAAiB,IAAI,cAAc,IAAI,uBACzC,QAAO;GAAE,YAAY;GAAM,UAAU;GAAe;AAItD,MAAI,uBACF,QAAO;GAAE,YAAY;GAAM,UAAU;GAAe;;AAIxD,QAAO;EAAE,YAAY;EAAO,UAAU;EAAM;;AAG9C,SAAS,oBAAoB,QAAsB,aAAqB,UAA4C;CAClH,IAAI,cAAuB;EAAE,MAAM;EAAa,MAAM;EAAU;CAChE,MAAM,eAAwB,EAAE;CAGhC,MAAM,cAA0D,EAAE;AAClE,KAAI,OAAO;OACJ,MAAM,OAAO,OAAO,MACvB,KAAI,IAAI,WAAY,aAAY,KAAK,IAAI,WAAW;;AAGxD,KAAI,OAAO,WACT,aAAY,KAAK,OAAO,WAAW;AAGrC,MAAK,MAAM,SAAS,aAAa;EAC/B,MAAM,WAAW,MAAM;AACvB,MAAI,CAAC,SAAU;AAEf,MAAI,SAAS,SAAS,WAAW,SAAS,OAAO;GAC/C,MAAM,QAAQ,SAAS;AACvB,OAAI,MAAM,KACR,eAAc,gBAAgB,OAAO,YAAY;YACxC,MAAM,SAAS,YAAY,MAAM,YAAY;IACtD,MAAM,WAAW,YAAY,QAAQ,aAAa,GAAG,GAAG;AACxD,kBAAc;KAAE,MAAM;KAAS,MAAM;KAAU;AAC/C,iBAAa,KAAK,GAAG,mBAAmB,UAAU,MAAM,CAAC;;;;AAK/D,QAAO;EACL,UAAU;GAAE,MAAM;GAAS,OAAO;GAAa;EAC/C;EACA,aAAa;EACb;EACA,UAAU;EACX;;AAGH,SAAS,0BAA0B,QAAkE;AACnG,KAAI,CAAC,OAAO,WAAY,QAAO;AAI/B,MAAK,MAAM,QADO,CAAC,UAAU,OAAO,EACN;EAC5B,MAAM,QAAQ,OAAO,WAAW;AAChC,MAAI,CAAC,MAAO;AACZ,MAAI,MAAM,UAAU,KAAA,KAAa,OAAO,MAAM,UAAU,SACtD,QAAO;GAAE,UAAU;GAAM,OAAO,MAAM;GAAO;AAE/C,MAAI,MAAM,QAAQ,MAAM,KAAK,WAAW,KAAK,OAAO,MAAM,KAAK,OAAO,SACpE,QAAO;GAAE,UAAU;GAAM,OAAO,MAAM,KAAK;GAAI;;AAKnD,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,OAAO,WAAW,EAAE;AAC7D,MAAI,CAAC,MAAO;AACZ,MAAI,MAAM,UAAU,KAAA,KAAa,OAAO,MAAM,UAAU,SACtD,QAAO;GAAE,UAAU;GAAM,OAAO,MAAM;GAAO;AAE/C,MAAI,MAAM,QAAQ,MAAM,KAAK,WAAW,KAAK,OAAO,MAAM,KAAK,OAAO,SACpE,QAAO;GAAE,UAAU;GAAM,OAAO,MAAM,KAAK;GAAI;;AAInD,QAAO;;AAGT,SAAS,wBAAwB,QAA+B;AAC9D,KAAI,OAAO,SAAS,SAAU,QAAO;AACrC,KAAI,CAAC,OAAO,WAAY,QAAO;CAG/B,IAAI;AACJ,KAAI,OAAO,YAAY,OAAO,SAAS,WAAW,EAChD,cAAa,OAAO,SAAS;MACxB;EACL,MAAM,WAAW,OAAO,KAAK,OAAO,WAAW;AAC/C,MAAI,SAAS,WAAW,EACtB,cAAa,SAAS;;AAG1B,KAAI,CAAC,WAAY,QAAO;CAExB,MAAM,aAAa,OAAO,WAAW;AACrC,KAAI,CAAC,WAAY,QAAO;AAGxB,KAAI,WAAW,SAAS,YAAY,0BAA0B,WAAW,KAAK,KAAM,QAAO;AAG3F,KAAI,WAAW,MACb,QAAO,WAAW,MAAM,MAAM,MAAM,EAAE,SAAS,YAAY,0BAA0B,EAAE,KAAK,KAAK;AAGnG,QAAO;;AAGT,SAAS,uBAAuB,QAAsB,aAA+C;CACnG,MAAM,QAAQ,OAAO;CAErB,MAAM,aAAa,MADA,OAAO,YAAY,OAAO,SAAS,WAAW,IAAI,OAAO,SAAS,KAAK,OAAO,KAAK,MAAM,CAAC;CAE7G,MAAM,eAAwB,EAAE;CAGhC,MAAM,eAAe,YAAY,QAAQ,aAAa,GAAG;AAEzD,KAAI,WAAW,OAAO;EACpB,MAAM,gBAAgB,WAAW,MAAM,MAAM,MAAM,EAAE,SAAS,YAAY,0BAA0B,EAAE,KAAK,KAAK;AAEhH,MAAI,eAAe;GACjB,MAAM,YAAY,gBAAgB,eAAe,aAAa;AAC9D,gBAAa,KAAK,GAAG,mBAAmB,WAAW,cAAc,CAAC;GAElE,MAAM,iBAAiB,WAAW,MAAM,MACrC,MAAM,EAAE,SAAS,UAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,OAAO,CAC9E;GAED,MAAM,WAAoB;IAAE,MAAM;IAAS,MAAM;IAAW;AAC5D,UAAO;IACL,UAAU,iBAAiB;KAAE,MAAM;KAAY,OAAO;KAAU,GAAG;IACnE;IACA,aAAa;IACd;;;CAKL,MAAM,YAAY,gBAAgB,YAAY,aAAa;AAC3D,cAAa,KAAK,GAAG,mBAAmB,WAAW,WAAW,CAAC;AAE/D,QAAO;EACL,UAAU;GAAE,MAAM;GAAS,MAAM;GAAW;EAC5C;EACA,aAAa;EACd;;AAGH,SAAS,sBAAsB,QAAsB,aAA+C;CAClG,MAAM,eAAwB,EAAE;AAGhC,KAAI,OAAO,eAAe,OAAO,SAAS,YAAY,CAAC,OAAO,OAAO;EACnE,MAAM,YAAY,gBAAgB,QAAQ,YAAY;AACtD,eAAa,KAAK,GAAG,mBAAmB,WAAW,OAAO,CAAC;AAC3D,SAAO;GACL,UAAU;IAAE,MAAM;IAAS,MAAM;IAAW;GAC5C;GACA,aAAa;GACd;;AAIH,KAAI,OAAO,OAAO;EAChB,MAAM,mBAA6D,EAAE;EACrE,MAAM,iBAA2B,EAAE;AACnC,OAAK,MAAM,OAAO,OAAO,OAAO;AAC9B,OAAI,IAAI,WACN,QAAO,OAAO,kBAAkB,IAAI,WAAW;AAEjD,OAAI,IAAI,SACN,gBAAe,KAAK,GAAG,IAAI,SAAS;;AAGxC,MAAI,OAAO,KAAK,iBAAiB,CAAC,SAAS,GAAG;GAC5C,MAAM,SAAuB;IAAE,MAAM;IAAU,YAAY;IAAkB,UAAU;IAAgB;GACvG,MAAM,YAAY,gBAAgB,QAAQ,YAAY;AACtD,gBAAa,KAAK,GAAG,mBAAmB,WAAW,OAAO,CAAC;AAC3D,UAAO;IACL,UAAU;KAAE,MAAM;KAAS,MAAM;KAAW;IAC5C;IACA,aAAa;IACd;;;AAML,KAAI,OAAO;OACJ,MAAM,WAAW,OAAO,MAC3B,KAAI,QAAQ,eAAe,QAAQ,SAAS,YAAY,CAAC,QAAQ,OAAO;GACtE,MAAM,YAAY,gBAAgB,SAAS,YAAY;AAEvD,OAAI,CADkB,IAAI,IAAI,aAAa,KAAK,MAAM,EAAE,KAAK,CAAC,CAC3C,IAAI,UAAU,CAC/B,cAAa,KAAK,GAAG,mBAAmB,WAAW,QAAQ,CAAC;;;AAOpE,KAAI,OAAO,SAAS,WAAW,OAAO,OAAO;EAC3C,MAAM,QAAQ,OAAO;AACrB,MAAI,MAAM,KACR,QAAO;GACL,UAAU;IAAE,MAAM;IAAS,OAAO,gBAAgB,OAAO,YAAY;IAAE;GACvE;GACA,aAAa;GACd;AAEH,MAAI,MAAM,eAAe,MAAM,SAAS,YAAY,CAAC,MAAM,OAAO;GAChE,MAAM,WAAW,YAAY,QAAQ,aAAa,GAAG,GAAG;AACxD,gBAAa,KAAK,GAAG,mBAAmB,UAAU,MAAM,CAAC;AACzD,UAAO;IACL,UAAU;KAAE,MAAM;KAAS,OAAO;MAAE,MAAM;MAAS,MAAM;MAAU;KAAE;IACrE;IACA,aAAa;IACd;;;AAKL,QAAO;EACL,UAAU,gBAAgB,QAAQ,YAAY;EAC9C;EACA,aAAa;EACd;;AAGH,SAAS,gBAAgB,QAAsB,UAA0B;AACvE,KAAI,CAAC,OAAO,WAAY,QAAO,aAAa,SAAS;AAIrD,MAAK,MAAM,QADO,CAAC,UAAU,OAAO,EACN;EAC5B,MAAM,QAAQ,OAAO,WAAW;AAChC,MAAI,SAAS,MAAM,SAAS,OAAO,MAAM,UAAU,SACjD,QAAO,aAAa,MAAM,MAAM;;AAKpC,MAAK,MAAM,GAAG,UAAU,OAAO,QAAQ,OAAO,WAAW,CACvD,KAAI,SAAS,MAAM,SAAS,OAAO,MAAM,UAAU,SACjD,QAAO,aAAa,MAAM,MAAM;AAIpC,QAAO,aAAa,SAAS;;;;;;;AAQ/B,SAAS,kBAAkB,YAAoB,WAA2B;CACxE,MAAM,cAAc,aAAa,UAAU;AAE3C,KAAI,YAAY,WAAW,WAAW,CAAE,QAAO;CAI/C,MAAM,YAAY,GADE,qBAAqB,WAAW,GACjB;CAEnC,MAAM,QAAQ,UAAU,MAAM,yBAAyB;AACvD,KAAI,SAAS,MAAM,IAAI;EACrB,MAAM,WAAWC,cAAY,MAAM,GAAG;AACtC,SAAO,MAAM,KAAK;;AAEpB,QAAO;;AAGT,SAAS,mBAAmB,MAAc,QAA+B;CACvE,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;CAClD,MAAM,SAAkB,EAAE;CAC1B,MAAM,aAAa,OAAO,cAAc,EAAE;CAC1C,MAAM,eAAwB,EAAE;AAEhC,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,WAAW,EAAE;AACjE,MAAI,CAAC,YAAa;AAClB,SAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,YAAY,CAAC;AAI5E,MAAI,YAAY,SAAS,YAAY,YAAY,YAAY;GAC3D,MAAM,aAAa,kBAAkB,MAAM,UAAU;AACrD,gBAAa,KAAK,GAAG,mBAAmB,YAAY,YAAY,CAAC;;AAEnE,MAAI,YAAY,SAAS,WAAW,YAAY,OAAO;GACrD,MAAM,QAAQ,YAAY;AAC1B,OAAI,MAAM,SAAS,YAAY,MAAM,YAAY;IAC/C,MAAM,aAAa,kBAAkB,MAAM,UAAU;AACrD,iBAAa,KAAK,GAAG,mBAAmB,YAAY,MAAM,CAAC;;;AAI/D,MAAI,YAAY,OAAO;GACrB,MAAM,mBAA6D,EAAE;GACrE,MAAM,iBAA2B,EAAE;AACnC,QAAK,MAAM,OAAO,YAAY,OAAO;AACnC,QAAI,IAAI,WAAY,QAAO,OAAO,kBAAkB,IAAI,WAAW;AACnE,QAAI,IAAI,SAAU,gBAAe,KAAK,GAAG,IAAI,SAAS;;AAExD,OAAI,OAAO,KAAK,iBAAiB,CAAC,SAAS,GAAG;IAC5C,MAAM,aAAa,kBAAkB,MAAM,UAAU;IACrD,MAAM,SAAuB;KAAE,MAAM;KAAU,YAAY;KAAkB,UAAU;KAAgB;AAEvG,QAAI,CADkB,IAAI,IAAI,aAAa,KAAK,MAAM,EAAE,KAAK,CAAC,CAC3C,IAAI,WAAW,CAChC,cAAa,KAAK,GAAG,mBAAmB,YAAY,OAAO,CAAC;;;AAKlE,MAAI,YAAY,OAAO;GACrB,MAAM,gBAAgB,YAAY,MAAM,MAAM,MAAM,EAAE,eAAe,EAAE,SAAS,YAAY,CAAC,EAAE,MAAM;AACrG,OAAI,eAAe;IACjB,MAAM,aAAa,kBAAkB,MAAM,UAAU;AAErD,QAAI,CADkB,IAAI,IAAI,aAAa,KAAK,MAAM,EAAE,KAAK,CAAC,CAC3C,IAAI,WAAW,CAChC,cAAa,KAAK,GAAG,mBAAmB,YAAY,cAAc,CAAC;;;;AAM3E,QAAO,CAAC;EAAE;EAAM,aAAa,OAAO;EAAa;EAAQ,EAAE,GAAG,aAAa;;;;ACxW7E,MAAM,eAA6B;CAAC;CAAO;CAAQ;CAAO;CAAS;CAAU;CAAQ;CAAW;CAAQ;AAOxG,SAAgB,kBACd,OACA,sBACA,kBAC2B;AAC3B,KAAI,CAAC,MAAO,QAAO;EAAE,UAAU,EAAE;EAAE,cAAc,EAAE;EAAE;CAErD,MAAM,6BAAa,IAAI,KAA0B;CACjD,MAAM,eAAwB,EAAE;AAEhC,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,MAAM,EAAE;EACpD,MAAM,kBAAkB,SAAS,cAAc,EAAE;AAEjD,OAAK,MAAM,UAAU,cAAc;GACjC,MAAM,KAAK,SAAS;AACpB,OAAI,CAAC,GAAI;GAET,MAAM,cAAc,iBAAiB,MAAM,GAAG,OAAO,GAAG;GAExD,MAAM,EAAE,WAAW,cAAc,aAAa,eAC5C,QACA,MACA,IACA,iBACA,sBACA,aACA,iBACD;AACD,gBAAa,KAAK,GAAG,SAAS;GAC9B,MAAM,MAAM,WAAW,IAAI,YAAY,IAAI,EAAE;AAC7C,OAAI,KAAK,UAAU;AACnB,cAAW,IAAI,aAAa,IAAI;;;AAOpC,MAAK,MAAM,CAAC,aAAa,eAAe,YAAY;EAClD,MAAM,6BAAa,IAAI,KAA0B;AACjD,OAAK,MAAM,MAAM,YAAY;GAC3B,MAAM,WAAW,GAAG,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CAAC,MAAM;GAC1D,MAAM,WAAW,SAAS,WAAW,IAAI,GAAG,cAAc,aAAa,SAAS;GAChF,MAAM,QAAQ,WAAW,IAAI,SAAS,IAAI,EAAE;AAC5C,SAAM,KAAK,GAAG;AACd,cAAW,IAAI,UAAU,MAAM;;AAIjC,MAAI,WAAW,OAAO;OACD,CAAC,GAAG,WAAW,MAAM,CAAC,CAAC,MAAM,MAAM,MAAM,YAAY,EACxD;AACd,eAAW,OAAO,YAAY;AAC9B,SAAK,MAAM,CAAC,WAAW,aAAa,YAAY;KAC9C,MAAM,WAAW,WAAW,IAAI,UAAU,IAAI,EAAE;AAChD,cAAS,KAAK,GAAG,SAAS;AAC1B,gBAAW,IAAI,WAAW,SAAS;;;;;AAS3C,MAAK,MAAM,GAAG,eAAe,WAC3B,4BAA2B,WAAW;AAQxC,QAAO;EAAE,UALQ,MAAM,KAAK,WAAW,SAAS,CAAC,CAAC,KAAK,CAAC,MAAM,iBAAiB;GAC7E;GACA;GACD,EAAE;EAEgB;EAAc;;AAGnC,SAAS,iBAAiB,MAAc,KAAsB;AAG5D,KAAI,IACF,QAAO,aAAa,IAAI;CAI1B,MAAM,QADW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CACzB,MAAM;AAE7B,KAAI,MAAM,WAAW,IAAI,CAAE,QAAO;AAClC,QAAO,aAAa,MAAM;;;;;;;;;;;AAY5B,SAAS,8BAA8B,aAA6B;AAClE,QAAO,YAAY,QAAQ,eAAe,GAAG;;AAG/C,SAAS,mBACP,QACA,MACA,aACA,sBACQ;AACR,KAAI,aAAa;EACf,MAAM,aAAa,8BAA8B,YAAY;AAC7D,MAAI,qBACF,QAAO,qBAAqB,WAAW;AAEzC,SAAO,YAAY,WAAW;;CAKhC,MAAM,OAAO,UAAU,QAAQ,KAAK;CACpC,MAAM,WAAW,sBAAsB,KAAK;AAC5C,QAAO,WAAW,YAAY,GAAG,KAAK,GAAG,WAAW,GAAG;;;;;AAMzD,SAAS,UAAU,QAAoB,MAAsB;CAC3D,MAAM,WAAW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;CAChD,MAAM,mBAAmB,SAAS,SAAS,KAAK,SAAS,SAAS,SAAS,GAAG,WAAW,IAAI;AAE7F,SAAQ,QAAR;EACE,KAAK,MACH,QAAO,mBAAmB,QAAQ;EACpC,KAAK,OACH,QAAO;EACT,KAAK;EACL,KAAK,QACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,QACE,QAAO;;;;;;;;;;;;;;AAeb,SAAS,sBAAsB,MAA6B;CAC1D,MAAM,WAAW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;AAChD,KAAI,SAAS,UAAU,EAAG,QAAO;CAGjC,IAAI,kBAAiC;AACrC,MAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,IACxC,KAAI,CAAC,SAAS,GAAG,WAAW,IAAI,EAAE;AAChC,oBAAkB,SAAS;AAC3B;;AAIJ,KAAI,CAAC,gBAAiB,QAAO;AAE7B,KAAI,oBAAoB,SAAS,GAAI,QAAO;AAE5C,QAAO,aAAa,gBAAgB;;;;;;;;;;;AAYtC,SAAS,2BAA2B,YAA+B;CAEjE,MAAM,yBAAS,IAAI,KAA0B;AAC7C,MAAK,MAAM,MAAM,YAAY;EAC3B,MAAM,QAAQ,OAAO,IAAI,GAAG,KAAK,IAAI,EAAE;AACvC,QAAM,KAAK,GAAG;AACd,SAAO,IAAI,GAAG,MAAM,MAAM;;AAG5B,MAAK,MAAM,CAAC,MAAM,UAAU,QAAQ;AAClC,MAAI,MAAM,UAAU,EAAG;AAKvB,MADoB,IAAI,IAAI,MAAM,KAAK,OAAO,GAAG,KAAK,CAAC,CACvC,QAAQ,EAAG;AAE3B,OAAK,MAAM,MAAM,OAAO;GACtB,MAAM,WAAW,sBAAsB,GAAG,KAAK;AAC/C,OAAI,SAED,IAAwB,OADT,YAAY,GAAG,KAAK,GAAG,WAAW;;EAOtD,MAAM,0BAAU,IAAI,KAA0B;AAC9C,OAAK,MAAM,MAAM,OAAO;GACtB,MAAM,SAAS,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE;AACzC,UAAO,KAAK,GAAG;AACf,WAAQ,IAAI,GAAG,MAAM,OAAO;;AAE9B,OAAK,MAAM,GAAG,WAAW,SAAS;AAChC,OAAI,OAAO,UAAU,EAAG;AAGxB,QAAK,MAAM,MAAM,QAAQ;IACvB,MAAM,SAAS,mBAAmB,GAAG,KAAK;AAC1C,QAAI,OACD,IAAwB,OAAO,YAAY,GAAG,GAAG,KAAK,GAAG,SAAS;;;;;;;;;;;;AAc7E,SAAS,mBAAmB,MAA6B;CAEvD,MAAM,YADW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CACrB,QAAQ,MAAM,CAAC,EAAE,WAAW,IAAI,CAAC;AAE5D,KAAI,UAAU,UAAU,EACtB,QAAO,aAAa,UAAU,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,CAAC;AAEvD,QAAO;;;;;;;AAQT,SAAS,uBACP,IACA,aACA,kBAC8B;CAC9B,MAAM,MAAM,GAAG;AACf,KAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO,KAAA;CAE5C,MAAM,8BAAc,IAAI,KAAwB;AAChD,MAAK,MAAM,KAAK,YACd,aAAY,IAAI,EAAE,MAAM,EAAE;CAG5B,MAAM,SAA2B,EAAE;AAEnC,MAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,IAAI,EAAE;AACvD,MAAI,CAAC,YAAY,OAAO,aAAa,SACnC,OAAM,IAAI,MACR,mDAAmD,UAAU,MAAM,iBAAiB,sDACrF;AAGH,MAAI,OAAO,SAAS,aAAa,UAC/B,OAAM,IAAI,MACR,mDAAmD,UAAU,eAAe,iBAAiB,uBAC9F;AAGH,MAAI,CAAC,SAAS,YAAY,OAAO,SAAS,aAAa,SACrD,OAAM,IAAI,MACR,mDAAmD,UAAU,eAAe,iBAAiB,sEAC9F;AAGH,MAAI,OAAO,KAAK,SAAS,SAAS,CAAC,WAAW,EAC5C,OAAM,IAAI,MACR,mDAAmD,UAAU,MAAM,iBAAiB,4BACrF;EAGH,MAAM,WAAW,OAAO,QAAQ,SAAS,SAAS,CAAC,KAAK,CAAC,aAAa,gBAAgB;AACpF,OAAI,CAAC,MAAM,QAAQ,WAAW,IAAI,WAAW,WAAW,EACtD,OAAM,IAAI,MACR,mDAAmD,UAAU,YAAY,YAAY,MAAM,iBAAiB,kDAC7G;AAWH,UAAO;IAAE,MAAM;IAAa,YATI,WAAW,KAAK,UAAU;KACxD,MAAM,UAAU,YAAY,IAAI,MAAM;AACtC,SAAI,CAAC,QACH,OAAM,IAAI,MACR,yCAAyC,UAAU,YAAY,YAAY,yBAAyB,MAAM,0DAA0D,iBAAiB,IACtL;AAEH,YAAO;MACP;IACsC;IACxC;AAEF,SAAO,KAAK;GACV,MAAM;GACN,UAAU,SAAS;GACnB;GACD,CAAC;;AAGJ,QAAO,OAAO,SAAS,IAAI,SAAS,KAAA;;;;;;;;;;AAWtC,SAAS,2BAA2B,IAAqB,kBAAwD;CAC/G,MAAM,MAAM,GAAG;AACf,KAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO,KAAA;CAK5C,MAAM,aAAa,GAAG,aAAa,UAAU,qBAAqB;CAClE,MAAM,sCAAsB,IAAI,KAA2B;AAE3D,KAAI,YAAY;AAEd,OAAK,MAAM,OAAO,WAAW,SAAS,EAAE,CACtC,MAAK,MAAM,WAAW,IAAI,SAAS,EAAE,CACnC,KAAI,QAAQ;QACL,MAAM,CAAC,MAAM,gBAAgB,OAAO,QAAQ,QAAQ,WAAW,CAClE,KAAI,YAAa,qBAAoB,IAAI,MAAM,YAAY;;AAMnE,OAAK,MAAM,WAAW,WAAW,SAAS,EAAE,CAC1C,KAAI,QAAQ;QACL,MAAM,CAAC,MAAM,gBAAgB,OAAO,QAAQ,QAAQ,WAAW,CAClE,KAAI,YAAa,qBAAoB,IAAI,MAAM,YAAY;;;CAMnE,MAAM,SAA2B,EAAE;AAEnC,MAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,IAAI,EAAE;AACvD,MAAI,CAAC,YAAY,OAAO,aAAa,SAAU;AAC/C,MAAI,OAAO,SAAS,aAAa,UAAW;AAC5C,MAAI,CAAC,SAAS,YAAY,OAAO,SAAS,aAAa,SAAU;AACjE,MAAI,OAAO,KAAK,SAAS,SAAS,CAAC,WAAW,EAAG;EAEjD,MAAM,WAAW,OAAO,QAAQ,SAAS,SAAS,CAAC,KAAK,CAAC,aAAa,gBAAgB;AACpF,OAAI,CAAC,MAAM,QAAQ,WAAW,IAAI,WAAW,WAAW,EACtD,OAAM,IAAI,MACR,8CAA8C,UAAU,YAAY,YAAY,MAAM,iBAAiB,kDACxG;AAcH,UAAO;IAAE,MAAM;IAAa,YAZI,WAAW,KAAK,UAAU;KACxD,MAAM,cAAc,oBAAoB,IAAI,MAAM;AAIlD,YAAO;MACL,MAAM;MACN,MALyB,cACvB,gBAAgB,aAAa,aAAa,MAAM,CAAC,GACjD;OAAE,MAAM;OAAa,MAAM;OAAU;MAIvC,UAAU;MACV,aAAa,aAAa;MAC3B;MACD;IACsC;IACxC;AAEF,SAAO,KAAK;GACV,MAAM;GACN,UAAU,SAAS;GACnB;GACD,CAAC;;AAGJ,QAAO,OAAO,SAAS,IAAI,SAAS,KAAA;;AAGtC,SAAS,eACP,QACA,MACA,IACA,iBACA,sBACA,aACA,kBACiD;CACjD,MAAM,YAAY,CAAC,GAAG,iBAAiB,GAAI,GAAG,cAAc,EAAE,CAAE;CAEhE,MAAM,uBAAuB,UAAU,MAAM,MAAM,EAAE,OAAO,YAAY,EAAE,KAAK,aAAa,KAAK,kBAAkB;CAInH,MAAM,YAAY;CAClB,MAAM,aAAa,cAAc,WAAW,QAAQ,WAAW,iBAAiB;CAChF,MAAM,cAAc,cAAc,WAAW,SAAS,WAAW,iBAAiB;CAClF,MAAM,eAAe,cAAc,WAAW,UAAU,WAAW,iBAAiB,CAAC,QAClF,MAAM,EAAE,KAAK,aAAa,KAAK,kBACjC;CACD,MAAM,eAAe,cAAc,WAAW,UAAU,WAAW,iBAAiB;CAEpF,MAAM,gBAAyB,EAAE;CACjC,MAAM,EAAE,MAAM,aAAa,UAAU,wBAAwB,mBAAmB,GAAG,aAAa,IAAI,cAAc;CAClH,MAAM,EACJ,UACA,kBACA,QACA,cACA,aACA,UAAU,kBACV,UAAU,qBACR,iBAAiB,GAAG,WAAW,IAAI,MAAM,OAAO;AACpD,cAAa,KAAK,GAAG,cAAc;CAGnC,MAAM,uBAAuB,iBAAiB,UAAU,aAAa,iBAAiB;CACtF,IAAI;AACJ,KAAI,aAAa;EACf,MAAM,WAAW,qBAAqB,SAAS,SAAS,UAAU,SAAS,QAAQ;AACnF,eAAa;GACX,UAAU,sBAAsB,YAAY;GAC5C,OAAO,sBAAsB,SAAS;GACtC,YAAY,sBAAsB;GAClC,UAAU,oBAAoB,sBAAsB;GACpD;GACD;YACQ,qBACT,cAAa;CAIf,MAAM,WAAW,yBAAyB,GAAG,SAAS;CAGtD,MAAM,cAAc;EAAC,GAAG;EAAY,GAAG;EAAa,GAAG;EAAc,GAAG;EAAa;CACrF,MAAM,UAAU,GAAG,eAAe,GAAG,OAAO,aAAa,CAAC,GAAG;CAC7D,MAAM,mBAAmB,uBAAuB,IAAI,aAAa,QAAQ;CAGzE,MAAM,kBAAkB,2BAA2B,IAAI,QAAQ;CAG/D,MAAM,kBACJ,oBAAoB,kBAAkB,CAAC,GAAI,oBAAoB,EAAE,EAAG,GAAI,mBAAmB,EAAE,CAAE,GAAG,KAAA;AAEpG,QAAO;EACL,WAAW;GACT,MAAM,mBAAmB,QAAQ,MAAM,GAAG,aAAa,qBAAqB;GAC5E,aAAa,iBAAiB,GAAG,SAAS,GAAG,YAAY;GACzD,YAAY;GACZ;GACA;GACA;GACA;GACA,cAAc,aAAa,SAAS,IAAI,eAAe,KAAA;GACvD;GACA;GACA;GACA;GACA;GACA;GACA,sBAAsB;GACtB,YAAY,GAAG,cAAc,KAAA;GAC7B,OAAO,GAAG;GACV;GACA;GACD;EACD;EACD;;;;;;;;AASH,SAAS,yBACP,UACmC;AACnC,KAAI,CAAC,YAAY,SAAS,WAAW,EAAG,QAAO,KAAA;CAE/C,MAAM,eAAsC,EAAE;AAC9C,MAAK,MAAM,SAAS,SAClB,MAAK,MAAM,CAAC,YAAY,WAAW,OAAO,QAAQ,MAAM,CACtD,cAAa,KAAK;EAAE;EAAY,QAAQ,UAAU,EAAE;EAAE,CAAC;AAG3D,QAAO,aAAa,SAAS,IAAI,eAAe,KAAA;;AAGlD,SAAS,iBAAiB,SAA6B,aAAqD;AAC1G,KAAI,WAAW,eAAe,YAAY,YACxC,QAAO,GAAG,QAAQ,MAAM;AAE1B,QAAO,eAAe;;AAGxB,SAAS,cACP,QACA,UACA,kBACA,kBACa;AACb,QAAO,OACJ,QAAQ,MAAM,EAAE,OAAO,SAAS,CAChC,KAAK,MAAM;EACV,MAAM,YAAY,sBAAsB,EAAE,QAAQ,iBAAiB;AACnE,SAAO;GACL,MAAM,EAAE;GACR,MAAM,EAAE,SACJ,gBAAgB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,aAAa,iBAAiB,GAAG,KAAA,EAAU,GAC/F;IAAE,MAAM;IAAa,MAAM;IAAU;GAC1C,UAAU,EAAE,YAAY;GACxB,aAAa,EAAE;GACf,YAAY,EAAE,cAAc,EAAE,QAAQ,cAAc,WAAW,cAAc,KAAA;GAC7E,SAAS,EAAE,QAAQ,WAAW,WAAW;GACzC,SAAS,EAAE,WAAW,EAAE,QAAQ,WAAW,WAAW;GACtD,OAAO,EAAE;GACT,SAAS,EAAE;GACZ;GACD;;;;;;;;;;;;AAaN,SAAS,sBACP,QACA,kBAC0B;AAC1B,KAAI,CAAC,UAAU,CAAC,iBAAkB,QAAO,KAAA;CACzC,MAAM,MAAO,OAA6B;AAC1C,KAAI,CAAC,IAAK,QAAO,KAAA;CACjB,MAAM,QAAQ,iCAAiC,KAAK,IAAI;AACxD,KAAI,CAAC,MAAO,QAAO,KAAA;AACnB,QAAO,iBAAiB,MAAM;;AAGhC,SAAS,mBACP,MACA,IACA,cAC6F;AAC7F,KAAI,CAAC,MAAM,QAAS,QAAO,EAAE;CAG7B,IAAI,WAAyE;CAC7E,IAAI;AAEJ,KAAI,KAAK,QAAQ,qBAAqB,QAAQ;AAC5C,aAAW;AACX,WAAS,KAAK,QAAQ,oBAAqB;YAClC,KAAK,QAAQ,wBAAwB,QAAQ;AACtD,aAAW;AACX,WAAS,KAAK,QAAQ,uBAAwB;YACrC,KAAK,QAAQ,sCAAsC,QAAQ;AACpE,aAAW;AACX,WAAS,KAAK,QAAQ,qCAAsC;YACnD,KAAK,QAAQ,6BAA6B;AACnD,aAAW;AACX,WAAS,KAAK,QAAQ,4BAA6B;YAC1C,KAAK,QAAQ,eAAe;AACrC,aAAW;AACX,WAAS,KAAK,QAAQ,cAAe;;AAGvC,KAAI,CAAC,QAAQ;AAEX,MAAI,aAAa,SACf,QAAO;GAAE,MAAM;IAAE,MAAM;IAAa,MAAM;IAAU,QAAQ;IAAU;GAAE;GAAU;AAEpF,MAAI,aAAa,OACf,QAAO;GAAE,MAAM;IAAE,MAAM;IAAa,MAAM;IAAU;GAAE;GAAU;AAElE,SAAO,EAAE;;CAMX,MAAM,cAAc,gBAHJ,IAAI,cAChB,aAAa,8BAA8B,GAAG,YAAY,CAAC,GAAG,YAC9D,cACwC;AAG5C,KAAI,OAAO,eAAe,OAAO,SAAS,YAAY,CAAC,OAAO,OAAO;EACnE,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;EAClD,MAAM,SAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,OAAO,WAAW,EAAE;AACxE,OAAI,CAAC,YAAa;AAClB,UAAO,KAAK,qBAAqB,WAAW,aAAa,aAAa,YAAY,CAAC;;AAErF,eAAa,KAAK;GAAE,MAAM;GAAa,aAAa,KAAA;GAAW;GAAQ,CAAC;AACxE,SAAO;GAAE,MAAM;IAAE,MAAM;IAAS,MAAM;IAAa;GAAE;GAAU;;AAKjE,KAAI,OAAO,OAAO;EAChB,MAAM,WAAsB,EAAE;AAE9B,OAAK,MAAM,WAAW,OAAO,MAC3B,KAAI,QAAQ,MAAM;GAChB,MAAM,MAAM,gBAAgB,SAAS,YAAY;AACjD,YAAS,KAAK,IAAI;aACT,QAAQ,SAAS,QAAQ,YAEzB,QAAQ,eAAe,QAAQ,SAAS,YAAY,CAAC,QAAQ,OAAO;GAC7E,MAAM,cAAc,uBAAuB,SAAS,aAAa,aAAa;GAC9E,MAAM,cAAc,IAAI,IAAI,QAAQ,YAAY,EAAE,CAAC;GACnD,MAAM,SAAkB,EAAE;AAC1B,QAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,QAAQ,WAAW,EAAE;AACzE,QAAI,CAAC,YAAa;AAClB,WAAO,KAAK,qBAAqB,WAAW,aAAa,aAAa,YAAY,CAAC;;AAErF,gBAAa,KAAK;IAAE,MAAM;IAAa,aAAa,QAAQ;IAAa;IAAQ,CAAC;AAClF,YAAS,KAAK;IAAE,MAAM;IAAS,MAAM;IAAa,CAAC;QAEnD,UAAS,KAAK,gBAAgB,SAAS,YAAY,CAAC;EAIxD,MAAM,UAAU,OAAO,MAAM,MAC1B,MAAoB,EAAE,SAAS,UAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,OAAO,CAC5F;EACD,MAAM,QAAiB;GACrB,MAAM;GACN;GACA,GAAI,OAAO,gBACP,EACE,eAAe;IAAE,UAAU,OAAO,cAAc;IAAc,SAAS,OAAO,cAAc,WAAW,EAAE;IAAE,EAC5G,GACD,EAAE;GACP;AAED,SAAO;GAAE,MADI,UAAW;IAAE,MAAM;IAAY,OAAO;IAAO,GAAe;GAC1D;GAAU;;AAG3B,QAAO;EAAE,MAAM,gBAAgB,QAAQ,YAAY;EAAE;EAAU;;;AAIjE,SAAS,uBAAuB,SAAuB,UAAkB,gBAAiC;AAExG,KAAI,QAAQ;OACL,MAAM,GAAG,eAAe,OAAO,QAAQ,QAAQ,WAAW,CAC7D,KAAI,YAAY,SAAS,OAAO,WAAW,UAAU,SACnD,QAAO,aAAa,WAAW,MAAM,GAAG,SAAS,QAAQ,YAAY,GAAG,GAAG;;CAKjF,MAAM,gBAAgB,IAAI,IAAI,eAAe,KAAK,MAAM,EAAE,KAAK,CAAC;CAChE,IAAI,OAAO;CACX,IAAI,SAAS;AACb,QAAO,cAAc,IAAI,KAAK,EAAE;AAC9B,SAAO,GAAG,WAAW;AACrB;;AAEF,QAAO;;AAGT,SAAS,mBAAmB,IAAiC,MAAc,QAA4B;AACrG,KAAI,IAAI,YACN,QAAO,gBAAgB,aAAa,8BAA8B,GAAG,YAAY,CAAC,GAAG,WAAW;AAIlG,QAAO,aAFU,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CACtB,MAAM,UACH,GAAG,aAAa,OAAO,GAAG;;AAGzD,SAAS,iBACP,WACA,IACA,MACA,QASA;CACA,MAAM,SAA0B,EAAE;CAClC,IAAI,WAAoB;EAAE,MAAM;EAAa,MAAM;EAAU;CAC7D,IAAI,eAAwB,EAAE;CAC9B,IAAI,cAAc;CAClB,IAAI;CACJ,IAAI;AAEJ,KAAI,CAAC,UAAW,QAAO;EAAE;EAAU;EAAQ;EAAc;EAAa;CAEtE,MAAM,sBAAyC,EAAE;AAEjD,MAAK,MAAM,CAAC,YAAY,SAAS,OAAO,QAAQ,UAAU,EAAE;EAC1D,MAAM,OAAO,SAAS,YAAY,GAAG;AAErC,MAAI,QAAQ,OAAO,OAAO,KAAK;GAC7B,IAAI,gBAAyB;IAAE,MAAM;IAAa,MAAM;IAAW;GACnE,MAAM,cAAc,KAAK,UAAU;AACnC,OAAI,aAAa,QAAQ;IACvB,MAAM,cAAc,mBAAmB,IAAI,QAAQ,KAAK,UAAU,MAAM;IACxE,MAAM,SAAS,2BAA2B,YAAY,QAAQ,YAAY;AAC1E,oBAAgB,OAAO;AAEvB,mBAAe,OAAO;AACtB,kBAAc,OAAO;AACrB,eAAW,OAAO;AAClB,eAAW,OAAO;cACT,KAAK,QAEd,KAAI,KAAK,QAAQ,+BAA+B,KAAK,QAAQ,mBAC3D,iBAAgB;IAAE,MAAM;IAAa,MAAM;IAAU,QAAQ;IAAU;YAEvE,KAAK,QAAQ,iBACb,KAAK,QAAQ,gBACb,KAAK,QAAQ,eACb,KAAK,QAAQ,mBAEb,iBAAgB;IAAE,MAAM;IAAa,MAAM;IAAU;QAChD;IAEL,MAAM,WAAW,OAAO,KAAK,KAAK,QAAQ,CAAC;AAC3C,QAAI,UAAU;KACZ,MAAM,eAAe,KAAK,QAAQ;AAClC,SAAI,cAAc,OAChB,iBAAgB,gBACd,aAAa,QACb,mBAAmB,IAAI,QAAQ,KAAK,UAAU,MAAM,CACrD;;;AAKT,uBAAoB,KAAK;IAAE,YAAY;IAAM,MAAM;IAAe,CAAC;aAC1D,QAAQ,OAAO,OAAO,IAE/B,qBAAoB,KAAK;GAAE,YAAY;GAAM,MAAM;IAAE,MAAM;IAAa,MAAM;IAAW;GAAE,CAAC;WACnF,QAAQ,KAAK;GACtB,MAAM,cAAc,KAAK,UAAU;GACnC,MAAM,OAAO,aAAa,SAAS,gBAAgB,YAAY,QAAQ,QAAQ,OAAO,GAAG,KAAA;AACzF,UAAO,KAAK;IAAE,YAAY;IAAM;IAAM,CAAC;;;AAK3C,KAAI,oBAAoB,SAAS,GAAG;EAClC,MAAM,SAAS,CAAC,GAAG,oBAAoB,CAAC,MAAM,GAAG,MAAM,EAAE,aAAa,EAAE,WAAW;AAGnF,cADE,OAAO,MAAM,MAAM,EAAE,KAAK,SAAS,eAAgB,EAAE,KAA0B,SAAS,UAAU,IAAI,OAAO,IAC5F;;CAGrB,MAAM,mBAAmB,oBAAoB,SAAS,IAAI,sBAAsB,KAAA;AAEhF,QAAO;EAAE;EAAU;EAAkB;EAAQ;EAAc;EAAa;EAAU;EAAU;;;;ACv2B9F,SAAS,kBAAkB,QAA0B;CACnD,MAAM,yBAAS,IAAI,KAAoB;AACvC,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,WAAW,OAAO,IAAI,MAAM,KAAK;AACvC,MAAI,CAAC,YAAY,MAAM,OAAO,SAAS,SAAS,OAAO,OACrD,QAAO,IAAI,MAAM,MAAM,MAAM;;AAGjC,QAAO,CAAC,GAAG,OAAO,QAAQ,CAAC;;AAG7B,SAAS,gBAAgB,KAAc,SAAiB,SAAuB;AAC7E,aAAY,KAAK,EACf,QAAQ,MAAM;AACZ,MAAI,EAAE,SAAS,QAAU,GAAuB,OAAO;IAE1D,CAAC;;AAGJ,SAAS,iBAAiB,QAAiB,UAAqB,SAAiB,SAAuB;AACtG,MAAK,MAAM,SAAS,OAClB,MAAK,MAAM,SAAS,MAAM,OACxB,iBAAgB,MAAM,MAAM,SAAS,QAAQ;AAGjD,MAAK,MAAM,WAAW,SACpB,MAAK,MAAM,MAAM,QAAQ,YAAY;AACnC,kBAAgB,GAAG,UAAU,SAAS,QAAQ;AAC9C,MAAI,GAAG,YACL,iBAAgB,GAAG,aAAa,SAAS,QAAQ;;;AAMzD,SAAgB,0BAA0B,cAAuB,cAAgC;CAC/F,MAAM,qBAAqB,CAAC,GAAG,aAAa;CAC5C,MAAM,mBAAmB,IAAI,IAAI,mBAAmB,KAAK,MAAM,EAAE,KAAK,CAAC;CACvE,MAAM,qBAAqB,IAAI,IAAI,mBAAmB,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAE9E,MAAM,2BAA2B,aAAa,QAAQ,UAAU;AAC9D,MAAI,CAAC,iBAAiB,IAAI,MAAM,KAAK,CAAE,QAAO;EAE9C,MAAM,WAAW,mBAAmB,IAAI,MAAM,KAAK;EACnD,MAAM,qBAAqB,IAAI,IAAI,SAAS,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;EACtE,MAAM,mBAAmB,IAAI,IAAI,MAAM,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;EACjE,MAAM,gBACJ,MAAM,OAAO,MAAM,MAAM,CAAC,mBAAmB,IAAI,EAAE,KAAK,CAAC,IACzD,SAAS,OAAO,MAAM,MAAM,CAAC,iBAAiB,IAAI,EAAE,KAAK,CAAC;AAE5D,MAAI,iBAAiB,MAAM,OAAO,SAAS,SAAS,OAAO,QAAQ;GACjE,MAAM,MAAM,mBAAmB,QAAQ,SAAS;AAChD,OAAI,QAAQ,GAAI,oBAAmB,OAAO;AAC1C,sBAAmB,IAAI,MAAM,MAAM,MAAM;AACzC,WAAQ,KACN,kCAAkC,MAAM,KAAK,2CAA2C,MAAM,OAAO,OAAO,MAAM,SAAS,OAAO,OAAO,iCAC1I;aACQ,cACT,SAAQ,KACN,kCAAkC,MAAM,KAAK,uEAC9C;AAGH,SAAO;GACP;AAEF,QAAO,CAAC,GAAG,oBAAoB,GAAG,kBAAkB,yBAAyB,CAAC;;AAGhF,SAAgB,uBAAuB,gBAAyB,mBAAqC;CACnG,MAAM,aAAa,IAAI,IAAI,eAAe,KAAK,MAAM,EAAE,KAAK,CAAC;CAC7D,MAAM,eAAe,IAAI,IAAI,eAAe,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAEpE,MAAM,0BAA0B,kBAAkB,QAAQ,UAAU;AAClE,MAAI,CAAC,WAAW,IAAI,MAAM,KAAK,CAAE,QAAO;EAExC,MAAM,WAAW,aAAa,IAAI,MAAM,KAAK;EAC7C,MAAM,qBAAqB,IAAI,IAAI,SAAS,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;EACtE,MAAM,mBAAmB,IAAI,IAAI,MAAM,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;AAKjE,MAHE,MAAM,OAAO,MAAM,MAAM,CAAC,mBAAmB,IAAI,EAAE,KAAK,CAAC,IACzD,SAAS,OAAO,MAAM,MAAM,CAAC,iBAAiB,IAAI,EAAE,KAAK,CAAC,CAG1D,SAAQ,KACN,kCAAkC,MAAM,KAAK,uEAC9C;AAGH,SAAO;GACP;AAEF,QAAO,CAAC,GAAG,gBAAgB,GAAG,kBAAkB,wBAAwB,CAAC;;AAG3E,SAAS,0BAA0B,OAAuB;AACxD,QAAO,MAAM,OAAO,MACjB,OAAO,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,EAAE,KAAK,SAAS,aAAa,OAAO,EAAE,KAAK,UAAU,SAC3G;;AAGH,SAAS,0BAA0B,MAAc,QAAiB,cAAoC;AACpG,MAAK,MAAM,SAAS,QAAQ;AAC1B,MAAI,aAAa,IAAI,MAAM,KAAK,CAAE;AAClC,OAAK,MAAM,SAAS,MAAM,QAAQ;GAChC,IAAI,QAAQ;AACZ,eAAY,MAAM,MAAM,EACtB,QAAQ,MAAM;AACZ,QAAI,EAAE,SAAS,KAAM,SAAQ;MAEhC,CAAC;AACF,OAAI,MAAO,QAAO;;;AAGtB,QAAO;;AAGT,SAAgB,yBAAyB,QAAiB,UAA8B;CACtF,MAAM,mBAAmB,CAAC,GAAG,OAAO;CACpC,MAAM,SAAS,IAAI,IAAI,iBAAiB,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAGhE,MAAM,kBAAiE,EAAE;AACzE,MAAK,MAAM,SAAS,kBAAkB;AACpC,MAAI,CAAC,MAAM,KAAK,SAAS,OAAO,CAAE;EAElC,MAAM,WAAW,MAAM,KAAK,MAAM,GAAG,GAAG;EACxC,MAAM,YAAY,OAAO,IAAI,SAAS;AACtC,MAAI,CAAC,aAAa,MAAM,OAAO,UAAU,UAAU,OAAO,OAAQ;AAGlE,MAAI,CADe,UAAU,OAAO,OAAO,MAAM,MAAM,OAAO,MAAM,OAAO,GAAG,SAAS,EAAE,KAAK,CAAC,CAC9E;AAGjB,MAAI,0BAA0B,MAAM,IAAI,0BAA0B,UAAU,CAAE;AAG9E,MAAI,0BAA0B,MAAM,MAAM,kBAAkB,IAAI,IAAI,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC,CAAE;AAE9F,kBAAgB,KAAK;GAAE,WAAW;GAAO;GAAW,CAAC;;CAIvD,MAAM,2BAAW,IAAI,KAAa;AAClC,MAAK,MAAM,EAAE,WAAW,eAAe,iBAAiB;AACtD,YAAU,SAAS,UAAU;AAC7B,WAAS,IAAI,UAAU,KAAK;AAC5B,mBAAiB,kBAAkB,UAAU,UAAU,MAAM,UAAU,KAAK;AAC5E,UAAQ,KACN,mBAAmB,UAAU,KAAK,UAAU,UAAU,KAAK,KAAK,UAAU,OAAO,OAAO,oBACzF;;AAMH,MAAK,MAAM,EAAE,WAAW,eAAe,iBAAiB;EACtD,MAAM,aAAa,UAAU;EAC7B,MAAM,aAAa,UAAU;AAE7B,OAAK,MAAM,SAAS,kBAAkB;AACpC,OAAI,SAAS,IAAI,MAAM,KAAK,CAAE;AAC9B,OAAI,MAAM,KAAK,UAAU,WAAW,OAAQ;AAC5C,OAAI,CAAC,MAAM,KAAK,WAAW,WAAW,CAAE;GAExC,MAAM,UAAU,aAAa,MAAM,KAAK,MAAM,WAAW,OAAO;GAChE,MAAM,WAAW,OAAO,IAAI,QAAQ;AAEpC,OAAI,YAAY,CAAC,SAAS,IAAI,SAAS,KAAK,EAAE;AAC5C,aAAS,IAAI,MAAM,KAAK;AACxB,qBAAiB,kBAAkB,UAAU,MAAM,MAAM,QAAQ;AACjE,YAAQ,KAAK,4BAA4B,MAAM,KAAK,mBAAmB,QAAQ,GAAG;UAC7E;AACL,qBAAiB,kBAAkB,UAAU,MAAM,MAAM,QAAQ;AACjE,UAAM,OAAO;AACb,WAAO,IAAI,SAAS,MAAM;AAC1B,YAAQ,KAAK,0BAA0B,WAAW,QAAQ,QAAQ,GAAG;;;;AAK3E,QAAO,iBAAiB,QAAQ,MAAM,CAAC,SAAS,IAAI,EAAE,KAAK,CAAC;;;;ACrL9D,SAAgB,6BAA6B,QAAiB,OAAqB;CACjF,MAAM,YAAY,IAAI,IAAI,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC;AACnD,MAAK,MAAM,SAAS,OAClB,MAAK,MAAM,SAAS,MAAM,OACxB,0BAAyB,MAAM,MAAM,OAAO,UAAU;;;;;;AAS5D,SAAgB,iCAAiC,UAAqB,OAAqB;CACzF,MAAM,YAAY,IAAI,IAAI,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC;AACnD,MAAK,MAAM,WAAW,SACpB,MAAK,MAAM,MAAM,QAAQ,WACvB,MAAK,MAAM,SAAS;EAAC,GAAG,GAAG;EAAY,GAAG,GAAG;EAAa,GAAG,GAAG;EAAc,GAAI,GAAG,gBAAgB,EAAE;EAAE,CACvG,0BAAyB,MAAM,MAAM,OAAO,UAAU;;;;AClB9D,SAAgB,kBAAkB,MAAqB;CACrD,MAAM,6BAAa,IAAI,KAAa;AACpC,MAAK,MAAM,KAAK,KAAK,OAAQ,YAAW,IAAI,EAAE,KAAK;AACnD,MAAK,MAAM,KAAK,KAAK,MAAO,YAAW,IAAI,EAAE,KAAK;CAElD,SAAS,QAAQ,KAAc,SAAuB;AACpD,cAAY,KAAK,EACf,QAAQ,MAAM;AACZ,OAAI,CAAC,WAAW,IAAI,EAAE,KAAK,CACzB,SAAQ,KAAK,gDAAgD,EAAE,KAAK,cAAc,QAAQ,GAAG;KAGlG,CAAC;;AAGJ,MAAK,MAAM,SAAS,KAAK,OACvB,MAAK,MAAM,SAAS,MAAM,OACxB,SAAQ,MAAM,MAAM,GAAG,MAAM,KAAK,GAAG,MAAM,OAAO;AAItD,MAAK,MAAM,WAAW,KAAK,SACzB,MAAK,MAAM,MAAM,QAAQ,YAAY;AACnC,OAAK,MAAM,KAAK;GAAC,GAAG,GAAG;GAAY,GAAG,GAAG;GAAa,GAAG,GAAG;GAAa,CACvE,SAAQ,EAAE,MAAM,GAAG,QAAQ,KAAK,GAAG,GAAG,KAAK,GAAG,EAAE,OAAO;AAEzD,MAAI,GAAG,YAAa,SAAQ,GAAG,aAAa,GAAG,QAAQ,KAAK,GAAG,GAAG,KAAK,cAAc;AACrF,UAAQ,GAAG,UAAU,GAAG,QAAQ,KAAK,GAAG,GAAG,KAAK,WAAW;;;;;ACqBjE,eAAsB,UAAU,UAAkB,SAA0C;CAC1F,MAAM,EAAE,WAAW,MAAM,kBAAkB,SAAS;CAGpD,MAAM,OAFc,SAAS,gBAAgB,QAAQ,cAAc,OAAO,GAAG;CAiB7E,MAAM,UAAU,KAAK,WAAW;AAChC,KAAI,CAAC,QAAQ,WAAW,KAAK,CAC3B,OAAM,IAAI,eACR,gCAAgC,QAAQ,+BACxC,oHAAoH,SAAS,KAC9H;CAGH,MAAM,EAAE,QAAQ,UAAU,eACxB,KAAK,YAAY,SACjB,EAAE,qBAAqB,SAAS,qBAAqB,CACtD;CAED,MAAM,EAAE,UAAU,iBAAiB,kBACjC,KAAK,OACL,SAAS,sBACT,KAAK,YAAY,QAClB;CAED,MAAM,2BAA2B,0BAA0B,QAAQ,aAAa;CAMhF,MAAM,oBAAoB,+BACxB,KAAK,YAAY,QAClB;AACD,2BAA0B;CAE1B,MAAM,cAAc,yBADM,uBAAuB,0BAA0B,kBAAkB,EAC7B,SAAS;AACzE,iBAAgB,aAAa,SAAS,WAAW;AACjD,8BAA6B,aAAa,MAAM;AAChD,kCAAiC,UAAU,MAAM;CAEjD,MAAM,OAAO,mBAAmB,KAAK,YAAY,gBAAgB;CAEjE,MAAM,iBAAgC,KAAK,WAAW,EAAE,EACrD,KAAK,OAAO;EAAE,KAAK,EAAE,OAAO;EAAI,aAAa,EAAE;EAAa,EAAE,CAC9D,QAAQ,MAAM,EAAE,IAAI;CAEvB,MAAM,SAAkB;EACtB,MAAM,KAAK,MAAM,SAAS;EAC1B,SAAS,KAAK,MAAM,WAAW;EAC/B,aAAa,KAAK,MAAM;EACxB,SAAS,cAAc,IAAI,OAAO;EAClC,SAAS,cAAc,SAAS,IAAI,gBAAgB,KAAA;EACpD;EACA,QAAQ;EACR;EACA;EACA,KAAK,oBAAoB;EAC1B;AAED,mBAAkB,OAAO;AAEzB,QAAO;;;;;;;AAOT,SAAS,gBACP,QACA,YACM;AACN,KAAI,CAAC,WAAY;AACjB,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,QAAQ,WAAW,MAAM;AAC/B,MAAI,CAAC,MAAO;AACZ,OAAK,MAAM,SAAS,MAAM,QAAQ;GAChC,MAAM,aAAa,MAAM,MAAM;AAC/B,OAAI,WAAY,OAAM,aAAa;;;;;AAMzC,SAAS,mBACP,iBAI0B;AAC1B,KAAI,CAAC,gBAAiB,QAAO,KAAA;CAC7B,MAAM,UAAwB,EAAE;AAChC,MAAK,MAAM,GAAG,WAAW,OAAO,QAAQ,gBAAgB,CACtD,KAAI,OAAO,SAAS,UAAU,OAAO,WAAW,SAC9C,SAAQ,KAAK,EAAE,MAAM,UAAU,CAAC;UACvB,OAAO,SAAS,YAAY,OAAO,MAAM,OAAO,KACzD,SAAQ,KAAK;EAAE,MAAM;EAAU,IAAI,OAAO;EAAqC,MAAM,OAAO;EAAM,CAAC;UAC1F,OAAO,SAAS,YAAY,OAAO,MAC5C,SAAQ,KAAK;EAAE,MAAM;EAAU,OAAO,OAAO;EAAO,CAAC;AAGzD,QAAO,QAAQ,SAAS,IAAI,UAAU,KAAA;;;;ACpKxC,eAAsB,aAAa,MAKjB;CAChB,MAAM,KAAK,MAAM,UAAU,KAAK,MAAM;EACpC,sBAAsB,KAAK;EAC3B,qBAAqB,KAAK;EAC1B,eAAe,KAAK;EACrB,CAAC;AACF,SAAQ,IAAI,KAAK,UAAU,IAAI,MAAM,EAAE,CAAC;;;;;;;;;;;;;ACD1C,SAAgB,sBAAsB,YAA+B,QAAkD;CACrH,MAAM,cAAc,IAAI,IAAI,OAAO,gBAAgB;CACnD,MAAM,eAAe,IAAI,IAAI,OAAO,iBAAiB;CACrD,MAAM,qBAAqB,IAAI,IAAI,OAAO,uBAAuB;CACjE,MAAM,YAAY,OAAO,sBAAsB,IAAI,IAAI,OAAO,oBAAoB,GAAG;CAGrF,MAAM,QAA6B,CAAC,WAAW;AAE/C,QAAO,MAAM,SAAS,GAAG;EACvB,MAAM,OAAO,MAAM,KAAK;AAExB,MAAI,YAAY,IAAI,KAAK,KAAK,EAAE;GAC9B,MAAM,KAAK,mBAAmB,MAAM,cAAc,mBAAmB;AACrE,OAAI,IAAI,WAAW,IAAI,CAAE,QAAO;;AAKlC,MAAI,aAAa,aAAa,MAAM,UAAU,EAAE;GAC9C,MAAM,KAAK,sBAAsB,MAAM,aAAa,cAAc,mBAAmB;AACrF,OAAI,IAAI,WAAW,IAAI,CAAE,QAAO;;AAIlC,OAAK,IAAI,IAAI,KAAK,aAAa,GAAG,KAAK,GAAG,KAAK;GAC7C,MAAM,QAAQ,KAAK,MAAM,EAAE;AAC3B,OAAI,MAAO,OAAM,KAAK,MAAM;;;;;;;AAUlC,SAAS,mBACP,YACA,cACA,oBACoB;AAEpB,KAAI,WAAW,oBAAoB,EACjC,QAAO,0BAA0B,YAAY,WAAW,KAAK,CAAC;CAIhE,IAAI,SAAS;AACb,MAAK,IAAI,IAAI,GAAG,IAAI,WAAW,YAAY,KAAK;EAC9C,MAAM,QAAQ,WAAW,MAAM,EAAE;AACjC,MAAI,aAAa,IAAI,MAAM,KAAK,CAC9B,WAAU,MAAM;WACP,mBAAmB,IAAI,MAAM,KAAK,CAC3C,WAAU;;AAKd,QAAO,SAAS,0BAA0B,OAAO,GAAG,0BAA0B,YAAY,WAAW,KAAK,CAAC;;;AAI7G,SAAS,aAAa,MAAyB,WAAiC;AAE9E,KAAI,KAAK,SAAS,oBAAoB;EACpC,MAAM,YAAY,KAAK,kBAAkB,QAAQ,EAAE;AACnD,SAAO,CAAC,EAAE,aAAa,UAAU,IAAI,UAAU,QAAQ,MAAM,GAAG,CAAC;;AAGnE,KAAI,KAAK,SAAS,kBAAmB,QAAO;CAC5C,MAAM,SAAS,KAAK,kBAAkB,WAAW;AACjD,KAAI,CAAC,OAAQ,QAAO;AAGpB,KAAI,UAAU,IAAI,OAAO,KAAK,CAAE,QAAO;AAGvC,KAAI,OAAO,SAAS,yBAAyB,OAAO,SAAS,qBAAqB;EAChF,MAAM,OAAO,OAAO,kBAAkB,QAAQ,IAAI,OAAO,kBAAkB,WAAW;AACtF,MAAI,QAAQ,UAAU,IAAI,KAAK,KAAK,CAAE,QAAO;;AAE/C,QAAO;;;AAIT,SAAS,sBACP,UACA,aACA,cACA,oBACoB;CACpB,MAAM,OAAO,SAAS,kBAAkB,YAAY;AACpD,KAAI,CAAC,KAAM,QAAO,KAAA;AAElB,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK;EACxC,MAAM,MAAM,KAAK,MAAM,EAAE;AACzB,MAAI,YAAY,IAAI,IAAI,KAAK,CAC3B,QAAO,mBAAmB,KAAK,cAAc,mBAAmB;;;;AAOtE,SAAS,YAAY,MAAsB;CAEzC,MAAM,QAAQ,KAAK,MAAM,6EAA6E;AACtG,KAAI,MAAO,QAAO,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM;AAC9E,QAAO;;;AAIT,SAAS,0BAA0B,GAAmB;AACpD,QAAO,EAAE,QAAQ,YAAY,KAAK;;;;ACnHpC,MAAM,gCAAgC;CACpC,iBAAiB,CAAC,kBAAkB,iCAAiC;CACrE,kBAAkB,CAAC,kBAAkB,yBAAyB;CAC9D,wBAAwB,CAAC,gBAAgB;CAC1C;AAED,MAAM,oBAAoB,IAAI,IAAI;CAChC;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAASC,yBAAuB,MAAwC;AACtE,KAAI,kBAAkB,IAAI,KAAK,KAAK,CAElC,SADiB,KAAK,kBAAkB,OAAO,IAAI,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,aAAa,GACpF,QAAQ;AAE3B,KAAI,KAAK,SAAS,2BAA2B,KAAK,SAAS,qCAAqC;EAC9F,MAAM,WACJ,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,iBAAiB,IAAI,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,aAAa;AAC9G,SAAO,WAAW,eAAe,SAAS,SAAS;;AAErD,QAAO;;AAGT,SAAS,+BACP,UACA,OACA,QACsB;CACtB,IAAI,UAAU;CACd,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK;EACnC,MAAM,OAAO,SAAS;AACtB,MAAI,KAAK,SAAS,UAEhB,KADa,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS,CAChD,WAAW,MAAM,EAAE;AAC1B,OAAI,YAAY,GAAI,WAAU;AAC9B,cAAW;QAEX;MAGF;;AAGJ,KAAI,aAAa,GAAI,QAAO;CAC5B,MAAM,QAAQ,SAAS;CACvB,MAAM,OAAO,SAAS;AACtB,QAAO;EAAE,MAAM,OAAO,MAAM,MAAM,YAAY,KAAK,SAAS;EAAE,YAAY,MAAM;EAAY,UAAU,KAAK;EAAU;;;;;AAMvH,SAAS,oBACP,UACA,QACA,YACA,SACA,eACA,uBACM;AACN,MAAK,MAAM,SAAS,UAAU;AAC5B,MAAI,MAAM,SAAS,UAAW;AAE9B,MAAI,MAAM,SAAS,mBAAmB;GACpC,MAAM,OAAO,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAC3D,WAAQ,KAAK;IAAE,KAAK,KAAK,MAAM;IAAE;IAAM,CAAC;AACxC,iBAAc,KAAK,KAAK;AACxB;;AAGF,MAAI,MAAM,SAAS,qCAAqC;AACtD,yBAAsB,QAAQ,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAE5E;;AAGF,MAAI,MAAM,SAAS,yBAAyB;AAC1C,yBAAsB,QAAQ,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;GAE5E,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,EAAE,SAAS,mBAAmB;AACtE,OAAI,KACF,qBAAoB,KAAK,eAAe,QAAQ,YAAY,SAAS,eAAe,sBAAsB;AAE5G;;EAGF,MAAM,OAAOA,yBAAuB,MAAM;AAC1C,aAAW,KAAK;GACd,KAAK;GACL,MAAM,OAAO,gBAAgB;GAC7B,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;GACrD,CAAC;;;AAIN,MAAa,qBAAmC;CAC9C,UAAU;CACV,eAAe;CACf,kBAAkB,CAAC,cAAc;CACjC,sBAAsB;CACtB,gBAAgB,MAAM,QAAQ;EAC5B,MAAM,UAAyB,EAAE;EACjC,MAAM,gBAA0B,EAAE;EAClC,MAAM,aAA+B,EAAE;EACvC,MAAM,wBAA4C,EAAE;AAEpD,sBAAoB,KAAK,SAAS,UAAU,QAAQ,YAAY,SAAS,eAAe,sBAAsB;AAE9G,SAAO;GACL;GACA;GACA,uBAAuB,sBAAsB;GAC7C;GACD;;CAEH,cAAc,SAAS;AACrB,SAAO,QAAQ,KAAK,UAAU,MAAM,KAAK;;CAE3C,kBAAkB,MAAM,QAAQ;EAC9B,MAAM,yBAAS,IAAI,KAA+B;EAElD,SAAS,gBAAgB,UAAqC;AAC5D,QAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;IACxC,MAAM,QAAQ,SAAS;AAGvB,QAAI,MAAM,SAAS,yBAAyB;KAC1C,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,EAAE,SAAS,mBAAmB;AACtE,SAAI,KAAM,iBAAgB,KAAK,SAAS;AACxC;;IAGF,MAAM,OAAOA,yBAAuB,MAAM;AAC1C,QAAI,CAAC,QAAQ,KAAK,WAAW,eAAe,CAAE;IAE9C,MAAM,YAAY,+BAA+B,UAAU,GAAG,OAAO;IACrE,MAAM,0BAAU,IAAI,KAA+B;IAGnD,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,EAAE,SAAS,mBAAmB;AACtE,QAAI,MAAM;KACR,MAAM,eAAe,KAAK;AAC1B,UAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;MAC5C,MAAM,SAAS,aAAa;AAC5B,UAAI,OAAO,SAAS,wBAAwB,OAAO,SAAS,uBAAwB;MAEpF,MAAM,cAAc,OAAO,SAAS,QAAQ,MAAM,EAAE,SAAS,aAAa;MAC1E,MAAM,aACJ,OAAO,SAAS,uBACZ,YAAY,UAAU,IACpB,YAAY,GAAI,OAChB,YAAY,IAAI,OAClB,YAAY,IAAI;AACtB,UAAI,CAAC,WAAY;MACjB,MAAM,YAAY,+BAA+B,cAAc,GAAG,OAAO;AACzE,cAAQ,IAAI,YAAY;OACtB,WAAW;OACX,gBAAgB,OAAO;OACvB,YAAY,OAAO,cAAc;OACjC,gBAAgB,sBAAsB,QAAQ,8BAA8B;OAC7E,CAAC;;;AAIN,WAAO,IAAI,MAAM;KACf;KACA,gBAAgB,MAAM;KACtB,YAAY,MAAM,cAAc;KAChC;KACD,CAAC;;;AAIN,kBAAgB,KAAK,SAAS,SAAS;AACvC,SAAO;;CAEV;;;ACrLD,MAAM,gCAAgC;CACpC,iBAAiB,CAAC,SAAS;CAC3B,kBAAkB,CAAC,iBAAiB;CACpC,wBAAwB,CAAC,gBAAgB;CAC1C;AAED,SAAS,YAAY,MAAkC;AACrD,QAAO,KAAK,SAAS,UAAU,KAAK,SAAS,IAAI,SAAS;;AAG5D,SAAS,cAAc,MAAwC;AAC7D,KAAI,CAAC,YAAY,KAAK,CAAE,QAAO;CAC/B,MAAM,OAAO,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,YAAY;AAC9D,KAAI,CAAC,KAAM,QAAO;AAElB,QADc,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,QAAQ,EAC7C,QAAQ;;AAGxB,SAAS,WAAW,MAAmD;AACrE,QAAO,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,WAAW,IAAI;;;AAI7D,SAAS,eAAe,MAAwC;AAC9D,KAAI,KAAK,SAAS,iBAAkB,QAAO;CAC3C,MAAM,OAAO,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,OAAO;AACzD,KAAI,CAAC,KAAM,QAAO;CAClB,MAAM,KAAK,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,aAAa;AAC7D,KAAI,IAAI,SAAS,eAAe,IAAI,SAAS,MAAO,QAAO,GAAG;AAC9D,QAAO;;;AAIT,SAAS,WAAW,MAAwC;AAC1D,KAAI,KAAK,SAAS,OAAQ,QAAO;CACjC,MAAM,KAAK,KAAK,SAAS;AACzB,KAAI,CAAC,MAAO,GAAG,SAAS,SAAS,GAAG,SAAS,OAAS,QAAO;CAC7D,MAAM,OAAO,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,YAAY;AAC9D,KAAI,CAAC,KAAM,QAAO;AAElB,MAAK,MAAM,OAAO,KAAK,eAAe;AACpC,MAAI,IAAI,SAAS,aAAc,QAAO,IAAI;AAC1C,MAAI,IAAI,SAAS,OAEf,QADiB,IAAI,SAAS,MAAM,MAAM,EAAE,SAAS,aAAa,EACjD,QAAQ;;AAG7B,QAAO;;;AAIT,SAAS,aAAa,MAAkC;AACtD,KAAI,KAAK,SAAS,OAAQ,QAAO;CACjC,MAAM,KAAK,KAAK,SAAS;AACzB,QAAO,IAAI,SAAS,gBAAgB;EAAC;EAAS;EAAU;EAAW;EAAM,CAAC,SAAS,GAAG,KAAK;;AAG7F,MAAa,qBAAmC;CAC9C,UAAU;CACV,eAAe;CACf,kBAAkB,CAAC,cAAc;CACjC,sBAAsB;CACtB,gBAAgB,MAAM,QAAQ;EAC5B,MAAM,UAAyB,EAAE;EACjC,MAAM,gBAA0B,EAAE;EAClC,MAAM,aAA+B,EAAE;AAEvC,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,UAAW;AAG9B,OAAI,aAAa,MAAM,EAAE;IACvB,MAAM,OAAO,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAC3D,YAAQ,KAAK;KAAE,KAAK,KAAK,MAAM;KAAE;KAAM,CAAC;AACxC,kBAAc,KAAK,KAAK;AACxB;;GAGF,MAAM,aAAa,cAAc,MAAM;AACvC,cAAW,KAAK;IACd,KAAK;IACL,MAAM,aAAa,gBAAgB;IACnC,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IACrD,CAAC;;AAGJ,SAAO;GAAE;GAAS;GAAe;GAAY;;CAE/C,cAAc,SAAS;AACrB,SAAO,QAAQ,KAAK,UAAU,MAAM,KAAK;;CAE3C,kBAAkB,MAAM,QAAQ;EAC9B,MAAM,yBAAS,IAAI,KAA+B;EAClD,MAAM,eAAe,KAAK,SAAS;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;GAC5C,MAAM,QAAQ,aAAa;GAC3B,MAAM,aAAa,cAAc,MAAM;AACvC,OAAI,CAAC,WAAY;GAGjB,IAAI,YAAkC;GACtC,MAAM,UAAU,WAAW,MAAM;GACjC,MAAM,0BAAU,IAAI,KAA+B;AAEnD,OAAI,SAAS;IACX,MAAM,eAAe,QAAQ;AAG7B,SAAK,MAAM,aAAa,aACtB,KAAI,eAAe,UAAU,KAAK,aAAa;AAC7C,iBAAY;MACV,MAAM,OAAO,MAAM,UAAU,YAAY,UAAU,SAAS;MAC5D,YAAY,UAAU;MACtB,UAAU,UAAU;MACrB;AACD;;AAKJ,SAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;KAC5C,MAAM,YAAY,aAAa;KAC/B,MAAM,UAAU,WAAW,UAAU;AACrC,SAAI,CAAC,QAAS;KAGd,IAAI,YAAkC;AACtC,UAAK,IAAI,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;MAC/B,MAAM,OAAO,aAAa;AAC1B,UAAI,eAAe,KAAK,KAAK,OAAO;AAClC,mBAAY;QACV,MAAM,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS;QAClD,YAAY,KAAK;QACjB,UAAU,KAAK;QAChB;AACD;;AAEF,UAAI,KAAK,SAAS,UAAW;AAC7B;;AAGF,aAAQ,IAAI,SAAS;MACnB,WAAW;MACX,gBAAgB,UAAU;MAC1B,YAAY,UAAU,cAAc;MACpC,gBAAgB,sBAAsB,WAAW,8BAA8B;MAChF,CAAC;;;AAIN,UAAO,IAAI,YAAY;IACrB;IACA,gBAAgB,MAAM;IACtB,YAAY,MAAM,cAAc;IAChC;IACD,CAAC;;AAGJ,SAAO;;CAEV;;;ACzKD,MAAM,4BAA4B;CAChC,iBAAiB,CAAC,6BAA6B;CAC/C,kBAAkB,CAAC,qCAAqC;CACxD,wBAAwB,EAAE;CAC1B,qBAAqB,CAAC,UAAU;CACjC;AAED,SAAS,eAAe,MAA6B;CACnD,MAAM,UAAU,CAAC,GAAG,KAAK,SAAS,0BAA0B,CAAC;AAC7D,QAAO,QAAQ,SAAS,IAAI,QAAQ,QAAQ,SAAS,GAAI,KAAK;;AAGhE,SAAS,YAAY,MAAwC;CAC3D,MAAM,WAAW,KAAK,kBAAkB,WAAW;AACnD,KAAI,CAAC,SAAU,QAAO;AACtB,QAAO,eAAe,SAAS,KAAK;;AAGtC,SAASC,iBAAe,MAAwC;AAC9D,SAAQ,KAAK,MAAb;EACE,KAAK,kBAAkB;GACrB,MAAM,MAAM,eAAe,KAAK,KAAK;AACrC,UAAO,MAAM,aAAa,QAAQ;;EAEpC,KAAK,mBAGH,UAFa,KAAK,iBAAiB,SAAS,cAAc,KAAK,kBAAkB,KAAK,cAAc,KAC7E,kBAAkB,OAAO,GAC/B,QAAQ;EAE3B,KAAK,uBACH,QAAO,KAAK,kBAAkB,OAAO,EAAE,QAAQ;EAEjD,KAAK,sBAAsB;GACzB,MAAM,OAAO,KAAK,kBAAkB,OAAO,EAAE,QAAQ;GACrD,MAAM,WAAW,YAAY,KAAK;AAClC,UAAO,QAAQ,WAAW,UAAU,SAAS,GAAG,SAAS;;EAE3D,KAAK;EACL,KAAK,kBACH,QAAO,KAAK,KAAK,MAAM,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI;EAErD,QACE,QAAO;;;AAIb,SAAS,cAAc,MAAyB,QAA+B;CAC7E,MAAM,UAAyB,EAAE;CAEjC,MAAM,WAAW,SAAkC;EACjD,MAAM,OAAO,KAAK,kBAAkB,OAAO,EAAE,QAAQ,KAAK;EAC1D,MAAM,OAAO,KAAK,kBAAkB,OAAO,EAAE,QAAQ;EACrD,MAAM,OAAO,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS;AACzD,UAAQ,KAAK;GACX,KAAK,GAAG,KAAK,GAAG,KAAK,QAAQ,UAAU,GAAG;GAC1C;GACD,CAAC;;AAGJ,MAAK,MAAM,SAAS,KAAK,eAAe;AACtC,MAAI,MAAM,SAAS,eAAe;AAChC,WAAQ,MAAM;AACd;;AAEF,MAAI,MAAM,SAAS;QACZ,MAAM,QAAQ,MAAM,cACvB,KAAI,KAAK,SAAS,cAAe,SAAQ,KAAK;;;AAKpD,QAAO;;AAGT,SAAS,2BACP,UACA,OACA,QACsB;CACtB,IAAI,UAAU;CACd,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK;EACnC,MAAM,OAAO,SAAS;AACtB,MAAI,KAAK,SAAS,UAEhB,KADa,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS,CAChD,WAAW,KAAK,EAAE;AACzB,OAAI,YAAY,GAAI,WAAU;AAC9B,cAAW;QAEX;MAGF;;AAGJ,KAAI,aAAa,GAAI,QAAO;CAC5B,MAAM,QAAQ,SAAS;CACvB,MAAM,OAAO,SAAS;AACtB,QAAO;EAAE,MAAM,OAAO,MAAM,MAAM,YAAY,KAAK,SAAS;EAAE,YAAY,MAAM;EAAY,UAAU,KAAK;EAAU;;AAGvH,MAAa,iBAA+B;CAC1C,UAAU;CACV,eAAe;CACf,kBAAkB,CAAC,aAAa;CAChC,sBAAsB;CACtB,gBAAgB,MAAM,QAAQ;EAC5B,MAAM,UAAyB,EAAE;EACjC,MAAM,gBAA0B,EAAE;EAClC,IAAI;EACJ,MAAM,aAA+B,EAAE;AAEvC,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,UAAW;AAE9B,OAAI,MAAM,SAAS,iBACjB,yBAAwB,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAGxE,OAAI,MAAM,SAAS,sBAAsB;AACvC,YAAQ,KAAK,GAAG,cAAc,OAAO,OAAO,CAAC;AAC7C,kBAAc,KAAK,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS,CAAC;AAClE;;GAGF,MAAM,MAAMA,iBAAe,MAAM;AACjC,cAAW,KAAK;IACd;IACA,MAAM,MAAM,gBAAgB;IAC5B,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IACrD,CAAC;;AAGJ,SAAO;GAAE;GAAS;GAAe;GAAuB;GAAY;;CAEtE,cAAc,SAAS;AACrB,MAAI,QAAQ,WAAW,EAAG,QAAO,EAAE;AACnC,MAAI,QAAQ,WAAW,EAAG,QAAO,CAAC,UAAU,QAAQ,GAAI,OAAO;AAC/D,SAAO,CAAC,aAAa,QAAQ,KAAK,UAAU,KAAK,MAAM,OAAO,CAAC,KAAK,KAAK,CAAC,KAAK;;CAEjF,kBAAkB,MAAM,QAAQ;EAC9B,MAAM,yBAAS,IAAI,KAA+B;EAClD,MAAM,eAAe,KAAK,SAAS;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;GAC5C,MAAM,QAAQ,aAAa;GAC3B,MAAM,MAAMA,iBAAe,MAAM;AACjC,OAAI,CAAC,OAAO,IAAI,WAAW,aAAa,CAAE;GAE1C,MAAM,YAAY,2BAA2B,cAAc,GAAG,OAAO;AACrE,UAAO,IAAI,KAAK;IACd;IACA,gBAAgB,MAAM;IACtB,YAAY,MAAM,cAAc;IAChC,yBAAS,IAAI,KAAK;IACnB,CAAC;;AAGJ,SAAO;;CAEV;;;ACtJD,MAAM,gCAAgC;CACpC,iBAAiB,CAAC,iBAAiB;CACnC,kBAAkB,CAAC,iBAAiB;CACpC,wBAAwB,CAAC,0BAA0B;CACpD;AAED,SAAS,uBAAuB,MAAwC;AACtE,KAAI,KAAK,SAAS,oBAGhB,QADiB,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,kBAAkB,EACvD,QAAQ;AAE3B,KAAI,KAAK,SAAS,uBAEhB,QADiB,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,oBAAoB,EACzD,QAAQ;AAE3B,KAAI,KAAK,SAAS,qBAEhB,QADiB,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,kBAAkB,EACvD,QAAQ;AAE3B,KAAI,KAAK,SAAS,aAEhB,QADiB,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,kBAAkB,EACvD,QAAQ;AAE3B,KAAI,KAAK,SAAS,wBAAwB;EACxC,MAAM,WAAW,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,uBAAuB;AAC7E,MAAI,SAEF,QADW,SAAS,SAAS,MAAM,MAAM,EAAE,SAAS,oBAAoB,EAC7D,QAAQ;;AAGvB,QAAO;;AAGT,SAAS,kBAAkB,UAA+B,OAAe,QAAsC;AAC7G,MAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK;EACnC,MAAM,OAAO,SAAS;AACtB,MAAI,KAAK,SAAS,qBAAqB;GACrC,MAAM,OAAO,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS;AACzD,OAAI,KAAK,WAAW,MAAM,CACxB,QAAO;IAAE;IAAM,YAAY,KAAK;IAAY,UAAU,KAAK;IAAU;AAEvE,UAAO;;AAET,MAAI,KAAK,SAAS,eAAgB;AAClC,SAAO;;AAET,QAAO;;AAGT,SAAS,0BAA0B,WAA8B,QAA+B;CAC9F,MAAM,UAAyB,EAAE;CACjC,MAAM,WAAW,UAAU;AAE3B,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,QAAQ,SAAS;EACvB,IAAI,aAA4B;AAEhC,MAAI,MAAM,SAAS,uBAEjB,cADgB,MAAM,SAAS,MAAM,MAAM,EAAE,SAAS,uBAAuB,EACvD,SAAS,MAAM,MAAM,EAAE,SAAS,oBAAoB,EAAE,QAAQ;WAC3E,MAAM,SAAS,uBACxB,cAAa,MAAM,SAAS,MAAM,MAAM,EAAE,SAAS,oBAAoB,EAAE,QAAQ;WACxE,MAAM,SAAS,mBACxB,cAAa;AAGf,MAAI,CAAC,WAAY;EAGjB,IAAI,SAAS,MAAM;AACnB,MAAI,MAAM,SAAS,uBACjB,QAAO,IAAI,IAAI,SAAS,QAAQ;GAC9B,MAAM,OAAO,SAAS,IAAI;AAC1B,OAAI,KAAK,SAAS,YAAY,KAAK,SAAS,UAAU;AACpD,aAAS,KAAK;AACd;SAEA;;EAON,IAAI,WAAW,MAAM;AACrB,OAAK,IAAI,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;GAC/B,MAAM,OAAO,SAAS;AACtB,OAAI,KAAK,SAAS,qBAAqB;AAErC,QADa,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS,CAChD,WAAW,MAAM,CAAE,YAAW,KAAK;AAC5C;;AAEF,OAAI,KAAK,SAAS,eAAgB;AAClC;;AAGF,UAAQ,KAAK;GAAE,KAAK;GAAY,MAAM,OAAO,MAAM,UAAU,OAAO;GAAE,YAAY;GAAU,UAAU;GAAQ,CAAC;;AAGjH,QAAO;;;;;;;;;AAUT,MAAM,8BACJ;AAEF,MAAa,qBAAmC;CAC9C,UAAU;CACV,eAAe;CACf,kBAAkB,CAAC,YAAY;CAC/B,sBAAsB;CACtB,gBAAgB,MAAM,QAAQ;EAC5B,MAAM,UAAyB,EAAE;EACjC,MAAM,gBAA0B,EAAE;EAClC,MAAM,aAA+B,EAAE;AAEvC,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,uBAAuB,MAAM,SAAS,eAAgB;AAEzE,OAAI,MAAM,SAAS,eAAe;IAChC,MAAM,WAAW,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAC/D,kBAAc,KAAK,SAAS;AAC5B,SAAK,MAAM,OAAO,MAAM,cACtB,KAAI,IAAI,SAAS,iBAAiB;KAChC,MAAM,OAAO,OAAO,MAAM,IAAI,YAAY,IAAI,SAAS,CAAC,MAAM;KAG9D,MAAM,MADS,IAAI,SAAS,MAAM,MAAM,EAAE,SAAS,aAAa,EAC5C,QAAQ;AAC5B,aAAQ,KAAK;MAAE;MAAK;MAAM,CAAC;;AAG/B;;GAGF,MAAM,OAAO,uBAAuB,MAAM;AAC1C,cAAW,KAAK;IACd,KAAK;IACL,MAAM,OAAO,gBAAgB;IAC7B,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IACrD,CAAC;;AAGJ,SAAO;GAAE;GAAS;GAAe;GAAY;;CAE/C,cAAc,SAAS;AACrB,SAAO,QAAQ,KAAK,UAAU,MAAM,KAAK;;CAE3C,gBAAgB,QAAQ;AACtB,SAAO,4BAA4B,KAAK,OAAO,KAAK;;CAEtD,oBAAoB,aAAa,oBAAoB,YAAY;EAE/D,MAAM,UAAU,WAAW,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK;AACxD,OAAK,MAAM,SAAS,QAAQ,SAAS,eAAe,EAAE;GACpD,MAAM,WAAW,MAAM;AACvB,OAAI,YAAY,CAAC,mBAAmB,IAAI,SAAS,CAAE,QAAO;;AAE5D,SAAO;;CAET,eAAe,MAAM,QAAQ;EAC3B,MAAM,yBAAS,IAAI,KAA8B;AAEjD,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,oBAAqB;GACxC,MAAM,WAAW,MAAM,SAAS,MAAM,MAAM,EAAE,SAAS,kBAAkB;AACzE,OAAI,CAAC,SAAU;GACf,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,EAAE,SAAS,aAAa;AAChE,OAAI,CAAC,KAAM;GAEX,MAAM,UAAU,0BAA0B,MAAM,OAAO;GACvD,MAAM,cAAc,KAAK;GACzB,MAAM,eAAe,cAAc,IAAI,OAAO,YAAY,cAAc,OAAO,GAAG,KAAA;AAClF,UAAO,IAAI,SAAS,MAAM;IAAE;IAAS,aAAa,KAAK,YAAY;IAAK;IAAc,CAAC;;AAGzF,SAAO;;CAET,kBAAkB,MAAM,QAAQ;EAC9B,MAAM,yBAAS,IAAI,KAA+B;EAClD,MAAM,eAAe,KAAK,SAAS;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;GAC5C,MAAM,QAAQ,aAAa;GAC3B,MAAM,OAAO,uBAAuB,MAAM;AAC1C,OAAI,CAAC,KAAM;GAEX,MAAM,YAAY,kBAAkB,cAAc,GAAG,OAAO;GAC5D,MAAM,0BAAU,IAAI,KAA+B;AAGnD,OAAI,MAAM,SAAS,qBAAqB;IACtC,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,EAAE,SAAS,gBAAgB,EAAE,SAAS,kBAAkB;AAChG,QAAI,MAAM;KACR,MAAM,eAAe,KAAK;AAC1B,UAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;MAC5C,MAAM,SAAS,aAAa;MAC5B,MAAM,aAAa,uBAAuB,OAAO;AACjD,UAAI,CAAC,WAAY;MACjB,MAAM,YAAY,kBAAkB,cAAc,GAAG,OAAO;AAC5D,cAAQ,IAAI,YAAY;OACtB,WAAW;OACX,gBAAgB,OAAO;OACvB,YAAY,OAAO,cAAc;OACjC,gBAAgB,sBAAsB,QAAQ,8BAA8B;OAC7E,CAAC;;;;AAKR,UAAO,IAAI,MAAM;IACf;IACA,gBAAgB,MAAM;IACtB,YAAY,MAAM,cAAc;IAChC;IACD,CAAC;;AAGJ,SAAO;;CAEV;;;AClOD,MAAM,kBAAkB;AAExB,SAAS,gBAAgB,MAAwC;CAC/D,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,KAAI,SAAU,QAAO,SAAS;AAE9B,KAAI,KAAK,SAAS,uBAAuB;EACvC,MAAM,aAAa,KAAK;AACxB,MAAI,YAAY,SAAS,uBAAuB;GAC9C,MAAM,OAAO,WAAW,kBAAkB,OAAO;AACjD,OAAI,KAAM,QAAO,KAAK;;;AAI1B,QAAO;;AAGT,SAAS,eAAe,MAA+E;AACrG,KAAI,KAAK,SAAS,oBAAoB;EACpC,MAAM,OAAO,KAAK,kBAAkB,cAAc;AAClD,MAAI,KACF,QAAO;GAAE,KAAK,gBAAgB,KAAK;GAAE,MAAM;GAAe;EAG5D,MAAM,SAAS,KAAK,kBAAkB,SAAS;AAC/C,MAAI,OACF,QAAO;GAAE,KAAK,GAAG,kBAAkB,qBAAqB,OAAO,KAAK;GAAI,MAAM;GAAY;AAG5F,SAAO;GAAE,KAAK;GAAM,MAAM;GAAS;;AAErC,QAAO;EAAE,KAAK,gBAAgB,KAAK;EAAE,MAAM,gBAAgB,KAAK,GAAG,gBAAgB;EAAS;;AAG9F,SAAS,oBAAoB,WAA8B,QAA+B;CACxF,MAAM,UAAyB,EAAE;AACjC,MAAK,MAAM,SAAS,UAAU,cAC5B,KAAI,MAAM,SAAS,qBAAqB;EACtC,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,MAAI,YAAY,SAAS,SAAS,cAChC,SAAQ,KAAK;GAAE,KAAK,SAAS;GAAM,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;GAAE,CAAC;YAEnF,MAAM,SAAS,2BAA2B;EACnD,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,MAAI,UAAU;GAGZ,IAAI,SAAS,MAAM;AACnB,OAAI,OAAO,YAAY,IACrB,WAAU;AAEZ,WAAQ,KAAK;IAAE,KAAK,SAAS;IAAM,MAAM,OAAO,MAAM,MAAM,YAAY,OAAO;IAAE,CAAC;;;AAIxF,QAAO;;AAGT,SAAS,wBAAwB,MAAyB,QAA+B;CACvF,MAAM,UAAyB,EAAE;AACjC,MAAK,MAAM,SAAS,KAAK,cACvB,KAAI,MAAM,SAAS,wBAAwB,MAAM,SAAS,oBAAoB;EAC5E,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,MAAI,SACF,SAAQ,KAAK;GAAE,KAAK,SAAS;GAAM,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;GAAE,CAAC;;AAIhG,QAAO;;AAGT,SAAS,mBAAmB,MAAyB,QAA+B;CAClF,MAAM,UAAyB,EAAE;AACjC,MAAK,MAAM,SAAS,KAAK,cACvB,KAAI,MAAM,SAAS,mBAAmB;EACpC,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,MAAI,SACF,SAAQ,KAAK;GAAE,KAAK,SAAS;GAAM,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;GAAE,CAAC;YAEnF,MAAM,SAAS,sBACxB,SAAQ,KAAK;EAAE,KAAK,MAAM;EAAM,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;EAAE,CAAC;AAG3F,QAAO;;AAGT,SAAS,cAAc,MAAkC;AAGvD,QAAO,KAAK,SAAS,aAAc,KAAa,gBAAgB;;AAGlE,SAAS,uBAAuB,UAA+B,OAAe,QAAsC;AAClH,MAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK;EACnC,MAAM,OAAO,SAAS;AACtB,MAAI,cAAc,KAAK,EAAE;GACvB,MAAM,OAAO,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS;AACzD,OAAI,KAAK,WAAW,MAAM,CACxB,QAAO;IAAE;IAAM,YAAY,KAAK;IAAY,UAAU,KAAK;IAAU;AAEvE,UAAO;;AAET,MAAI,KAAK,SAAS,OAAO,KAAK,SAAS,OAAO,KAAK,SAAS,IAAK;AACjE,SAAO;;AAET,QAAO;;AAGT,MAAM,qBAAqB,IAAI,IAAI,CAAC,qBAAqB,0BAA0B,CAAC;AACpF,MAAM,yBAAyB,IAAI,IAAI,CAAC,sBAAsB,mBAAmB,CAAC;AAClF,MAAM,oBAAoB,IAAI,IAAI,CAAC,mBAAmB,sBAAsB,CAAC;AAE7E,MAAM,8BAA8B;CAClC,iBAAiB,CAAC,UAAU,kBAAkB;CAC9C,kBAAkB,CAAC,kBAAkB;CACrC,wBAAwB,CAAC,wBAAwB;CAClD;AAED,SAAS,4BACP,MACA,QACA,aAIA;CACA,MAAM,yBAAS,IAAI,KAGhB;CACH,MAAM,cAAc,KAAK;AACzB,MAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;EAC3C,MAAM,QAAQ,YAAY;AAC1B,MAAI,CAAC,YAAY,IAAI,MAAM,KAAK,CAAE;EAClC,IAAI,aAA4B;AAChC,MAAI,MAAM,SAAS,sBACjB,cAAa,MAAM;OACd;GACL,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,OAAI,SAAU,cAAa,SAAS;;AAEtC,MAAI,CAAC,cAAc,eAAe,cAAe;EACjD,MAAM,YAAY,uBAAuB,aAAa,GAAG,OAAO;EAChE,MAAM,KAAK,sBAAsB,OAAO,4BAA4B;AACpE,SAAO,IAAI,YAAY;GACrB;GACA,gBAAgB,MAAM;GACtB,YAAY,MAAM,cAAc;GAChC,gBAAgB;GACjB,CAAC;;AAEJ,QAAO;;AAGT,MAAa,mBAAiC;CAC5C,UAAU;CACV,eAAe;CACf,mBAAmB;CACnB,kBAAkB,CAAC,0BAA0B;CAC7C,sBAAsB;CACtB,oBAAoB,aAAa,oBAAoB,YAAY;EAG/D,MAAM,UAAU,WAAW,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK;AACxD,OAAK,MAAM,SAAS,QAAQ,SAAS,eAAe,EAAE;GACpD,MAAM,WAAW,MAAM;AACvB,OAAI,YAAY,CAAC,mBAAmB,IAAI,SAAS,CAC/C,QAAO;;AAGX,SAAO;;CAET,gBAAgB,MAAM,QAAQ;EAC5B,MAAM,UAAyB,EAAE;EACjC,MAAM,gBAA0B,EAAE;EAClC,MAAM,aAA+B,EAAE;AAEvC,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,UAAW;AAE9B,OAAI,MAAM,SAAS,oBAAoB;IACrC,MAAM,OAAO,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IAG3D,MAAM,aAAa,MAAM,kBAAkB,SAAS;IACpD,MAAM,aAAa,aAAa,qBAAqB,WAAW,KAAK,GAAG,qBAAqB,KAAK,MAAM,CAAC;AACzG,YAAQ,KAAK;KAAE,KAAK;KAAY;KAAM,CAAC;AACvC,kBAAc,KAAK,KAAK;AACxB;;GAGF,MAAM,EAAE,KAAK,SAAS,eAAe,MAAM;AAC3C,cAAW,KAAK;IACd;IACA;IACA,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IACrD,CAAC;;AAGJ,SAAO;GAAE;GAAS;GAAe;GAAY;;CAE/C,cAAc,SAAS;AACrB,SAAO,QAAQ,KAAK,UAAU,MAAM,KAAK;;CAE3C,eAAe,MAAM,QAAQ;EAC3B,MAAM,yBAAS,IAAI,KAA8B;AAEjD,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,mBAAoB;GACvC,MAAM,OAAO,MAAM,kBAAkB,cAAc;AACnD,OAAI,CAAC,KAAM;GAEX,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,OAAI,CAAC,SAAU;GACf,MAAM,aAAa,SAAS;AAE5B,OAAI,KAAK,SAAS,qBAAqB;IACrC,MAAM,OAAO,KAAK,kBAAkB,OAAO;AAC3C,QAAI,CAAC,KAAM;IACX,MAAM,UAAU,oBAAoB,MAAM,OAAO;IACjD,MAAM,cAAc,KAAK;IACzB,MAAM,eAAe,cAAc,IAAI,OAAO,YAAY,cAAc,OAAO,GAAG,KAAA;AAClF,WAAO,IAAI,YAAY;KAAE;KAAS,aAAa,KAAK,YAAY;KAAK;KAAc,CAAC;cAC3E,KAAK,SAAS,yBAAyB;IAChD,MAAM,OAAO,KAAK,kBAAkB,OAAO;AAC3C,QAAI,CAAC,KAAM;IACX,MAAM,UAAU,wBAAwB,MAAM,OAAO;IACrD,MAAM,cAAc,KAAK;IACzB,MAAM,eAAe,cAAc,IAAI,OAAO,YAAY,cAAc,OAAO,GAAG,KAAA;AAClF,WAAO,IAAI,YAAY;KAAE;KAAS,aAAa,KAAK,YAAY;KAAK;KAAc,CAAC;cAC3E,KAAK,SAAS,oBAAoB;IAC3C,MAAM,OAAO,KAAK,kBAAkB,OAAO;AAC3C,QAAI,CAAC,KAAM;IACX,MAAM,UAAU,mBAAmB,MAAM,OAAO;IAChD,MAAM,cAAc,KAAK;IACzB,MAAM,eAAe,cAAc,IAAI,OAAO,YAAY,cAAc,OAAO,GAAG,KAAA;AAClF,WAAO,IAAI,YAAY;KAAE;KAAS,aAAa,KAAK,YAAY;KAAK;KAAc,CAAC;;;AAIxF,SAAO;;CAET,kBAAkB,MAAM,QAAQ;EAC9B,MAAM,yBAAS,IAAI,KAA+B;EAClD,MAAM,eAAe,KAAK,SAAS;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;GAC5C,MAAM,QAAQ,aAAa;AAC3B,OAAI,MAAM,SAAS,mBAAoB;GACvC,MAAM,OAAO,MAAM,kBAAkB,cAAc;AACnD,OAAI,CAAC,KAAM;GACX,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,OAAI,CAAC,SAAU;GAGf,MAAM,YAAY,uBAAuB,cAAc,GAAG,OAAO;GAGjE,IAAI,0BAAU,IAAI,KAA8F;GAChH,MAAM,OAAO,KAAK,kBAAkB,OAAO;AAC3C,OAAI;QACE,KAAK,SAAS,oBAChB,WAAU,4BAA4B,MAAM,QAAQ,mBAAmB;aAC9D,KAAK,SAAS,wBACvB,WAAU,4BAA4B,MAAM,QAAQ,uBAAuB;aAClE,KAAK,SAAS,mBACvB,WAAU,4BAA4B,MAAM,QAAQ,kBAAkB;;AAI1E,UAAO,IAAI,SAAS,MAAM;IACxB;IACA,gBAAgB,MAAM;IACtB,YAAY,MAAM,cAAc;IAChC;IACD,CAAC;;AAGJ,SAAO;;CAEV;;;AC1RD,MAAM,6BAA6B;CACjC,iBAAiB,CAAC,mBAAmB,SAAS;CAC9C,kBAAkB,CAAC,iBAAiB;CACpC,wBAAwB,CAAC,gBAAgB;CAC1C;AAED,SAAS,0BAA0B,MAAwC;AACzE,SAAQ,KAAK,MAAb;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,sBAEH,QADiB,KAAK,kBAAkB,OAAO,EAC9B,QAAQ;EAE3B,KAAK,wBAAwB;GAC3B,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,UAAO,WAAW,eAAe,SAAS,SAAS;;EAErD,QACE,QAAO;;;AAIb,SAAS,iBAAiB,UAA+B,OAAe,QAAsC;AAC5G,MAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK;EACnC,MAAM,OAAO,SAAS;AACtB,MAAI,KAAK,SAAS,WAAW;GAC3B,MAAM,OAAO,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS;AACzD,OAAI,KAAK,WAAW,MAAM,CACxB,QAAO;IAAE;IAAM,YAAY,KAAK;IAAY,UAAU,KAAK;IAAU;AAEvE,UAAO;;AAET,MAAI,KAAK,SAAS,OAAO,KAAK,SAAS,IAAK;AAC5C,SAAO;;AAET,QAAO;;AAGT,MAAa,kBAAgC;CAC3C,UAAU;CACV,eAAe;CACf,kBAAkB,CAAC,aAAa;CAChC,sBAAsB;CACtB,iBAAiB,QAAQ;EAEvB,MAAM,IAAK,KAAiC,WAAW;AACvD,MAAI,OAAO,MAAM,YAAY,MAAM,QAAQ,SAAU,EACnD,QAAQ,EAAuB;AACjC,SAAO;;CAET,gBAAgB,MAAM,QAAQ;EAC5B,MAAM,UAAyB,EAAE;EACjC,MAAM,gBAA0B,EAAE;EAClC,IAAI;EACJ,MAAM,aAA+B,EAAE;AAEvC,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,UAAW;AAE9B,OAAI,MAAM,SAAS,uBACjB,yBAAwB,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAGxE,OAAI,MAAM,SAAS,6BAA6B;IAC9C,MAAM,OAAO,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAC3D,YAAQ,KAAK;KAAE,KAAK,KAAK,MAAM;KAAE;KAAM,CAAC;AACxC,kBAAc,KAAK,KAAK;AACxB;;GAGF,MAAM,kBAAkB,0BAA0B,MAAM;GACxD,MAAM,OAA+B,kBAAkB,gBAAgB;AAEvE,cAAW,KAAK;IACd,KAAK;IACL;IACA,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IACrD,CAAC;;AAGJ,SAAO;GAAE;GAAS;GAAe;GAAuB;GAAY;;CAEtE,cAAc,SAAS;AACrB,SAAO,QAAQ,KAAK,UAAU,MAAM,KAAK;;CAE3C,kBAAkB,MAAM,QAAQ;EAC9B,MAAM,yBAAS,IAAI,KAA+B;EAClD,MAAM,eAAe,KAAK,SAAS;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;GAC5C,MAAM,QAAQ,aAAa;GAC3B,MAAM,OAAO,0BAA0B,MAAM;AAC7C,OAAI,CAAC,QAAQ,KAAK,WAAW,eAAe,CAAE;GAE9C,MAAM,YAAY,iBAAiB,cAAc,GAAG,OAAO;GAC3D,MAAM,0BAAU,IAAI,KAA+B;GAEnD,MAAM,OAAO,MAAM,kBAAkB,OAAO;AAC5C,OAAI,MAAM;IACR,MAAM,eAAe,KAAK;AAC1B,SAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;KAC5C,MAAM,SAAS,aAAa;AAC5B,SAAI,OAAO,SAAS,qBAAsB;KAC1C,MAAM,aAAa,OAAO,kBAAkB,OAAO,EAAE;AACrD,SAAI,CAAC,WAAY;KACjB,MAAM,YAAY,iBAAiB,cAAc,GAAG,OAAO;AAC3D,aAAQ,IAAI,YAAY;MACtB,WAAW;MACX,gBAAgB,OAAO;MACvB,YAAY,OAAO,cAAc;MACjC,gBAAgB,sBAAsB,QAAQ,2BAA2B;MAC1E,CAAC;;;AAIN,UAAO,IAAI,MAAM;IACf;IACA,gBAAgB,MAAM;IACtB,YAAY,MAAM,cAAc;IAChC;IACD,CAAC;;AAGJ,SAAO;;CAEV;;;AChID,MAAM,gCAAgC;CACpC,iBAAiB,CAAC,SAAS;CAC3B,kBAAkB,CAAC,iBAAiB;CACpC,wBAAwB,CAAC,gBAAgB;CAC1C;AAED,SAAS,6BAA6B,MAAwC;AAC5E,KAAI,KAAK,SAAS,sBAAsB,KAAK,SAAS,sBAEpD,QADiB,KAAK,kBAAkB,OAAO,EAC9B,QAAQ;AAI3B,KAAI,KAAK,SAAS,wBAAwB;EACxC,MAAM,aAAa,KAAK;AACxB,MAAI,YAAY,SAAS,cAAc;GACrC,MAAM,OAAO,WAAW,kBAAkB,OAAO;AACjD,OAAI,MAAM,SAAS,gBAAgB,KAAK,SAAS,UAC/C,QAAO;;;AAKb,QAAO;;AAGT,SAAS,uBAAuB,UAA6B,QAAsC;AAGjG,MAAK,MAAM,SAAS,SAAS,eAAe;AAC1C,MAAI,MAAM,SAAS;OACJ,MAAM,iBACT,SAAS,SAEjB,QAAO;IAAE,MADI,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IAC5C,YAAY,MAAM;IAAY,UAAU,MAAM;IAAU;;AAI3E;;AAEF,QAAO;;AAGT,SAAS,+BACP,UACA,OACA,QACsB;CACtB,IAAI,UAAU;CACd,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,IAE9B,KADa,SAAS,GACb,SAAS,WAAW;AAC3B,MAAI,YAAY,GAAI,WAAU;AAC9B,aAAW;OAEX;AAGJ,KAAI,aAAa,GAAI,QAAO;CAC5B,MAAM,QAAQ,SAAS;CACvB,MAAM,OAAO,SAAS;AACtB,QAAO;EAAE,MAAM,OAAO,MAAM,MAAM,YAAY,KAAK,SAAS;EAAE,YAAY,MAAM;EAAY,UAAU,KAAK;EAAU;;AAGvH,MAAa,qBAAmC;CAC9C,UAAU;CACV,eAAe;CACf,kBAAkB,CAAC,wBAAwB,aAAa;CACxD,sBAAsB;CACtB,gBAAgB,MAAM,QAAQ;EAC5B,MAAM,UAAyB,EAAE;EACjC,MAAM,gBAA0B,EAAE;EAClC,MAAM,aAA+B,EAAE;AAEvC,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,UAAW;AAE9B,OAAI,MAAM,SAAS,sBAAsB,MAAM,SAAS,yBAAyB;IAC/E,MAAM,OAAO,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAC3D,YAAQ,KAAK;KAAE,KAAK,KAAK,MAAM;KAAE;KAAM,CAAC;AACxC,kBAAc,KAAK,KAAK;AACxB;;GAGF,MAAM,kBAAkB,6BAA6B,MAAM;GAC3D,MAAM,OAA+B,kBAAkB,gBAAgB;AAEvE,cAAW,KAAK;IACd,KAAK;IACL;IACA,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IACrD,CAAC;;AAGJ,SAAO;GAAE;GAAS;GAAe;GAAY;;CAE/C,cAAc,SAAS;AACrB,SAAO,QAAQ,KAAK,UAAU,MAAM,KAAK;;CAE3C,kBAAkB,MAAM,QAAQ;EAC9B,MAAM,yBAAS,IAAI,KAA+B;EAClD,MAAM,eAAe,KAAK,SAAS;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;GAC5C,MAAM,QAAQ,aAAa;GAC3B,MAAM,OAAO,6BAA6B,MAAM;AAChD,OAAI,CAAC,KAAM;GAGX,IAAI,YAAkC;GACtC,MAAM,OAAO,MAAM,kBAAkB,OAAO;AAC5C,OAAI,KACF,aAAY,uBAAuB,MAAM,OAAO;AAGlD,OAAI,CAAC,UACH,aAAY,+BAA+B,cAAc,GAAG,OAAO;GAGrE,MAAM,0BAAU,IAAI,KAA+B;AAGnD,OAAI,MAAM,SAAS,sBAAsB,KACvC,MAAK,MAAM,UAAU,KAAK,eAAe;AACvC,QAAI,OAAO,SAAS,sBAAuB;IAC3C,MAAM,aAAa,OAAO,kBAAkB,OAAO,EAAE;AACrD,QAAI,CAAC,WAAY;IAEjB,IAAI,YAAkC;IACtC,MAAM,aAAa,OAAO,kBAAkB,OAAO;AACnD,QAAI,WACF,aAAY,uBAAuB,YAAY,OAAO;AAGxD,YAAQ,IAAI,YAAY;KACtB,WAAW;KACX,gBAAgB,OAAO;KACvB,YAAY,OAAO,cAAc;KACjC,gBAAgB,sBAAsB,QAAQ,8BAA8B;KAC7E,CAAC;;AAIN,UAAO,IAAI,MAAM;IACf;IACA,gBAAgB,MAAM;IACtB,YAAY,MAAM,cAAc;IAChC;IACD,CAAC;;AAGJ,SAAO;;CAEV;;;AC1JD,MAAM,8BAA8B;CAClC,iBAAiB,CAAC,SAAS;CAC3B,kBAAkB,CAAC,iBAAiB;CACpC,wBAAwB,CAAC,gBAAgB;CAC1C;AAED,SAAS,cAAc,MAAkC;AACvD,KAAI,KAAK,SAAS,OAAQ,QAAO;CACjC,MAAM,SAAS,KAAK,kBAAkB,SAAS;AAC/C,KAAI,CAAC,OAAQ,QAAO;AACpB,QAAO,OAAO,SAAS,aAAa,OAAO,SAAS;;AAGtD,SAAS,2BAA2B,MAAwC;AAC1E,KAAI,KAAK,SAAS,WAAW,KAAK,SAAS,SAAU,QAAO;AAE5D,QADiB,KAAK,kBAAkB,OAAO,EAC9B,QAAQ;;AAG3B,SAAS,6BACP,UACA,OACA,QACsB;CACtB,IAAI,UAAU;CACd,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK;EACnC,MAAM,OAAO,SAAS;AAEtB,OADkB,KAAa,eAAe,KAAK,UAClC,UAEf,KADa,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS,CAChD,WAAW,IAAI,EAAE;AACxB,OAAI,YAAY,GAAI,WAAU;AAC9B,cAAW;QAEX;MAGF;;AAGJ,KAAI,aAAa,GAAI,QAAO;CAC5B,MAAM,QAAQ,SAAS;CACvB,MAAM,OAAO,SAAS;AACtB,QAAO;EAAE,MAAM,OAAO,MAAM,MAAM,YAAY,KAAK,SAAS;EAAE,YAAY,MAAM;EAAY,UAAU,KAAK;EAAU;;AAGvH,MAAa,mBAAiC;CAC5C,UAAU;CACV,eAAe;CACf,kBAAkB,CAAC,cAAc,aAAa;CAC9C,sBAAsB;CACtB,gBAAgB,MAAM,QAAQ;EAC5B,MAAM,UAAyB,EAAE;EACjC,MAAM,gBAA0B,EAAE;EAClC,MAAM,aAA+B,EAAE;AAEvC,OAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,OAAI,MAAM,SAAS,UAAW;GAE9B,MAAM,kBAAkB,2BAA2B,MAAM;AACzD,OAAI,cAAc,MAAM,EAAE;IACxB,MAAM,OAAO,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAC3D,YAAQ,KAAK;KAAE,KAAK,KAAK,MAAM;KAAE;KAAM,CAAC;AACxC,kBAAc,KAAK,KAAK;AACxB;;GAGF,MAAM,OAA+B,kBAAkB,gBAAgB;AAEvE,cAAW,KAAK;IACd,KAAK;IACL;IACA,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;IACrD,CAAC;;AAGJ,SAAO;GAAE;GAAS;GAAe;GAAY;;CAE/C,cAAc,SAAS;AACrB,SAAO,QAAQ,KAAK,UAAU,MAAM,KAAK;;CAE3C,kBAAkB,MAAM,QAAQ;EAC9B,MAAM,yBAAS,IAAI,KAA+B;EAClD,MAAM,eAAe,KAAK,SAAS;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;GAC5C,MAAM,QAAQ,aAAa;GAC3B,MAAM,OAAO,2BAA2B,MAAM;AAC9C,OAAI,CAAC,KAAM;GAEX,MAAM,YAAY,6BAA6B,cAAc,GAAG,OAAO;GACvE,MAAM,0BAAU,IAAI,KAA+B;AAInD,OAAI,MAAM,SAAS,WAAW,MAAM,SAAS,UAAU;IACrD,MAAM,mBAAmB,MAAM;IAC/B,MAAM,OAAO,MAAM,kBAAkB,OAAO;IAI5C,IAAI,0BAAgD;AACpD,SAAK,IAAI,IAAI,GAAG,IAAI,iBAAiB,QAAQ,IAC3C,KAAI,iBAAiB,OAAO,QAAQ,iBAAiB,GAAG,SAAS,kBAAkB;AACjF,+BAA0B,6BAA6B,kBAAkB,GAAG,OAAO;AACnF;;AAIJ,QAAI,MAAM;KACR,MAAM,eAAe,KAAK;KAC1B,IAAI,qBAAqB;AACzB,UAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;MAC5C,MAAM,SAAS,aAAa;AAC5B,UAAI,OAAO,SAAS,SAAU;MAC9B,MAAM,aAAa,OAAO,kBAAkB,OAAO,EAAE;AACrD,UAAI,CAAC,WAAY;MAEjB,IAAI;AACJ,UAAI,CAAC,sBAAsB,yBAAyB;AAClD,mBAAY;AACZ,4BAAqB;aAChB;AACL,mBAAY,6BAA6B,cAAc,GAAG,OAAO;AACjE,4BAAqB;;AAGvB,cAAQ,IAAI,YAAY;OACtB,WAAW;OACX,gBAAgB,OAAO;OACvB,YAAY,OAAO,cAAc;OACjC,gBAAgB,sBAAsB,QAAQ,4BAA4B;OAC3E,CAAC;;;;AAKR,UAAO,IAAI,MAAM;IACf;IACA,gBAAgB,MAAM;IACtB,YAAY,MAAM,cAAc;IAChC;IACD,CAAC;;AAGJ,SAAO;;CAEV;;;AC5JD,MAAM,8BAA8B;CAClC,iBAAiB,CAAC,iBAAiB;CACnC,kBAAkB,CAAC,iBAAiB;CACpC,wBAAwB,EAAE;CAC3B;AAED,SAAS,eAAe,MAAwC;AAC9D,SAAQ,KAAK,MAAb;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,aACH,QAAO,KAAK,kBAAkB,OAAO,EAAE,QAAQ;EAEjD,KAAK,aAAa;GAChB,MAAM,WAAW,KAAK,kBAAkB,OAAO,EAAE,QAAQ;GACzD,MAAM,YAAY,KAAK,kBAAkB,QAAQ,EAAE;AACnD,UAAO,YAAY,QAAQ,UAAU,IAAI,aAAa,QAAQ;;EAEhE,QACE,QAAO;;;AAIb,SAAS,gCACP,UACA,OACA,QACsB;CACtB,IAAI,UAAU;CACd,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK;EACnC,MAAM,OAAO,SAAS;AACtB,MAAI,KAAK,SAAS,eAEhB,KADa,OAAO,MAAM,KAAK,YAAY,KAAK,SAAS,CAChD,WAAW,MAAM,EAAE;AAC1B,OAAI,YAAY,GAAI,WAAU;AAC9B,cAAW;QAEX;MAGF;;AAGJ,KAAI,aAAa,GAAI,QAAO;CAC5B,MAAM,QAAQ,SAAS;CACvB,MAAM,OAAO,SAAS;AACtB,QAAO;EAAE,MAAM,OAAO,MAAM,MAAM,YAAY,KAAK,SAAS;EAAE,YAAY,MAAM;EAAY,UAAU,KAAK;EAAU;;;;AC1CvH,MAAM,WAAW,IAAI,IAA0B;CAC7C,CAAC,UAAU,mBAAmB;CAC9B,CAAC,UAAU,mBAAmB;CAC9B,CAAC,MAAM,eAAe;CACtB,CAAC,UAAU,mBAAmB;CAC9B,CAAC,QAAQ,iBAAiB;CAC1B,CAAC,OAAO,gBAAgB;CACxB,CAAC,UAAU,mBAAmB;CAC9B,CAAC,QAAQ,iBAAiB;CAC1B,CAAC,QDoC2C;EAC5C,UAAU;EACV,eAAe;EACf,kBAAkB,CAAC,cAAc,yBAAyB;EAC1D,sBAAsB;EACtB,gBAAgB,MAAM,QAAQ;GAC5B,MAAM,UAAyB,EAAE;GACjC,MAAM,gBAA0B,EAAE;GAClC,MAAM,aAA+B,EAAE;AAEvC,QAAK,MAAM,SAAS,KAAK,SAAS,UAAU;AAC1C,QAAI,MAAM,SAAS,UAAW;AAE9B,QAAI,MAAM,SAAS,mBAAmB;KACpC,MAAM,OAAO,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;AAC3D,aAAQ,KAAK;MAAE,KAAK,KAAK,MAAM;MAAE;MAAM,CAAC;AACxC,mBAAc,KAAK,KAAK;AACxB;;IAGF,MAAM,MAAM,eAAe,MAAM;AACjC,eAAW,KAAK;KACd;KACA,MAAM,MAAM,gBAAgB;KAC5B,MAAM,OAAO,MAAM,MAAM,YAAY,MAAM,SAAS;KACrD,CAAC;;AAGJ,UAAO;IAAE;IAAS;IAAe;IAAY;;EAE/C,cAAc,SAAS;AACrB,UAAO,QAAQ,KAAK,UAAU,MAAM,KAAK;;EAE3C,kBAAkB,MAAM,QAAQ;GAC9B,MAAM,yBAAS,IAAI,KAA+B;GAClD,MAAM,eAAe,KAAK,SAAS;AAEnC,QAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;IAC5C,MAAM,QAAQ,aAAa;IAC3B,MAAM,MAAM,eAAe,MAAM;AACjC,QAAI,CAAC,IAAK;IAEV,MAAM,YAAY,gCAAgC,cAAc,GAAG,OAAO;AAC1E,WAAO,IAAI,KAAK;KACd;KACA,gBAAgB,MAAM;KACtB,YAAY,MAAM,cAAc;KAChC,yBAAS,IAAI,KAAK;KACnB,CAAC;;AAGJ,UAAO;;EAEV,CCzF2B;CAC3B,CAAC;AAEF,SAAgB,gBAAgB,UAA4C;AAC1E,QAAO,SAAS,IAAI,SAAS;;;;ACZ/B,MAAM,gBAAgB;AAEtB,SAAgB,UAAU,QAAgB,QAA6B;AACrE,KAAI,OAAO,SAAS,cAClB,QAAO,OAAO,MAAM,OAAO;AAE7B,QAAO,OAAO,OAAO,WAAmB,OAAO,MAAM,QAAQ,SAAS,cAAc,CAAC;;;;;;;;;;;;;;ACFvF,MAAM,8BAAc,IAAI,KAAqB;;;;;;;AAY7C,SAAS,uBAAuB,aAAqB,cAA8B;AAEjF,KAAI,CAAC,YAAY,SAAS,cAAc,CAAE,QAAO;AAGjD,KAAI,aAAa,SAAS,cAAc,CAAE,QAAO;CAIjD,MAAM,kBAA4B,EAAE;AACpC,MAAK,MAAM,QAAQ,YAAY,MAAM,KAAK,CACxC,KAAI,gBAAgB,KAAK,KAAK,EAAE;EAE9B,MAAM,QAAQ,KAAK,MAAM,kBAAkB;AAC3C,MAAI,OAAO;GAET,MAAM,UAAU,MAAM,GAAG,QAAQ,eAAe,GAAG;AACnD,mBAAgB,KAAK,QAAQ,UAAU;;;AAI7C,KAAI,gBAAgB,WAAW,EAAG,QAAO;CAGzC,MAAM,aAAa,aAAa,YAAY,KAAK;AACjD,KAAI,eAAe,GAAI,QAAO;CAC9B,MAAM,SAAS,aAAa,MAAM,GAAG,WAAW;CAChD,MAAM,QAAQ,aAAa,MAAM,WAAW;AAC5C,QAAO,SAAS,gBAAgB,KAAK,KAAK,GAAG,QAAQ;;AAUvD,SAAS,mBAAmB,QAAiC;CAC3D,MAAM,UAA2B,EAAE;CACnC,MAAM,WAAW;CACjB,MAAM,SAAS;CACf,IAAI,aAAa;AAEjB,QAAO,MAAM;EACX,MAAM,WAAW,OAAO,QAAQ,UAAU,WAAW;AACrD,MAAI,aAAa,GAAI;EACrB,MAAM,SAAS,OAAO,QAAQ,QAAQ,WAAW,GAAgB;AACjE,MAAI,WAAW,GAAI;AACnB,UAAQ,KAAK;GAAE,YAAY;GAAU,UAAU,SAAS;GAAe,CAAC;AACxE,eAAa,SAAS;;AAGxB,QAAO;;AAGT,SAAS,wBAAwB,YAA2C,SAAuC;AACjH,KAAI,QAAQ,WAAW,EAAG,wBAAO,IAAI,KAAK;CAC1C,MAAM,0BAAU,IAAI,KAAa;AACjC,MAAK,MAAM,CAAC,MAAM,SAAS,WACzB,KAAI,QAAQ,MAAM,MAAM,KAAK,kBAAkB,EAAE,cAAc,KAAK,kBAAkB,EAAE,SAAS,CAC/F,SAAQ,IAAI,KAAK;AAGrB,QAAO;;AAGT,SAAS,WAAW,OAAe,eAA+B;AAChE,KAAI,CAAC,OAAO,SAAS,MAAM,CAAE,QAAO;AACpC,KAAI,QAAQ,EAAG,QAAO;AACtB,KAAI,QAAQ,cAAe,QAAO;AAClC,QAAO;;;;;;;AAQT,SAAS,qBAAqB,SAAiB,gBAAgC;CAC7E,MAAM,MAAM,WAAW,gBAAgB,QAAQ,OAAO;CACtD,MAAM,cAAc,QAAQ,YAAY,MAAM,KAAK,IAAI,GAAG,MAAM,EAAE,CAAC;AACnE,QAAO,gBAAgB,KAAK,IAAI,cAAc;;;;;;AAOhD,SAAS,gBACP,SACA,SACA,gBACA,eACA,aACgC;CAChC,MAAM,WAAW,WAAW,gBAAgB,QAAQ,OAAO;CAC3D,MAAM,oBAAoB,WAAW,eAAe,QAAQ,OAAO;CACnE,MAAM,kBAAkB,WAAW,aAAa,QAAQ,OAAO;CAC/D,MAAM,QAAQ,QAAQ,YAAY,SAAS,SAAS;AACpD,KAAI,UAAU,GACZ,QAAO;EAAE,OAAO;EAAO,KAAK,QAAQ,QAAQ;EAAQ;AAEtD,QAAO;EAAE,OAAO;EAAmB,KAAK;EAAiB;;;;;AAM3D,SAAgB,WAAW,UAA2B;AACpD,QAAO,gBAAgB,SAAS,KAAK,KAAA;;AAGvC,eAAe,UAAU,UAAmC;CAC1D,MAAM,SAAS,YAAY,IAAI,SAAS;AACxC,KAAI,OAAQ,QAAO;CAEnB,MAAM,UAAU,gBAAgB,SAAS;AACzC,KAAI,CAAC,QACH,OAAM,IAAI,MACR,mDAAmD,SAAS,mFAE7D;CAGH,MAAM,MAAM,MAAM,OAAO,QAAQ;CACjC,MAAM,WAAW,QAAQ,iBAAiB,QAAQ,eAAe,IAAI,GAAG;CACxE,MAAM,UAAW,SAAmC,WAAW;CAC/D,MAAM,SAAS,IAAI,QAAQ;AAC3B,QAAO,YAAY,QAAQ;AAC3B,aAAY,IAAI,UAAU,OAAO;AACjC,QAAO;;;;;;AAiDT,eAAsB,kBAAkB,QAAgB,UAA4C;CAClG,MAAM,SAAS,MAAM,UAAU,SAAS;CACxC,MAAM,UAAU,gBAAgB,SAAS;AACzC,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,6CAA6C,SAAS,GAAG;CAE3E,MAAM,OAAO,UAAU,QAAQ,OAAO;AACtC,QAAO,QAAQ,gBAAgB,MAAM,OAAO;;;;;;;;AAS9C,eAAsB,qBACpB,QACA,UAC+C;CAE/C,MAAM,OAAO,UADE,MAAM,UAAU,SAAS,EACT,OAAO;CACtC,MAAM,sBAAM,IAAI,KAAsC;CAEtD,SAAS,iBAAiB,MAA+B;EACvD,MAAM,WACJ,KAAK,kBAAkB,OAAO,IAC9B,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,qBAAqB,EAAE,SAAS,aAAa;AACpF,MAAI,CAAC,SAAU;EACf,MAAM,OAAO,SAAS;EAEtB,MAAM,OACJ,KAAK,kBAAkB,OAAO,IAAI,KAAK,SAAS,MAAM,MAAM,EAAE,SAAS,gBAAgB,EAAE,SAAS,OAAO;EAC3G,MAAM,SAAS,OAAO,KAAK,YAAY,MAAM,KAAK,YAAY;AAG9D,MAFiB,OAAO,OAAO,KAAK,WAAW,IAAI,KAAK,WAAW,OAElD,IACf,KAAI,IAAI,MAAM,EAAE,aAAa,QAAQ,CAAC;MAEtC,KAAI,IAAI,MAAM,EAAE,aAAa,SAAS,GAAG,CAAC;;CAO9C,SAAS,KAAK,MAA+B;AAC3C,MAAI,KAAK,SAAS,WAAW,KAAK,SAAS,sBAAsB,KAAK,SAAS,oBAC7E,kBAAiB,KAAK;AAExB,MAAI,KAAK,SAAS;QACX,MAAM,SAAS,KAAK,cACvB,KAAI,MAAM,SAAS,mBAAoB,kBAAiB,MAAM;;AAGlE,MAAI,KAAK,SAAS;QACX,MAAM,SAAS,KAAK,cACvB,KAAI,MAAM,SAAS,oBAAqB,kBAAiB,MAAM;;AAGnE,OAAK,MAAM,SAAS,KAAK,cAAe,MAAK,MAAM;;AAErD,MAAK,MAAM,SAAS,KAAK,SAAS,SAChC,MAAK,MAAM;AAGb,QAAO;;;;;;;;;;;AAmBT,eAAsB,kBACpB,iBACA,kBACA,UACA,QACsB;CACtB,MAAM,UAAU,gBAAgB,SAAS;AACzC,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,6CAA6C,SAAS,GAAG;CAI3E,MAAM,qBAAqB,MAAM,kBAAkB,iBAAiB,SAAS;CAC7E,MAAM,sBAAsB,MAAM,kBAAkB,kBAAkB,SAAS;CAE/E,MAAM,+BAAe,IAAI,KAAa;CACtC,MAAM,uCAAuB,IAAI,KAAa;CAC9C,MAAM,qCAAqB,IAAI,KAAa;CAC5C,MAAM,oCAAoB,IAAI,KAAa;CAC3C,IAAI,qBAAqB;CAIzB,MAAM,wCAAwB,IAAI,KAAa;AAC/C,MAAK,MAAM,OAAO,mBAAmB,SAAS;AAC5C,qBAAmB,IAAI,IAAI,IAAI;EAE/B,MAAM,aAAa,IAAI,KAAK,MAAM,cAAc;AAChD,MAAI,WACF,MAAK,MAAM,QAAQ,WAAW,GAAG,MAAM,IAAI,EAAE;GAC3C,MAAM,UAAU,KAAK,QAAQ,YAAY,GAAG,CAAC,MAAM;AACnD,OAAI,QAAS,uBAAsB,IAAI,QAAQ;;;AAIrD,MAAK,MAAM,UAAU,mBAAmB,cAGtC,sBAFoB,gBAAgB,MAAM,GAAG,gBAAgB,QAAQ,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,IACjF,OAAO,MAAM,KAAK,CAAC,SACU;AAEjD,KAAI,uBAAuB,MAAM,mBAAmB,sBAKlD,sBAHE,gBAAgB,MAAM,GAAG,gBAAgB,QAAQ,mBAAmB,sBAAsB,CAAC,CAAC,MAAM,KAAK,CAAC,SACxG,IACgB,mBAAmB,sBAAsB,MAAM,KAAK,CAAC,SACxB;CAMjD,MAAM,wCAAwB,IAAI,KAAa;AAE/C,MAAK,MAAM,QAAQ,mBAAmB,YAAY;AAChD,MAAI,KAAK,SAAS,YAAY;AAC5B,qBAAkB,IAAI,QAAQ,oBAAoB,QAAQ,kBAAkB,KAAK,KAAK,MAAM,CAAC,GAAG,KAAK,KAAK,MAAM,CAAC;GAEjH,MAAM,aAAa,KAAK,KAAK,MAAM,cAAc;AACjD,OAAI,WACF,MAAK,MAAM,QAAQ,WAAW,GAAG,MAAM,IAAI,EAAE;IAC3C,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM,WAAW;IAC9C,MAAM,gBAAgB,SAAS,MAAM,SAAS,IAAI,MAAM;AACxD,QAAI,aAAc,uBAAsB,IAAI,aAAa;;;AAI/D,MAAI,KAAK,KAAK;AACZ,gBAAa,IAAI,KAAK,IAAI;AAC1B,yBAAsB,IAAI,KAAK,IAAI;QAEnC,sBAAqB,IAAI,KAAK,KAAK,MAAM,CAAC;;CAI9C,MAAM,aAAa,OAAO,MAAM;CAEhC,MAAM,aAA4B,EAAE;CACpC,MAAM,WAAqB,EAAE;CAC7B,IAAI,YAAY;AAEhB,MAAK,MAAM,OAAO,oBAAoB,SAAS;AAC7C,MAAI,IAAI,KAAK,MAAM,KAAK,WAAY;AACpC,MAAI,mBAAmB,IAAI,IAAI,IAAI,EAAE;GAMnC,MAAM,aAAa,IAAI,KAAK,MAAM,cAAc;AAChD,OAAI,YAAY;IAKd,MAAM,WAJQ,WAAW,GACtB,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,QAAQ,YAAY,GAAG,CAAC,MAAM,CAAC,CAC5C,OAAO,QAAQ,CACK,QAAQ,MAAM,CAAC,sBAAsB,IAAI,EAAE,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC;AAC3F,QAAI,SAAS,SAAS,GAAG;KAEvB,MAAM,SADe,IAAI,KAAK,WAAW,CAAC,WAAW,cAAc,GACrC,gBAAgB;KAC9C,MAAM,cAAc,IAAI,KAAK,MAAM,4BAA4B;AAC/D,SAAI,YACF,YAAW,KAAK;MACd,KAAK,IAAI,MAAM;MACf,MAAM,GAAG,OAAO,KAAK,SAAS,KAAK,KAAK,CAAC,UAAU,YAAY,GAAG;MACnE,CAAC;;;AAIR;AACA;;EAMF,MAAM,aAAa,IAAI,KAAK,MAAM,cAAc;AAChD,MAAI,YAAY;GACd,MAAM,QAAQ,WAAW,GACtB,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,QAAQ,YAAY,GAAG,CAAC,MAAM,CAAC,CAC5C,OAAO,QAAQ;GAElB,MAAM,oBAAoB,MAAc,sBAAsB,IAAI,EAAE,IAAI,aAAa,IAAI,EAAE;AAC3F,OAAI,MAAM,SAAS,KAAK,MAAM,MAAM,iBAAiB,EAAE;AACrD;AACA;;AAGF,OAAI,MAAM,KAAK,iBAAiB,EAAE;IAChC,MAAM,WAAW,MAAM,QAAQ,MAAM,CAAC,iBAAiB,EAAE,CAAC;AAC1D,QAAI,SAAS,WAAW,GAAG;AACzB;AACA;;IAIF,MAAM,SADe,IAAI,KAAK,WAAW,CAAC,WAAW,cAAc,GACrC,gBAAgB;IAC9C,MAAM,cAAc,IAAI,KAAK,MAAM,4BAA4B;AAC/D,QAAI,aAAa;KACf,MAAM,UAAU,GAAG,OAAO,KAAK,SAAS,KAAK,KAAK,CAAC,UAAU,YAAY,GAAG;AAC5E,gBAAW,KAAK;MAAE,KAAK,IAAI;MAAK,MAAM;MAAS,CAAC;AAChD;;;;AAIN,aAAW,KAAK,IAAI;;AAGtB,MAAK,MAAM,QAAQ,oBAAoB,YAAY;AAEjD,MAAI,KAAK,KAAK,MAAM,KAAK,WAAY;AAKrC,MAAI,KAAK,SAAS,YAAY;GAC5B,MAAM,iBAAiB,QAAQ,oBAAoB,QAAQ,kBAAkB,KAAK,KAAK,MAAM,CAAC,GAAG,KAAK,KAAK,MAAM;AACjH,OAAI,kBAAkB,IAAI,eAAe,IAAK,KAAK,QAAQ,QAAQ,aAAa,IAAI,KAAK,IAAI,EAAG;AAC9F;AACA;;GAMF,MAAM,aAAa,KAAK,KAAK,MAAM,cAAc;AACjD,OAAI,YAAY;IACd,MAAM,gBAAgB,WAAW,GAC9B,MAAM,IAAI,CACV,KAAK,MAAM;KACV,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,WAAW;AACxC,aAAQ,MAAM,MAAM,MAAM,IAAI,MAAM;MACpC,CACD,OAAO,QAAQ;AAClB,QAAI,cAAc,SAAS,KAAK,cAAc,OAAO,MAAM,sBAAsB,IAAI,EAAE,CAAC,EAAE;AACxF;AACA;;;;AAKN,MAAI,KAAK,QAAQ,aAAa,IAAI,KAAK,IAAI,IAAI,sBAAsB,IAAI,KAAK,IAAI,GAAG;AACnF;AACA;;AAGF,MAAI,CAAC,KAAK;OACJ,qBAAqB,IAAI,KAAK,KAAK,MAAM,CAAC,EAAE;AAC9C;AACA;;;AAIJ,WAAS,KAAK,KAAK,KAAK;;AAG1B,KAAI,WAAW,WAAW,KAAK,SAAS,WAAW;MAE7C,CAAC,QAAQ,gBAAgB;;CAK/B,IAAI,SAAS;AAGb,KAAI,SAAS,SAAS,EACpB,UAAS,OAAO,SAAS,GAAG,SAAS,SAAS,KAAK,OAAO,GAAG;CAK/D,IAAI,YAAY;CAChB,IAAI,aAAa;CACjB,MAAM,aAA+C,EAAE;AACvD,KAAI,QAAQ,gBAAgB;EAC1B,MAAM,SAAS,MAAM,UAAU,SAAS;EACxC,MAAM,aAAa,UAAU,QAAQ,OAAO;EAC5C,MAAM,gBAAgB,UAAU,QAAQ,iBAAiB;EACzD,MAAM,gBAAgB,QAAQ,eAAe,YAAY,OAAO;EAChE,MAAM,mBAAmB,QAAQ,eAAe,eAAe,iBAAiB;EAGhF,MAAM,eAAe,UAAU,QAAQ,gBAAgB;EAGvD,MAAM,qBAAqB,wBAFN,QAAQ,kBAAkB,cAAc,gBAAgB,EAClD,mBAAmB,gBAAgB,CACsB;AAOpF,MAAI,QAAQ,iBAAiB;GAC3B,MAAM,aAA+C,EAAE;AACvD,QAAK,MAAM,CAAC,YAAY,cAAc,kBAAkB;AACtD,QAAI,mBAAmB,IAAI,WAAW,CAAE;IACxC,MAAM,cAAc,cAAc,IAAI,WAAW;AACjD,QAAI,CAAC,YAAa;IAClB,MAAM,gBAAgB,IAAI,IAAI,UAAU,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC;AAClE,SAAK,MAAM,eAAe,YAAY,SAAS;AAC7C,SAAI,cAAc,IAAI,YAAY,IAAI,CAAE;AACxC,SAAI,YAAY,eAAe,KAAA,KAAa,YAAY,aAAa,KAAA,EAAW;AAChF,SAAI,CAAC,QAAQ,gBAAgB,YAAY,CAAE;AAC3C,gBAAW,KAAK;MAAE,OAAO,YAAY;MAAY,KAAK,YAAY;MAAU,CAAC;;;AAGjF,OAAI,WAAW,SAAS,GAAG;AACzB,eAAW,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAC5C,SAAK,MAAM,QAAQ,YAAY;KAC7B,IAAI,MAAM,KAAK;AACf,YAAO,MAAM,OAAO,WAAW,OAAO,SAAS,OAAO,OAAO,SAAS,KAAO;AAC7E,SAAI,OAAO,SAAS,KAAM;AAC1B,cAAS,OAAO,MAAM,GAAG,KAAK,MAAM,GAAG,OAAO,MAAM,IAAI;;AAE1D,iBAAa,WAAW;IAExB,MAAM,SAAS,UAAU,QAAQ,OAAO;AACxC,kBAAc,OAAO;AACrB,SAAK,MAAM,CAAC,GAAG,MAAM,QAAQ,eAAe,QAAQ,OAAO,CAAE,eAAc,IAAI,GAAG,EAAE;;;AAKxF,OAAK,MAAM,CAAC,YAAY,cAAc,kBAAkB;AACtD,OAAI,mBAAmB,IAAI,WAAW,CAAE;GACxC,MAAM,cAAc,cAAc,IAAI,WAAW;AACjD,OAAI,CAAC,YAAa;GAElB,MAAM,qBAAqB,IAAI,IAAI,YAAY,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC;GACzE,MAAM,aAAa,UAAU,QAAQ,QAAQ,MAAM,CAAC,mBAAmB,IAAI,EAAE,IAAI,CAAC;AAElF,OAAI,WAAW,SAAS,GAAG;AAGzB,QAAI,QAAQ,sBAAsB,YAAY,oBAAoB,WAAW,CAC3E;IAGF,MAAM,SAAS,YAAY,gBAAgB;IAC3C,MAAM,aAAa,WAAW,KAAK,MAAM,SAAS,EAAE,KAAK,CAAC,KAAK,OAAO;AAEtE,eAAW,KAAK;KAAE,MAAM,YAAY;KAAa,MAAM,OAAO;KAAY,CAAC;AAC3E,iBAAa,WAAW;;;AAI5B,MAAI,WAAW,SAAS,GAAG;AAEzB,cAAW,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK;GAC1C,MAAM,cAAc,OAAO,MAAM,KAAK;AACtC,QAAK,MAAM,OAAO,WAChB,aAAY,OAAO,IAAI,MAAM,GAAG,IAAI,KAAK;AAE3C,YAAS,YAAY,KAAK,KAAK;;;AASnC,KAAI,WAAW,SAAS,MAAM,SAAS,SAAS,KAAK,YAAY,IAAI;EAEnE,MAAM,aAAuB,CAAC,GAAG,SAAS;AAC1C,MAAI,WACF,MAAK,MAAM,OAAO,WAChB,YAAW,KAAK,IAAI,KAAK;EAG7B,MAAM,gBAAgB,WAAW,KAAK,KAAK;EAQ3C,MAAM,kBAAiC,EAAE;AACzC,OAAK,MAAM,OAAO,YAAY;GAC5B,MAAM,aAAa,IAAI,KAAK,MAAM,cAAc;AAChD,OAAI,CAAC,YAAY;AAEf,oBAAgB,KAAK,IAAI;AACzB;;GAEF,MAAM,QAAQ,WAAW,GACtB,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,QAAQ,YAAY,GAAG,CAAC,MAAM,CAAC,CAC5C,OAAO,QAAQ;GAClB,MAAM,YAAY,MAAM,QAAQ,SAAS,cAAc,SAAS,KAAK,CAAC;AACtE,OAAI,UAAU,WAAW,EAAG;AAC5B,OAAI,UAAU,WAAW,MAAM,OAE7B,iBAAgB,KAAK,IAAI;QACpB;IAGL,MAAM,SADe,IAAI,KAAK,WAAW,CAAC,WAAW,cAAc,GACrC,gBAAgB;IAC9C,MAAM,cAAc,IAAI,KAAK,MAAM,4BAA4B;AAC/D,QAAI,YACF,iBAAgB,KAAK;KACnB,KAAK,IAAI;KACT,MAAM,GAAG,OAAO,KAAK,UAAU,KAAK,KAAK,CAAC,UAAU,YAAY,GAAG;KACpE,CAAC;QAEF,iBAAgB,KAAK,IAAI;;;AAK/B,MAAI,gBAAgB,SAAS,GAAG;GAC9B,MAAM,kBAAkB,QAAQ,gBAC5B,QAAQ,cAAc,gBAAgB,GACtC,gBAAgB,KAAK,UAAU,MAAM,KAAK;GAC9C,MAAM,QAAQ,OAAO,MAAM,KAAK;GAChC,MAAM,YAAY,qBAAqB;AACvC,SAAM,OAAO,WAAW,GAAG,GAAG,gBAAgB;AAC9C,YAAS,MAAM,KAAK,KAAK;;;CAK7B,IAAI,mBAAmB;CACvB;EACE,MAAM,SAAS,MAAM,UAAU,SAAS;EACxC,MAAM,aAAa,UAAU,QAAQ,OAAO;EAC5C,MAAM,gBAAgB,UAAU,QAAQ,iBAAiB;EACzD,MAAM,aAAa,QAAQ,kBAAkB,YAAY,OAAO;EAChE,MAAM,gBAAgB,QAAQ,kBAAkB,eAAe,iBAAiB;EAEhF,MAAM,oBAAoB,wBAAwB,YADxB,mBAAmB,OAAO,CAC4B;EAEhF,MAAM,QAA2D,EAAE;AAEnE,OAAK,MAAM,CAAC,YAAY,YAAY,eAAe;GACjD,MAAM,YAAY,WAAW,IAAI,WAAW;AAC5C,OAAI,CAAC,UAAW;AAChB,OAAI,kBAAkB,IAAI,WAAW,CAAE;GAGvC,MAAM,SAAS,QAAQ,aAAa,QAAQ,UAAU,KAAK,MAAM,KAAK,aAAa,QAAQ,YAAY;AAGvG,OAAI,OACF,KAAI,UAAU;QAER,CADgB,UAAU,UAAU,KAAK,SAAS,gBAAgB,IAClD,UAAU,UAAU,SAAS,OAAO,MAAM;KAC5D,MAAM,UAAU,uBAAuB,UAAU,UAAU,MAAM,OAAO,KAAK;KAC7E,MAAM,QAAQ,gBACZ,QACA,UAAU,UAAU,MACpB,UAAU,gBACV,UAAU,UAAU,YACpB,UAAU,UAAU,SACrB;AACD,WAAM,KAAK;MACT,OAAO,MAAM;MACb,KAAK,MAAM;MACX;MACD,CAAC;AACF;;UAEG;IACL,MAAM,YAAY,qBAAqB,QAAQ,UAAU,eAAe;IACxE,MAAM,SAAS,IAAI,OAAO,UAAU,WAAW;AAC/C,UAAM,KAAK;KACT,OAAO;KACP,KAAK;KACL,SAAS,SAAS,OAAO,OAAO;KACjC,CAAC;AACF;;GAKJ,MAAM,sCAAsB,IAAI,KAAa;AAC7C,QAAK,MAAM,CAAC,YAAY,cAAc,QAAQ,SAAS;IACrD,MAAM,cAAc,UAAU,QAAQ,IAAI,WAAW;AACrD,QAAI,CAAC,YAAa;AAClB,wBAAoB,IAAI,WAAW;AACnC,QAAI,CAAC,UAAU,UAAW;AAE1B,QAAI,YAAY;SAEV,CADgB,YAAY,UAAU,KAAK,SAAS,gBAAgB,IACpD,YAAY,UAAU,SAAS,UAAU,UAAU,MAAM;MAC3E,MAAM,UAAU,uBAAuB,YAAY,UAAU,MAAM,UAAU,UAAU,KAAK;MAC5F,MAAM,QAAQ,gBACZ,QACA,YAAY,UAAU,MACtB,YAAY,gBACZ,YAAY,UAAU,YACtB,YAAY,UAAU,SACvB;AACD,YAAM,KAAK;OACT,OAAO,MAAM;OACb,KAAK,MAAM;OACX;OACD,CAAC;AACF;;WAEG;KACL,MAAM,YAAY,qBAAqB,QAAQ,YAAY,eAAe;KAC1E,MAAM,SAAS,IAAI,OAAO,YAAY,WAAW;AACjD,WAAM,KAAK;MACT,OAAO;MACP,KAAK;MACL,SAAS,SAAS,UAAU,UAAU,OAAO;MAC9C,CAAC;AACF;;;GAcJ,MAAM,mCAAmB,IAAI,KAG1B;AACH,QAAK,MAAM,CAAC,SAAS,cAAc,QAAQ,SAAS;AAClD,QAAI,oBAAoB,IAAI,QAAQ,CAAE;AACtC,QAAI,CAAC,UAAU,aAAa,CAAC,UAAU,eAAgB;AAEvD,QAAI,UAAU,QAAQ,IAAI,QAAQ,CAAE;IACpC,MAAM,SAAS,iBAAiB,IAAI,UAAU,eAAe,IAAI,EAAE;AACnE,WAAO,KAAK;KAAE,MAAM;KAAS,QAAQ;KAAW,CAAC;AACjD,qBAAiB,IAAI,UAAU,gBAAgB,OAAO;;GAExD,MAAM,qCAAqB,IAAI,KAG5B;AACH,QAAK,MAAM,CAAC,WAAW,gBAAgB,UAAU,SAAS;AACxD,QAAI,oBAAoB,IAAI,UAAU,CAAE;AACxC,QAAI,CAAC,YAAY,eAAgB;IACjC,MAAM,SAAS,mBAAmB,IAAI,YAAY,eAAe,IAAI,EAAE;AACvE,WAAO,KAAK;KAAE,MAAM;KAAW,QAAQ;KAAa,CAAC;AACrD,uBAAmB,IAAI,YAAY,gBAAgB,OAAO;;AAE5D,QAAK,MAAM,CAAC,IAAI,cAAc,kBAAkB;AAC9C,QAAI,UAAU,WAAW,EAAG;IAC5B,MAAM,cAAc,mBAAmB,IAAI,GAAG;AAC9C,QAAI,CAAC,eAAe,YAAY,WAAW,EAAG;IAC9C,MAAM,YAAY,UAAU,GAAG;IAC/B,MAAM,aAAa,YAAY;IAC/B,MAAM,cAAc,WAAW;AAC/B,QAAI,CAAC,UAAU,UAAW;AAE1B,QAAI,YAAY,WAAW;AAEzB,SADoB,YAAY,UAAU,KAAK,SAAS,gBAAgB,CACvD;AACjB,SAAI,YAAY,UAAU,SAAS,UAAU,UAAU,MAAM;MAC3D,MAAM,UAAU,uBAAuB,YAAY,UAAU,MAAM,UAAU,UAAU,KAAK;MAC5F,MAAM,QAAQ,gBACZ,QACA,YAAY,UAAU,MACtB,YAAY,gBACZ,YAAY,UAAU,YACtB,YAAY,UAAU,SACvB;AACD,YAAM,KAAK;OACT,OAAO,MAAM;OACb,KAAK,MAAM;OACX;OACD,CAAC;AACF;;WAEG;KACL,MAAM,YAAY,qBAAqB,QAAQ,YAAY,eAAe;KAC1E,MAAM,SAAS,IAAI,OAAO,YAAY,WAAW;AACjD,WAAM,KAAK;MACT,OAAO;MACP,KAAK;MACL,SAAS,SAAS,UAAU,UAAU,OAAO;MAC9C,CAAC;AACF;;AAEF,wBAAoB,IAAI,WAAW,KAAK;;;AAI5C,MAAI,MAAM,SAAS,GAAG;AACpB,SAAM,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AACvC,QAAK,MAAM,QAAQ,MACjB,UAAS,OAAO,MAAM,GAAG,KAAK,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,KAAK,IAAI;;;CAYlF,MAAM,cANJ,SAAS,SAAS,KAAK,YAAY,IAC/B,QAAQ,gBACN,QAAQ,cAAc,WAAW,CAAC,SAClC,WAAW,SACb,KACuC,SAAS,SACnB;AAEnC,KAAI,eAAe,KAAK,qBAAqB,KAAK,eAAe,EAC/D,QAAO;EAAE,SAAS;EAAiB,OAAO;EAAG;EAAW,SAAS;EAAO;AAG1E,QAAO;EACL,SAAS;EACT,OAAO;EACP;EACA,SAAS;EACV;;;;;;;;;;;ACz0BH,SAAgB,cAAc,UAAmB,WAA6B;AAC5E,KACE,OAAO,aAAa,YACpB,aAAa,QACb,CAAC,MAAM,QAAQ,SAAS,IACxB,OAAO,cAAc,YACrB,cAAc,QACd,CAAC,MAAM,QAAQ,UAAU,EACzB;EACA,MAAM,SAAkC,EAAE,GAAI,UAAsC;AACpF,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,UAAqC,CAC7E,KAAI,OAAO,OACT,QAAO,OAAO,cAAc,OAAO,MAAM,MAAM;MAE/C,QAAO,OAAO;AAGlB,SAAO;;AAIT,QAAO;;;;;;;;;;;;;;ACKT,eAAsB,WACpB,OACA,WACA,SACsB;CACtB,MAAM,SAAsB;EAC1B,SAAS,EAAE;EACX,QAAQ,EAAE;EACV,SAAS,EAAE;EACX,WAAW,EAAE;EACb,SAAS,EAAE;EACZ;CACD,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;CACtE,MAAM,WAAW,SAAS;CAC1B,MAAM,SAAS,SAAS,UAAU;AAElC,MAAK,MAAM,QAAQ,QAAQ;EACzB,MAAM,WAAWC,OAAK,KAAK,WAAW,KAAK,KAAK;AAOhD,QAAM,uBAAuB,SAAS;EAGtC,IAAI,kBAAiC;AACrC,MAAI;AACF,qBAAkB,MAAM,GAAG,SAAS,UAAU,QAAQ;UAChD;AAKR,MAAI,oBAAoB,MAAM;AAC5B,SAAM,GAAG,MAAMA,OAAK,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AAC3D,SAAM,GAAG,UAAU,UAAU,KAAK,SAAS,QAAQ;AACnD,UAAO,QAAQ,KAAK,KAAK,KAAK;AAC9B;;AAMF,MAAI,KAAK,cAAc;AACrB,OAAI,UAAU,CAAC,gBAAgB,WAAW,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS,QAAQ,CAC/E,OAAM,GAAG,UAAU,UAAU,SAAS,SAAS,iBAAiB,QAAQ;AAE1E,UAAO,QAAQ,KAAK,KAAK,KAAK;AAC9B;;AAIF,MAAI,gBAAgB,SAAS,qBAAqB,EAAE;AAClD,UAAO,QAAQ,KAAK,KAAK,KAAK;AAC9B;;EAQF,MAAM,UAAU,WAAW,gBAAgB,SAAS,GAAG,KAAA;AAIvD,MAHmB,SAAS,mBACxB,QAAQ,iBAAiB,MAAM,MAAM,EAAE,KAAK,KAAK,KAAK,CAAC,GACvD,kBAAkB,KAAK,KAAK;OAG1B,EAD4B,UAAU,gBAAgB,WAAW,OAAO,KAC5C,CAAC,KAAK,mBAAmB;AACvD,WAAO,QAAQ,KAAK,KAAK,KAAK;AAC9B;;;AAMJ,MAAI,oBAAoB,KAAK,SAAS;AACpC,UAAO,UAAU,KAAK,KAAK,KAAK;AAChC;;AAIF,MAAI,KAAK,mBAAmB;GAC1B,MAAM,UACJ,gBAAgB,SAAS,sBAAsB,IAAI,YAAY,WAAW,SAAS,GAC/E,MAAM,8BAA8B,iBAAiB,KAAK,SAAS,SAAS,GAC5E,KAAK;AACX,SAAM,GAAG,UAAU,UAAU,SAAS,QAAQ;AAC9C,UAAO,QAAQ,KAAK,KAAK,KAAK;AAC9B;;AAIF,MAAI,KAAK,KAAK,SAAS,QAAQ,EAAE;AAC/B,OAAI;IAGF,MAAM,SAAS,cAFM,KAAK,MAAM,gBAAgB,EAC1B,KAAK,MAAM,KAAK,QAAQ,CACW;IACzD,MAAM,gBAAgB,KAAK,UAAU,QAAQ,MAAM,EAAE,GAAG;AACxD,QAAI,kBAAkB,gBACpB,QAAO,UAAU,KAAK,KAAK,KAAK;SAC3B;AACL,WAAM,GAAG,UAAU,UAAU,eAAe,QAAQ;AACpD,YAAO,OAAO,KAAK,KAAK,KAAK;;WAEzB;AAEN,UAAM,GAAG,UAAU,UAAU,KAAK,SAAS,QAAQ;AACnD,WAAO,QAAQ,KAAK,KAAK,KAAK;;AAEhC;;AAIF,MAAI,YAAY,WAAW,SAAS,CAClC,KAAI;GACF,MAAM,cAAc,MAAM,kBAAkB,iBAAiB,KAAK,SAAS,UAAU,OAAO;GAG5F,IAAI,eAAe,YAAY;AAC/B,OAAI,UAAU,CAAC,aAAa,WAAW,OAAO,CAC5C,gBAAe,SAAS,SAAS;AAGnC,OAAI,CAAC,YAAY,WAAW,iBAAiB,iBAAiB;AAC5D,WAAO,UAAU,KAAK,KAAK,KAAK;AAChC;;AAGF,SAAM,GAAG,UAAU,UAAU,cAAc,QAAQ;AACnD,UAAO,OAAO,KAAK,KAAK,KAAK;AAC7B;WACO,KAAK;AAEZ,WAAQ,KACN,gCAAgC,KAAK,KAAK,8BAA8B,eAAe,QAAQ,IAAI,IAAI,YAAY,KACpH;AACD,SAAM,GAAG,UAAU,UAAU,KAAK,SAAS,QAAQ;AACnD,UAAO,QAAQ,KAAK,KAAK,KAAK;AAC9B;;AAKJ,SAAO,QAAQ,KAAK,KAAK,KAAK;;AAGhC,QAAO;;;;;;;;AAST,eAAe,uBAAuB,UAAiC;CACrE,MAAM,MAAMA,OAAK,QAAQ,SAAS;CAClC,MAAM,SAASA,OAAK,SAAS,SAAS;CACtC,IAAI;AACJ,KAAI;AACF,YAAU,MAAM,GAAG,QAAQ,IAAI;SACzB;AACN;;AAEF,KAAI,QAAQ,SAAS,OAAO,CAAE;CAC9B,MAAM,cAAc,OAAO,aAAa;CACxC,MAAM,WAAW,QAAQ,MAAM,MAAM,EAAE,aAAa,KAAK,YAAY;AACrE,KAAI,CAAC,SAAU;CACf,MAAM,UAAUA,OAAK,KAAK,KAAK,SAAS;CACxC,MAAM,WAAWA,OAAK,KAAK,KAAK,eAAe,QAAQ,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,SAAS;AACrF,OAAM,GAAG,OAAO,SAAS,SAAS;AAClC,OAAM,GAAG,OAAO,UAAU,SAAS;;;AAIrC,SAAS,kBAAkB,UAA2B;AACpD,QACE,0BAA0B,KAAK,SAAS,IACxC,SAAS,SAAS,WAAW,IAC7B,SAAS,SAAS,WAAW,IAC7B,SAAS,SAAS,WAAW,IAC7B,uBAAuB,KAAK,SAAS,IACrC,SAAS,SAAS,WAAW,IAC7B,SAAS,SAAS,WAAW,IAC7B,SAAS,SAAS,WAAW,IAC7B,yBAAyB,KAAK,SAAS;;;;;;;;;;;AAe3C,eAAsB,8BACpB,iBACA,kBACA,UACiB;CACjB,MAAM,gBAAgB,gBAAgB,MAAM,KAAK;CACjD,MAAM,iBAAiB,iBAAiB,MAAM,KAAK;CAInD,MAAM,SAAkG,EAAE;AAC1G,MAAK,IAAI,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC7C,MAAI,CAAC,cAAc,GAAG,SAAS,sBAAsB,CAAE;EACvD,MAAM,WAAW;AACjB,SAAO,IAAI,cAAc,UAAU,CAAC,cAAc,GAAG,SAAS,oBAAoB,CAAE;EACpF,IAAI,SAAS;AACb,OAAK,IAAI,IAAI,IAAI,GAAG,IAAI,cAAc,QAAQ,IAC5C,KAAI,cAAc,GAAG,MAAM,EAAE;AAC3B,YAAS,cAAc,GAAG,WAAW;AACrC;;AAGJ,SAAO,KAAK;GACV,iBAAiB,oBAAoB,eAAe,SAAS;GAC7D,iBAAiB,4BAA4B,eAAe,SAAS;GACrE,OAAO,cAAc,MAAM,UAAU,IAAI,EAAE;GAC3C;GACD,CAAC;;AAEJ,KAAI,OAAO,WAAW,EAAG,QAAO;CAOhC,MAAM,SAAS,mBAAmB,eAAe;AACjD,oBAAmB,eAAe,OAAO;CAKzC,MAAM,gBAAgB,MAAM,qBADV,OAAO,KAAK,KAAK,EACyB,SAAS;CAGrE,MAAM,gCAAgB,IAAI,KAAkF;AAC5G,MAAK,MAAM,KAAK,QAAQ;AACtB,MAAI,CAAC,cAAc,IAAI,EAAE,gBAAgB,CAAE,eAAc,IAAI,EAAE,iBAAiB,EAAE,CAAC;AACnF,gBAAc,IAAI,EAAE,gBAAgB,CAAE,KAAK;GACzC,iBAAiB,EAAE;GACnB,OAAO,EAAE;GACT,QAAQ,EAAE;GACX,CAAC;;CAOJ,MAAM,kCAAkB,IAAI,KAAa;CACzC,MAAM,mCAAmB,IAAI,KAAa;CAC1C,MAAM,eAIA,EAAE;AACR,MAAK,MAAM,CAAC,WAAW,gBAAgB,eAAe;EAKpD,IAAI,cAAc;AAClB,MAAI,CAAC,YACH,MAAK,MAAM,SAAS,aAAa;AAC/B,QAAK,MAAM,KAAK,MAAM,OAAO;IAC3B,MAAM,IAAI,EAAE,MAAM,+BAA+B;AACjD,QAAI,KAAK,cAAc,IAAI,EAAE,GAAG,EAAE;AAChC,mBAAc,EAAE;AAChB;;;AAGJ,OAAI,YAAa;;AAGrB,MAAI,CAAC,YAAa;AAOlB,MAAI,CANkB,YAAY,MAAM,UACtC,MAAM,MAAM,MAAM,MAAM;AAEtB,UADU,EAAE,MAAM,+BAA+B,GACtC,OAAO;IAClB,CACH,CACmB;EACpB,MAAM,OAAO,cAAc,IAAI,YAAY;AAC3C,MAAI,CAAC,KAAM;EACX,MAAM,YAAY,0BAA0B,QAAQ,aAAa,KAAK,YAAY;AAClF,MAAI,YAAY,EAAG;EACnB,MAAM,UAAoB,EAAE;AAC5B,OAAK,MAAM,SAAS,aAAa;AAC/B,WAAQ,KAAK,GAAG;AAChB,WAAQ,KAAK,GAAG,MAAM,MAAM;;AAE9B,eAAa,KAAK;GAAE;GAAW,SAAS,KAAK;GAAa;GAAS,CAAC;AACpE,kBAAgB,IAAI,YAAY;AAChC,mBAAiB,IAAI,UAAU;;AAGjC,cAAa,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,UAAU;AACtD,MAAK,MAAM,OAAO,aAChB,QAAO,OAAO,IAAI,WAAW,IAAI,UAAU,IAAI,WAAW,GAAG,IAAI,QAAQ;CAS3E,IAAI,yBAAyB;CAC7B;EACE,MAAM,kBAAkB,cAAc,IAAI,GAAG;AAC7C,MAAI,iBAAiB;GAGnB,MAAM,gBAAgB,iBAAiB,IAAI,GAAG;GAC9C,MAAM,YAAoC,EAAE;AAC5C,QAAK,MAAM,SAAS,iBAAiB;IACnC,MAAM,UAAU,MAAM,+BAA+B,QAAQ,MAAM,OAAO,UAAU,CAAC,cAAc;AACnG,QAAI,QAAQ,OAAQ;AACpB,QAAI,CAAC,iBAAiB,CAAC,QAAQ,OAAQ,WAAU,KAAK,MAAM;;AAE9D,OAAI,CAAC,cACH,KAAI,UAAU,WAAW,EACvB,eAAc,OAAO,GAAG;OAExB,eAAc,IAAI,IAAI,UAAU;;;CAQxC,IAAI,yBAAyB;AAC7B,KAAI,gBAAgB,OAAO,KAAK,yBAAyB,EACvD,0BAAyB,MAAM,qBAAqB,OAAO,KAAK,KAAK,EAAE,SAAS;CAGlF,MAAM,aAAmE,EAAE;CAC3E,IAAI,iBAAiB;AACrB,MAAK,MAAM,CAAC,WAAW,gBAAgB,eAAe;AACpD,MAAI,iBAAiB,IAAI,UAAU,IAAI,gBAAgB,IAAI,UAAU,CAAE;EACvE,MAAM,OAAO,YAAY,uBAAuB,IAAI,UAAU,GAAG,KAAA;AAGjE,OAAK,MAAM,SAAS,aAAa;GAC/B,IAAI;GAWJ,MAAM,oBAAoB,eAAe,KAAK,MAAM,OAAO;AAC3D,OACE,MAAM,UACN,CAAC,MAAM,OAAO,SAAS,gBAAgB,IACvC,CAAC,qBACD,uBAAuB,KAAK,MAAM,OAAO;SAEpC,IAAI,KAAK,GAAG,KAAK,OAAO,QAAQ,KACnC,KAAI,OAAO,IAAI,WAAW,KAAK,MAAM,QAAQ;AAC3C,kBAAa;AACb;;;AAQN,OAAI,eAAe,KAAA,EACjB,KAAI,KACF,cAAa,KAAK;QACb;IACL,MAAM,eAAe,MAAM,kBACvB,yBAAyB,QAAQ,MAAM,gBAAgB,GACvD,KAAA;IACJ,MAAM,0BAA0B,MAAM,MAAM,MAAM,MAAc,sBAAsB,KAAK,EAAE,CAAC;AAC9F,QAAI,iBAAiB,KAAA,EACnB,cAAa;aACJ,2BAA2B,uBAAuB,MAAM,MAAM,EAAE;KACzE,IAAI,iBAAiB;AACrB,UAAK,IAAI,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM;MACzC,MAAM,UAAU,OAAO,IAAI,WAAW;AACtC,UAAI,mBAAmB,KAAK,QAAQ,CAAE,kBAAiB,KAAK;;AAE9D,kBAAa;UAEb,cAAa,OAAO;;AAU1B,OADwB,MAAM,MAAM,MAAM,MAAc,eAAe,KAAK,EAAE,CAAC,CAE7E,QACE,cAAc,KACd,OAAO,aAAa,IAAI,MAAM,KAAK,MACnC,4BAA4B,KAAK,OAAO,aAAa,MAAM,GAAG,CAE9D;GAQJ,MAAM,WAAW,aAAa,IAAK,OAAO,aAAa,IAAI,WAAW,IAAI,KAAM;GAGhF,MAAM,eAFe,YAAY,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,IACvD,aAAa,KAAK,aAAa,KACA,CAAC,GAAG,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,MAAM,MAAM;AAI1F,QADiB,OAAO,aAAa,WAAW,IAAI,IACvC,WAAW,MAAM,CAC5B,cAAa,KAAK,GAAG;AAEvB,cAAW,KAAK;IAAE,MAAM;IAAY,OAAO;IAAkB,SAAS;IAAc,CAAC;;;AAOzF,YAAW,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM;AAC/D,MAAK,MAAM,OAAO,WAChB,QAAO,OAAO,IAAI,MAAM,GAAG,GAAG,IAAI,QAAQ;AAG5C,6CAA4C,OAAO;AAEnD,QAAO,OAAO,KAAK,KAAK;;;;;;;;AAS1B,SAAS,mBAAmB,OAA2B;CACrD,MAAM,MAAgB,EAAE;CACxB,IAAI,WAAW;AACf,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,YAAY,KAAK,SAAS,sBAAsB,EAAE;AACrD,cAAW;AAGX,UAAO,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,GAAG,MAAM,KAAK,GAAI,KAAI,KAAK;AACrE;;AAEF,MAAI,UAAU;AACZ,OAAI,KAAK,SAAS,oBAAoB,CAAE,YAAW;AACnD;;AAEF,MAAI,KAAK,KAAK;;AAEhB,QAAO;;;AAIT,SAAS,oBAAoB,OAAiB,SAAyB;AACrE,KAAI,MAAM,KAAK,MAAM,YAAY,GAAG,CAAE,QAAO;AAI7C,MAAK,IAAI,IAAI,UAAU,GAAG,KAAK,GAAG,KAAK;EACrC,MAAM,IAAI,MAAM,GAAG,MACjB,uGACD;AACD,MAAI,EAAG,QAAO,EAAE;;AAElB,QAAO;;AAGT,SAAS,4BAA4B,OAAiB,SAAyB;CAC7E,MAAM,aAAa,MAAM,YAAY;AACrC,KAAI,MAAM,KAAK,WAAW,CAAE,QAAO;CACnC,MAAM,eAAe,cAAc,WAAW;AAC9C,MAAK,IAAI,IAAI,UAAU,GAAG,KAAK,GAAG,KAAK;EACrC,MAAM,OAAO,MAAM;AAEnB,MADe,cAAc,KAAK,IACpB,aAAc;EAC5B,MAAM,QAAQ,KAAK,MAAM,mCAAmC;AAC5D,MAAI,MAAO,QAAO,MAAM;AACxB,MAAI,gCAAgC,KAAK,KAAK,CAAE,QAAO;;AAEzD,QAAO;;AAGT,SAAS,yBAAyB,OAAiB,WAAuC;AACxF,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,QAAQ,MAAM,GAAG,MAAM,mCAAmC;AAChE,MAAI,CAAC,SAAS,MAAM,OAAO,UAAW;EAEtC,IAAI,QAAQ;AACZ,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAS,UAAU,MAAM,IAAI,IAAI;AACjC,YAAS,UAAU,MAAM,IAAI,IAAI;AACjC,OAAI,IAAI,KAAK,SAAS,EAAG,QAAO;;;;AAMtC,SAAS,cAAc,MAAsB;AAC3C,QAAO,KAAK,MAAM,OAAO,GAAG,GAAG,UAAU;;AAG3C,SAAS,UAAU,MAAc,MAAsB;AACrD,QAAO,CAAC,GAAG,KAAK,CAAC,QAAQ,MAAM,MAAM,KAAK,CAAC;;AAG7C,SAAS,uBAAuB,OAA0B;AACxD,QAAO,MAAM,MAAM,SACjB,4EAA4E,KAAK,KAAK,MAAM,CAAC,CAC9F;;;;;;AAOH,SAAS,0BAA0B,OAAiB,WAAmB,YAA4B;CAEjG,MAAM,eAAe,IAAI,OAAO,gCAAgC,UAAU,KAAK;AAC/E,MAAK,IAAI,IAAI,aAAa,GAAG,KAAK,GAAG,KAAK;AACxC,MAAI,CAAC,aAAa,KAAK,MAAM,GAAG,CAAE;EAElC,IAAI,QAAQ;AACZ,SAAO,QAAQ,KAAK,WAAW,KAAK,MAAM,QAAQ,GAAG,CACnD;AAEF,SAAO;;AAET,QAAO;;;;;;;;;;AAaT,MAAM,6BACJ;;AAGF,SAAS,2BAA2B,YAAmC;CACrE,MAAM,wBAAQ,IAAI,KAAa;AAC/B,MAAK,MAAM,QAAQ,YAAY;AAC7B,MAAI,KAAK,SAAS,gBAAgB,CAAE;EACpC,MAAM,IAAI,KAAK,MAAM,2BAA2B;AAChD,MAAI,EAAG,OAAM,IAAI,EAAE,GAAG;;AAExB,QAAO;;;AAIT,SAAS,8BAA8B,OAAwD;CAC7F,MAAM,SAAgD,EAAE;CACxD,IAAI,QAAQ;AACZ,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,MAAI,UAAU,MAAM,MAAM,GAAG,SAAS,sBAAsB,EAAE;AAC5D,WAAQ;AACR;;AAEF,MAAI,UAAU,MAAM,MAAM,GAAG,SAAS,oBAAoB,EAAE;AAC1D,UAAO,KAAK;IAAE;IAAO,KAAK;IAAG,CAAC;AAC9B,WAAQ;;;AAGZ,QAAO;;;;;;;;AAST,SAAS,4BAA4B,OAAiB,WAA2B;CAC/E,IAAI,IAAI;AACR,QAAO,IAAI,GAAG;EACZ,MAAM,OAAO,MAAM,IAAI,GAAG,MAAM;AAChC,MAAI,SAAS,MAAM,KAAK,SAAS,gBAAgB,CAAE;AAEnD,MAAI,EADc,KAAK,WAAW,KAAK,IAAI,KAAK,WAAW,KAAK,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,EAChG;AAChB;;AAEF,QAAO;;;;;;;;;;;;AAaT,eAAe,+BACb,QACA,YACA,UACA,YAC+C;CAC/C,MAAM,QAAQ,2BAA2B,WAAW;AACpD,KAAI,MAAM,SAAS,EAAG,QAAO;EAAE,QAAQ;EAAO,QAAQ;EAAO;CAE7D,MAAM,SAAS,OAAO,KAAK,KAAK;CAChC,IAAI;AACJ,KAAI;AACF,WAAS,MAAM,kBAAkB,QAAQ,SAAS;SAC5C;AACN,SAAO;GAAE,QAAQ;GAAO,QAAQ;GAAO;;CAGzC,MAAM,eAAe,8BAA8B,OAAO;CAC1D,MAAM,YAAY,SAAiB,aAAa,MAAM,MAAM,QAAQ,EAAE,SAAS,QAAQ,EAAE,IAAI;CAE7F,MAAM,QAA+C,EAAE;AACvD,MAAK,MAAM,QAAQ,OAAO,YAAY;AACpC,MAAI,KAAK,SAAS,iBAAiB,CAAC,KAAK,OAAO,CAAC,MAAM,IAAI,KAAK,IAAI,CAAE;EAGtE,IAAI,MAAM,OAAO,QAAQ,KAAK,KAAK;EACnC,IAAI,YAAY;AAChB,SAAO,QAAQ,IAAI;GACjB,MAAM,OAAO,OAAO,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,SAAS;AACvD,OAAI,CAAC,SAAS,KAAK,EAAE;AACnB,gBAAY;AACZ;;AAEF,SAAM,OAAO,QAAQ,KAAK,MAAM,MAAM,EAAE;;AAE1C,MAAI,cAAc,GAAI;EACtB,MAAM,UAAU,YAAY,KAAK,KAAK,MAAM,KAAK,CAAC,SAAS;AAC3D,QAAM,KAAK;GAAE,OAAO,4BAA4B,QAAQ,UAAU;GAAE,KAAK;GAAS,CAAC;;AAErF,KAAI,MAAM,WAAW,EAAG,QAAO;EAAE,QAAQ;EAAO,QAAQ;EAAO;AAE/D,OAAM,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAGvC,MAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;EAC1C,MAAM,OAAO,MAAM;EACnB,IAAI,cAAc,KAAK,MAAM,KAAK,QAAQ;EAE1C,MAAM,YAAY,KAAK,UAAU,MAAM,OAAO,KAAK,QAAQ,MAAM,IAAI,MAAM,KAAK;EAChF,MAAM,aAAa,OAAO,KAAK,MAAM,MAAM,IAAI,MAAM,KAAK;AAC1D,MAAI,aAAa,aAAa,KAAK,MAAM,IAAI,OAAO,OAAQ;AAC5D,SAAO,OAAO,KAAK,OAAO,YAAY;;CAGxC,MAAM,QAAQ,MAAM;AACpB,KAAI,YAAY;AACd,SAAO,OAAO,MAAM,OAAO,MAAM,MAAM,MAAM,QAAQ,GAAG,GAAG,WAAW;AACtE,SAAO;GAAE,QAAQ;GAAM,QAAQ;GAAM;;CAGvC,IAAI,cAAc,MAAM,MAAM,MAAM,QAAQ;CAC5C,MAAM,YAAY,MAAM,UAAU,MAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,MAAM,KAAK;CAClF,MAAM,aAAa,OAAO,MAAM,MAAM,MAAM,IAAI,MAAM,KAAK;AAC3D,KAAI,aAAa,aAAa,MAAM,MAAM,IAAI,OAAO,OAAQ;AAC7D,QAAO,OAAO,MAAM,OAAO,YAAY;AACvC,QAAO;EAAE,QAAQ;EAAO,QAAQ;EAAM;;;;;;AAOxC,SAAS,mBAAmB,OAA2C;CACrE,MAAM,2BAAW,IAAI,KAA0B;AAC/C,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,MAAI,CAAC,WAAW,KAAK,MAAM,GAAG,CAAE;EAEhC,IAAI,WAAW,MAAM;AACrB,MAAI,SAAS,SAAS,IAAI,IAAI,CAAC,SAAS,SAAS,IAAI,CACnD,QAAO,IAAI,IAAI,MAAM,QAAQ;AAC3B;AACA,eAAY,MAAM,MAAM,GAAG,MAAM;AACjC,OAAI,MAAM,GAAG,SAAS,IAAI,CAAE;;EAKhC,MAAM,QADa,SAAS,QAAQ,SAAS,GAAG,CAAC,QAAQ,QAAQ,IAAI,CAAC,MAAM,CACnD,MAAM,iCAAiC;AAChE,MAAI,CAAC,MAAO;EAEZ,MAAM,MAAM,MAAM;AAClB,MAAI,CAAC,SAAS,IAAI,IAAI,CAAE,UAAS,IAAI,qBAAK,IAAI,KAAK,CAAC;AACpD,OAAK,MAAM,MAAM,MAAM,GACpB,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ,CAChB,UAAS,IAAI,IAAI,CAAE,IAAI,GAAG;;AAG9B,QAAO;;;;;;;AAyBT,SAAS,iBAAiB,OAA4B;CACpD,MAAM,MAAiB;EACrB,uBAAO,IAAI,KAAK;EAChB,0BAAU,IAAI,KAAK;EACnB,0BAAU,IAAI,KAAK;EACnB,4BAAY,IAAI,KAAK;EACrB,6BAAa,IAAI,KAAK;EACvB;AAED,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,UAAU,MAAM,GAAG,MAAM;AAC/B,MAAI,CAAC,gBAAgB,KAAK,QAAQ,CAAE;EAGpC,IAAI,WAAW,MAAM;AACrB,MAAI,SAAS,SAAS,IAAI,IAAI,CAAC,SAAS,SAAS,IAAI,CACnD,QAAO,IAAI,IAAI,MAAM,QAAQ;AAC3B;AACA,eAAY,MAAM,MAAM,GAAG,MAAM;AACjC,OAAI,MAAM,GAAG,SAAS,IAAI,CAAE;;EAIhC,MAAM,aAAa,SAAS,QAAQ,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,SAAS,GAAG;EAG5E,IAAI,IAAI,WAAW,MAAM,8BAA8B;AACvD,MAAI,GAAG;AACL,OAAI,YAAY,IAAI,EAAE,GAAG;AACzB;;AAIF,MAAI,WAAW,MAAM,uDAAuD;AAC5E,MAAI,GAAG;AACL,OAAI,WAAW,IAAI,EAAE,IAAI,EAAE,GAAG;AAC9B;;AAIF,MAAI,WAAW,MAAM,oFAAoF;AACzG,MAAI,GAAG;GACL,MAAM,aAAa,CAAC,CAAC,EAAE;GACvB,MAAM,cAAc,EAAE;GACtB,MAAM,WAAW,EAAE;GACnB,MAAM,MAAM,EAAE;AACd,OAAI,YAAa,KAAI,SAAS,IAAI,KAAK,YAAY;GACnD,MAAM,QAAQ,SACX,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,QAAQ,gBAAgB,GAAG,CAAC,CAChD,OAAO,QAAQ;AAClB,QAAK,MAAM,WAAW,OAAO;IAC3B,MAAM,mBAAmB,QAAQ,WAAW,QAAQ;IACpD,MAAM,OAAO,QAAQ,QAAQ,YAAY,GAAG;IAC5C,MAAM,SAAS,cAAc,mBAAmB,IAAI,WAAW,IAAI;AACnE,QAAI,CAAC,OAAO,IAAI,IAAI,CAAE,QAAO,IAAI,qBAAK,IAAI,KAAK,CAAC;AAChD,WAAO,IAAI,IAAI,CAAE,IAAI,KAAK;;AAE5B;;AAIF,MAAI,WAAW,MAAM,yDAAyD;AAC9E,MAAI,GAAG;AACL,OAAI,SAAS,IAAI,EAAE,IAAI,EAAE,GAAG;AAC5B;;;AAIJ,QAAO;;;;;;;;;;;;;;;AAgBT,SAAS,8BAA8B,aAAuB,SAA4B;AACxF,KAAI,QAAQ,SAAS,EAAG;CACxB,MAAM,MAAgB,EAAE;AACxB,MAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;EAC3C,MAAM,OAAO,YAAY;EACzB,MAAM,UAAU,KAAK,MAAM;AAE3B,MAAI,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,QAAQ,SAAS,IAAI,EAAE;AACxD,OAAI,KAAK,KAAK;AACd;;EAGF,MAAM,OAAO,CAAC,KAAK;AACnB,SAAO,CAAC,KAAK,KAAK,IAAI,CAAC,SAAS,IAAI,IAAI,IAAI,IAAI,YAAY,QAAQ;AAClE;AACA,QAAK,KAAK,YAAY,GAAG;;EAG3B,MAAM,IADa,KAAK,KAAK,IAAI,CAAC,QAAQ,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,SAAS,GAAG,CAC7D,MAAM,oFAAoF;AAC/G,MAAI,CAAC,GAAG;AACN,QAAK,MAAM,KAAK,KAAM,KAAI,KAAK,EAAE;AACjC;;EAEF,MAAM,aAAa,CAAC,CAAC,EAAE;EACvB,MAAM,cAAc,EAAE;EACtB,MAAM,QAAQ,EAAE,GACb,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ;EAClB,MAAM,YAAY,EAAE;EACpB,MAAM,OAAO,MAAM,QAAQ,QAAQ;GACjC,MAAM,gBAAgB,cAAc,IAAI,WAAW,QAAQ;GAC3D,MAAM,OAAO,IAAI,QAAQ,YAAY,GAAG;AACxC,UAAO,EAAE,iBAAiB,QAAQ,IAAI,KAAK;IAC3C;AACF,MAAI,KAAK,WAAW,MAAM,QAAQ;AAEhC,QAAK,MAAM,KAAK,KAAM,KAAI,KAAK,EAAE;AACjC;;AAEF,MAAI,KAAK,WAAW,KAAK,CAAC,YAAa;EACvC,MAAM,OAAO,KAAK,MAAM,SAAS,GAAG,MAAM;EAC1C,MAAM,SAAS,aAAa,iBAAiB;EAC7C,MAAM,cAAc,cAAc,GAAG,YAAY,MAAM;AACvD,MAAI,KAAK,GAAG,OAAO,SAAS,YAAY,IAAI,KAAK,KAAK,KAAK,CAAC,UAAU,UAAU,GAAG;;AAErF,aAAY,OAAO,GAAG,YAAY,QAAQ,GAAG,IAAI;;;;;;;;;;;;;;AAenD,SAAS,uBAAuB,OAA2B;CACzD,MAAM,MAAgB,EAAE;CACxB,IAAI,WAAW;AACf,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,YAAY,KAAK,SAAS,sBAAsB,EAAE;AACrD,cAAW;AACX;;AAEF,MAAI,UAAU;AACZ,OAAI,KAAK,SAAS,oBAAoB,CAAE,YAAW;AACnD;;AAEF,MAAI,KAAK,KAAK;;AAEhB,QAAO;;AAGT,SAAS,6BAA6B,OAAyB;CAC7D,MAAM,MAAgB,EAAE;CACxB,IAAI,WAAW;AACf,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,YAAY,KAAK,SAAS,sBAAsB,EAAE;AACrD,cAAW;AACX;;AAEF,MAAI,CAAC,SAAU;AACf,MAAI,sBAAsB,KAAK,KAAK,CAAE;AACtC,MAAI,KAAK,KAAK;AACd,MAAI,KAAK,SAAS,oBAAoB,CAAE,YAAW;;AAErD,QAAO,IAAI,KAAK,KAAK;;AAGvB,SAAS,4CAA4C,OAAuB;CAC1E,MAAM,iCAAiB,IAAI,KAAa;CACxC,MAAM,mBAAmB,wBAAwB,MAAM;AACvD,MAAK,MAAM,QAAQ,iBACjB,KAAI,KAAK,SAAU,gBAAe,IAAI,yBAAyB,KAAK,MAAM,CAAC;AAE7E,KAAI,eAAe,SAAS,EAAG;AAE/B,MAAK,MAAM,QAAQ,CAAC,GAAG,iBAAiB,CAAC,SAAS,EAAE;AAClD,MAAI,KAAK,SAAU;AACnB,MAAI,eAAe,IAAI,yBAAyB,KAAK,MAAM,CAAC,CAC1D,OAAM,OAAO,KAAK,OAAO,KAAK,MAAM,KAAK,QAAQ,EAAE;;;AAKzD,SAAS,wBACP,OAC2E;CAC3E,MAAM,aAAwF,EAAE;CAChG,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,OAAO,MAAM;AACnB,MAAI,CAAC,YAAY,KAAK,SAAS,sBAAsB,EAAE;AACrD,cAAW;AACX;;AAEF,MAAI,YAAY,KAAK,SAAS,oBAAoB,EAAE;AAClD,cAAW;AACX;;AAEF,MAAI,CAAC,aAAa,KAAK,CAAE;EAEzB,MAAM,QAAQ;EACd,IAAI,MAAM;EACV,MAAM,iBAAiB,CAAC,KAAK;AAG7B,OAFe,KAAK,MAAM,QAAQ,IAAI,EAAE,EAAE,UAC1B,KAAK,MAAM,QAAQ,IAAI,EAAE,EAAE,QACvB;AAClB,UAAO,MAAM,IAAI,MAAM,QAAQ;AAC7B;AACA,mBAAe,KAAK,MAAM,KAAK;AAC/B,SAAK,MAAM,KAAK,MAAM,QAAQ,IAAI,EAAE,EAAE,SAAS,KAAK,WAAW,KAAK,MAAM,KAAK,CAAE;;AAEnF,OAAI;;AAEN,aAAW,KAAK;GAAE;GAAO;GAAK,OAAO;GAAgB;GAAU,CAAC;;AAElE,QAAO;;AAGT,SAAS,yBAAyB,OAAyB;AACzD,QAAO,MAAM,KAAK,KAAK,CAAC,QAAQ,UAAU,KAAK,CAAC,QAAQ,QAAQ,IAAI,CAAC,MAAM;;AAG7E,SAAS,aAAa,MAAuB;CAC3C,MAAM,UAAU,KAAK,MAAM;AAC3B,QACE,gBAAgB,KAAK,QAAQ,IAC7B,WAAW,KAAK,QAAQ,IACxB,gBAAgB,KAAK,QAAQ,IAC7B,8BAA8B,KAAK,QAAQ;;AAI/C,SAAS,eAAe,QAAgB,YAA6B;AACnE,QAAO,IAAI,OAAO,MAAM,WAAW,QAAQ,uBAAuB,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO;;AAG9F,SAAS,mBAAmB,eAAyB,aAA6B;CAIhF,MAAM,wBAAwB,uBAAuB,cAAc;CACnE,MAAM,mBAAmB,6BAA6B,cAAc;CAMpE,MAAM,wBAAwB,MAAc,eAAe,KAAK,EAAE,IAAI,CAAC,WAAW,KAAK,EAAE,IAAI,CAAC,OAAO,KAAK,EAAE;CAG5G,MAAM,iBAAiB,IAAI,IAAI,sBAAsB,OAAO,qBAAqB,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;CACvG,MAAM,kBAAkB,IAAI,IAAI,YAAY,OAAO,qBAAqB,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9F,MAAM,cAAc,CAAC,GAAG,eAAe,CAAC,QAAQ,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC;CAG9E,MAAM,eAAe,mBAAmB,sBAAsB;CAC9D,MAAM,gBAAgB,mBAAmB,YAAY;CAKrD,MAAM,kCAAkB,IAAI,KAAa;AACzC,MAAK,MAAM,OAAO,cAAc,QAAQ,CACtC,MAAK,MAAM,MAAM,IAAK,iBAAgB,IAAI,GAAG;CAG/C,MAAM,iBAA2B,EAAE;AACnC,MAAK,MAAM,CAAC,KAAK,aAAa,cAAc;EAC1C,MAAM,SAAS,cAAc,IAAI,IAAI;AACrC,MAAI,CAAC,QAAQ;GAGX,MAAM,QAAQ,CAAC,GAAG,SAAS,CAAC,QAAQ,OAAO,CAAC,gBAAgB,IAAI,GAAG,CAAC;AACpE,OAAI,MAAM,SAAS,EACjB,gBAAe,KAAK,QAAQ,IAAI,UAAU,MAAM,KAAK,KAAK,GAAG;SAE1D;GACL,MAAM,QAAQ,CAAC,GAAG,SAAS,CAAC,QAAQ,OAAO,CAAC,OAAO,IAAI,GAAG,IAAI,CAAC,gBAAgB,IAAI,GAAG,CAAC;AACvF,OAAI,MAAM,SAAS,EACjB,gBAAe,KAAK,QAAQ,IAAI,UAAU,MAAM,KAAK,KAAK,GAAG;;;CAMnE,MAAM,aAAa,iBAAiB,sBAAsB;CAC1D,MAAM,cAAc,iBAAiB,YAAY;CACjD,MAAM,eAAyB,EAAE;CAiBjC,MAAM,oCAAoB,IAAI,KAAa;CAC3C,MAAM,oCAAoB,IAAI,KAAa;AAC3C,MAAK,MAAM,OAAO,YAAY,MAAM,QAAQ,CAC1C,MAAK,MAAM,MAAM,KAAK;AACpB,oBAAkB,IAAI,GAAG;AACzB,oBAAkB,IAAI,GAAG;;AAE7B,MAAK,MAAM,OAAO,YAAY,SAAS,QAAQ,CAAE,MAAK,MAAM,MAAM,IAAK,mBAAkB,IAAI,GAAG;AAChG,MAAK,MAAM,QAAQ,YAAY,SAAS,QAAQ,EAAE;AAChD,oBAAkB,IAAI,KAAK;AAC3B,oBAAkB,IAAI,KAAK;;AAE7B,MAAK,MAAM,QAAQ,YAAY,WAAW,QAAQ,EAAE;AAClD,oBAAkB,IAAI,KAAK;AAC3B,oBAAkB,IAAI,KAAK;;CAQ7B,MAAM,oCAAoB,IAAI,KAAa;CAC3C,MAAM,qBAAqB,OAAwB,kBAAkB,IAAI,GAAG;CAC5E,MAAM,wBAAwB,OAAwB,kBAAkB,IAAI,GAAG,IAAI,CAAC,kBAAkB,IAAI,GAAG;AAE7G,MAAK,MAAM,OAAO,WAAW,YAC3B,KAAI,CAAC,YAAY,YAAY,IAAI,IAAI,CAAE,cAAa,KAAK,WAAW,IAAI,IAAI;AAE9E,MAAK,MAAM,CAAC,KAAK,SAAS,WAAW,UAAU;AAC7C,MAAI,YAAY,SAAS,IAAI,IAAI,CAAE;AACnC,MAAI,CAAC,eAAe,kBAAkB,KAAK,CAAE;AAC7C,MAAI,kBAAkB,KAAK,CAAE;AAC7B,MAAI,qBAAqB,KAAK,CAAE,mBAAkB,IAAI,KAAK;AAC3D,eAAa,KAAK,UAAU,KAAK,SAAS,IAAI,IAAI;;AAEpD,MAAK,MAAM,CAAC,KAAK,SAAS,WAAW,YAAY;AAC/C,MAAI,CAAC,eAAe,kBAAkB,KAAK,CAAE;AAC7C,MAAI,kBAAkB,KAAK,CAAE;AAC7B,MAAI,YAAY,WAAW,IAAI,IAAI,CAAE;AACrC,MAAI,qBAAqB,KAAK,CAAE,mBAAkB,IAAI,KAAK;AAC3D,eAAa,KAAK,eAAe,KAAK,SAAS,IAAI,IAAI;;AAEzD,MAAK,MAAM,CAAC,KAAK,aAAa,WAAW,OAAO;EAC9C,MAAM,QAAQ,CAAC,GAAG,SAAS,CAAC,QAAQ,OAAO,CAAC,kBAAkB,GAAG,IAAI,eAAe,kBAAkB,GAAG,CAAC;AAC1G,OAAK,MAAM,MAAM,MAAO,KAAI,qBAAqB,GAAG,CAAE,mBAAkB,IAAI,GAAG;AAC/E,MAAI,MAAM,SAAS,EAAG,cAAa,KAAK,YAAY,MAAM,KAAK,KAAK,CAAC,WAAW,IAAI,IAAI;;AAE1F,MAAK,MAAM,CAAC,KAAK,aAAa,WAAW,UAAU;EACjD,MAAM,QAAQ,CAAC,GAAG,SAAS,CAAC,QAAQ,OAAO,CAAC,kBAAkB,IAAI,GAAG,IAAI,eAAe,kBAAkB,GAAG,CAAC;AAC9G,MAAI,MAAM,SAAS,EAAG,cAAa,KAAK,iBAAiB,MAAM,KAAK,KAAK,CAAC,WAAW,IAAI,IAAI;;AAK/F,+BAA8B,aAAa,kBAAkB;CAK7D,MAAM,kBAAkB,MAAc,8CAA8C,KAAK,EAAE;CAC3F,MAAM,iBAAiB,IAAI,IAAI,sBAAsB,OAAO,eAAe,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;CACjG,MAAM,kBAAkB,IAAI,IAAI,YAAY,OAAO,eAAe,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;CACxF,MAAM,cAAc,CAAC,GAAG,eAAe,CAAC,QAAQ,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC;CAM9E,MAAM,gBAAgB;CACtB,MAAM,kBAAkB,MAAkC;EACxD,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,cAAc;AACvC,SAAO,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,KAAA;;CAElC,MAAM,2CAA2B,IAAI,KAAa;AAClD,MAAK,MAAM,KAAK,aAAa;EAC3B,MAAM,MAAM,eAAe,EAAE;AAC7B,MAAI,IAAK,0BAAyB,IAAI,IAAI;;CAE5C,MAAM,mCAAmB,IAAI,KAAa;CAC1C,MAAM,mBAA6B,EAAE;AACrC,MAAK,MAAM,KAAK,uBAAuB;EACrC,MAAM,MAAM,eAAe,EAAE;AAC7B,MAAI,CAAC,IAAK;AACV,MAAI,yBAAyB,IAAI,IAAI,CAAE;AACvC,MAAI,iBAAiB,IAAI,IAAI,CAAE;AAC/B,mBAAiB,IAAI,IAAI;AACzB,mBAAiB,KAAK,EAAE,MAAM,CAAC;;CAGjC,MAAM,WAAW;EAAC,GAAG;EAAa,GAAG;EAAgB,GAAG;EAAc,GAAG;EAAa,GAAG;EAAiB;AAC1G,KAAI,SAAS,WAAW,EAAG;CAK3B,MAAM,iBAAiB,MACrB,mBAAmB,KAAK,EAAE,IAC1B,WAAW,KAAK,EAAE,IAClB,mBAAmB,KAAK,EAAE,IAC1B,iCAAiC,KAAK,EAAE;CAC1C,IAAI,gBAAgB;AACpB,MAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,MAAI,CAAC,cAAc,YAAY,GAAG,CAAE;AACpC,kBAAgB;AAGhB,OAFe,YAAY,GAAG,MAAM,QAAQ,IAAI,EAAE,EAAE,UACpC,YAAY,GAAG,MAAM,QAAQ,IAAI,EAAE,EAAE,OAEnD,QAAO,IAAI,IAAI,YAAY,QAAQ;AACjC;AACA,mBAAgB;AAChB,QAAK,YAAY,GAAG,MAAM,QAAQ,IAAI,EAAE,EAAE,SAAS,EAAG;;;AAK5D,KAAI,iBAAiB,GAAG;AACtB,cAAY,OAAO,gBAAgB,GAAG,GAAG,GAAG,SAAS;AACrD;;CAMF,IAAI,WAAW;CACf,IAAI,iBAAiB;AACrB,MAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;EAC3C,MAAM,IAAI,YAAY,GAAG,MAAM;AAC/B,MAAI,gBAAgB;AAClB,cAAW,IAAI;AACf,OAAI,EAAE,SAAS,KAAK,CAAE,kBAAiB;AACvC;;AAEF,MAAI,EAAE,WAAW,KAAK,EAAE;AACtB,cAAW,IAAI;AACf;;AAEF,MAAI,EAAE,WAAW,KAAK,EAAE;AACtB,cAAW,IAAI;AACf,oBAAiB,CAAC,EAAE,SAAS,KAAK;AAClC;;AAEF;;AAEF,aAAY,OAAO,UAAU,GAAG,GAAG,SAAS;;;;;AC3tC9C,SAAS,QAAQ,GAAmB;AAClC,QAAO,EACJ,QAAQ,mBAAmB,QAAQ,CACnC,QAAQ,YAAY,IAAI,CACxB,aAAa;;;;;;;AAgGlB,MAAM,eAAe,IAAI,IAAI;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,MAAM,YAAwC;CAC5C,KAAK;CACL,MAAM;CACN,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,SAAS;CACT,OAAO;CACR;;;;;AAMD,SAAS,YAAY,MAAsB;AACzC,KAAI,KAAK,UAAU,EAAG,QAAO;AAC7B,KAAI,KAAK,SAAS,MAAM,CAAE,QAAO,KAAK,MAAM,GAAG,GAAG,GAAG;AACrD,KACE,KAAK,SAAS,MAAM,IACpB,KAAK,SAAS,MAAM,IACpB,KAAK,SAAS,MAAM,IACpB,KAAK,SAAS,OAAO,IACrB,KAAK,SAAS,OAAO,CAErB,QAAO,KAAK,MAAM,GAAG,GAAG;AAE1B,KAAI,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,KAAK,CAAE,QAAO;AAC9E,KAAI,KAAK,SAAS,IAAI,CAAE,QAAO,KAAK,MAAM,GAAG,GAAG;AAChD,QAAO;;;;;;;;;;;;;AAcT,SAAgB,iBAAiB,IAAe,UAA2B;CACzE,MAAM,WAAW,GAAG,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;CAGnD,MAAM,iBAA2B,EAAE;CACnC,IAAI,gBAAgB;AACpB,MAAK,MAAM,OAAO,SAChB,KAAI,IAAI,WAAW,IAAI,IAAI,IAAI,SAAS,IAAI,CAC1C,iBAAgB;MACX;AACL,iBAAe,KAAK,IAAI;AACxB,kBAAgB;;AAIpB,KAAI,eAAe,WAAW,EAC5B,QAAO,GAAG,UAAU,GAAG,eAAe,MAAM;CAG9C,MAAM,WAAW,QAAQ,eAAe,eAAe,SAAS,GAAG;AAGnE,KAAI,aAAa,IAAI,SAAS,EAAE;EAE9B,MAAM,UAAU,eAAe,MAAM,GAAG,GAAG,CAAC,QAAQ,MAAM,CAAC,EAAE,WAAW,IAAI,CAAC;EAC7E,MAAM,WAAW,QAAQ,SAAS,IAAI,QAAQ,YAAY,QAAQ,QAAQ,SAAS,GAAG,CAAC,GAAG;AAC1F,MAAI,SACF,QAAO,GAAG,SAAS,GAAG;AAExB,SAAO;;CAIT,IAAI,OAAO,UAAU,GAAG,eAAe;AAGvC,KAAI,GAAG,eAAe,SAAS,cAC7B,QAAO;CAOT,IAAI,WAAW,QAAQ,SAAS;AAChC,KAAI,eAAe,UAAU,GAAG;EAC9B,MAAM,cAAc,eAAe,eAAe,SAAS;EAG3D,MAAM,SAAS,SAAS,YAAY,YAAY;EAChD,MAAM,UAAU,SAAS,YAAY,eAAe,eAAe,SAAS,GAAG;AAE/E,MADwB,SAAS,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,MAAM,EAAE,WAAW,IAAI,CAAC,CAGxF,YAAW,GADI,QAAQ,YAAY,YAAY,CAAC,CAC3B,GAAG;;CAS5B,MAAM,OADmB,iBAAiB,SAAS,WACnB,YAAY,SAAS,GAAG;AAKxD,QAAO,GAAG,KAAK,GAFG,SAAS,SAAS,WAAW;;;;;;;;;;AAajD,SAAgB,kBACd,MACA,OACA,YACqB;CACrB,MAAM,WAAgC,EAAE;CACxC,MAAM,UAAU,SAAS,EAAE;CAC3B,MAAM,SAAS,cAAc,EAAE;AAE/B,MAAK,MAAM,WAAW,KAAK,SACzB,MAAK,MAAM,MAAM,QAAQ,YAAY;EAEnC,MAAM,OAAO,QADD,GAAG,GAAG,WAAW,aAAa,CAAC,GAAG,GAAG;EAIjD,MAAM,aAAa,MAAM,QAAQ,iBAAiB,IAAI,QAAQ;EAG9D,MAAM,UAAU,MAAM,WAAW,OAAO,QAAQ,SAAS,QAAQ;EAGjE,IAAI;AACJ,MAAI,MAAM,MACR,YAAW,KAAK,MAAM,KAAK,QAAQ;GACjC,MAAM,GAAG;GACT,eAAe,GAAG;GAClB,UAAU,GAAG,YAAY,EAAE;GAC3B,iBAAiB,GAAG,mBAAmB,EAAE;GACzC,eAAe,GAAG,iBAAiB,EAAE;GACrC,gBAAgB,GAAG,kBAAkB,EAAE;GACvC,mBAAmB,yBAAyB,GAAG;GAChD,EAAE;AAGL,WAAS,KAAK;GACZ,WAAW;GACX;GACA;GACA;GACA;GACA,UAAU,MAAM,YAAY,EAAE;GAC9B,iBAAiB,MAAM,mBAAmB,EAAE;GAC5C,YAAY,MAAM,cAAc;GACjC,CAAC;;AAIN,QAAO;;;AAIT,SAAS,yBAAyB,IAA8B;AAC9D,KAAI,GAAG,eAAe,SAAU,QAAO;CACvC,MAAM,MAAM,GAAG;AACf,KAAI,IAAI,SAAS,QAAS,QAAO,IAAI;AACrC,KAAI,IAAI,SAAS,cAAc,IAAI,MAAM,SAAS,QAAS,QAAO,IAAI,MAAM;AAC5E,QAAO;;;;ACtST,SAAgB,oBACd,MACA,SAagB;CAChB,MAAM,qBAAqB,kBAAkB,MAAM,QAAQ,gBAAgB,QAAQ,WAAW;CAO9F,IAAI;CACJ,IAAI;AACJ,KAAI,QAAQ,kBAAkB,QAAQ,eAAe,OAAO,GAAG;EAC7D,MAAM,WAAW,QAAQ;EAIzB,MAAM,YAAY,uBAHa,KAAK,SAAS,QAAQ,MACnD,mBAAmB,MAAM,MAAM,EAAE,QAAQ,SAAS,EAAE,QAAQ,SAAS,IAAI,EAAE,QAAQ,CAAC,CACrF,EACgE,KAAK,QAAQ,EAAE,0BAA0B,OAAO,CAAC;AAClH,qBAAmB,UAAU;AAC7B,oBAAkB,UAAU;;AAG9B,QAAO;EACL,WAAW,YAAY,QAAQ,UAAU;EACzC,iBAAiB,QAAQ;EACzB;EACA,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB,eAAe,QAAQ;EACvB;EACA,YAAY,QAAQ;EACpB,gBAAgB,QAAQ;EACxB,WAAW,QAAQ;EACnB,0BAA0B,QAAQ;EAClC,gBAAgB,QAAQ;EACxB;EACA;EACD;;;;;;;AAQH,SAAgB,uBACd,UACA,QACA,OAA+C,EAAE,EACJ;CAM7C,MAAM,2BAA2B,KAAK,6BAA6B;CACnE,MAAM,mCAAmB,IAAI,KAAa;CAC1C,MAAM,kCAAkB,IAAI,KAAa;CAEzC,MAAM,sBAAsB,QAAuB;AACjD,cAAY,KAAK;GACf,QAAQ,MAAM,iBAAiB,IAAI,EAAE,KAAK;GAC1C,OAAO,MAAM,gBAAgB,IAAI,EAAE,KAAK;GACzC,CAAC;;AAIJ,MAAK,MAAM,WAAW,SACpB,MAAK,MAAM,MAAM,QAAQ,YAAY;AACnC,OAAK,MAAM,KAAK;GAAC,GAAG,GAAG;GAAY,GAAG,GAAG;GAAa,GAAG,GAAG;GAAc,GAAI,GAAG,gBAAgB,EAAE;GAAE,CACnG,oBAAmB,EAAE,KAAK;AAE5B,MAAI,GAAG,YAAa,oBAAmB,GAAG,YAAY;AACtD,qBAAmB,GAAG,SAAS;AAC/B,MAAI,GAAG,WAAY,oBAAmB,GAAG,WAAW,SAAS;AAC7D,OAAK,MAAM,OAAO,GAAG,OACnB,KAAI,IAAI,KAAM,oBAAmB,IAAI,KAAK;AAE5C,MAAI,GAAG,iBACL,MAAK,MAAM,MAAM,GAAG,iBAClB,oBAAmB,GAAG,KAAK;;AAgBnC,KAAI,yBACF,MAAK,MAAM,SAAS,QAAQ;AAC1B,MAAI,qBAAqB,MAAM,CAC7B,kBAAiB,IAAI,MAAM,KAAK;EAElC,MAAM,OAAO,MAAM;AACnB,MAAI,MAAM,QACR,MAAK,MAAM,eAAe,OAAO,OAAO,KAAK,QAAQ,CACnD,kBAAiB,IAAI,YAAY;;CAOzC,MAAM,eAAe,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAC5D,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,QAAQ,CAAC,GAAG,iBAAiB;AACnC,QAAO,MAAM,SAAS,GAAG;EACvB,MAAM,OAAO,MAAM,KAAK;AACxB,MAAI,QAAQ,IAAI,KAAK,CAAE;AACvB,UAAQ,IAAI,KAAK;EACjB,MAAM,QAAQ,aAAa,IAAI,KAAK;AACpC,MAAI,CAAC,MAAO;EAIZ,MAAM,OAAO,MAAM;AACnB,MAAI,MAAM;QACH,MAAM,eAAe,OAAO,OAAO,KAAK,QAAQ,CACnD,KAAI,CAAC,iBAAiB,IAAI,YAAY,EAAE;AACtC,qBAAiB,IAAI,YAAY;AACjC,UAAM,KAAK,YAAY;;;AAI7B,OAAK,MAAM,SAAS,MAAM,QAAQ;AAChC,sBAAmB,MAAM,KAAK;AAE9B,QAAK,MAAM,KAAK,iBACd,KAAI,CAAC,QAAQ,IAAI,EAAE,CAAE,OAAM,KAAK,EAAE;;;AAKxC,QAAO;EAAE,QAAQ;EAAkB,OAAO;EAAiB;;AAG7D,SAAS,qBAAqB,OAAuB;AACnD,QAAO,MAAM,OAAO,MACjB,WACE,MAAM,SAAS,WAAW,MAAM,SAAS,UAAU,MAAM,SAAS,aAAa,MAAM,KAAK,SAAS,UACvG;;;;;;;;;;;;AAaH,SAAgB,iBAAiB,MAAe,SAAkB,KAAsC;CACtG,MAAM,aAAa,uBAAuB,KAAK,UAAU,KAAK,OAAO;CACrE,MAAM,kBAAkB,KAAK,OAAO,QAAQ,MAAM,WAAW,OAAO,IAAI,EAAE,KAAK,CAAC;CAChF,MAAM,iBAAiB,KAAK,MAAM,QAAQ,MAAM,WAAW,MAAM,IAAI,EAAE,KAAK,CAAC;CAC7E,MAAM,gBAAyB;EAAE,GAAG;EAAM,QAAQ;EAAiB,OAAO;EAAgB;AAE1F,QAAO;EACL,GAAG,QAAQ,eAAe,iBAAiB,IAAI;EAC/C,GAAG,QAAQ,cAAc,gBAAgB,IAAI;EAC7C,GAAG,QAAQ,kBAAkB,KAAK,UAAU,IAAI;EAChD,GAAG,QAAQ,eAAe,MAAM,IAAI;EACpC,GAAG,QAAQ,eAAe,IAAI;EAC9B,GAAI,QAAQ,yBAAyB,eAAe,IAAI,IAAI,EAAE;EAC9D,GAAG,QAAQ,cAAc,eAAe,IAAI;EAC7C;;;AAIH,SAAgB,iBAAiB,OAAwB,QAAiC;AACxF,QAAO,MAAM,KAAK,OAAO;EACvB,GAAG;EACH,SACE,CAAC,UAAU,EAAE,KAAK,SAAS,QAAQ,IAAI,EAAE,oBAAoB,SAAS,EAAE,UAAU,SAAS,SAAS,EAAE;EACxG,cAAc,EAAE,gBAAgB;EACjC,EAAE;;AAGL,SAAgB,cACd,MACA,SACA,SAc6F;CAC7F,MAAM,MAAM,oBAAoB,MAAM,QAAQ;CAC9C,MAAM,QAAQ,iBAAiB,MAAM,SAAS,IAAI;CAClD,MAAM,aAAa,QAAQ,qBAAqB,MAAM,IAAI;CAC1D,MAAM,SAAS,QAAQ,YAAY;AACnC,QAAO;EAAE,OAAO,iBAAiB,OAAO,OAAO;EAAE;EAAK;EAAQ;EAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3M5E,SAAgB,sBACd,MACA,UACA,YACa;CACb,MAAM,SAAS,cAAc,EAAE;CAC/B,MAAM,iBAAiB,SAAyB,OAAO,SAAS;CAChE,MAAM,iBAAiB,IAAI,IAAI,KAAK,SAAS,KAAK,MAAM,cAAc,EAAE,KAAK,CAAC,CAAC;CAC/E,MAAM,cAAc,IAAI,IAAI,SAAS;CAErC,MAAM,UAAU,CAAC,GAAG,YAAY,CAAC,QAAQ,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC;AACtE,KAAI,QAAQ,SAAS,GAAG;EACtB,MAAM,sBAAM,IAAI,MACd,uBAAuB,QAAQ,MAAM,CAAC,KAAK,KAAK,CAAC,+BACjB,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,KAAK,GACtE;AACD,MAAI,OAAO;AACX,QAAM;;AAGR,QAAO;;;;;;;;ACrCT,SAAS,kBACP,cACA,kBACA,YACoB;CAEpB,MAAM,UAAU,iBAAiB,QAAQ,gBAAgB,GAAG;AAE5D,KAAI,CAAC,QAAQ,WAAW,IAAI,CAAE,QAAO,KAAA;CAErC,MAAM,MAAM,KAAK,QAAQ,aAAa;CACtC,MAAM,WAAW,KAAK,UAAU,KAAK,KAAK,KAAK,QAAQ,CAAC;AAGxD,MAAK,MAAM,aAAa;EAAC;EAAU,GAAG,SAAS;EAAM,GAAG,SAAS;EAAW,CAC1E,KAAI,WAAW,IAAI,UAAU,CAAE,QAAO;;;;;;;;;;AAa1C,SAAS,WAAW,UAA2B;AAE7C,KAAI,SAAS,SAAS,aAAa,CAAE,QAAO;AAG5C,KAAI,SAAS,SAAS,WAAW,IAAI,SAAS,SAAS,WAAW,CAAE,QAAO;AAE3E,KAAI,SAAS,SAAS,gBAAgB,CAAE,QAAO;AAE/C,KAAI,SAAS,SAAS,eAAe,IAAI,CAAC,SAAS,SAAS,YAAY,CAAE,QAAO;AAEjF,QAAO;;;;;;AAOT,eAAsB,eAAe,OAAwB,UAA4C;AACvG,KAAI,CAAC,WAAW,SAAS,CAAE,QAAO;CAElC,MAAM,aAAa,IAAI,IAAI,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC;CAGpD,MAAM,uBAAO,IAAI,KAA0B;AAC3C,MAAK,MAAM,QAAQ,OAAO;AAExB,MAAI,CAAC,KAAK,KAAK,SAAS,MAAM,IAAI,CAAC,KAAK,KAAK,SAAS,MAAM,EAAE;AAC5D,QAAK,IAAI,KAAK,sBAAM,IAAI,KAAK,CAAC;AAC9B;;EAEF,MAAM,SAAS,MAAM,kBAAkB,KAAK,SAAS,SAAS;EAC9D,MAAM,2BAAW,IAAI,KAAa;AAClC,OAAK,MAAM,OAAO,OAAO,SAAS;GAChC,MAAM,WAAW,kBAAkB,KAAK,MAAM,IAAI,KAAK,WAAW;AAClE,OAAI,SAAU,UAAS,IAAI,SAAS;;AAGtC,OAAK,MAAM,QAAQ,OAAO,WACxB,KAAI,KAAK,SAAS,YAAY;GAE5B,MAAM,QAAQ,KAAK,KAAK,MAAM,0BAA0B;AACxD,OAAI,OAAO;IACT,MAAM,WAAW,kBAAkB,KAAK,MAAM,MAAM,IAAI,WAAW;AACnE,QAAI,SAAU,UAAS,IAAI,SAAS;;;AAI1C,OAAK,IAAI,KAAK,MAAM,SAAS;;CAI/B,MAAM,iBAAiB,IAAI,IAAI;EAC7B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CAGF,MAAM,4BAAY,IAAI,KAAa;CACnC,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,MAAM,KAAK,KAAK,MAAM,KAAK,KAAK,YAAY,IAAI,CAAC;AAGvD,MAAI,CAAC,eAAe,IAAI,IAAI,EAAE;AAC5B,aAAU,IAAI,KAAK,KAAK;AACxB;;AAEF,MAAI,WAAW,KAAK,KAAK,EAAE;AACzB,aAAU,IAAI,KAAK,KAAK;AACxB,SAAM,KAAK,KAAK,KAAK;;;AAGzB,QAAO,MAAM,SAAS,GAAG;EACvB,MAAM,UAAU,MAAM,KAAK;EAC3B,MAAM,WAAW,KAAK,IAAI,QAAQ;AAClC,MAAI,CAAC,SAAU;AACf,OAAK,MAAM,OAAO,SAChB,KAAI,CAAC,UAAU,IAAI,IAAI,EAAE;AACvB,aAAU,IAAI,IAAI;AAClB,SAAM,KAAK,IAAI;;;AAKrB,QAAO,MAAM,QAAQ,MAAM,UAAU,IAAI,EAAE,KAAK,CAAC;;AAGnD,SAAgB,6BAA6B,OAAwB,UAAmC;CACtG,MAAM,aAAa,GAAG,SAAS;AAC/B,QAAO,MACJ,QAAQ,MAAM,EAAE,oBAAoB,MAAM,CAC1C,KAAK,MAAM;EACV,MAAM,WAAW,EAAE,KAAK,WAAW,WAAW,GAAG,EAAE,KAAK,QAAQ,YAAY,GAAG,GAAG,EAAE;AACpF,SAAO;GACL,GAAG;GACH,cAAc;GACd,MAAM;GACP;GACD;;;;;;;;;;;;AAaN,eAAe,gCACb,OACA,WACyD;CACzD,MAAM,SAAS,CAAC,GAAG,MAAM;CACzB,MAAM,WAAqB,EAAE;AAE7B,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,OAAO,OAAO;EAEpB,MAAM,QAAQ,KAAK,KAAK,MAAM,uBAAuB;AACrD,MAAI,CAAC,MAAO;EAEZ,MAAM,UAAU,MAAM;EACtB,MAAM,iBAAiB,GAAG,QAAQ;EAClC,MAAM,iBAAiB,KAAK,KAAK,WAAW,eAAe;EAE3D,IAAI;AACJ,MAAI;AACF,mBAAgB,MAAM,GAAG,SAAS,gBAAgB,QAAQ;UACpD;AACN;;EAIF,MAAM,aAAa,GAAG,QAAQ;AAC9B,SAAO,KAAK;GACV,MAAM;GACN,SAAS;GACT,mBAAmB;GACpB,CAAC;EAKF,MAAM,eAAe;EACrB,MAAM,kBAAkB,KAAK,QAAQ,SAAS,KAAK,GAAG,KAAK,UAAU,KAAK,UAAU;AACpF,SAAO,KAAK;GACV,GAAG;GACH,SAAS,kBAAkB,eAAe;GAC3C;AAGD,WAAS,KAAK,eAAe;;AAG/B,QAAO;EAAE,OAAO;EAAQ;EAAU;;AAQpC,eAAsB,wBAAwB,MAKjB;CAC3B,MAAM,SAAS,6BAA6B,KAAK,OAAO,KAAK,SAAS;CAItE,MAAM,EAAE,OAAO,UAAU,aAAa,MAAM,gCAH7B,MAAM,eAAe,QAAQ,KAAK,SAAS,EAG0B,KAAK,UAAU;CAEnG,MAAM,SAAS,MAAM,WAAW,UAAU,KAAK,WAAW;EACxD,UAAU,KAAK;EACf,QAAQ,KAAK;EACd,CAAC;AAGF,MAAK,MAAM,YAAY,SACrB,KAAI;AACF,QAAM,GAAG,OAAO,SAAS;SACnB;AAQV,QAAO;EAAE,GAAG;EAAQ,cAAc,OAAO,KAAK,MAAM,EAAE,KAAK;EAAE;;;;;;;;;;;ACxO/D,MAAM,gBAAgB,UAAU,SAAS;;;;;AAMzC,eAAsB,kBAAkB,SAAkB,WAAmB,WAAoC;AAC/G,KAAI,UAAU,WAAW,EAAG;AAC5B,KAAI,CAAC,QAAQ,cAAe;CAE5B,MAAM,YAAY,QAAQ,cAAc,UAAU;AAClD,KAAI,CAAC,UAAW;CAEhB,MAAM,gBAAgB,UAAU,KAAK,MAAMC,OAAK,QAAQ,WAAW,EAAE,CAAC;CACtE,MAAM,YAAY,UAAU,aAAa;AAEzC,SAAQ,OAAO,MACb,sBAAsB,cAAc,OAAO,gBAAgB,UAAU,IAAI,UAAU,UAAU,KAC9F;AAED,MAAK,IAAI,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK,WAAW;EACxD,MAAM,QAAQ,cAAc,MAAM,GAAG,IAAI,UAAU;AACnD,MAAI;AACF,SAAM,cAAc,UAAU,KAAK,CAAC,GAAG,UAAU,MAAM,GAAG,MAAM,EAAE;IAChE,KAAK;IACL,WAAW,KAAK,OAAO;IACvB,SAAS;IACV,CAAC;WACK,KAAK;GAIZ,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC5D,WAAQ,OAAO,MAAM,mCAAmC,IAAI,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;ACvBtE,MAAa,oBAAoB;AACjC,MAAM,mBAAmB;;AAuCzB,eAAsB,aAAa,KAAuC;CACxE,MAAM,eAAeC,OAAK,KAAK,KAAK,kBAAkB;CACtD,IAAI;AACJ,KAAI;AACF,QAAM,MAAM,GAAG,SAAS,cAAc,QAAQ;SACxC;AACN,SAAO;;AAET,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,MACE,OAAO,OAAO,YAAY,YAC1B,OAAO,OAAO,aAAa,YAC3B,OAAO,OAAO,gBAAgB,YAC9B,CAAC,MAAM,QAAQ,OAAO,MAAM,IAC5B,CAAC,OAAO,MAAM,OAAO,MAAmB,OAAO,MAAM,SAAS,CAE9D,QAAO;AAET,MAAI,OAAO,UAAU,kBAAkB;AACrC,WAAQ,KACN,WAAW,kBAAkB,kBAAkB,OAAO,QAAQ,4BAA4B,iBAAiB,0BAC5G;AACD,UAAO;;AAGT,SAAO;SACD;AACN,SAAO;;;;AAmBX,eAAsB,cAAc,KAAa,MAAwC;CACvF,MAAM,eAAeA,OAAK,KAAK,KAAK,kBAAkB;CACtD,MAAM,WAAqB;EACzB,SAAS;EACT,UAAU,KAAK;EACf,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,SAAS,KAAK,SAAS,GAAG,EAAE;EAC/D,8BAAa,IAAI,MAAM,EAAC,aAAa;EACrC,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,SAAS,KAAK,SAAS,GAAG,EAAE;EAC/D,GAAI,KAAK,aAAa,KAAA,IAAY,EAAE,UAAU,KAAK,UAAU,GAAG,EAAE;EAClE,GAAI,KAAK,eAAe,KAAA,IAAY,EAAE,YAAY,KAAK,YAAY,GAAG,EAAE;EACxE,GAAI,KAAK,mBAAmB,KAAA,IAAY,EAAE,gBAAgB,KAAK,gBAAgB,GAAG,EAAE;EACpF,GAAI,KAAK,cAAc,KAAA,IAAY,EAAE,WAAW,KAAK,WAAW,GAAG,EAAE;EACrE,GAAI,KAAK,wBAAwB,KAAA,IAAY,EAAE,qBAAqB,KAAK,qBAAqB,GAAG,EAAE;EACnG,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,MAAM;EACtC,GAAI,KAAK,eAAe,KAAA,IAAY,EAAE,YAAY,KAAK,YAAY,GAAG,EAAE;EACzE;CACD,MAAM,WAAW,MAAM,aAAa,IAAI;AACxC,KAAI,YAAY,8BAA8B,UAAU,SAAS,CAC/D,UAAS,cAAc,SAAS;AAElC,OAAM,GAAG,MAAM,KAAK,EAAE,WAAW,MAAM,CAAC;AACxC,OAAM,GAAG,UAAU,cAAc,KAAK,UAAU,UAAU,MAAM,EAAE,GAAG,MAAM,QAAQ;;AAGrF,SAAS,8BAA8B,GAAa,GAAsB;CACxE,MAAM,EAAE,aAAa,eAAe,GAAG,gBAAgB;CACvD,MAAM,EAAE,aAAa,eAAe,GAAG,gBAAgB;AACvD,QAAO,KAAK,UAAU,YAAY,KAAK,KAAK,UAAU,YAAY;;;AAIpE,SAAgB,kBAAkB,MAAgB,cAA0C;CAC1F,MAAM,UAAU,IAAI,IAAI,aAAa;AACrC,QAAO,KAAK,MAAM,QAAQ,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM;;;;;;;;;;;;;;;AAgBzD,SAAgB,2BACd,MACA,aACA,kBAC2D;CAC3D,MAAM,iBAAiB,CAAC,GAAG,YAAY;AACvC,KAAI,CAAC,KACH,QAAO;EAAE,OAAO;EAAgB,YAAY;EAAkB;CAEhE,MAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM;CACrE,MAAM,WAAW,KAAK;AAEtB,QAAO;EAAE;EAAO,YADG,YAAY,mBAAmB;GAAE,GAAG;GAAU,GAAG;GAAkB,GAAG,KAAA;EAC7D;;;;;;;;;;;;;AAc9B,eAAsB,gBACpB,KACA,OACA,OAA4B,EAAE,EACR;CACtB,MAAM,SAAmB,EAAE;CAC3B,MAAM,YAAsB,EAAE;CAC9B,MAAM,UAAoB,EAAE;AAE5B,MAAK,MAAM,WAAW,OAAO;EAC3B,MAAM,WAAWA,OAAK,KAAK,KAAK,QAAQ;EACxC,IAAI;AACJ,MAAI;AACF,aAAU,MAAM,GAAG,SAAS,UAAU,QAAQ;UACxC;AACN,WAAQ,KAAK,QAAQ;AACrB;;AAEF,MAAI,KAAK,UAAU,CAAC,QAAQ,WAAW,KAAK,OAAO,EAAE;AACnD,aAAU,KAAK,QAAQ;AACvB;;AAEF,MAAI;AACF,SAAM,GAAG,OAAO,SAAS;AACzB,UAAO,KAAK,QAAQ;UACd;AAEN,WAAQ,KAAK,QAAQ;AACrB;;AAEF,QAAM,mBAAmBA,OAAK,QAAQ,SAAS,EAAE,IAAI;;AAGvD,QAAO;EAAE;EAAQ;EAAW;EAAS;;;;;;AAOvC,eAAe,mBAAmB,UAAkB,SAAgC;CAClF,IAAI,UAAUA,OAAK,QAAQ,SAAS;CACpC,MAAM,OAAOA,OAAK,QAAQ,QAAQ;AAClC,QAAO,QAAQ,WAAW,OAAOA,OAAK,IAAI,IAAI,YAAY,MAAM;EAC9D,IAAI;AACJ,MAAI;AACF,aAAU,MAAM,GAAG,QAAQ,QAAQ;UAC7B;AACN;;AAEF,MAAI,QAAQ,SAAS,EAAG;AACxB,MAAI;AACF,SAAM,GAAG,MAAM,QAAQ;UACjB;AACN;;AAEF,YAAUA,OAAK,QAAQ,QAAQ;;;;;AC/NnC,eAAsB,SACpB,MACA,SACA,SAuB0B;CAK1B,MAAM,iBACJ,QAAQ,YAAY,QAAQ,SAAS,SAAS,IAC1C,sBAAsB,MAAM,QAAQ,UAAU,QAAQ,WAAW,GACjE,KAAA;CACN,MAAM,SAAS,mBAAmB,KAAA;CAElC,MAAM,UAAU,QAAQ,YAAY,QAAQ;CAO5C,MAAM,mBAAmB,QAAQ,YAAY,QAAQ,CAAC;CACtD,MAAM,2BAA2B,mBAAmB,OAAO,MAAM,aAAa,QAAQ,UAAU;CAChG,MAAM,uBAAuB,QAAQ,UAAU,CAAC,mBAAmB,MAAM,aAAa,QAAQ,OAAO,GAAG;CACxG,MAAM,2BAA2B,uBAC7B,IAAI,IAAI,qBAAqB,MAAM,GACnC,2BACE,IAAI,IAAI,yBAAyB,MAAM,GACvC,KAAA;CAEN,MAAM,EACJ,OAAO,aACP,QACA,eACE,cAAc,MAAM,SAAS;EAC/B,GAAG;EACH;EACA;EACD,CAAC;AAEF,KAAI,QAAQ,QAAQ;AAClB,MAAI,QAAQ,QAAQ;AAClB,WAAQ,IAAI,yBAAyB,QAAQ,OAAO,IAAI;AACxD,QAAK,MAAM,KAAK,YACd,SAAQ,IAAI,KAAK,EAAE,OAAO;;AAG9B,SAAO;;CAIT,MAAM,qBAAqB;CAE3B,MAAM,cAAc,MAAM,WAAW,aAAa,QAAQ,WAAW;EACnE,UAAU,QAAQ;EAClB;EACD,CAAC;AAEF,KAAI,YAAY,OAAO,SAAS,EAC9B,SAAQ,IAAI,eAAe,YAAY,OAAO,OAAO,iCAAiC;AAExF,KAAI,YAAY,QAAQ,SAAS,EAC/B,SAAQ,IAAI,WAAW,YAAY,QAAQ,OAAO,6BAA6B;CAGjF,MAAM,qBAAqB,YAAY,KAAK,MAAM,EAAE,KAAK;AACzD,OAAM,mBAAmB;EACvB,KAAK,QAAQ;EACb,OAAO;EACP,cAAc;EACd,cAAc;EACd,UAAU,QAAQ;EAClB;EACA;EACA;EACA;EACD,CAAC;CAGF,MAAM,iBAAiB,CAAC,GAAG,YAAY,SAAS,GAAG,YAAY,OAAO;AACtE,KAAI,eAAe,SAAS,EAC1B,OAAM,kBAAkB,SAAS,QAAQ,WAAW,eAAe;AAIrE,KAAI,QAAQ,QAAQ;EAGlB,MAAM,qBAAqB;EAE3B,MAAM,eAAe,MAAM,wBAAwB;GACjD,OAAO;GACP,UAAU,QAAQ;GAClB,WAAW,QAAQ;GACnB;GACD,CAAC;AAEF,MAAI,aAAa,QAAQ,SAAS,EAChC,SAAQ,IAAI,mBAAmB,aAAa,QAAQ,OAAO,YAAY;AAEzE,MAAI,aAAa,OAAO,SAAS,EAC/B,SAAQ,IAAI,uBAAuB,aAAa,OAAO,OAAO,iCAAiC;AAEjG,MAAI,aAAa,QAAQ,SAAS,EAChC,SAAQ,IAAI,mBAAmB,aAAa,QAAQ,OAAO,iCAAiC;AAG9F,QAAM,mBAAmB;GACvB,KAAK,QAAQ;GACb,OAAO;GACP,cAAc;GACd,cAAc,aAAa;GAC3B,UAAU,QAAQ;GAClB;GACA;GACA;GACA;GACD,CAAC;EAGF,MAAM,iBAAiB;GAAC,GAAG,aAAa;GAAS,GAAG,aAAa;GAAQ,GAAG,aAAa;GAAU;AACnG,MAAI,eAAe,SAAS,EAC1B,OAAM,kBAAkB,SAAS,QAAQ,QAAQ,eAAe;;AAIpE,QAAO;;;;;;AAOT,eAAe,mBAAmB,MAWhB;CAIhB,MAAM,UAAU,KAAK,SACjB,2BAA2B,KAAK,cAAc,KAAK,cAAc,KAAK,WAAW,GACjF;EAAE,OAAO,KAAK;EAAc,YAAY,KAAK;EAAY;CAC7D,MAAM,eAAe;EAAE,UAAU,KAAK;EAAU,OAAO,QAAQ;EAAO,YAAY,QAAQ;EAAY;AACtG,KAAI,KAAK,SAAS;AAEhB,QAAM,cAAc,KAAK,KAAK,aAAa;AAC3C;;AAGF,KAAI,CAAC,KAAK,cAAc;AACtB,UAAQ,IACN,GAAG,KAAK,MAAM,OAAO,kBAAkB,uEACxC;AACD,QAAM,cAAc,KAAK,KAAK,aAAa;AAC3C;;CAGF,MAAM,QAAQ,kBAAkB,KAAK,cAAc,KAAK,aAAa;AACrE,KAAI,MAAM,SAAS,GAAG;EACpB,MAAM,EAAE,QAAQ,cAAc,MAAM,gBAAgB,KAAK,KAAK,OAAO,EAAE,QAAQ,KAAK,QAAQ,CAAC;AAC7F,MAAI,OAAO,SAAS,EAClB,SAAQ,IAAI,GAAG,KAAK,MAAM,WAAW,OAAO,OAAO,aAAa,OAAO,WAAW,IAAI,KAAK,MAAM;AAEnG,MAAI,UAAU,SAAS,GAAG;AACxB,WAAQ,IACN,GAAG,KAAK,MAAM,cAAc,UAAU,OAAO,OAAO,UAAU,WAAW,IAAI,KAAK,IAAI,qFACvF;AACD,QAAK,MAAM,KAAK,UAAW,SAAQ,IAAI,KAAK,IAAI;;;AAIpD,OAAM,cAAc,KAAK,KAAK,aAAa;;;;AC1N7C,MAAM,2BAAW,IAAI,KAAsB;AAE3C,SAAgB,gBAAgB,SAAwB;AACtD,UAAS,IAAI,QAAQ,UAAU,QAAQ;;AAGzC,SAAgB,WAAW,UAA2B;CACpD,MAAM,UAAU,SAAS,IAAI,SAAS;AACtC,KAAI,CAAC,QAEH,OAAM,IAAI,cACR,qBAAqB,SAAS,eAFd,CAAC,GAAG,SAAS,MAAM,CAAC,CAAC,KAAK,KAAK,IAAI,YAGnD,4BAA4B,SAAS,6EACtC;AAEH,QAAO;;;;;ACdT,MAAM,uBAAuB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,gBAAgB;;AAG7B,SAAgB,oBAAoB,MAAc,SAA8B;AAC9E,QAAO,CAAC,EAAE,QAAQ,WAAW,SAAS,QAAQ,QAAQ,SAAS,QAAQ,MAAM;;;AAI/E,SAAS,iBAAiB,GAAqB;AAC7C,QAAO,WAAW,EAAE,CAAC,QAAQ,MAAM,EAAE,SAAS,EAAE;;;;;;;AAQlD,SAAgB,sBAAsB,GAAW,GAAW,aAAa,GAAY;CACnF,MAAM,UAAU,EAAE,QAAQ,aAAa,GAAG;CAC1C,MAAM,UAAU,EAAE,QAAQ,aAAa,GAAG;CAC1C,MAAM,SAAS,IAAI,IAAI,iBAAiB,QAAQ,CAAC,KAAK,MAAM,EAAE,aAAa,CAAC,CAAC;CAC7E,MAAM,SAAS,IAAI,IAAI,iBAAiB,QAAQ,CAAC,KAAK,MAAM,EAAE,aAAa,CAAC,CAAC;CAC7E,MAAM,UAAU,CAAC,GAAG,OAAO,CAAC,QAAQ,MAAM,OAAO,IAAI,EAAE,CAAC;AACxD,QAAO,QAAQ,UAAU,cAAc,QAAQ,UAAU,KAAK,IAAI,OAAO,MAAM,OAAO,KAAK,GAAG;;;AAIhG,SAAS,kBAAkB,GAAqB;AAC9C,QAAO,EACJ,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ;;;;;;AAoBpB,MAAa,YAA2B;CACtC,cAAc,MAA6B;EACzC,MAAM,UAAU,kBAAkB,KAAK;EACvC,MAAM,WAAW,QAAQ,QAAQ,MAAM,MAAM,OAAO;AACpD,MAAI,SAAS,WAAW,QAAQ,OAC9B,QAAO;AAET,SAAO,SAAS,KAAK,MAAM;;CAG7B,yBAAyB,GAAW,GAAoB;AACtD,UAAQ,UAAU,cAAc,EAAE,IAAI,QAAQ,UAAU,cAAc,EAAE,IAAI,MAAM,MAAM;;CAG1F,eAAe,GAAW,GAAoB;EAC5C,MAAM,WAAW,kBAAkB,EAAE,CAAC,MAAM;EAC5C,MAAM,WAAW,kBAAkB,EAAE,CAAC,MAAM;AAC5C,MAAI,SAAS,WAAW,SAAS,UAAU,SAAS,SAAS,EAAG,QAAO;AACvE,SAAO,SAAS,OAAO,GAAG,MAAM,MAAM,SAAS,GAAG;;CAGpD,mBAAmB,MAAuB;AACxC,MAAI,UAAU,KAAK,KAAK,CAAE,QAAO;AACjC,MAAI,oBAAoB,KAAK,KAAK,CAAE,QAAO;AAC3C,MAAI,cAAc,KAAK,KAAK,IAAI,wBAAwB,KAAK,KAAK,CAAE,QAAO;AAC3E,SAAO;;CAGT,qBAAqB,MAAuB;AAC1C,SAAO,SAAS,SAAS,SAAS;;CAGpC,0BAA0B;CAE1B,sBAAsB,YAAmC;EACvD,IAAI,QAAQ;AACZ,SAAO,MAAM,WAAW,WAAW,IAAI,MAAM,SAAS,IAAI,CACxD,SAAQ,MAAM,MAAM,GAAG,GAAG;EAE5B,MAAM,eAAe,MAAM,MAAM,oBAAoB;AACrD,MAAI,aACF,SAAQ,aAAa;AAEvB,UAAQ,MAAM,QAAQ,SAAS,GAAG;AAClC,MAAI;GAAC;GAAQ;GAAU;GAAU;GAAW;GAAO;GAAW;GAAQ;GAAY,CAAC,SAAS,MAAM,CAChG,QAAO;AAET,SAAO;;CAGT,qBAAqB,WAAkC;AACrD,MAAI;GAAC;GAAU;GAAU;GAAW;GAAO;GAAU,CAAC,SAAS,UAAU,CACvE,QAAO;AAET,SAAO;;CAGT,qBAAqB,cAAsB,WAA4B;AAIrE,SADuB,aAAa,QAAQ,SAAS,GAAG,CAAC,aAAa,KAC5C,UAAU,aAAa;;CAGnD,kBAAkB,WAA6B;AAC7C,SAAO,CAAC,GAAG,UAAU,WAAW,aAAa,YAAY;;CAG3D,iBAAiB,cAAsB,eAAuB,kBAAuC;EASnG,MAAM,WAAW,iBAAiB,MAAM;AACxC,MAAI,UAAU;GACZ,MAAM,gBAAgB,IAAI,IAAI,OAAO,OAAO,SAAS,QAAQ,CAAC,SAAS,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;GACnG,MAAM,cAAc,kBAAkB,aAAa;AACnD,OAAI,YAAY,SAAS,KAAK,YAAY,OAAO,MAAM,cAAc,IAAI,EAAE,CAAC,CAC1E,QAAO;;AAMX,MAAI,qBAAqB,IAAI,aAAa,IAAI,qBAAqB,IAAI,cAAc,CACnF,QAAO;AAMT,MAAI,aAAa,WAAW,IAAI,IAAI,aAAa,SAAS,IAAI;OACxD,oBAAoB,eAAe,iBAAiB,CACtD,QAAO;;EAWX,MAAM,YAAY,aAAa,QAAQ,SAAS,GAAG;EACnD,MAAM,YAAY,cAAc,QAAQ,SAAS,GAAG;EACpD,MAAM,gBAAgB,aAAa,SAAS,KAAK,KAAK,cAAc,SAAS,KAAK;AAGlF,MAAI;OACE,cAAc,YAAY,cAAc,cAAc,YAAY,WACpE,QAAO;;AAOX,MAAI,iBAAiB,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU;OAC7E,oBAAoB,WAAW,iBAAiB,EAAE;AAEpD,QAAI,UAAU,SAAS,UAAU,IAAI,UAAU,SAAS,UAAU,CAChE,QAAO;IAGT,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;IACrD,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;AACrD,QAAI,WAAW,SAAS,WAAW,IAAI,WAAW,SAAS,WAAW,CACpE,QAAO;AAKT,QAAI,sBAAsB,WAAW,WAAW,EAAE,CAChD,QAAO;;;AAKb,SAAO;;CAEV;;;;;;;;ACxLD,SAAS,qBACP,SACA,qBACA,OACoB;AACpB,MAAK,MAAM,CAAC,WAAW,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AAE9D,MAAI,MAAM,qBAAqB,qBAAqB,UAAU,CAC5D,QAAO;AAKT,OAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,IAAI,WAAW,CAC3D,KAAI,aAAa,qBAAqB;GACpC,MAAM,WAAY,KAA2B;AAC7C,OAAI,YAAY,QAAQ,QAAQ,UAC9B,QAAO;AAGT;;;CAQN,MAAM,YAAY,WAAW,oBAAoB,CAAC,KAAK,MAAM,EAAE,aAAa,CAAC;AAC7E,KAAI,UAAU,SAAS,EACrB,MAAK,MAAM,CAAC,cAAc,OAAO,QAAQ,QAAQ,QAAQ,EAAE;EACzD,MAAM,aAAa,WAAW,UAAU,CAAC,KAAK,MAAM,EAAE,aAAa,CAAC;AACpE,MAAI,WAAW,SAAS,KAAK,WAAW,SAAS,UAAU,QAAQ;GACjE,MAAM,SAAS,UAAU,MAAM,UAAU,SAAS,WAAW,OAAO;AACpE,OAAI,WAAW,OAAO,GAAG,MAAM,MAAM,OAAO,GAAG,CAC7C,QAAO;;;;AASjB,SAAgB,mBACd,SACA,UACA,MACA,OACA,SACe;CACf,MAAM,gBAAgB,SAASC;CAC/B,MAAM,SAAwB;EAC5B,mCAAmB,IAAI,KAAK;EAC5B,iCAAiB,IAAI,KAAK;EAC1B,iCAAiB,IAAI,KAAK;EAC1B,iCAAiB,IAAI,KAAK;EAC1B,iCAAiB,IAAI,KAAK;EAC1B,+BAAe,IAAI,KAAK;EACxB,8BAAc,IAAI,KAAK;EACxB;AAGD,KAAI,SACF,MAAK,MAAM,SAAS,UAAU;EAC5B,MAAM,MAAM,GAAG,MAAM,WAAW,aAAa,CAAC,GAAG,MAAM;EACvD,MAAM,YAAY,qBAAqB,SAAS,MAAM,qBAAqB,cAAc;AACzF,MAAI,WAAW;GACb,IAAI,qBAAqB,MAAM;GAC/B,IAAI,UAAU,QAAQ,QAAQ,YAAY,QAAQ;AAMlD,OAAI,CAAC,SAAS;IACZ,MAAM,eAAe,QAAQ,QAAQ,YAAY,WAAW,EAAE;IAC9D,MAAM,SAAS,mBAAmB,aAAa;IAC/C,MAAM,aAAsC,EAAE;AAC9C,SAAK,MAAM,CAAC,MAAM,cAAc,OAAO,QAAQ,aAAa,CAC1D,KAAI,KAAK,aAAa,CAAC,WAAW,OAAO,IAAI,SAAS,mBACpD,YAAW,KAAK,CAAC,MAAM,UAAU,CAAC;AAGtC,QAAI,WAAW,WAAW,GAAG;AAC3B,eAAU,WAAW,GAAG;AACxB,0BAAqB,WAAW,GAAG;eAC1B,WAAW,SAAS,GAAG;KAKhC,MAAM,eACJ,MAAM,KACH,MAAM,IAAI,CACV,OAAO,QAAQ,CAAC,IACf,QAAQ,WAAW,GAAG,IAAI;AAChC,SAAI,cAAc;MAChB,MAAM,WAAW,aAAa,aAAa;MAE3C,MAAM,cAAc,SAAS,SAAS,IAAI,GAAG,SAAS,MAAM,GAAG,GAAG,GAAG;MACrE,MAAM,OAAO,WAAW,MAAM,CAAC,UAAU;OACvC,MAAM,QAAQ,KAAK,aAAa;AAChC,cAAO,UAAU,SAAS,YAAY,UAAU,SAAS;QACzD;AACF,UAAI,MAAM;AACR,iBAAU,KAAK;AACf,4BAAqB,KAAK;;;AAO9B,SAAI,CAAC,SAAS;MACZ,MAAM,YAAY,uBAAuB,YAAY,MAAM,WAAW;AACtE,UAAI,WAAW;AACb,iBAAU,UAAU;AACpB,4BAAqB,UAAU;;;;;AAWvC,OAAI,CAAC,SAAS;IACZ,MAAM,eAAe,QAAQ,QAAQ,YAAY,WAAW,EAAE;IAC9D,MAAM,SAAS,mBAAmB,aAAa;IAC/C,MAAM,aAAsC,EAAE;AAC9C,SAAK,MAAM,CAAC,MAAM,cAAc,OAAO,QAAQ,aAAa,CAC1D,KAAI,KAAK,aAAa,CAAC,SAAS,OAAO,IAAI,SAAS,mBAClD,YAAW,KAAK,CAAC,MAAM,UAAU,CAAC;AAGtC,QAAI,WAAW,WAAW,GAAG;AAC3B,eAAU,WAAW,GAAG;AACxB,0BAAqB,WAAW,GAAG;;;AASvC,OAAI,CAAC,SAAS;IACZ,MAAM,gBAAgB,eAAe,mBAAmB;AACxD,QAAI,cAAc,UAAU,GAAG;KAC7B,MAAM,eAAe,QAAQ,QAAQ,YAAY,WAAW,EAAE;KAC9D,MAAM,aAAsC,EAAE;AAC9C,UAAK,MAAM,CAAC,MAAM,cAAc,OAAO,QAAQ,aAAa,EAAE;AAC5D,UAAI,SAAS,mBAAoB;MACjC,MAAM,eAAe,eAAe,KAAK;AACzC,UAAI,aAAa,SAAS,cAAc,UAAU,cAAc,eAAe,aAAa,CAC1F,YAAW,KAAK,CAAC,MAAM,UAAU,CAAC;;AAGtC,SAAI,WAAW,WAAW,GAAG;AAC3B,gBAAU,WAAW,GAAG;AACxB,2BAAqB,WAAW,GAAG;gBAC1B,WAAW,SAAS,GAAG;MAChC,MAAM,YAAY,uBAAuB,YAAY,MAAM,WAAW;AACtE,UAAI,WAAW;AACb,iBAAU,UAAU;AACpB,4BAAqB,UAAU;;;;;AASvC,OAAI,CAAC,SAAS;IACZ,MAAM,eAAe,QAAQ,QAAQ,YAAY,WAAW,EAAE;IAC9D,MAAM,gBAAgB,mBAAmB,aAAa;IACtD,MAAM,aAAsC,EAAE;AAC9C,SAAK,MAAM,CAAC,MAAM,cAAc,OAAO,QAAQ,aAAa,EAAE;AAC5D,SAAI,SAAS,mBAAoB;AACjC,SAAI,cAAc,WAAW,KAAK,aAAa,CAAC,IAAI,KAAK,UAAU,EACjE,YAAW,KAAK,CAAC,MAAM,UAAU,CAAC;;AAGtC,QAAI,WAAW,WAAW,GAAG;AAC3B,eAAU,WAAW,GAAG;AACxB,0BAAqB,WAAW,GAAG;eAC1B,WAAW,SAAS,GAAG;KAChC,MAAM,YAAY,uBAAuB,YAAY,MAAM,WAAW;AACtE,SAAI,WAAW;AACb,gBAAU,UAAU;AACpB,2BAAqB,UAAU;;;;GAKrC,MAAM,SAAS,UAAU;AACzB,OAAI,QAAQ;AACV,WAAO,kBAAkB,IAAI,KAAK;KAChC;KACA,YAAY;KACZ,QAAQ,OAAO;KACf,YAAY,OAAO;KACpB,CAAC;AACF,WAAO,gBAAgB,IAAI,GAAG,UAAU,GAAG,sBAAsB,IAAI;;;;AAO7E,MAAK,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,CAChD,QAAO,gBAAgB,IAAI,MAAM,KAAK;AAExC,MAAK,MAAM,QAAQ,OAAO,KAAK,QAAQ,YAAY,CACjD,QAAO,gBAAgB,IAAI,MAAM,KAAK;AAIxC,MAAK,MAAM,CAAC,MAAM,YAAY,OAAO,QAAQ,QAAQ,QAAQ,CAC3D,QAAO,gBAAgB,IAAI,MAAM,IAAI,IAAI,QAAQ,CAAC;AAIpD,MAAK,MAAM,UAAU;EAAC,QAAQ;EAAS,QAAQ;EAAY,QAAQ;EAAa,QAAQ;EAAM,CAI5F,MAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,OAAO,CAC/C,KAAI,KAAK,WAAY,QAAO,aAAa,IAAI,MAAM,KAAK,WAAW;AAKvE,KAAI,MAAM;AACR,oBAAkB,SAAS,MAAM,QAAQ,eAAe,QAAQ;AAGhE,OAAK,MAAM,CAAC,QAAQ,YAAY,OAAO,eAAe;GACpD,MAAM,WAAW,OAAO,aAAa,IAAI,QAAQ;AACjD,OAAI,SACF,QAAO,aAAa,IAAI,QAAQ,SAAS;;;AAK/C,QAAO;;;AAQT,MAAM,qBAA+C;CACnD,KAAK;EAAC;EAAQ;EAAO;EAAS;EAAY;EAAO;CACjD,MAAM;EAAC;EAAU;EAAO;EAAU;EAAO;CACzC,KAAK;EAAC;EAAO;EAAU;EAAW;EAAM;CACxC,OAAO;EAAC;EAAU;EAAS;EAAS;CACpC,QAAQ;EAAC;EAAU;EAAU;EAAS;CACvC;;;;;AAMD,SAAS,uBAA0B,YAA2B,YAA6C;CACzG,MAAM,WAAW,mBAAmB,WAAW,aAAa;AAC5D,KAAI,CAAC,SAAU,QAAO,KAAA;CAEtB,MAAM,iBAAiB,WAAW,QAAQ,CAAC,UAAU;EACnD,MAAM,QAAQ,KAAK,aAAa;AAChC,SAAO,SAAS,MAAM,MAAM,MAAM,WAAW,EAAE,CAAC;GAChD;AAEF,KAAI,eAAe,WAAW,EAAG,QAAO,eAAe;;;AASzD,SAAS,eAAe,MAAwB;CAC9C,MAAM,QAAkB,EAAE;CAC1B,IAAI,QAAQ;AACZ,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,IAC/B,KAAI,KAAK,MAAM,OAAO,KAAK,MAAM,KAAK;AACpC,QAAM,KAAK,KAAK,MAAM,OAAO,EAAE,CAAC;AAChC,UAAQ;;AAGZ,OAAM,KAAK,KAAK,MAAM,MAAM,CAAC;AAC7B,QAAO;;;AAIT,SAAS,cAAc,QAAkB,UAA6B;CACpE,IAAI,KAAK;AACT,MAAK,IAAI,KAAK,GAAG,KAAK,SAAS,UAAU,KAAK,OAAO,QAAQ,KAC3D,KAAI,OAAO,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,CAAE;AAE/D,QAAO,OAAO,OAAO;;;;;;AAWvB,SAAS,mBAAmB,MAAsB;AAChD,QAAO,YAAY,KAAK;;;;;;AAO1B,SAAS,kBAAkB,GAAgB,GAAyD;AAClG,KAAI,EAAE,SAAS,KAAK,EAAE,SAAS,EAAG,QAAO;EAAE,OAAO;EAAG,cAAc;EAAG;CACtE,IAAI,eAAe;AACnB,MAAK,MAAM,QAAQ,EACjB,KAAI,EAAE,IAAI,KAAK,CAAE;CAEnB,MAAM,QAAQ,EAAE,OAAO,EAAE,OAAO;AAChC,QAAO;EAAE,OAAO,UAAU,IAAI,IAAI,eAAe;EAAO;EAAc;;;;;AAMxE,SAAS,sBAAsB,OAA2B;AACxD,QAAO,IAAI,IAAI,MAAM,OAAO,KAAK,MAAM,mBAAmB,EAAE,KAAK,CAAC,CAAC;;;;;AAMrE,SAAS,2BAA2B,OAAkC;AACpE,QAAO,IAAI,IAAI,OAAO,KAAK,MAAM,OAAO,CAAC,IAAI,mBAAmB,CAAC;;;;;;;;;;;;;;;AAgBnE,SAAS,kBACP,SACA,MACA,QACA,OACA,SACM;CACN,MAAM,yBAAS,IAAI,KAAa;CAChC,MAAM,+BAAe,IAAI,KAAa;AAGtC,KAAI,OAAO,kBAAkB,OAAO,EAClC,MAAK,MAAM,WAAW,KAAK,SACzB,MAAK,MAAM,MAAM,QAAQ,YAAY;EACnC,MAAM,UAAU,GAAG,GAAG,WAAW,aAAa,CAAC,GAAG,GAAG;EACrD,MAAM,gBAAgB,OAAO,kBAAkB,IAAI,QAAQ;AAC3D,MAAI,CAAC,cAAe;AAGpB,MAAI,GAAG,SAAS,SAAS,WAAW,CAAC,OAAO,IAAI,GAAG,SAAS,KAAK,EAAE;GACjE,MAAM,cAAc,MAAM,sBAAsB,cAAc,WAAW;AACzE,OAAI,eAAe,QAAQ,WAAW,cAAc;AAClD,WAAO,cAAc,IAAI,GAAG,SAAS,MAAM,YAAY;AACvD,WAAO,IAAI,GAAG,SAAS,KAAK;AAC5B,iBAAa,IAAI,YAAY;;;AAKjC,MAAI,GAAG,aAAa,SAAS,WAAW,CAAC,OAAO,IAAI,GAAG,YAAY,KAAK,CACtE,MAAK,MAAM,SAAS,cAAc,QAAQ;GACxC,MAAM,cAAc,MAAM,qBAAqB,MAAM,KAAK;AAC1D,OAAI,eAAe,QAAQ,WAAW,cAAc;AAClD,WAAO,cAAc,IAAI,GAAG,YAAY,MAAM,YAAY;AAC1D,WAAO,IAAI,GAAG,YAAY,KAAK;AAC/B,iBAAa,IAAI,YAAY;AAC7B;;;;CAUZ,MAAM,gBAA6E,EAAE;AACrF,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,WAAW,EAAE;AAC9D,MAAI,aAAa,IAAI,KAAK,CAAE;EAC5B,MAAM,SAAS,2BAA2B,MAAM;AAChD,MAAI,OAAO,QAAQ,EACjB,eAAc,KAAK;GAAE;GAAM;GAAQ,YAAY,OAAO;GAAM,CAAC;;CAIjE,MAAM,oBAAoB,IAAI,IAAI,cAAc,KAAK,MAAM,EAAE,KAAK,CAAC;AAEnE,MAAK,MAAM,SAAS,KAAK,QAAQ;AAC/B,MAAI,OAAO,IAAI,MAAM,KAAK,CAAE;AAC5B,MAAI,MAAM,OAAO,SAAS,EAAG;AAM7B,MAAI,kBAAkB,IAAI,MAAM,KAAK,IAAI,CAAC,aAAa,IAAI,MAAM,KAAK,EAAE;AACtE,UAAO,cAAc,IAAI,MAAM,MAAM,MAAM,KAAK;AAChD,UAAO,IAAI,MAAM,KAAK;AACtB,gBAAa,IAAI,MAAM,KAAK;AAC5B;;EAIF,MAAM,eAAe,MAAM,kBAAkB,MAAM,KAAK;AACxD,OAAK,MAAM,WAAW,aACpB,KAAI,kBAAkB,IAAI,QAAQ,IAAI,CAAC,aAAa,IAAI,QAAQ,EAAE;AAChE,UAAO,cAAc,IAAI,MAAM,MAAM,QAAQ;AAC7C,UAAO,IAAI,MAAM,KAAK;AACtB,gBAAa,IAAI,QAAQ;AACzB;;AAGJ,MAAI,OAAO,IAAI,MAAM,KAAK,CAAE;AAG5B,MAAI,SAAS,iBAAkB;EAG/B,MAAM,WAAW,sBAAsB,MAAM;EAC7C,IAAI,YAA2B;EAC/B,IAAI,YAAY;AAEhB,OAAK,MAAM,OAAO,eAAe;AAC/B,OAAI,aAAa,IAAI,IAAI,KAAK,CAAE;GAEhC,MAAM,EAAE,OAAO,iBAAiB,kBAAkB,UAAU,IAAI,OAAO;GAGvE,MAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,OAAO,GAAI,CAAC;AACnE,OAAI,QAAQ,aAAa,SAAS,MAAO,gBAAgB,iBAAiB;AACxE,gBAAY;AACZ,gBAAY,IAAI;;;AAIpB,MAAI,WAAW;AACb,UAAO,cAAc,IAAI,MAAM,MAAM,UAAU;AAC/C,UAAO,IAAI,MAAM,KAAK;AACtB,gBAAa,IAAI,UAAU;;;;;AAMjC,MAAM,uBAAuB,IAAI,IAAI,CAAC,kBAAkB,iBAAiB,CAAC;;AAG1E,SAAgB,kBAAkB,QAAmC;AACnE,QAAO,qBAAqB,IAAI,OAAO,SAAS;;;;;;;AAQlD,SAAgB,aAAa,SAAwB,SAA6B,UAAqC;CACrH,MAAM,UAAyB;EAC7B,mBAAmB,IAAI,IAAI,QAAQ,kBAAkB;EACrD,iBAAiB,IAAI,IAAI,QAAQ,gBAAgB;EACjD,iBAAiB,IAAI,IAAI,QAAQ,gBAAgB;EACjD,iBAAiB,IAAI,IAAI,QAAQ,gBAAgB;EACjD,iBAAiB,IAAI,IAAI,MAAM,KAAK,QAAQ,gBAAgB,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;EACxG,eAAe,IAAI,IAAI,QAAQ,cAAc;EAC7C,cAAc,IAAI,IAAI,QAAQ,aAAa;EAC5C;CAED,IAAI,iBAAiB;AAErB,MAAK,MAAM,KAAK,SAAS;AACvB,MAAI,CAAC,kBAAkB,EAAE,CAAE;EAG3B,MAAM,QAAQ,EAAE,OAAO,MAAM,IAAI;AACjC,MAAI,MAAM,WAAW,GAAG;GACtB,MAAM,CAAC,WAAW,cAAc;GAChC,MAAM,YAAY,SAAS,QAAQ;AACnC,OAAI,aAAa,UAAU,QAAQ,aAAa,SAAS,GAAG;IAC1D,MAAM,UAAU,QAAQ,gBAAgB,IAAI,GAAG,UAAU,GAAG,aAAa;AACzE,QAAI,CAAC,WAAW,QAAQ,gBAAgB,SAAS,KAAK,CAAC,gBAAgB;AACrE,aAAQ,KACN,kMAED;AACD,sBAAiB;;AAEnB,QAAI,SAAS;KACX,MAAM,SAAS,UAAU,QAAQ,YAAY;AAC7C,aAAQ,kBAAkB,IAAI,SAAS;MACrC;MACA;MACA,QAAQ,OAAO;MACf,YAAY,OAAO;MACpB,CAAC;;;AAIN,OADkB,SAAS,WAAW,WAEpC,SAAQ,gBAAgB,IAAI,WAAW,UAAU;aAE1C,MAAM,WAAW,GAAG;GAC7B,MAAM,OAAO,MAAM;AACnB,OAAI,SAAS,WAAW,MACtB,SAAQ,gBAAgB,IAAI,MAAM,KAAK;AAEzC,OAAI,SAAS,YAAY,MACvB,SAAQ,gBAAgB,IAAI,MAAM,KAAK;;;AAK7C,QAAO;;;;ACpjBT,MAAM,6BAAa,IAAI,KAAwB;AAE/C,SAAgB,kBAAkB,WAA4B;AAC5D,YAAW,IAAI,UAAU,UAAU,UAAU;;AAG/C,SAAgB,aAAa,UAA6B;CACxD,MAAM,YAAY,WAAW,IAAI,SAAS;AAC1C,KAAI,CAAC,UAEH,OAAM,IAAI,cACR,yCAAyC,SAAS,eAFlC,CAAC,GAAG,WAAW,MAAM,CAAC,CAAC,KAAK,KAAK,IAAI,YAGrD,8BAA8B,SAAS,sEACxC;AAEH,QAAO;;;;;;;;;;ACIT,SAAgB,iBAAiB,KAA0C;CACzE,MAAM,eAAeC,OAAK,KAAK,KAAK,kBAAkB;AACtD,KAAI,CAAC,WAAW,aAAa,CAAE,QAAO,KAAA;AACtC,KAAI;EAEF,MAAM,aADS,KAAK,MAAM,aAAa,cAAc,QAAQ,CAAC,EACnC;AAC3B,MAAI,CAAC,cAAc,OAAO,eAAe,SAAU,QAAO,KAAA;AAC1D,SAAO,mCAAmC,WAAW;SAC/C;AACN;;;;AAKJ,SAAS,mCAAmC,YAAsD;CAChG,MAAM,UAA2B,EAAE;AACnC,MAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,WAAW,EAAE;EACzD,MAAM,WAAW,QAAQ,QAAQ,IAAI;EACrC,MAAM,aAAa,QAAQ,MAAM,GAAG,SAAS;EAC7C,MAAM,WAAW,QAAQ,MAAM,WAAW,EAAE;EAE5C,MAAM,SAAS,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;AACrD,OAAK,MAAM,KAAK,QAAQ;GACtB,MAAM,QAAQ;AACd,WAAQ,KAAK;IACX,aAAa;IACb,qBAAqB,MAAM,WAAW;IACtC,eAAe,MAAM,aAAa;IAClC;IACA,MAAM;IACN,YAAY,EAAE;IACd,YAAY,EAAE;IACd,aAAa,EAAE;IAChB,CAAC;;;AAGN,QAAO;;;;;;;;ACxCT,SAAgB,mBAAmB,MAKhB;CACjB,IAAI;AACJ,KAAI;AACF,QAAM,aAAa,KAAK,gBAAgB,QAAQ;SAC1C;AACN,QAAM,IAAI,YACR,+BAA+B,KAAK,eAAe,iCACnD,mEAAmE,KAAK,KAAK,0DAC9E;;CAEH,IAAI;AACJ,KAAI;AACF,eAAa,KAAK,MAAM,IAAI;UACrB,KAAK;AACZ,QAAM,IAAI,YACR,qCAAqC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACrF,WAAW,KAAK,eAAe,mEAChC;;CAIH,MAAM,WAAW,iBAAiB,KAAK,UAAU;CAEjD,IAAI,QAAuB;AAC3B,KAAI;AACF,UAAQ,aAAa,KAAK,KAAK,CAAC;SAC1B;CAIR,MAAM,gBAAgB,mBAAmB,YAAY,UAAU,KAAK,MAAM,MAAM;AAChF,QAAO;EAAE;EAAY;EAAe;;;;;;;;;;;AC7CtC,SAAgB,cAAc,MAAe,QAAyB;CAEpE,MAAM,OAAO,OAAO,QAAQ,QAAQ,GAAG;CAEvC,SAAS,OAAO,aAAqD;AACnE,MAAI,CAAC,YAAa,QAAO;AAEzB,SAAO,YAAY,QAAQ,kBAAkB,IAAI,KAAK,MAAM;;AAG9D,QAAO;EACL,GAAG;EACH,aAAa,OAAO,KAAK,YAAY;EACrC,UAAU,KAAK,SAAS,KAAK,aAAa;GACxC,GAAG;GACH,aAAa,OAAO,QAAQ,YAAY;GACxC,YAAY,QAAQ,WAAW,KAAK,QAAQ;IAC1C,GAAG;IACH,aAAa,OAAO,GAAG,YAAY;IACnC,YAAY,GAAG,WAAW,KAAK,OAAO;KAAE,GAAG;KAAG,aAAa,OAAO,EAAE,YAAY;KAAE,EAAE;IACpF,aAAa,GAAG,YAAY,KAAK,OAAO;KAAE,GAAG;KAAG,aAAa,OAAO,EAAE,YAAY;KAAE,EAAE;IACtF,cAAc,GAAG,aAAa,KAAK,OAAO;KAAE,GAAG;KAAG,aAAa,OAAO,EAAE,YAAY;KAAE,EAAE;IACzF,EAAE;GACJ,EAAE;EACH,QAAQ,KAAK,OAAO,KAAK,WAAW;GAClC,GAAG;GACH,aAAa,OAAO,MAAM,YAAY;GACtC,QAAQ,MAAM,OAAO,KAAK,OAAO;IAAE,GAAG;IAAG,aAAa,OAAO,EAAE,YAAY;IAAE,EAAE;GAChF,EAAE;EACH,OAAO,KAAK,MAAM,KAAK,OAAO;GAC5B,GAAG;GACH,QAAQ,EAAE,OAAO,KAAK,OAAO;IAAE,GAAG;IAAG,aAAa,OAAO,EAAE,YAAY;IAAE,EAAE;GAC5E,EAAE;EACJ;;;;ACnCH,eAAsB,gBAAgB,MA0BpB;CAChB,IAAI,KAAK,MAAM,UAAU,KAAK,MAAM;EAClC,sBAAsB,KAAK;EAC3B,qBAAqB,KAAK;EAC1B,eAAe,KAAK;EACpB,YAAY,KAAK;EAClB,CAAC;AACF,KAAI,KAAK,OACP,MAAK,cAAc,IAAI,KAAK,OAAO;CAErC,MAAM,UAAU,WAAW,KAAK,KAAK;CACrC,MAAM,YAAY,KAAK,aAAa,GAAG;CAMvC,MAAM,YADc,MAAM,QAAQ,KAAK,SAAS,GAAG,KAAK,WAAW,KAAK,UAAU,MAAM,IAAI,GAC9D,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC,OAAO,QAAQ;CAGlE,IAAI;CACJ,IAAI;AACJ,KAAI,KAAK,cAAc,KAAK,gBAAgB,OAAO;EACjD,MAAM,MAAM,mBAAmB;GAC7B,gBAAgB,KAAK;GACrB,WAAW,KAAK;GAChB,MAAM,KAAK;GACX,MAAM;GACP,CAAC;AACF,eAAa,IAAI;AACjB,kBAAgB,IAAI;;CAGtB,MAAM,QAAQ,MAAM,SAAS,IAAI,SAAS;EACxC;EACA,QAAQ,KAAK;EACb,WAAW,KAAK;EAChB,QAAQ,KAAK;EACb;EACA;EACA,gBAAgB,KAAK;EACrB,YAAY,KAAK;EACjB,YAAY,KAAK;EACjB,gBAAgB,KAAK;EACrB,SAAS,KAAK,UAAU;EACxB,UAAU,YAAY,SAAS,SAAS,IAAI,WAAW,KAAA;EACxD,CAAC;AAEF,KAAI,KAAK,OACP,MAAK,MAAM,KAAK,MACd,SAAQ,IAAI,EAAE,KAAK;MAEhB;AACL,UAAQ,IAAI,aAAa,MAAM,OAAO,YAAY,KAAK,SAAS;AAChE,MAAI,KAAK,OACP,SAAQ,IAAI,mBAAmB,KAAK,SAAS;;;;;ACtFnD,SAAgB,oBAAoB,MAA2B,WAAmB,YAAmC;AACnH,SAAQ,MAAR;EACE,KAAK,cACH,QAAO;GACL;GACA;GACA,gBAAgB,aAAa,aAAa;GAC3C;EACH,KAAK,gBACH,QAAO;GAAE;GAAM;GAAW,gBAAgB;GAAY;EACxD,KAAK,qBACH,QAAO;GAAE;GAAM;GAAW,gBAAgB;GAAY;EACxD,KAAK,uBAMH,QAAO;GAAE;GAAM;GAAW,gBAAgB;GAAY;EACxD,KAAK,yBACH,QAAO;GACL;GACA;GACA,gBAAgB,aAAa,aAAa;GAC1C,SAAS,aAAa,wBAAwB;GAC/C;EACH,KAAK,uBACH,QAAO;GAAE;GAAM;GAAW,gBAAgB;GAAY;;;AAI5D,SAAgB,oBAAoB,MAA2B,WAAmB,YAAmC;AACnH,SAAQ,MAAR;EACE,KAAK,cACH,QAAO;GACL;GACA;GACA,gBAAgB,aAAa,aAAa;GAC3C;EACH,KAAK,gBACH,QAAO;GAAE;GAAM;GAAW,gBAAgB;GAAY;EACxD,KAAK,qBACH,QAAO;GAAE;GAAM;GAAW,gBAAgB;GAAY;EACxD,KAAK,uBAGH,QAAO;GAAE;GAAM;GAAW,gBAAgB;GAAY;EACxD,KAAK,yBACH,QAAO;GACL;GACA;GACA,gBAAgB,aAAa,aAAa;GAC3C;EACH,KAAK,wBAKH,QAAO;GAAE;GAAM;GAAW,gBAAgB;GAAY;;;;;ACvD5D,SAAgB,WAAW,WAAoB,WAA8B;CAC3E,MAAM,UAAoB,EAAE;CAC5B,MAAM,YAAY,IAAI,IAAI,UAAU,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAC5D,MAAM,YAAY,IAAI,IAAI,UAAU,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAE5D,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EAAE,MAAM;EAAe;EAAM,gBAAgB;EAAY,CAAC;AAI3E,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EAAE,MAAM;EAAiB;EAAM,gBAAgB;EAAY,CAAC;AAI7E,MAAK,MAAM,CAAC,MAAM,aAAa,WAAW;EACxC,MAAM,WAAW,UAAU,IAAI,KAAK;AACpC,MAAI,CAAC,SAAU;EAEf,MAAM,eAAe,WAAW,UAAU,SAAS;AACnD,MAAI,aAAa,SAAS,GAAG;GAC3B,MAAM,cAAc,aAAa,MAAM,OAAO,GAAG,mBAAmB,WAAW;AAC/E,WAAQ,KAAK;IACX,MAAM;IACN;IACA;IACA,gBAAgB,cAAc,aAAa;IAC5C,CAAC;;;AAIN,QAAO;;AAGT,SAAS,WAAW,UAAiB,UAAgC;CACnE,MAAM,UAAyB,EAAE;CACjC,MAAM,YAAY,IAAI,IAAI,SAAS,OAAO,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAClE,MAAM,YAAY,IAAI,IAAI,SAAS,OAAO,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAElE,MAAK,MAAM,CAAC,MAAM,UAAU,UAC1B,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK,oBAAoB,eAAe,MAAM,MAAM,SAAS,CAAC;AAI1E,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK,oBAAoB,iBAAiB,KAAK,CAAC;AAI5D,MAAK,MAAM,CAAC,MAAM,aAAa,WAAW;EACxC,MAAM,WAAW,UAAU,IAAI,KAAK;AACpC,MAAI,CAAC,SAAU;AAEf,MAAI,CAAC,cAAc,SAAS,MAAM,SAAS,KAAK,CAC9C,KAAI,6BAA6B,SAAS,MAAM,SAAS,KAAK,CAC5D,SAAQ,KAAK;GACX,GAAG,oBAAoB,wBAAwB,KAAK;GACpD,SAAS,oBAAoB,SAAS,MAAM,SAAS,KAAK;GAC3D,CAAC;MAEF,SAAQ,KAAK;GACX,MAAM;GACN,WAAW;GACX,gBAAgB;GAChB,SAAS;GACV,CAAC;AAIN,MAAI,SAAS,aAAa,SAAS,SACjC,SAAQ,KAAK,oBAAoB,0BAA0B,MAAM,SAAS,SAAS,CAAC;AAGtF,MAAI,CAAC,CAAC,SAAS,aAAa,CAAC,CAAC,SAAS,YAAY,CAAC,CAAC,SAAS,cAAc,CAAC,CAAC,SAAS,UACrF,SAAQ,KAAK,oBAAoB,wBAAwB,KAAK,CAAC;;AAInE,QAAO;;;;;;;;;AAUT,SAAgB,6BAA6B,GAAY,GAAqB;AAC5E,KAAI,EAAE,SAAS,eAAe,EAAE,SAAS,YAAa,QAAO;AAC7D,KAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,SAAQ,EAAE,UAAU,SAAS,EAAE,UAAU;;AAG3C,SAAgB,oBAAoB,GAAY,GAAoB;CAClE,MAAM,SAAS,EAAE,SAAS,cAAc,EAAE,SAAS,KAAA;CACnD,MAAM,SAAS,EAAE,SAAS,cAAc,EAAE,SAAS,KAAA;AACnD,QAAO,UAAU,UAAU,UAAU,KAAK,UAAU;;AAGtD,SAAgB,cAAc,GAAY,GAAqB;AAC7D,KAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAE9B,SAAQ,EAAE,MAAV;EACE,KAAK,YACH,QAAO,EAAE,SAAS,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,SAAU,EAAe,UAAU;EACxG,KAAK,QACH,QAAO,EAAE,SAAS,WAAW,cAAc,EAAE,OAAO,EAAE,MAAM;EAC9D,KAAK,QACH,QAAO,EAAE,SAAS,WAAW,EAAE,SAAS,EAAE;EAC5C,KAAK,OACH,QAAO,EAAE,SAAS,UAAU,EAAE,SAAS,EAAE;EAC3C,KAAK,UACH,QAAO,EAAE,SAAS,aAAa,EAAE,UAAU,EAAE;EAC/C,KAAK,WACH,QAAO,EAAE,SAAS,cAAc,cAAc,EAAE,OAAO,EAAE,MAAM;EACjE,KAAK,SAAS;AACZ,OAAI,EAAE,SAAS,QAAS,QAAO;AAC/B,OAAI,EAAE,SAAS,WAAW,EAAE,SAAS,OAAQ,QAAO;AACpD,OAAI,CAAC,EAAE,SAAS,OAAO,GAAG,MAAM,cAAc,GAAG,EAAE,SAAS,GAAG,CAAC,CAAE,QAAO;AAEzE,OAAI,CAAC,EAAE,iBAAiB,CAAC,EAAE,cAAe,QAAO;AACjD,OAAI,CAAC,EAAE,iBAAiB,CAAC,EAAE,cAAe,QAAO;AACjD,OAAI,EAAE,cAAc,aAAa,EAAE,cAAc,SAAU,QAAO;GAClE,MAAM,QAAQ,OAAO,KAAK,EAAE,cAAc,QAAQ,CAAC,MAAM;GACzD,MAAM,QAAQ,OAAO,KAAK,EAAE,cAAc,QAAQ,CAAC,MAAM;AACzD,OAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAC1C,UAAO,MAAM,OAAO,GAAG,MAAM,MAAM,MAAM,MAAM,EAAE,cAAe,QAAQ,OAAO,EAAE,cAAe,QAAQ,GAAG;;EAE7G,KAAK,MACH,QAAO,EAAE,SAAS,SAAS,cAAc,EAAE,WAAW,EAAE,UAAU;;AAEtE,QAAO,YAAY,EAAE;;;;ACxIvB,SAAgB,eAAe,aAAqB,QAAqB,QAA+B;CACtG,MAAM,UAAoB,EAAE;CAC5B,MAAM,YAAY,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CACzD,MAAM,YAAY,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAEzD,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EACX,MAAM;EACN;EACA,eAAe;EACf,gBAAgB;EACjB,CAAC;AAIN,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EACX,MAAM;EACN;EACA,eAAe;EACf,gBAAgB;EACjB,CAAC;AAIN,MAAK,MAAM,CAAC,MAAM,UAAU,WAAW;EACrC,MAAM,QAAQ,UAAU,IAAI,KAAK;AACjC,MAAI,CAAC,MAAO;EAEZ,MAAM,eAAe,WAAW,OAAO,MAAM;EAC7C,MAAM,kBAAkB,CAAC,cAAc,MAAM,UAAU,MAAM,SAAS;EACtE,MAAM,qBAAqB,CAAC,mBAAmB,MAAM,aAAa,MAAM,YAAY;EACpF,MAAM,oBAAoB,MAAM,eAAe,MAAM;EACrD,MAAM,cAAc,MAAM,SAAS,MAAM;EACzC,MAAM,mBAAmB,CAAC,CAAC,MAAM,eAAe,CAAC,CAAC,MAAM;EACxD,MAAM,8BAA8B,MAAM,yBAAyB,MAAM;EACzE,MAAM,aAAa,qBAAqB,MAAM,QAAQ,MAAM,OAAO;EACnE,MAAM,gBAAgB,eAAe;AAYrC,MATE,aAAa,SAAS,KACtB,mBACA,sBACA,qBACA,eACA,oBACA,+BACA,eAEc;GAGd,MAAM,oBAAoB,oBAAoB,CAAC,MAAM;GAGrD,MAAM,+BAA+B,+BAA+B,CAAC,MAAM;GAG3E,MAAM,cACJ,mBACA,sBACA,qBACA,eACA,qBACA,gCARqB,eAAe,cAUpC,aAAa,MAAM,OAAO,GAAG,mBAAmB,WAAW;AAC7D,WAAQ,KAAK;IACX,MAAM;IACN;IACA,eAAe;IACf;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,gBAAgB,cAAc,aAAa;IAC5C,CAAC;;;AAIN,QAAO;;AAGT,SAAS,mBAAmB,GAA6B,GAAsC;AAC7F,KAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,KAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,QAAO,cAAc,GAAG,EAAE;;AAG5B,SAAS,qBACP,WACA,WACkC;CAClC,MAAM,YAAY,IAAI,IAAI,UAAU,KAAK,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;CAClE,MAAM,YAAY,IAAI,IAAI,UAAU,KAAK,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;CAElE,IAAI,cAAc;CAClB,IAAI,cAAc;AAGlB,MAAK,MAAM,QAAQ,UAAU,MAAM,CACjC,KAAI,CAAC,UAAU,IAAI,KAAK,CAAE,eAAc;AAI1C,MAAK,MAAM,QAAQ,UAAU,MAAM,CACjC,KAAI,CAAC,UAAU,IAAI,KAAK,CAAE,eAAc;AAI1C,MAAK,MAAM,CAAC,MAAM,WAAW,WAAW;EACtC,MAAM,SAAS,UAAU,IAAI,KAAK;AAClC,MAAI,CAAC,OAAQ;AACb,MAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,KAAM;AAClC,MAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,QAAQ,CAAC,cAAc,OAAO,MAAM,OAAO,KAAK,CAC1E,eAAc;;AAIlB,KAAI,YAAa,QAAO;AACxB,KAAI,YAAa,QAAO;AACxB,QAAO;;AAGT,SAAS,WAAW,OAAkB,OAAiC;CACrE,MAAM,UAAyB,EAAE;CACjC,MAAM,UAAU,KAAkC,WAChD,OAAO,KAAK,OAAO;EAAE;EAAG;EAAK,EAAE;CACjC,MAAM,eAAe;EACnB,GAAG,OAAO,QAAQ,MAAM,WAAW;EACnC,GAAG,OAAO,SAAS,MAAM,YAAY;EACrC,GAAG,OAAO,UAAU,MAAM,aAAa;EACxC;CACD,MAAM,eAAe;EACnB,GAAG,OAAO,QAAQ,MAAM,WAAW;EACnC,GAAG,OAAO,SAAS,MAAM,YAAY;EACrC,GAAG,OAAO,UAAU,MAAM,aAAa;EACxC;CACD,MAAM,YAAY,IAAI,IAAI,aAAa,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;CACjE,MAAM,YAAY,IAAI,IAAI,aAAa,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAEjE,MAAK,MAAM,CAAC,MAAM,UAAU,UAC1B,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK,oBAAoB,eAAe,MAAM,MAAM,EAAE,SAAS,CAAC;AAI5E,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK,oBAAoB,iBAAiB,KAAK,CAAC;AAI5D,MAAK,MAAM,CAAC,MAAM,aAAa,WAAW;EACxC,MAAM,WAAW,UAAU,IAAI,KAAK;AACpC,MAAI,CAAC,SAAU;AAEf,MAAI,CAAC,cAAc,SAAS,EAAE,MAAM,SAAS,EAAE,KAAK,CAClD,KAAI,6BAA6B,SAAS,EAAE,MAAM,SAAS,EAAE,KAAK,EAAE;GAClE,MAAM,SAAS,oBAAoB,wBAAwB,KAAK;AAChE,UAAO,UAAU,oBAAoB,SAAS,EAAE,MAAM,SAAS,EAAE,KAAK;AACtE,WAAQ,KAAK,OAAO;QAEpB,SAAQ,KAAK,oBAAoB,sBAAsB,KAAK,CAAC;AAIjE,MAAI,SAAS,EAAE,aAAa,SAAS,EAAE,SACrC,SAAQ,KAAK,oBAAoB,0BAA0B,MAAM,SAAS,EAAE,SAAS,CAAC;EAGxF,MAAM,aAAa,iBAAiB,SAAS,EAAE,QAAQ;EACvD,MAAM,aAAa,iBAAiB,SAAS,EAAE,QAAQ;AACvD,MAAI,eAAe,YAAY;GAC7B,MAAM,SAAS,oBAAoB,yBAAyB,KAAK;AACjE,UAAO,aAAa;AACpB,UAAO,aAAa;AACpB,UAAO,gBAAgB,SAAS;AAChC,UAAO,UAAU,WAAW,cAAc,UAAU,KAAK,cAAc;AACvE,WAAQ,KAAK,OAAO;;;AAIxB,QAAO;;AAGT,SAAS,iBAAiB,OAA+B;AACvD,KAAI,UAAU,KAAA,EAAW,QAAO;AAChC,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,OAAO,MAAM;AAIjF,KAAI;AACF,SAAO,KAAK,UAAU,MAAM;SACtB;AACN,SAAO,OAAO,MAAM;;;;;AC5MxB,SAAgB,aAAa,aAAwB,aAAkC;CACrF,MAAM,UAAoB,EAAE;CAC5B,MAAM,YAAY,IAAI,IAAI,YAAY,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAC9D,MAAM,YAAY,IAAI,IAAI,YAAY,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAE9D,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EAAE,MAAM;EAAiB;EAAM,gBAAgB;EAAY,CAAC;AAI7E,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EAAE,MAAM;EAAmB;EAAM,gBAAgB;EAAY,CAAC;AAI/E,MAAK,MAAM,CAAC,MAAM,eAAe,WAAW;EAC1C,MAAM,aAAa,UAAU,IAAI,KAAK;AACtC,MAAI,CAAC,WAAY;AAEjB,UAAQ,KAAK,GAAG,eAAe,MAAM,WAAW,YAAY,WAAW,WAAW,CAAC;;AAGrF,QAAO;;;;ACvBT,SAAgB,UAAU,SAAkB,SAA8B;CACxE,MAAM,UAAoB;EACxB,GAAG,WAAW,QAAQ,QAAQ,QAAQ,OAAO;EAC7C,GAAG,UAAU,QAAQ,OAAO,QAAQ,MAAM;EAC1C,GAAG,aAAa,QAAQ,UAAU,QAAQ,SAAS;EACpD;CAED,MAAM,kBAAkB,uBAAuB,QAAQ;AAEvD,QAAO;EACL,YAAY,QAAQ;EACpB,YAAY,QAAQ;EACpB;EACA;EACA,SAAS;GAAE,GAAG,UAAU,QAAQ;GAAE,iBAAiB,gBAAgB;GAAQ;EAC5E;;AAGH,SAAS,uBAAuB,SAAqC;CACnE,MAAM,MAAwB,EAAE;AAChC,MAAK,MAAM,KAAK,SAAS;AACvB,MAAI,EAAE,SAAS,qBAAsB;AACrC,OAAK,MAAM,MAAM,EAAE,cAAc;AAC/B,OAAI,GAAG,SAAS,wBAAyB;AACzC,OAAI,KAAK;IACP,MAAM;IACN,aAAa,EAAE;IACf,eAAe,EAAE;IACjB,WAAW,GAAG;IACd,eAAe,GAAG,iBAAiB;IACnC,YAAY,GAAG,cAAc;IAC7B,YAAY,GAAG,cAAc;IAC7B,gBAAgB;IACjB,CAAC;;;AAGN,QAAO;;AAGT,SAAS,UAAU,UAAkB,UAA4B;CAC/D,MAAM,UAAoB,EAAE;CAC5B,MAAM,YAAY,IAAI,IAAI,SAAS,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAC3D,MAAM,YAAY,IAAI,IAAI,SAAS,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAE3D,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EAAE,MAAM;EAAc;EAAM,gBAAgB;EAAY,CAAC;AAI1E,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EAAE,MAAM;EAAgB;EAAM,gBAAgB;EAAY,CAAC;AAI5E,MAAK,MAAM,CAAC,MAAM,YAAY,WAAW;EACvC,MAAM,UAAU,UAAU,IAAI,KAAK;AACnC,MAAI,CAAC,QAAS;EAEd,MAAM,eAAe,eAAe,SAAS,QAAQ;AACrD,MAAI,aAAa,SAAS,GAAG;GAC3B,MAAM,cAAc,aAAa,MAAM,OAAO,GAAG,mBAAmB,WAAW;AAC/E,WAAQ,KAAK;IACX,MAAM;IACN;IACA;IACA,gBAAgB,cAAc,aAAa;IAC5C,CAAC;;;AAIN,QAAO;;AAGT,SAAS,eAAe,SAAe,SAAkC;CACvE,MAAM,UAA6B,EAAE;CACrC,MAAM,YAAY,IAAI,IAAI,QAAQ,OAAO,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CACjE,MAAM,YAAY,IAAI,IAAI,QAAQ,OAAO,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAEjE,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EAAE,MAAM;EAAe,WAAW;EAAM,gBAAgB;EAAY,CAAC;AAItF,MAAK,MAAM,CAAC,SAAS,UACnB,KAAI,CAAC,UAAU,IAAI,KAAK,CACtB,SAAQ,KAAK;EAAE,MAAM;EAAiB,WAAW;EAAM,gBAAgB;EAAY,CAAC;AAIxF,MAAK,MAAM,CAAC,MAAM,WAAW,WAAW;EACtC,MAAM,SAAS,UAAU,IAAI,KAAK;AAClC,MAAI,CAAC,OAAQ;AAEb,MAAI,OAAO,UAAU,OAAO,MAC1B,SAAQ,KAAK;GACX,MAAM;GACN,WAAW;GACX,gBAAgB;GAChB,SAAS,uBAAuB,OAAO,MAAM,QAAQ,OAAO,MAAM;GACnE,CAAC;;AAIN,QAAO;;AAGT,SAAS,UAAU,SAAmB;CACpC,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,WAAW;CACf,IAAI,WAAW;CACf,IAAI,WAAW;AAEf,MAAK,MAAM,KAAK,SAAS;AACvB,MAAI,EAAE,KAAK,SAAS,SAAS,CAAE;WACtB,EAAE,KAAK,SAAS,WAAW,CAAE;WAC7B,EAAE,KAAK,SAAS,YAAY,CAAE;AAEvC,MAAI,EAAE,mBAAmB,WAAY;MAChC;;AAGP,QAAO;EAAE;EAAO;EAAS;EAAU;EAAU;EAAU;;;;AC7HzD,eAAsB,YAAY,MAOhB;CAChB,MAAM,eAAe;EACnB,sBAAsB,KAAK;EAC3B,qBAAqB,KAAK;EAC1B,eAAe,KAAK;EACrB;CACD,IAAI,CAAC,SAAS,WAAW,MAAM,QAAQ,IAAI,CAAC,UAAU,KAAK,KAAK,aAAa,EAAE,UAAU,KAAK,KAAK,aAAa,CAAC,CAAC;AAClH,KAAI,KAAK,QAAQ;AACf,YAAU,cAAc,SAAS,KAAK,OAAO;AAC7C,YAAU,cAAc,SAAS,KAAK,OAAO;;CAG/C,MAAM,OAAO,UAAU,SAAS,QAAQ;AACxC,SAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC1C,OAAM,IAAI,aACR,IACA,IACA,KAAK,QAAQ,WAAW,IACpB,IACA,KAAK,QAAQ,WAAW,KAAK,KAAK,QAAQ,UAAU,IAClD,IACA,KAAK,QAAQ,QAAQ,IACnB,IACA,EACT;;;;ACjCH,eAAsB,eAAe,MAAwE;CAC3G,MAAM,YAAY,aAAa,KAAK,KAAK;AACzC,SAAQ,IAAI,cAAc,KAAK,KAAK,oBAAoB,KAAK,QAAQ,KAAK;CAC1E,MAAM,UAAU,MAAM,UAAU,QAAQ,KAAK,QAAQ;AACrD,eAAc,KAAK,QAAQ,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;CAC5D,MAAM,cACJ,OAAO,KAAK,QAAQ,QAAQ,CAAC,SAC7B,OAAO,KAAK,QAAQ,WAAW,CAAC,SAChC,OAAO,KAAK,QAAQ,YAAY,CAAC,SACjC,OAAO,KAAK,QAAQ,MAAM,CAAC;AAC7B,SAAQ,IAAI,aAAa,YAAY,aAAa,KAAK,SAAS;;;;;ACclE,MAAM,oBAA2D;CAC/D,KAAK;EACH,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACD,QAAQ;EACN,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACD,MAAM;EACJ,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACD,IAAI;EACF,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACD,QAAQ;EACN,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACD,QAAQ;EACN,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACD,QAAQ;EACN,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACD,MAAM;EACJ,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACD,MAAM;EACJ,sBAAsB;EACtB,yBAAyB;EACzB,kCAAkC;EAClC,uCAAuC;EACvC,uBAAuB;EACvB,kBAAkB;EACnB;CACF;;AAGD,SAAgB,iBAAiB,UAAyC;AACxE,QAAO,EAAE,GAAG,kBAAkB,WAAW;;;AAI3C,SAAgB,YAAY,UAA6B,WAA0D;AACjH,QAAO;EAAE,GAAG;EAAU,GAAG;EAAW;;;;;AC3FtC,SAAgB,iBAAiB,MAAuC;AACtE,KAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;CACtD,MAAM,MAAM;AACZ,QACE,OAAO,IAAI,kBAAkB,YAC7B,OAAO,IAAI,WAAW,YACtB,IAAI,WAAW,QACf,OAAO,IAAI,aAAa,YACxB,IAAI,aAAa,QACjB,MAAM,QAAQ,IAAI,QAAQ;;;;;;;;;;ACoG9B,SAAgB,qBAAqB,SAAqC;CACxE,MAAM,WAAY,QAAQ,YAAY;CACtC,MAAM,UAA0B,EAAE;AAGlC,MAAK,MAAM,CAAC,WAAW,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AAC9D,UAAQ,KAAK;GACX,IAAI,SAAS;GACb,MAAM;GACN,QAAQ;GACR,aAAa;GACb,YAAY;GACZ,WAAW,IAAI,qBAAqB,eAAe;GACnD,YAAY;GACZ,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,YAAY,GAAG,EAAE;GACzD,CAAC;AAGF,MAAI,IAAI,kBAAkB,SAAS,EACjC,SAAQ,KAAK;GACX,IAAI,QAAQ;GACZ,MAAM;GACN,QAAQ,GAAG,UAAU;GACrB,aAAa;GACb,aAAa,OAAO;GACpB,YAAY;GACZ,WAAW;GACX,YAAY;GACZ,YAAY,IAAI,kBAAkB,KAAK,GAAG,MAAM,sBAAsB,GAAG,GAAG,SAAS,CAAC;GACtF,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,YAAY,GAAG,EAAE;GACzD,CAAC;AAIJ,OAAK,MAAM,CAAC,YAAY,cAAc,OAAO,QAAQ,IAAI,QAAQ,CAC/D,MAAK,IAAI,KAAK,GAAG,KAAK,UAAU,QAAQ,MAAM;GAC5C,MAAM,SAAS,UAAU;GACzB,MAAM,SAAS,UAAU,SAAS,IAAI,IAAI,OAAO;AACjD,WAAQ,KAAK;IACX,IAAI,UAAU,UAAU,GAAG,aAAa;IACxC,MAAM;IACN,QAAQ,GAAG,UAAU,GAAG;IACxB,aAAa;IACb,aAAa,GAAG,UAAU,GAAG;IAC7B,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,YAAY,OAAO,OAAO,KAAK,GAAG,MAAM,sBAAsB,GAAG,GAAG,SAAS,CAAC;IAC9E,SAAS,EAAE,MAAM,OAAO,YAAY;IACpC,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,YAAY,GAAG,EAAE;IACzD,CAAC;;AAKN,OAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,IAAI,WAAW,CAC3D,SAAQ,KAAK;GACX,IAAI,QAAQ,UAAU,GAAG;GACzB,MAAM;GACN,QAAQ,GAAG,UAAU,GAAG;GACxB,aAAa;GACb,aAAa,GAAG,UAAU,GAAG;GAC7B,YAAY;GACZ,WAAW;GACX,YAAY;GACZ,SAAS,EAAE,MAAM,KAAK,MAAM;GAC5B,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,YAAY,GAAG,EAAE;GACzD,CAAC;;AAKN,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,QAAQ,WAAW,EAAE;AACnE,UAAQ,KAAK;GACX,IAAI,SAAS;GACb,MAAM;GACN,QAAQ;GACR,aAAa;GACb,YAAY;GACZ,WAAW;GACX,YAAY;GACZ,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,YAAY,GAAG,EAAE;GAC7D,CAAC;AAEF,OAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,OAAO,CAC3D,SAAQ,KAAK;GACX,IAAI,SAAS,UAAU,GAAG;GAC1B,MAAM;GACN,QAAQ,GAAG,UAAU,GAAG;GACxB,aAAa;GACb,aAAa,GAAG,UAAU,GAAG;GAC7B,YAAY;GACZ,WAAW;GACX,YAAY;GACZ,SAAS,EAAE,MAAM,MAAM,MAAM;GAC7B,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,YAAY,GAAG,EAAE;GAC7D,CAAC;AAIJ,MAAI,MAAM,qBACR,SAAQ,KAAK;GACX,IAAI,QAAQ;GACZ,MAAM;GACN,QAAQ,GAAG,UAAU;GACrB,aAAa;GACb,aAAa,OAAO;GACpB,YAAY;GACZ,WAAW;GACX,YAAY;GACZ,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,YAAY,GAAG,EAAE;GAC7D,CAAC;;AAKN,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,QAAQ,YAAY,CAClE,SAAQ,KAAK;EACX,IAAI,SAAS;EACb,MAAM;EACN,QAAQ;EACR,aAAa;EACb,YAAY;EACZ,WAAW;EACX,YAAY;EACZ,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,YAAY,GAAG,EAAE;EAC7D,CAAC;AAIJ,MAAK,MAAM,CAAC,UAAU,YAAY,OAAO,QAAQ,QAAQ,MAAM,EAAE;AAC/D,UAAQ,KAAK;GACX,IAAI,QAAQ;GACZ,MAAM;GACN,QAAQ;GACR,aAAa;GACb,YAAY;GACZ,WAAW;GACX,YAAY;GACZ,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,YAAY,GAAG,EAAE;GACjE,CAAC;AAEF,OAAK,MAAM,CAAC,YAAY,gBAAgB,OAAO,QAAQ,QAAQ,QAAQ,CACrE,SAAQ,KAAK;GACX,IAAI,eAAe,SAAS,GAAG;GAC/B,MAAM;GACN,QAAQ,GAAG,SAAS,GAAG;GACvB,aAAa;GACb,aAAa,GAAG,SAAS,GAAG;GAC5B,YAAY;GACZ,WAAW;GACX,YAAY;GACZ,OAAO;GACP,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,YAAY,GAAG,EAAE;GACjE,CAAC;;AAIN,QAAO;EACL,eAAA;EACA,QAAQ,EAAE,aAAa,QAAQ,aAAa;EAC5C,UAAU,iBAAiB,SAAS;EACpC;EACD;;;AAIH,SAAS,sBAAsB,OAAiB,UAAkB,UAAuC;CACvG,MAAM,SAAS,iBAAiB,SAAS;CACzC,MAAM,UAAU,MAAM,gBAAgB,kBAAkB,SAAS;AACjE,QAAO;EACL,YAAY,MAAM;EAClB;EACA,UAAU,CAAC,MAAM;EACjB,UAAU;EACV,YAAY,MAAM;EAClB;EACA,MAAM,EAAE,MAAM,MAAM,MAAM;EAC1B,aAAa;GAIX,OAAO,YAAY;GACnB,YAAY,OAAO;GACnB,cAAc;GACd,MAAM;GACP;EACF;;;AAIH,SAAS,kBAAkB,UAA0C;AACnE,SAAQ,UAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,QACE,QAAO;;;;;AC/Tb,MAAM,oBAAoB;;AAG1B,SAAS,UAAU,MAAsB;AACvC,QAAO,KAAK,QAAQ,MAAM,GAAG,CAAC,aAAa;;;;;;AAO7C,SAAS,sBAAsB,YAA+D;CAC5F,MAAM,yBAAS,IAAI,KAA0B;AAC7C,MAAK,MAAM,SAAS,OAAO,OAAO,WAAW,EAAE;AAC7C,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM;EACjD,MAAM,EAAE,WAAW,YAAY;AAC/B,MAAI,OAAO,cAAc,YAAY,OAAO,YAAY,SAAU;EAClE,MAAM,MAAM,UAAU,QAAQ;AAC9B,MAAI,CAAC,OAAO,IAAI,IAAI,CAAE,QAAO,IAAI,qBAAK,IAAI,KAAK,CAAC;AAChD,SAAO,IAAI,IAAI,CAAE,IAAI,UAAU;;AAEjC,QAAO;;;;;;;;;;;;;AAcT,SAAS,wBACP,SACA,UAKA;CACA,MAAM,gBAAgB,IAAI,IAAI,SAAS,MAAM;CAC7C,MAAM,mBAAmB,SAAS,aAC9B,sBAAsB,SAAS,WAAW,mBAC1C,IAAI,KAA0B;CAElC,IAAI,gBAAgB;CACpB,IAAI,kBAAkB;CAGtB,MAAM,gBAAmD,WAAiD;EACxG,MAAM,SAA4B,EAAE;AACpC,OAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,OAAO,CAChD,KAAI,MAAM,cAAc,cAAc,IAAI,MAAM,WAAW,CACzD,QAAO,QAAQ;MAEf;AAGJ,SAAO;;CAIT,MAAM,kBAA4C,EAAE;AACpD,MAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AACzD,MAAI,IAAI,cAAc,CAAC,cAAc,IAAI,IAAI,WAAW,EAAE;AACxD;AACA;;AAKF,MADyB,iBAAiB,IAAI,UAAU,KAAK,CAAC,CAS5D,iBAAgB,QAAQ;GAAE,GAAG;GAAK,mBAAmB,EAAE;GAAE;MAGzD,iBAAgB,QAAQ;;CAK5B,MAAM,kBAA4C,EAAE;AACpD,MAAK,MAAM,CAAC,UAAU,YAAY,OAAO,QAAQ,QAAQ,QAAQ,CAC/D,KAAI,cAAc,IAAI,SAAS,CAC7B,iBAAgB,YAAY;AAIhC,QAAO;EACL,UAAU;GACR,GAAG;GACH,SAAS;GACT,YAAY,aAAa,QAAQ,WAAW;GAC5C,aAAa,aAAa,QAAQ,YAAY;GAC9C,OAAO,aAAa,QAAQ,MAAM;GAClC,SAAS;GACV;EACD;EACA;EACD;;AAGH,eAAsB,qBAAqB,MAOzB;CAChB,MAAM,YAAY,aAAa,KAAK,KAAK;AACzC,SAAQ,IAAI,cAAc,KAAK,KAAK,wBAAwB,KAAK,QAAQ,KAAK;CAE9E,IAAI,UAAU,MAAM,UAAU,QAAQ,KAAK,QAAQ;CAInD,MAAM,WAAW,MAAM,aAAa,KAAK,QAAQ;AACjD,KAAI,UAAU;EACZ,MAAM,EAAE,UAAU,kBAAkB,wBAAwB,SAAS,SAAS;AAC9E,YAAU;AACV,MAAI,gBAAgB,EAClB,SAAQ,IAAI,6BAA6B,cAAc,uBAAuB;;CAIlF,MAAM,WAAW,qBAAqB,QAAQ;AAG9C,KAAI,KAAK,MAAM;EACb,MAAM,cAAc,aAAa,KAAK,MAAM,QAAQ;AACpD,WAAS,OAAO,UAAU,WAAW,SAAS,CAAC,OAAO,YAAY,CAAC,OAAO,MAAM;AAMhF,wBAAsB,UAJH,MAAM,UAAU,KAAK,MAAM;GAC5C,qBAAqB,KAAK;GAC1B,eAAe,KAAK;GACrB,CAAC,CACyC;;CAG7C,MAAM,aAAa,QAAQ,KAAK,QAAQ,kBAAkB;AAC1D,eAAc,YAAY,KAAK,UAAU,UAAU,MAAM,EAAE,CAAC;AAC5D,SAAQ,IAAI,aAAa,SAAS,QAAQ,OAAO,aAAa,aAAa;;;;;;;;;;;;AAa7E,SAAS,sBAAsB,UAA0B,MAAqB;CAE5E,MAAM,2BAAW,IAAI,KAAoE;AACzF,MAAK,MAAM,WAAW,KAAK,SACzB,MAAK,MAAM,MAAM,QAAQ,YAAY;EACnC,MAAM,MAAM,GAAG,QAAQ,KAAK,GAAG,GAAG;AAClC,WAAS,IAAI,KAAK;GAChB,aAAa,GAAG;GAChB,QAAQ,GAAG;GACX,MAAM,GAAG;GACV,CAAC;;CAMN,MAAM,QAAQ,MAAc,EAAE,QAAQ,MAAM,GAAG,CAAC,aAAa;CAC7D,MAAM,8BAAc,IAAI,KAAgE;AACxF,MAAK,MAAM,SAAS,KAAK,QAAQ;EAC/B,MAAM,2BAAW,IAAI,KAAqB;AAC1C,OAAK,MAAM,SAAS,MAAM,OACxB,UAAS,IAAI,KAAK,MAAM,KAAK,EAAE,MAAM,KAAK;AAE5C,cAAY,IAAI,KAAK,MAAM,KAAK,EAAE;GAAE,UAAU,MAAM;GAAM,QAAQ;GAAU,CAAC;;AAG/E,MAAK,MAAM,OAAO,SAAS,SAAS;AAElC,MAAI,IAAI,SAAS,YAAY;GAC3B,MAAM,QAAQ,SAAS,IAAI,IAAI,OAAO;AACtC,OAAI,OAAO;AACT,QAAI,cAAc,MAAM;AACxB,QAAI,QAAQ;KAAE,QAAQ,MAAM;KAAQ,MAAM,MAAM;KAAM;;;AAK1D,MAAI,IAAI,aAAa;GAEnB,MAAM,aAAa,YAAY,IAAI,KAAK,IAAI,YAAY,CAAC;AACzD,OAAI,YAAY;IAEd,MAAM,YAAY,IAAI,OAAO,SAAS,IAAI,GAAG,IAAI,OAAO,MAAM,IAAI,CAAC,KAAK,GAAI,IAAI;IAChF,MAAM,aAAa,WAAW,OAAO,IAAI,KAAK,UAAU,CAAC;AACzD,QAAI,WACF,KAAI,aAAa,GAAG,WAAW,SAAS,GAAG;QAG3C,KAAI,aAAa,WAAW;;SAG3B;GAEL,MAAM,aAAa,YAAY,IAAI,KAAK,IAAI,OAAO,CAAC;AACpD,OAAI,WACF,KAAI,aAAa,WAAW;;;;;;ACxGpC,MAAM,sBAA2D,IAAI,IAA4B;CAC/F;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,uBAA4D,IAAI,IAA4B;CAChG;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,SAAgB,2BAA2B,UAAsD;AAC/F,KAAI,oBAAoB,IAAI,SAAmC,CAAE,QAAO;AACxE,KAAI,qBAAqB,IAAI,SAAmC,CAAE,QAAO;AACzE,QAAO;;;AAIT,SAAgB,uBAAuB,UAAgC,WAAqC;AAC1G,KAAI,cAAc,OAAQ,QAAO;AACjC,KAAI,cAAc,YAAa,QAAO,aAAa,cAAc,aAAa;AAC9E,QAAO,aAAa;;;;;;;;AC3GtB,SAAgB,sBACd,UACA,WACA,QACoB;CACpB,MAAM,UAA8B,EAAE;CAItC,MAAM,UAAU,SAAS,cAAc,WAAW;AAGlD,KAAI,CAAC,WAAW;AACd,UAAQ,KACN,WAAW;GACT,UAAU;GACV,QAAQ,SAAS;GACjB,KAAK,EAAE,QAAQ,SAAS,QAAQ;GAChC,KAAK,EAAE,QAAQ,aAAa;GAC5B,SAAS,WAAW,SAAS,YAAY;GACzC;GACA;GACD,CAAC,CACH;AACD,SAAO;;AAIT,KAAI,SAAS,WAAW,UAAU,UAAU,SAAS,OAAO,UAAU,GACpE,SAAQ,KACN,WAAW;EACT,UAAU;EACV,QAAQ,SAAS;EACjB,KAAK,EAAE,MAAM,SAAS,QAAQ;EAC9B,KAAK,EAAE,MAAM,UAAU,QAAQ;EAC/B,SAAS,wBAAwB,SAAS,YAAY,QAAQ,UAAU,YAAY;EACpF;EACA;EACD,CAAC,CACH;AAIH,KAAI,SAAS,cAAc,UAAU,WACnC,SAAQ,KAAK,GAAG,yBAAyB,UAAU,WAAW,QAAQ,QAAQ,CAAC;AAIjF,KAAI,SAAS,WAAW,UAAU,WAAW,SAAS,QAAQ,SAAS,UAAU,QAAQ,KACvF,SAAQ,KACN,WAAW;EACT,UAAU;EACV,QAAQ,SAAS;EACjB,KAAK,EAAE,YAAY,SAAS,QAAQ,MAAM;EAC1C,KAAK,EAAE,YAAY,UAAU,QAAQ,MAAM;EAC3C,SAAS,4BAA4B,SAAS,YAAY,UAAU,SAAS,QAAQ,KAAK,QAAQ,UAAU,QAAQ,KAAK;EACzH;EACA;EACD,CAAC,CACH;AAIH,KAAI,SAAS,WAAW,UAAU,WAAW,SAAS,QAAQ,SAAS,UAAU,QAAQ,KACvF,SAAQ,KACN,WAAW;EACT,UAAU;EACV,QAAQ,SAAS;EACjB,KAAK,EAAE,MAAM,SAAS,QAAQ,MAAM;EACpC,KAAK,EAAE,MAAM,UAAU,QAAQ,MAAM;EACrC,SAAS,qBAAqB,SAAS,YAAY,UAAU,SAAS,QAAQ,KAAK,QAAQ,UAAU,QAAQ,KAAK;EAClH;EACA;EACD,CAAC,CACH;AAIH,KACE,SAAS,SAAS,iBAClB,UAAU,SAAS,iBACnB,SAAS,UAAU,KAAA,KACnB,UAAU,UAAU,KAAA,KACpB,SAAS,UAAU,UAAU,MAE7B,SAAQ,KACN,WAAW;EACT,UAAU;EACV,QAAQ,SAAS;EACjB,KAAK,EAAE,OAAO,OAAO,SAAS,MAAM,EAAE;EACtC,KAAK,EAAE,OAAO,OAAO,UAAU,MAAM,EAAE;EACvC,SAAS,2BAA2B,SAAS,YAAY,UAAU,SAAS,MAAM,QAAQ,UAAU,MAAM;EAC1G;EACD,CAAC,CACH;AAGH,QAAO;;;;;AAMT,SAAS,yBACP,UACA,WACA,QACA,SACoB;CACpB,MAAM,UAA8B,EAAE;CACtC,MAAM,aAAa,SAAS,cAAc,EAAE;CAC5C,MAAM,aAAa,UAAU,cAAc,EAAE;CAE7C,MAAM,aAAa,IAAI,IAAI,WAAW,KAAK,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;CACpE,MAAM,aAAa,IAAI,IAAI,WAAW,KAAK,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;CACpE,MAAM,gBAAgB,SAAS,SAAS;AAGxC,MAAK,MAAM,aAAa,YAAY;EAClC,MAAM,YAAY,WAAW,IAAI,UAAU,WAAW;AAEtD,MAAI,CAAC,WAAW;GAEd,MAAM,kBAAkB,WAAW,UAAU;AAC7C,OAAI,mBAAmB,CAAC,WAAW,IAAI,gBAAgB,WAAW,EAAE;IAElE,MAAM,mBAAmB,yBAAyB,WAAW,QAAQ,cAAc;AACnF,YAAQ,KACN,WAAW;KACT,UAAU;KACV,QAAQ,SAAS;KACjB,KAAK,EAAE,WAAW,UAAU,YAAY;KACxC,KAAK,EAAE,WAAW,gBAAgB,YAAY;KAC9C,SAAS,cAAc,UAAU,WAAW,gBAAgB,gBAAgB,WAAW,QAAQ,SAAS,YAAY;KACpH;KACA;KACA,kBAAkB,mBAAmB,KAAA,IAAY;KAClD,CAAC,CACH;SAGD,SAAQ,KACN,WAAW;IACT,UAAU;IACV,QAAQ,SAAS;IACjB,KAAK,EAAE,WAAW,UAAU,YAAY;IACxC,KAAK,EAAE,WAAW,aAAa;IAC/B,SAAS,cAAc,UAAU,WAAW,kBAAkB,SAAS,YAAY;IACnF;IACA;IACD,CAAC,CACH;AAEH;;AAIF,MAAI,CAAC,UAAU,YAAY,UAAU,SACnC,SAAQ,KACN,WAAW;GACT,UAAU;GACV,QAAQ,SAAS;GACjB,KAAK;IAAE,WAAW,UAAU;IAAY,UAAU;IAAS;GAC3D,KAAK;IAAE,WAAW,UAAU;IAAY,UAAU;IAAQ;GAC1D,SAAS,cAAc,UAAU,WAAW,wBAAwB,SAAS,YAAY;GACzF;GACA;GACD,CAAC,CACH;AAIH,MAAI,UAAU,KAAK,SAAS,UAAU,KAAK,KACzC,SAAQ,KACN,WAAW;GACT,UAAU;GACV,QAAQ,SAAS;GACjB,KAAK;IAAE,WAAW,UAAU;IAAY,MAAM,UAAU,KAAK;IAAM;GACnE,KAAK;IAAE,WAAW,UAAU;IAAY,MAAM,UAAU,KAAK;IAAM;GACnE,SAAS,+BAA+B,UAAU,WAAW,QAAQ,SAAS,YAAY;GAC1F;GACA;GACD,CAAC,CACH;AAcH,MAAI,UAAU,aAAa,UAAU;OAC/B,cACF,KAAI,OAAO,wBACT,SAAQ,KACN,WAAW;IACT,UAAU;IACV,QAAQ,SAAS;IACjB,KAAK;KAAE,WAAW,UAAU;KAAY,UAAU,OAAO,UAAU,SAAS;KAAE;IAC9E,KAAK;KAAE,WAAW,UAAU;KAAY,UAAU,OAAO,UAAU,SAAS;KAAE;IAC9E,SAAS,cAAc,UAAU,WAAW,wBAAwB,UAAU,SAAS,MAAM,UAAU,SAAS,OAAO,SAAS,YAAY;IAC5I;IACA;IACD,CAAC,CACH;OAED,SAAQ,KACN,WAAW;IACT,UAAU;IACV,QAAQ,SAAS;IACjB,KAAK;KAAE,WAAW,UAAU;KAAY,UAAU,OAAO,UAAU,SAAS;KAAE;IAC9E,KAAK;KAAE,WAAW,UAAU;KAAY,UAAU,OAAO,UAAU,SAAS;KAAE;IAC9E,SAAS,cAAc,UAAU,WAAW,kBAAkB,SAAS,YAAY;IACnF;IACA;IACD,CAAC,CACH;YAEM,UAAU,YAAY,aAC/B,SAAQ,KACN,WAAW;IACT,UAAU;IACV,QAAQ,SAAS;IACjB,KAAK;KAAE,WAAW,UAAU;KAAY,UAAU,OAAO,UAAU,SAAS;KAAE;IAC9E,KAAK;KAAE,WAAW,UAAU;KAAY,UAAU,OAAO,UAAU,SAAS;KAAE;IAC9E,SAAS,cAAc,UAAU,WAAW,wBAAwB,UAAU,SAAS,MAAM,UAAU,SAAS,OAAO,SAAS,YAAY;IAC5I;IACA;IACD,CAAC,CACH;YACQ,UAAU,YAAY,QAC/B,SAAQ,KACN,WAAW;IACT,UAAU;IACV,QAAQ,SAAS;IACjB,KAAK;KAAE,WAAW,UAAU;KAAY,UAAU,OAAO,UAAU,SAAS;KAAE;IAC9E,KAAK;KAAE,WAAW,UAAU;KAAY,UAAU,OAAO,UAAU,SAAS;KAAE;IAC9E,SAAS,cAAc,UAAU,WAAW,kBAAkB,SAAS,YAAY;IACnF;IACA;IACD,CAAC,CACH;;;AAOP,MAAK,MAAM,aAAa,WACtB,KAAI,CAAC,WAAW,IAAI,UAAU,WAAW,EAAE;AAKzC,MAHiB,QAAQ,MACtB,MAAM,EAAE,aAAa,uBAAuB,EAAE,IAAI,cAAc,UAAU,WAC5E,CACa;EAEd,MAAM,aAAa,UAAU,aAAa,WAAW,SAAS;EAC9D,MAAM,WAAiC,UAAU,WAC7C,qCACA,aACE,sCACA;AAEN,MAAI,UAAU,SACZ,SAAQ,KACN,WAAW;GACT;GACA,QAAQ,SAAS;GACjB,KAAK,EAAE,WAAW,YAAY;GAC9B,KAAK;IAAE,WAAW,UAAU;IAAY,UAAU;IAAQ;GAC1D,SAAS,uBAAuB,UAAU,WAAW,cAAc,SAAS,YAAY;GACxF;GACA;GACD,CAAC,CACH;MAED,SAAQ,KACN,WAAW;GACT;GACA,QAAQ,SAAS;GACjB,KAAK,EAAE,WAAW,YAAY;GAC9B,KAAK,EAAE,WAAW,UAAU,YAAY;GACxC,SAAS,uBAAuB,UAAU,WAAW,cAAc,SAAS,YAAY;GACxF;GACA;GACD,CAAC,CACH;;AAKP,QAAO;;AAOT,SAAS,yBAAyB,OAAwB,QAA2B,eAAiC;AACpH,KAAI,MAAM,YAAY,WAAY,QAAO;AACzC,KAAI,cAAe,QAAO,OAAO;AACjC,QAAO,OAAO;;;;;;;;;;AAWhB,SAAS,wBACP,UACA,QACA,OACA,SACQ;CAER,MAAM,QAAQ;EAAC;EAAO;GADL,WAAW,QACa,QAAQ,mBAAmB,IAAI;EAAC;AACzE,KAAI,MAAM,UAAW,OAAM,KAAK,MAAM,UAAU;AAChD,KAAI,MAAM,OAAQ,OAAM,KAAK,MAAM,OAAO;AAC1C,QAAO,MAAM,KAAK,IAAI,CAAC,aAAa;;AAGtC,SAAS,WAAW,MAUC;AACnB,QAAO;EACL,UAAU,KAAK;EACf,UAAU,KAAK,oBAAoB,2BAA2B,KAAK,SAAS;EAC5E,QAAQ,KAAK;EACb,oBAAoB,wBAAwB,KAAK,UAAU,KAAK,QAAQ,KAAK,KAAK,KAAK,QAAQ;EAC/F,YAAY,KAAK,cAAc;EAC/B,KAAK,KAAK;EACV,KAAK,KAAK;EACV,SAAS,KAAK;EACf;;;;;AAMH,SAAgB,oBAAoB,QAAwC;AAC1E,QAAO;EACL,UAAU;EACV,UAAU;EACV,QAAQ,OAAO;EACf,oBAAoB,wBAAwB,gBAAgB,OAAO,QAAQ,EAAE,EAAE,OAAO,WAAW;EACjG,YAAY;EACZ,KAAK,EAAE,QAAQ,YAAY;EAC3B,KAAK,EAAE,QAAQ,OAAO,QAAQ;EAC9B,SAAS,WAAW,OAAO,YAAY;EACxC;;;AAIH,SAAgB,iBAAiB,SAA8D;CAC7F,IAAI,WAAW;CACf,IAAI,WAAW;CACf,IAAI,WAAW;AACf,MAAK,MAAM,KAAK,QACd,KAAI,EAAE,aAAa,WAAY;UACtB,EAAE,aAAa,YAAa;KAChC;AAEP,QAAO;EAAE;EAAU;EAAU;EAAU;;;;;;;;;AC5azC,SAAgB,iBAAiB,MAAe,OAAmC;CACjF,MAAM,wBAAQ,IAAI,KAAa;CAG/B,MAAM,oBAAoB,IAAI,IAAI,KAAK,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC;AAGhE,MAAK,MAAM,WAAW,KAAK,UAAU;AACnC,QAAM,IAAI,QAAQ,KAAK;AACvB,OAAK,MAAM,MAAM,QAAQ,YAAY;AAEnC,uBAAoB,GAAG,UAAU,OAAO,OAAO,kBAAkB;AACjE,OAAI,GAAG,YAAa,qBAAoB,GAAG,aAAa,OAAO,OAAO,kBAAkB;AACxF,QAAK,MAAM,KAAK;IAAC,GAAG,GAAG;IAAY,GAAG,GAAG;IAAa,GAAG,GAAG;IAAc,GAAI,GAAG,gBAAgB,EAAE;IAAE,CACnG,qBAAoB,EAAE,MAAM,OAAO,OAAO,kBAAkB;;;AAMlE,MAAK,MAAM,SAAS,KAAK,QAAQ;AAC/B,QAAM,IAAI,MAAM,KAAK;AACrB,OAAK,MAAM,WAAW,MAAM,kBAAkB,MAAM,KAAK,CACvD,OAAM,IAAI,QAAQ;AAEpB,OAAK,MAAM,SAAS,MAAM,OACxB,qBAAoB,MAAM,MAAM,OAAO,OAAO,kBAAkB;;AAKpE,MAAK,MAAM,KAAK,KAAK,MACnB,OAAM,IAAI,EAAE,KAAK;AAGnB,QAAO;;;;;;AAOT,SAAgB,sBAAsB,MAAkD;CACtF,MAAM,yBAAS,IAAI,KAAmC;AACtD,MAAK,MAAM,KAAK,KAAK,MACnB,QAAO,IAAI,EAAE,MAAM,IAAI,IAAI,EAAE,OAAO,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3D,QAAO;;;;;;;AAQT,SAAgB,sBAAsB,MAAe,OAAmC;CACtF,MAAM,wBAAQ,IAAI,KAAa;AAC/B,MAAK,MAAM,SAAS,KAAK,QAAQ;AAC/B,OAAK,MAAM,SAAS,MAAM,OACxB,OAAM,IAAI,GAAG,MAAM,KAAK,GAAG,MAAM,OAAO;AAG1C,OAAK,MAAM,WAAW,MAAM,kBAAkB,MAAM,KAAK,CACvD,MAAK,MAAM,SAAS,MAAM,OACxB,OAAM,IAAI,GAAG,QAAQ,GAAG,MAAM,OAAO;;AAI3C,QAAO;;;;;;;AAQT,SAAgB,uBAAuB,MAA4B;CACjE,MAAM,wBAAQ,IAAI,KAAa;AAC/B,MAAK,MAAM,WAAW,KAAK,SACzB,MAAK,MAAM,MAAM,QAAQ,WACvB,OAAM,IAAI,GAAG,QAAQ,KAAK,GAAG,GAAG,OAAO;AAG3C,QAAO;;AAiBT,SAAS,oBAAoB,KAAc,KAAkB,OAAsB,eAAmC;AACpH,aAAY,KAAK;EACf,QAAQ,MAAM;AACZ,OAAI,IAAI,EAAE,KAAK;AACf,QAAK,MAAM,WAAW,MAAM,kBAAkB,EAAE,KAAK,CACnD,KAAI,IAAI,QAAQ;;EAGpB,OAAO,MAAM;AAIX,OAAI,CAAC,iBAAiB,cAAc,IAAI,EAAE,KAAK,CAC7C,KAAI,IAAI,EAAE,KAAK;;EAGpB,CAAC;;AAGJ,SAAS,aAAgB,QAA2B,SAAyC;CAC3F,MAAM,SAA4B,EAAE;AACpC,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,OAAO,CAChD,KAAI,QAAQ,IAAI,KAAK,CAAE,QAAO,QAAQ;AAExC,QAAO;;;;;;;;;;;;;;;;;AAkBT,SAAgB,cACd,SACA,cACA,MAKY;CACZ,MAAM,EAAE,YAAY,aAAa,eAAe,QAAQ,EAAE;CAC1D,MAAM,qBAAqB,aAAa,QAAQ,YAAY,aAAa;AAGzE,KAAI,WACF,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,mBAAmB,EAAE;EAC9D,MAAM,iBAAgE,EAAE;AACxE,OAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,OAAO,CAE3D,KAAI,WAAW,IAAI,GAAG,KAAK,GAAG,YAAY,CACxC,gBAAe,aAAa;AAGhC,qBAAmB,QAAQ;GAAE,GAAG;GAAO,QAAQ;GAAgB;;CAInE,IAAI,kBAAkB,aAAa,QAAQ,SAAS,aAAa;AAGjE,KAAI,aAAa;EAGf,MAAM,oCAAoB,IAAI,KAAa;AAC3C,OAAK,MAAM,QAAQ,aAAa;GAC9B,MAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,OAAI,QAAQ,GAAI,mBAAkB,IAAI,KAAK,MAAM,GAAG,IAAI,CAAC;;EAG3D,MAAM,aAA+D,EAAE;AACvE,OAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,gBAAgB,CACvD,KAAI,kBAAkB,IAAI,KAAK,EAAE;GAE/B,MAAM,kBAAsC,EAAE;AAC9C,QAAK,MAAM,CAAC,YAAY,cAAc,OAAO,QAAQ,IAAI,QAAQ,CAC/D,KAAI,YAAY,IAAI,GAAG,KAAK,GAAG,aAAa,CAC1C,iBAAgB,cAAc;GAOlC,MAAM,qBAA4C,EAAE;AACpD,QAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,IAAI,WAAW,CAC3D,KAAI,YAAY,IAAI,GAAG,KAAK,GAAG,WAAW,CACxC,oBAAmB,YAAY;AAInC,cAAW,QAAQ;IACjB,GAAG;IACH,SAAS;IACT,YAAY;IACb;aACQ,YAAY;GAKrB,MAAM,qBAA4C,EAAE;AACpD,QAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,IAAI,WAAW,CAC3D,KAAI,WAAW,IAAI,GAAG,KAAK,GAAG,WAAW,CACvC,oBAAmB,YAAY;GAQnC,MAAM,kBAAsC,EAAE;AAC9C,QAAK,MAAM,CAAC,YAAY,cAAc,OAAO,QAAQ,IAAI,QAAQ,CAC/D,KAAI,WAAW,IAAI,GAAG,KAAK,GAAG,aAAa,IAAI,YAAY,IAAI,GAAG,KAAK,GAAG,aAAa,CACrF,iBAAgB,cAAc;AAIlC,cAAW,QAAQ;IACjB,GAAG;IACH,SAAS;IACT,YAAY;IACb;QAGD,YAAW,QAAQ;AAGvB,oBAAkB;;CAIpB,IAAI,gBAAgB,aAAa,QAAQ,OAAO,aAAa;AAC7D,KAAI,YAAY;EACd,MAAM,WAA2D,EAAE;AACnE,OAAK,MAAM,CAAC,MAAM,YAAY,OAAO,QAAQ,cAAc,EAAE;GAC3D,MAAM,aAAa,WAAW,IAAI,KAAK;AACvC,OAAI,CAAC,YAAY;AAEf,aAAS,QAAQ;AACjB;;GAKF,MAAM,kBAAkB,IAAI,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,MAAM,OAAO,EAAE,CAAC,aAAa,CAAC,CAAC;GACpF,MAAM,kBAA0C,EAAE;AAClD,QAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,QAAQ,QAAQ,CAC3D,KAAI,WAAW,IAAI,MAAM,IAAI,gBAAgB,IAAI,OAAO,MAAM,CAAC,aAAa,CAAC,CAC3E,iBAAgB,UAAU;AAG9B,YAAS,QAAQ;IAAE,GAAG;IAAS,SAAS;IAAiB;;AAE3D,kBAAgB;;AAGlB,QAAO;EACL,GAAG;EACH,SAAS;EACT,YAAY;EACZ,aAAa,aAAa,QAAQ,aAAa,aAAa;EAC5D,OAAO;EACP,SAAS,EAAE;EACZ;;;;;;;;ACpPH,SAAgB,cACd,UACA,WACA,QACkB;CAClB,MAAM,kBAAkB,UAAU,SAAS;CAC3C,MAAM,UAA8B,EAAE;CAKtC,MAAM,mCAAmB,IAAI,KAAa;AAC1C,MAAK,MAAM,OAAO,SAAS,QACzB,KAAI,IAAI,SAAS,mBAAoB,kBAAiB,IAAI,IAAI,OAAO;AAEvE,MAAK,MAAM,OAAO,UAAU,QAC1B,KAAI,IAAI,SAAS,mBAAoB,kBAAiB,IAAI,IAAI,OAAO;CAIvE,MAAM,2BAAW,IAAI,KAA2B;CAChD,MAAM,+BAAe,IAAI,KAA2B;AACpD,MAAK,MAAM,OAAO,UAAU,SAAS;AACnC,WAAS,IAAI,IAAI,IAAI,IAAI;AACzB,eAAa,IAAI,IAAI,QAAQ,IAAI;;CAInC,MAAM,+BAAe,IAAI,KAAa;AACtC,MAAK,MAAM,OAAO,SAAS,QACzB,cAAa,IAAI,IAAI,OAAO;AAI9B,MAAK,MAAM,WAAW,SAAS,SAAS;AACtC,MAAI,4BAA4B,SAAS,iBAAiB,CAAE;EAC5D,MAAM,UAAU,SAAS,IAAI,QAAQ,GAAG,IAAI,aAAa,IAAI,QAAQ,OAAO;AAC5E,UAAQ,KAAK,GAAG,sBAAsB,SAAS,SAAS,gBAAgB,CAAC;;AAI3E,MAAK,MAAM,WAAW,UAAU,QAC9B,KAAI,CAAC,aAAa,IAAI,QAAQ,OAAO,EAAE;AACrC,MAAI,4BAA4B,SAAS,iBAAiB,CAAE;AAC5D,UAAQ,KAAK,oBAAoB,QAAQ,CAAC;;AAS9C,qBAAoB,SAAS,UAAU,UAAU;CAcjD,MAAM,cAAc,kBAAkB,SAAS,UAAU,UAAU;CACnE,MAAM,cAAc,kBAAkB,SAAS,UAAU,UAAU;AAOnE,4BAA2B,aAAa,UAAU,WAAW,QAAQ;AACrE,yBAAwB,SAAS,aAAa,aAAa,UAAU,UAAU;AAE/E,QAAO;EACL;EACA,SAAS,iBAAiB,QAAQ;EACnC;;;;;;;;;;;;;;;;;;;AAoBH,SAAS,oBAAoB,SAA6B,UAA0B,WAAiC;CAGnH,MAAM,qBAAqB,qBAAqB,SAAS;CACzD,MAAM,sBAAsB,qBAAqB,UAAU;CAC3D,MAAM,oBAAoB,IAAI,IAAI,mBAAmB,MAAM,CAAC;AAE5D,MAAK,MAAM,UAAU,SAAS;AAC5B,MAAI,OAAO,YAAa;EAExB,IAAI;EACJ,IAAI;AACJ,MAAI,OAAO,aAAa,uBAAuB;AAC7C,aAAU,OAAO,IAAI;AACrB,aAAU,OAAO,IAAI;aACZ,OAAO,aAAa,sBAAsB;AACnD,aAAU,OAAO,IAAI;AACrB,aAAU,OAAO,IAAI;QAErB;AAEF,MAAI,CAAC,WAAW,CAAC,WAAW,YAAY,QAAS;EAIjD,MAAM,cAAc,aAAa,QAAQ;EACzC,MAAM,cAAc,aAAa,QAAQ;AAGzC,MAAI,kBAAkB,IAAI,YAAY,CAAE;EAExC,MAAM,YAAY,mBAAmB,IAAI,YAAY;EACrD,MAAM,YAAY,oBAAoB,IAAI,YAAY;AACtD,MAAI,CAAC,aAAa,CAAC,UAAW;AAC9B,MAAI,UAAU,SAAS,EAAG;EAG1B,IAAI,aAAa;AACjB,OAAK,MAAM,KAAK,UACd,KAAI,CAAC,UAAU,IAAI,EAAE,EAAE;AACrB,gBAAa;AACb;;AAGJ,MAAI,CAAC,WAAY;AAEjB,SAAO,cACL,WAAW,YAAY,gBAAgB,YAAY,+DACb,YAAY;;;;;;;AAUxD,SAAS,qBAAqB,UAAoD;CAChF,MAAM,yBAAS,IAAI,KAA0B;AAC7C,MAAK,MAAM,OAAO,SAAS,SAAS;AAClC,MAAI,IAAI,SAAS,WAAW,IAAI,SAAS,WAAY;AACrD,MAAI,CAAC,IAAI,YAAa;EACtB,MAAM,YAAY,IAAI,OAAO,SAAS,IAAI,GAAG,IAAI,OAAO,MAAM,IAAI,OAAO,YAAY,IAAI,GAAG,EAAE,GAAG,IAAI;EACrG,IAAI,MAAM,OAAO,IAAI,IAAI,YAAY;AACrC,MAAI,CAAC,KAAK;AACR,yBAAM,IAAI,KAAa;AACvB,UAAO,IAAI,IAAI,aAAa,IAAI;;AAElC,MAAI,IAAI,UAAU,aAAa,CAAC;;AAElC,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCT,SAAS,kBACP,SACA,UACA,WACqB;CACrB,MAAM,4BAAY,IAAI,KAAqB;CAC3C,MAAM,qBAAqB,qBAAqB,SAAS;CACzD,MAAM,sBAAsB,qBAAqB,UAAU;CAC3D,MAAM,oBAAoB,IAAI,IAAI,mBAAmB,MAAM,CAAC;CAC5D,MAAM,uBAAuB,CAAC,GAAG,oBAAoB,SAAS,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,GAAG,CAAC;CAOxG,MAAM,sCAAsB,IAAI,KAA+B;AAC/D,MAAK,MAAM,UAAU,QACnB,KAAI,OAAO,aAAa,oBAAoB,OAAO,aAAa,WAC9D,qBAAoB,IAAI,OAAO,IAAI,UAAU,IAAI,OAAO;AAU5D,MAAK,MAAM,CAAC,kBAAkB,mBAAmB,oBAAoB;AACnE,MAAI,eAAe,SAAS,EAAG;EAG/B,MAAM,iBAAiB,oBAAoB,IAAI,iBAAiB;AAChE,MAAI,kBAAkB,UAAU,gBAAgB,eAAe,CAAE;EAIjE,MAAM,QAAQ,qBAAqB,MAAM,CAAC,UAAU,gBAAgB;AAClE,OAAI,kBAAkB,IAAI,SAAS,CAAE,QAAO;AAC5C,QAAK,MAAM,KAAK,eACd,KAAI,CAAC,WAAW,IAAI,EAAE,CAAE,QAAO;AAEjC,UAAO;IACP;AACF,MAAI,CAAC,MAAO;EACZ,MAAM,CAAC,WAAW;AAElB,YAAU,IAAI,kBAAkB,QAAQ;EASxC,MAAM,gBAAgB,oBAAoB,IAAI,iBAAiB;AAC/D,MAAI,cACF,eAAc,cACZ,SAAS,iBAAiB,qCAAqC,QAAQ,0HAEjB,QAAQ,qCAC5C,iBAAiB,kFACY,iBAAiB,KAAK,QAAQ;;AAInF,QAAO;;;;;;;;;;;;;;;;;;;;;;;AAwBT,SAAS,2BACP,aACA,UACA,WACA,SACM;AACN,KAAI,YAAY,SAAS,EAAG;CAI5B,MAAM,oCAAoB,IAAI,KAAqB;AACnD,MAAK,MAAM,OAAO,SAAS,SAAS;AAClC,MAAI,IAAI,SAAS,WAAW,IAAI,SAAS,WAAY;AACrD,MAAI,CAAC,IAAI,eAAe,CAAC,IAAI,QAAS;EACtC,MAAM,YAAY,IAAI,OAAO,SAAS,IAAI,GAAG,IAAI,OAAO,MAAM,IAAI,OAAO,YAAY,IAAI,GAAG,EAAE,GAAG,IAAI;AACrG,oBAAkB,IAAI,GAAG,IAAI,YAAY,GAAG,UAAU,aAAa,IAAI,IAAI,QAAQ,KAAK;;CAE1F,MAAM,qCAAqB,IAAI,KAAqB;AACpD,MAAK,MAAM,OAAO,UAAU,SAAS;AACnC,MAAI,IAAI,SAAS,WAAW,IAAI,SAAS,WAAY;AACrD,MAAI,CAAC,IAAI,eAAe,CAAC,IAAI,QAAS;EACtC,MAAM,YAAY,IAAI,OAAO,SAAS,IAAI,GAAG,IAAI,OAAO,MAAM,IAAI,OAAO,YAAY,IAAI,GAAG,EAAE,GAAG,IAAI;AACrG,qBAAmB,IAAI,GAAG,IAAI,YAAY,GAAG,UAAU,aAAa,IAAI,IAAI,QAAQ,KAAK;;CAI3F,MAAM,sCAAsB,IAAI,KAA+B;AAC/D,MAAK,MAAM,UAAU,QACnB,KAAI,OAAO,aAAa,oBAAoB,OAAO,aAAa,WAC9D,qBAAoB,IAAI,OAAO,IAAI,UAAU,IAAI,OAAO;CAQ5D,MAAM,iBAAiB,CAAC,GAAG,YAAY,SAAS,CAAC;AACjD,MAAK,MAAM,CAAC,UAAU,aAAa,eAGjC,MAAK,MAAM,CAAC,aAAa,yBAAyB,mBAAmB;AACnE,MAAI,CAAC,YAAY,WAAW,GAAG,SAAS,GAAG,CAAE;EAC7C,MAAM,YAAY,YAAY,MAAM,SAAS,SAAS,EAAE;EACxD,MAAM,eAAe,GAAG,SAAS,GAAG;EACpC,MAAM,wBAAwB,mBAAmB,IAAI,aAAa;AAClE,MAAI,CAAC,sBAAuB;EAE5B,MAAM,OAAO,aAAa,qBAAqB;EAC/C,MAAM,OAAO,aAAa,sBAAsB;AAChD,MAAI,CAAC,QAAQ,CAAC,QAAQ,SAAS,KAAM;AACrC,MAAI,YAAY,IAAI,KAAK,CAAE;AAE3B,cAAY,IAAI,MAAM,KAAK;EAC3B,MAAM,UAAU,oBAAoB,IAAI,KAAK;AAC7C,MAAI,QAGF,SAAQ,cACN,SAAS,KAAK,qCAAqC,KAAK,wDACH,SAAS,OAAO,SAAS,WACpE,UAAU,mCAAmC,KAAK,QAAQ,KAAK,iDAC1B,KAAK,KAAK,KAAK;;;;;;;;;;;;;;;;;;;;AAuBxE,SAAS,kBACP,SACA,UACA,WACqB;CACrB,MAAM,4BAAY,IAAI,KAAqB;CAC3C,MAAM,qBAAqB,qBAAqB,SAAS;CACzD,MAAM,sBAAsB,qBAAqB,UAAU;CAC3D,MAAM,oBAAoB,IAAI,IAAI,mBAAmB,MAAM,CAAC;CAE5D,MAAM,uBAAuB,CAAC,GAAG,oBAAoB,SAAS,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,GAAG,CAAC;CAIxG,MAAM,sCAAsB,IAAI,KAA+B;AAC/D,MAAK,MAAM,UAAU,QACnB,KAAI,OAAO,aAAa,oBAAoB,OAAO,aAAa,WAC9D,qBAAoB,IAAI,OAAO,IAAI,UAAU,IAAI,OAAO;AAY5D,MAAK,MAAM,CAAC,kBAAkB,mBAAmB,oBAAoB;AACnE,MAAI,eAAe,SAAS,EAAG;EAG/B,MAAM,iBAAiB,oBAAoB,IAAI,iBAAiB;AAChE,MAAI,kBAAkB,UAAU,gBAAgB,eAAe,CAAE;EAIjE,MAAM,QAAQ,qBAAqB,MAChC,CAAC,UAAU,gBAAgB,CAAC,kBAAkB,IAAI,SAAS,IAAI,UAAU,gBAAgB,WAAW,CACtG;AACD,MAAI,CAAC,MAAO;EACZ,MAAM,CAAC,WAAW;AAElB,YAAU,IAAI,kBAAkB,QAAQ;EAOxC,MAAM,gBAAgB,oBAAoB,IAAI,iBAAiB;AAC/D,MAAI,cACF,eAAc,cACZ,SAAS,iBAAiB,qCAAqC,QAAQ;;AAO7E,QAAO;;;;;;;;;;;;;;;;AAiBT,SAAS,wBACP,SACA,aACA,aACA,UACA,WACM;CAON,IAAI;CACJ,IAAI;CACJ,MAAM,0BAAoD;AACxD,MAAI,CAAC,mBAAoB,sBAAqB,qBAAqB,SAAS;AAC5E,SAAO;;CAET,MAAM,2BAAqD;AACzD,MAAI,CAAC,oBAAqB,uBAAsB,qBAAqB,UAAU;AAC/E,SAAO;;;;;;;;;;;;;CAcT,MAAM,4BAA4B,MAAc,SAA0B;AACxE,MAAI,CAAC,QAAQ,CAAC,QAAQ,SAAS,KAAM,QAAO;EAC5C,MAAM,iBAAiB,mBAAmB;EAC1C,MAAM,kBAAkB,oBAAoB;AAG5C,MAAI,eAAe,IAAI,KAAK,CAAE,QAAO;EACrC,MAAM,YAAY,eAAe,IAAI,KAAK;EAC1C,MAAM,YAAY,gBAAgB,IAAI,KAAK;AAC3C,MAAI,CAAC,aAAa,CAAC,UAAW,QAAO;AACrC,MAAI,UAAU,SAAS,EAAG,QAAO;AACjC,OAAK,MAAM,KAAK,UACd,KAAI,CAAC,UAAU,IAAI,EAAE,CAAE,QAAO;AAEhC,SAAO;;AAGT,MAAK,MAAM,UAAU,SAAS;AAC5B,MAAI,OAAO,aAAa,WAAY;AAEpC,MAAI,OAAO,aAAa,kBAAkB;GACxC,MAAM,UAAU,OAAO,IAAI,UAAU;GACrC,MAAM,SAAS,QAAQ,QAAQ,IAAI;AACnC,OAAI,UAAU,EAAG;GACjB,MAAM,YAAY,QAAQ,MAAM,GAAG,OAAO;GAC1C,MAAM,YAAY,YAAY,IAAI,UAAU,IAAI,YAAY,IAAI,UAAU;AAC1E,OAAI,CAAC,UAAW;AAChB,UAAO,WAAW;AAClB,UAAO,cACL,4BAA4B,UAAU,UAAU,UAAU,sDACP,UAAU,GAAG,QAAQ,MAAM,SAAS,EAAE,CAAC;AAC5F;;AAGF,MAAI,OAAO,aAAa,uBAAuB;GAC7C,MAAM,OAAO,aAAa,OAAO,IAAI,cAAc,GAAG;GACtD,MAAM,OAAO,aAAa,OAAO,IAAI,cAAc,GAAG;AACtD,OAAI,YAAY,IAAI,KAAK,KAAK,MAAM;AAClC,WAAO,WAAW;AAClB,WAAO,cACL,6CAA6C,KAAK,OAAO,KAAK,wEACQ,KAAK;cACpE,yBAAyB,MAAM,KAAK,EAAE;AAK/C,WAAO,WAAW;AAClB,QAAI,CAAC,OAAO,YACV,QAAO,cACL,0BAA0B,KAAK,QAAQ,KAAK,iDACzB,KAAK,qBAAqB,KAAK,4FAEhC,KAAK;;AAG7B;;AAGF,MAAI,OAAO,aAAa,sBAAsB;GAC5C,MAAM,OAAO,aAAa,OAAO,IAAI,QAAQ,GAAG;GAChD,MAAM,OAAO,aAAa,OAAO,IAAI,QAAQ,GAAG;AAEhD,QADkB,YAAY,IAAI,KAAK,IAAI,YAAY,IAAI,KAAK,MAC9C,MAAM;AACtB,WAAO,WAAW;AAClB,WAAO,cACL,4CAA4C,KAAK,OAAO,KAAK,iEACE,KAAK;cAC7D,yBAAyB,MAAM,KAAK,EAAE;AAC/C,WAAO,WAAW;AAClB,QAAI,CAAC,OAAO,YACV,QAAO,cACL,yBAAyB,KAAK,QAAQ,KAAK,iDACxB,KAAK,qBAAqB,KAAK;;;;;;;;;;;;;;;AAiB9D,SAAS,qBAAqB,UAAoD;CAChF,MAAM,yBAAS,IAAI,KAA0B;AAC7C,MAAK,MAAM,OAAO,SAAS,SAAS;AAClC,MAAI,IAAI,SAAS,cAAe;AAChC,MAAI,CAAC,IAAI,YAAa;AACtB,MAAI,IAAI,UAAU,KAAA,EAAW;EAC7B,IAAI,MAAM,OAAO,IAAI,IAAI,YAAY;AACrC,MAAI,CAAC,KAAK;AACR,yBAAM,IAAI,KAAa;AACvB,UAAO,IAAI,IAAI,aAAa,IAAI;;AAElC,MAAI,IAAI,OAAO,IAAI,MAAM,CAAC;;AAE5B,QAAO;;;AAIT,SAAS,UAAU,GAAgB,GAAyB;AAC1D,KAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,MAAK,MAAM,KAAK,EACd,KAAI,CAAC,EAAE,IAAI,EAAE,CAAE,QAAO;AAExB,QAAO;;;;;;;;AAST,SAAS,aAAa,GAAmB;CACvC,IAAI,IAAI,EAAE,MAAM;AAGhB,KAAI,EAAE,QAAQ,OAAO,GAAG;AAKxB,KAAI,EAAE,WAAW,KAAK,EAAE;EACtB,MAAM,gBAAgB,EAAE,YAAY,KAAK;AACzC,MAAI,EAAE,MAAM,gBAAgB,EAAE;;AAGhC,KAAI,EAAE,QAAQ,iBAAiB,GAAG,CAAC,QAAQ,OAAO,GAAG;AAErD,KAAI,EAAE,QAAQ,SAAS,GAAG;CAK1B,MAAM,eAAe,EAAE,MAAM,+DAA+D;AAC5F,KAAI,aAAc,QAAO,aAAa,aAAa,GAAG;CACtD,MAAM,iBAAiB,EAAE,MAAM,iEAAiE;AAChG,KAAI,eAAgB,QAAO,aAAa,eAAe,GAAG;AAC1D,QAAO;;;;;;;;;;;;;;AAeT,SAAS,4BAA4B,KAAmB,kBAAwC;AAC9F,KAAI,CAAC,IAAI,eAAe,CAAC,iBAAiB,IAAI,IAAI,YAAY,CAAE,QAAO;AACvE,KAAI,IAAI,SAAS,cAAe,QAAO;AACvC,KAAI,IAAI,SAAS,cAAc,IAAI,OAAO,SAAS,eAAe,CAAE,QAAO;AAC3E,QAAO;;;;;;;;;;;ACppBT,SAAgB,sBACd,oBACkB;CAClB,MAAM,0BAAU,IAAI,KAA+B;AAEnD,MAAK,MAAM,EAAE,MAAM,QAAQ,cAAc,mBACvC,MAAK,MAAM,UAAU,OAAO,SAAS;EACnC,MAAM,WAAW,QAAQ,IAAI,OAAO,mBAAmB;AACvD,MAAI,SACF,UAAS,OAAO,YAAY,OAAO;MAEnC,SAAQ,IAAI,OAAO,oBAAoB;GACrC,IAAI,OAAO;GACX,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,QAAQ,GAAG,WAAW,OAAO,UAAU;GACvC,SAAS,OAAO;GAChB,KAAK,OAAO;GACZ,KAAK,OAAO;GACb,CAAC;;AAKR,QAAO,EACL,mBAAmB,CAAC,GAAG,QAAQ,QAAQ,CAAC,EACzC;;;AAIH,SAAgB,gBAAgB,QAAgD;CAC9E,MAAM,aAAa,OAAO,OAAO,OAAO,OAAO;AAC/C,KAAI,WAAW,SAAS,WAAW,CAAE,QAAO;AAC5C,KAAI,WAAW,SAAS,YAAY,CAAE,QAAO;AAC7C,QAAO;;;AAIT,SAAgB,2BAA2B,QAIzC;CACA,IAAI,WAAW;CACf,IAAI,WAAW;CACf,IAAI,WAAW;AACf,MAAK,MAAM,UAAU,OAAO,mBAAmB;EAC7C,MAAM,MAAM,gBAAgB,OAAO;AACnC,MAAI,QAAQ,WAAY;WACf,QAAQ,YAAa;MACzB;;AAEP,QAAO;EAAE;EAAU;EAAU;EAAU;;;;;ACpDzC,SAAgB,eAAe,MAAwB,UAAiC;AACtF,QAAO;EACL,eAAe;EACf,UAAU,YAAY;EACtB,SAAS,KAAK;EACd,SAAS,KAAK,QAAQ,KAAK,OAAO;GAChC,UAAU,EAAE;GACZ,UAAU,EAAE;GACZ,QAAQ,EAAE;GACV,oBAAoB,EAAE;GACtB,YAAY,EAAE;GACd,KAAK,EAAE;GACP,KAAK,EAAE;GACP,GAAI,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;GAC3C,GAAI,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,GAAG,EAAE;GACxD,EAAE;EACJ;;;AAQH,SAAgB,mBAAmB,MAAwB,MAAyD;CAClH,MAAM,QAAkB,EAAE;AAE1B,OAAM,KAAK,gBAAgB,MAAM,WAAW,QAAQ,KAAK,aAAa,GAAG,GAAG;AAC5E,OAAM,KACJ,KAAK,KAAK,QAAQ,SAAS,aAAa,KAAK,QAAQ,SAAS,cAAc,KAAK,QAAQ,SAAS,WACnG;AAED,KAAI,KAAK,QAAQ,WAAW,GAAG;AAC7B,QAAM,KAAK,uCAAuC;AAClD,SAAO,MAAM,KAAK,KAAK;;CAIzB,MAAM,WAAW,KAAK,QAAQ,QAAQ,MAAM,EAAE,aAAa,WAAW;CACtE,MAAM,WAAW,KAAK,QAAQ,QAAQ,MAAM,EAAE,aAAa,YAAY;CACvE,MAAM,WAAW,KAAK,QAAQ,QAAQ,MAAM,EAAE,aAAa,WAAW;AAEtE,KAAI,SAAS,SAAS,GAAG;AACvB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,cAAc;AACzB,OAAK,MAAM,KAAK,UAAU;AACxB,SAAM,KAAK,QAAQ,EAAE,SAAS,IAAI,EAAE,OAAO,KAAK,EAAE,UAAU;AAC5D,OAAI,EAAE,YACJ,OAAM,KAAK,eAAe,EAAE,cAAc;AAE5C,OAAI,MAAM,WAAW,EAAE,eAAe,UACpC,OAAM,KAAK,qBAAqB,EAAE,aAAa;;;AAKrD,KAAI,SAAS,SAAS,GAAG;AACvB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,eAAe;AAC1B,OAAK,MAAM,KAAK,UAAU;AACxB,SAAM,KAAK,QAAQ,EAAE,SAAS,IAAI,EAAE,OAAO,KAAK,EAAE,UAAU;AAC5D,OAAI,EAAE,YACJ,OAAM,KAAK,eAAe,EAAE,cAAc;AAE5C,OAAI,MAAM,WAAW,EAAE,eAAe,UACpC,OAAM,KAAK,qBAAqB,EAAE,aAAa;;;AAKrD,KAAI,SAAS,SAAS,GAAG;AACvB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,eAAe,SAAS,OAAO,gBAAgB;;AAG5D,QAAO,MAAM,KAAK,KAAK;;;;AC9GzB,eAAsB,kBAAkB,MAMtB;CAChB,MAAM,eAAe,KAAK,MAAM,aAAa,KAAK,UAAU,QAAQ,CAAC;CACrE,MAAM,gBAAgB,KAAK,MAAM,aAAa,KAAK,WAAW,QAAQ,CAAC;AAEvE,KAAI,CAAC,iBAAiB,aAAa,CACjC,OAAM,IAAI,MAAM,8BAA8B,KAAK,WAAW;AAEhE,KAAI,CAAC,iBAAiB,cAAc,CAClC,OAAM,IAAI,MAAM,+BAA+B,KAAK,YAAY;CAMlE,MAAM,OAAO,cAHI,cACC,cAE6B;AAG/C,SAAQ,IAAI,mBAAmB,MAAM,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC;AAGhE,KAAI,KAAK,QAAQ;EACf,MAAM,SAAS,eAAe,KAAK;AACnC,gBAAc,KAAK,QAAQ,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC3D,UAAQ,IAAI,qBAAqB,KAAK,SAAS;;CAIjD,MAAM,SAAU,KAAK,UAAU;AAE/B,KADmB,KAAK,QAAQ,MAAM,MAAM,uBAAuB,EAAE,UAAU,OAAO,CAAC,CAErF,SAAQ,WAAW;;;;;;;;;;;;;AC5BvB,eAAsB,qBAAqB,MAAqE;CAE9G,MAAM,WADQ,MAAM,QAAQ,KAAK,OAAO,GAAG,KAAK,SAAS,CAAC,KAAK,OAAO,EAChD,KAAK,MAAM,KAAK,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAiB;CAEtF,MAAM,KAAK,QAAQ,WAAW,IAAI,mBAAmB,QAAQ,GAAG,GAAG,0BAA0B,QAAQ;AAErG,KAAI,KAAK,QAAQ;AACf,gBAAc,KAAK,QAAQ,GAAG;AAC9B,UAAQ,IAAI,sBAAsB,KAAK,SAAS;OAEhD,SAAQ,OAAO,MAAM,GAAG;;AAQ5B,SAAS,mBAAmB,QAA8B;CACxD,MAAM,QAAkB,EAAE;CAC1B,MAAM,EAAE,UAAU,UAAU,aAAa,OAAO;CAChD,MAAM,QAAQ,WAAW,WAAW;AAEpC,KAAI,WAAW,EACb,OAAM,KAAK,gCAAgC,OAAO,WAAW;UACpD,WAAW,EACpB,OAAM,KAAK,4CAA4C,OAAO,WAAW;KAEzE,OAAM,KAAK,+CAA+C,OAAO,WAAW;AAG9E,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,uBAAuB;AAClC,OAAM,KAAK,gBAAgB;AAC3B,OAAM,KAAK,gBAAgB,SAAS,IAAI;AACxC,OAAM,KAAK,iBAAiB,SAAS,IAAI;AACzC,OAAM,KAAK,gBAAgB,SAAS,IAAI;AACxC,OAAM,KAAK,mBAAmB,MAAM,MAAM;AAE1C,KAAI,UAAU,GAAG;AACf,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,qCAAqC;AAChD,SAAO,MAAM,KAAK,KAAK,GAAG;;CAG5B,MAAM,kBAAkB,OAAO,QAAQ,QAAQ,MAAM,EAAE,aAAa,WAAW;AAC/E,KAAI,gBAAgB,SAAS,GAAG;AAC9B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,uBAAuB;AAClC,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,mBAAmB,gBAAgB,CAAC;;CAGjD,MAAM,kBAAkB,OAAO,QAAQ,QAAQ,MAAM,EAAE,aAAa,YAAY;AAChF,KAAI,gBAAgB,SAAS,GAAG;AAC9B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,YAAY;AACvB,QAAM,KAAK,+BAA+B,gBAAgB,OAAO,aAAa;AAC9E,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,mBAAmB,gBAAgB,CAAC;AAC/C,QAAM,KAAK,aAAa;;CAG1B,MAAM,kBAAkB,OAAO,QAAQ,QAAQ,MAAM,EAAE,aAAa,WAAW;AAC/E,KAAI,gBAAgB,SAAS,GAAG;AAC9B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,YAAY;AACvB,QAAM,KAAK,8BAA8B,gBAAgB,OAAO,aAAa;AAC7E,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,mBAAmB,gBAAgB,CAAC;AAC/C,QAAM,KAAK,aAAa;;AAG1B,QAAO,MAAM,KAAK,KAAK,GAAG;;AAO5B,SAAS,0BAA0B,SAAiC;CAClE,MAAM,YAAY,QAAQ,KAAK,MAAM,EAAE,SAAS;CAOhD,MAAM,SAAS,sBAJK,QAAQ,KAAK,OAAO;EACtC,MAAM;GAAE,SAAS,EAAE;GAAS,SAAS,EAAE;GAAS;EAChD,UAAU,EAAE;EACb,EAAE,CAC8C;CACjD,MAAM,UAAU,2BAA2B,OAAO;CAElD,MAAM,QAAkB,EAAE;AAG1B,KAAI,QAAQ,WAAW,EACrB,OAAM,KAAK,gCAAgC,QAAQ,SAAS,mBAAmB,UAAU,OAAO,YAAY;UACnG,QAAQ,WAAW,EAC5B,OAAM,KACJ,4CAA4C,QAAQ,SAAS,oBAAoB,UAAU,OAAO,YACnG;KAED,OAAM,KAAK,+CAA+C,UAAU,OAAO,YAAY;AAGzF,OAAM,KAAK,GAAG;AAGd,OAAM,KAAK,iDAAiD;AAC5D,OAAM,KAAK,4BAA4B;AACvC,MAAK,MAAM,KAAK,QACd,OAAM,KAAK,KAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,SAAS,KAAK,EAAE,QAAQ,SAAS,KAAK,EAAE,QAAQ,SAAS,IAAI;AAGzG,KAAI,OAAO,kBAAkB,WAAW,GAAG;AACzC,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,qCAAqC;AAChD,SAAO,MAAM,KAAK,KAAK,GAAG;;CAI5B,MAAM,mBAAmB,OAAO,kBAAkB,QAAQ,MAAM,gBAAgB,EAAE,KAAK,WAAW;AAClG,KAAI,iBAAiB,SAAS,GAAG;AAC/B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,uBAAuB;AAClC,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,sBAAsB,kBAAkB,UAAU,CAAC;;CAGhE,MAAM,mBAAmB,OAAO,kBAAkB,QAAQ,MAAM,gBAAgB,EAAE,KAAK,YAAY;AACnG,KAAI,iBAAiB,SAAS,GAAG;AAC/B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,YAAY;AACvB,QAAM,KAAK,+BAA+B,iBAAiB,OAAO,aAAa;AAC/E,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,sBAAsB,kBAAkB,UAAU,CAAC;AAC9D,QAAM,KAAK,aAAa;;CAG1B,MAAM,mBAAmB,OAAO,kBAAkB,QAAQ,MAAM,gBAAgB,EAAE,KAAK,WAAW;AAClG,KAAI,iBAAiB,SAAS,GAAG;AAC/B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,YAAY;AACvB,QAAM,KAAK,8BAA8B,iBAAiB,OAAO,aAAa;AAC9E,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,sBAAsB,kBAAkB,UAAU,CAAC;AAC9D,QAAM,KAAK,aAAa;;AAG1B,QAAO,MAAM,KAAK,KAAK,GAAG;;AAG5B,SAAS,sBACP,UACA,WACQ;CACR,MAAM,QAAkB,EAAE;CAC1B,MAAM,cAAc,UAAU,KAAK,MAAM,EAAE,CAAC,KAAK,MAAM;AACvD,OAAM,KAAK,yBAAyB,YAAY,IAAI;AACpD,OAAM,KAAK,iBAAiB,UAAU,UAAU,MAAM,CAAC,KAAK,MAAM,CAAC,IAAI;AACvE,MAAK,MAAM,KAAK,UAAU;EACxB,MAAM,aAAa,UAAU,KAAK,MAAM,aAAa,EAAE,OAAO,GAAG,CAAC,CAAC,KAAK,MAAM;AAC9E,QAAM,KAAK,OAAO,EAAE,OAAO,SAAS,EAAE,SAAS,OAAO,WAAW,IAAI;;AAEvE,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,aAAa,UAAoD;AACxE,KAAI,CAAC,SAAU,QAAO;AACtB,SAAQ,UAAR;EACE,KAAK,WACH,QAAO;EACT,KAAK,YACH,QAAO;EACT,KAAK,WACH,QAAO;;;AAQb,SAAS,mBAAmB,SAAuC;CACjE,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,iCAAiC;AAC5C,OAAM,KAAK,sBAAsB;AACjC,MAAK,MAAM,KAAK,SAAS;EACvB,MAAM,SAAS,EAAE,WAAW,aAAa,EAAE,KAAK,EAAE,IAAI;AACtD,QAAM,KAAK,OAAO,EAAE,SAAS,SAAS,EAAE,OAAO,OAAO,eAAe,OAAO,CAAC,IAAI;;AAEnF,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,aAAa,KAA6B,SAAyC;CAC1F,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,OAAO,OAAO,KAAK,IAAI,CAChC,KAAI,QAAQ,QAAQ,IAAI,SAAS,QAAQ,KACvC,OAAM,KAAK,GAAG,IAAI,MAAM,IAAI,KAAK,SAAS,QAAQ,KAAK,IAAI;AAG/D,QAAO,MAAM,SAAS,IAAI,MAAM,KAAK,KAAK,GAAG;;AAG/C,SAAS,eAAe,MAAsB;AAC5C,QAAO,KAAK,QAAQ,OAAO,MAAM,CAAC,QAAQ,OAAO,IAAI;;;;;;;;AC3IvD,SAAgB,cACd,QACA,WACA,UACuB;AACvB,MAAK,MAAM,YAAY,UACrB,KAAI,sBAAsB,UAAU,QAAQ,SAAS,CACnD,QAAO;AAGX,QAAO;;;;;;AA0BT,SAAgB,kBACd,SACA,WACA,UACoB;AACpB,QAAO,QAAQ,QAAQ,WAAW,CAAC,cAAc,QAAQ,WAAW,SAAS,CAAC;;AAOhF,SAAS,sBAAsB,UAA0B,QAA0B,UAA+B;AAEhH,KAAI,SAAS,aAAa,MAAO,QAAO;AAGxC,KAAI,SAAS,aAAa,OAAO,SAAU,QAAO;AAGlD,KAAI,CAAC,cAAc,SAAS,QAAQ,OAAO,OAAO,CAAE,QAAO;AAG3D,KAAI,CAAC,gBAAgB,SAAS,WAAW,SAAS,CAAE,QAAO;AAG3D,KAAI,SAAS,SAAS,CAAC,iBAAiB,SAAS,OAAO,OAAO,CAAE,QAAO;AAExE,QAAO;;AAGT,SAAS,cAAc,gBAAwB,cAA+B;AAE5E,KAAI,mBAAmB,aAAc,QAAO;AAM5C,QAF2B,eAAe,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,KACxD,aAAa,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI;;AAI/E,SAAS,gBAAgB,WAAwC,UAA+B;AAC9F,KAAI,CAAC,aAAa,cAAc,yBAA0B,QAAO;AACjE,QAAO,UAAU,SAAS,SAAS;;AAGrC,SAAS,iBAAiB,OAA6C,QAAmC;AACxG,KAAI,MAAM,WAAW;EAEnB,MAAM,aAAa,OAAO,IAAI,cAAc,MAAM;EAClD,MAAM,aAAa,OAAO,IAAI,cAAc,MAAM;AAClD,MAAI,CAAC,cAAc,CAAC,WAAY,QAAO;;AAEzC,KAAI,MAAM,QAAQ;EAChB,MAAM,cAAc,OAAO,IAAI,WAAW,MAAM;EAChD,MAAM,cAAc,OAAO,IAAI,WAAW,MAAM;AAChD,MAAI,CAAC,eAAe,CAAC,YAAa,QAAO;;AAE3C,KAAI,MAAM;MAEJ,CADc,OAAO,OAAO,OAAO,IAAI,CAAC,MAAM,MAAM,MAAM,MAAM,QAAQ,CAC5D,QAAO;;AAEzB,KAAI,MAAM;MAEJ,CADc,OAAO,OAAO,OAAO,IAAI,CAAC,MAAM,MAAM,MAAM,MAAM,QAAQ,CAC5D,QAAO;;AAEzB,QAAO;;;;ACvKT,eAAsB,eACpB,UACA,WACA,MACA,MACA,iBAC4B;CAC5B,MAAM,YAAY,aAAa,KAAK;CACpC,MAAM,YAAY,MAAM,UAAU,QAAQ,UAAU;CAEpD,IAAI,iBAAiB;CACrB,IAAI,eAAe;CACnB,IAAI;AACJ,KAAI,MAAM;AAKR,mBAAiB,cAAc,UAJf,iBAAiB,MAAM,UAAU,MAAM,EAIL;GAAE,YAHjC,sBAAsB,MAAM,UAAU,MAAM;GAGC,aAF5C,uBAAuB,KAAK;GAE6B,YAD5D,sBAAsB,KAAK;GACuD,CAAC;AACpG,iBAAe;AACf,sBACE,OAAO,KAAK,eAAe,WAAW,CAAC,SACvC,OAAO,KAAK,eAAe,QAAQ,CAAC,SACpC,OAAO,KAAK,eAAe,YAAY,CAAC,SACxC,OAAO,KAAK,eAAe,MAAM,CAAC;;CAGtC,MAAM,WAAW,qBAAqB,eAAe;CACrD,MAAM,WAAW,qBAAqB,UAAU;CAEhD,MAAM,SAAS;CAGf,MAAM,OAAO,cAAc,UAAU,UAFtB,kBAAkB,YAAY,iBAAiB,OAAO,EAAE,gBAAgB,GAAG,iBAAiB,OAAO,CAE5D;AAGtD,QAAO;EAAE,QAFM,KAAK,QAAQ,OAAO,MAAM,EAAE,aAAa,WAAW;EAElD;EAAM;EAAc;EAAmB;;;;;ACxC1D,MAAM,oBAAoB;CAAC;CAA2B;CAA2B;CAA8B;;;;;;AAO/G,SAAS,oBAAoB,KAAmB;CAC9C,IAAI;AACJ,KAAI;AACF,YAAU,YAAY,IAAI;SACpB;AACN;;AAEF,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,OAAOC,OAAK,KAAK,KAAK,MAAM;EAClC,IAAI;AACJ,MAAI;AACF,UAAO,SAAS,KAAK;UACf;AACN;;AAEF,MAAI,KAAK,aAAa,EAAE;AACtB,uBAAoB,KAAK;AACzB;;AAGF,MAAI,MAAM,SAAS,QAAQ,IAAI,MAAM,SAAS,QAAQ,CAAE;AAExD,MAAI;GACF,MAAM,MAAM,OAAO,MAAM,IAAI;GAC7B,MAAM,KAAK,SAAS,MAAM,IAAI;AAC9B,OAAI;AACF,aAAS,IAAI,KAAK,GAAG,KAAK,EAAE;aACpB;AACR,cAAU,GAAG;;GAEf,MAAM,SAAS,IAAI,SAAS,QAAQ;AACpC,OAAI,kBAAkB,MAAM,MAAM,OAAO,SAAS,EAAE,CAAC,CACnD,YAAW,KAAK;UAEZ;;;AAMZ,eAAsB,oBAAoB,MAQV;CAC9B,MAAM,EAAE,UAAU,YAAY,WAAW,MAAM,YAAY,WAAW,YAAY;CAMlF,IAAI,UAAU,mBAAmB,UAJhB,iBAAiB,UAAU,EAIS,YADnC,aAAa,KAAK,CACuC,MAAM;CACjF,IAAI,gBAAgB;CACpB,MAAM,sBAAgC,EAAE;AAExC,MAAK,IAAI,UAAU,GAAG,WAAW,YAAY,WAAW;EACtD,MAAM,eAAe,MAAM,eAAe,UAAU,WAAW,MAAM,WAAW;AAChF,MAAI,aAAa,OACf,QAAO;GACL,QAAQ;GACR,UAAU;GACV;GACA;GACD;AAGH,MAAI,YAAY,WACd,QAAO;GACL,QAAQ;GACR,UAAU;GACV;GACA;GACD;EAGH,MAAM,YAAY,aAAa,KAAK,QAAQ,OAAO,kBAAkB;AACrE,MAAI,UAAU,WAAW,EACvB,QAAO;GACL,QAAQ;GACR,UAAU;GACV;GACA;GACD;EAGH,MAAM,kBAAkB,aAAa,KAAK,QAAQ;AAElD,MAAI,UAAU,KAAK,mBAAmB,cACpC,QAAO;GACL,QAAQ;GACR,UAAU;GACV;GACA;GACD;AAEH,kBAAgB;AAChB,sBAAoB,KAAK,UAAU,OAAO;AAC1C,YAAU,UAAU,GAAG,YAAY,UAAU,OAAO;AAEpD,YAAU,aAAa,SAAS,WAAW,SAAS;AAMpD,sBAAoB,UAAU;AAG9B,QAAM,SAAS,YADC,WAAW,KAAK,EACI;GAClC,WAAW,aAAa,WAAW;GACnC;GACA,eAAe;GACf,YAAY;GACb,CAAC;;AAIJ,QAAO;EACL,QAAQ;EACR,UAAU;EACV;EACA,cALmB,MAAM,eAAe,UAAU,WAAW,MAAM,WAAW;EAM/E;;;;;;;;;;;;ACrIH,SAAgB,mBACd,aACA,SACA,SACA,OACa;CACb,MAAM,aAA0B,EAAE;CAGlC,MAAM,WAAW,iBAAiB,SAAS,MAAM;CACjD,MAAM,WAAW,iBAAiB,SAAS,MAAM;CAEjD,MAAM,+BAAe,IAAI,KAAa;AACtC,MAAK,MAAM,QAAQ,SACjB,KAAI,CAAC,SAAS,IAAI,KAAK,CAAE,cAAa,IAAI,KAAK;AAGjD,MAAK,MAAM,QAAQ,cAAc;AAC/B,MAAI,YAAY,QAAQ,MACtB,YAAW,KAAK;GACd,UAAU;GACV,UAAU;GACV,YAAY;GACZ,UAAU;GACV,WAAW;GACX,SAAS,UAAU,KAAK;GACzB,CAAC;AAEJ,MAAI,YAAY,WAAW,MACzB,YAAW,KAAK;GACd,UAAU;GACV,UAAU;GACV,YAAY;GACZ,UAAU;GACV,WAAW;GACX,SAAS,cAAc,KAAK;GAC7B,CAAC;AAEJ,MAAI,YAAY,YAAY,MAC1B,YAAW,KAAK;GACd,UAAU;GACV,UAAU;GACV,YAAY;GACZ,UAAU;GACV,WAAW;GACX,SAAS,eAAe,KAAK;GAC9B,CAAC;AAEJ,MAAI,YAAY,MAAM,MACpB,YAAW,KAAK;GACd,UAAU;GACV,UAAU;GACV,YAAY;GACZ,UAAU;GACV,WAAW;GACX,SAAS,SAAS,KAAK;GACxB,CAAC;;CAKN,MAAM,gBAAgB,sBAAsB,SAAS,MAAM;CAC3D,MAAM,gBAAgB,sBAAsB,SAAS,MAAM;AAE3D,MAAK,MAAM,aAAa,eAAe;AACrC,MAAI,cAAc,IAAI,UAAU,CAAE;EAElC,MAAM,CAAC,WAAW,aAAa,UAAU,MAAM,IAAI;AAGnD,MAAI,aAAa,IAAI,UAAU,CAAE;AAGjC,MADc,YAAY,WAAW,YAC1B,OAAO,WAChB,YAAW,KAAK;GACd,UAAU;GACV,UAAU;GACV,YAAY;GACZ,UAAU;GACV,WAAW;GACX,SAAS,UAAU,UAAU;GAC9B,CAAC;;CAKN,MAAM,OAAO,UAAU,SAAS,QAAQ;AACxC,MAAK,MAAM,UAAU,KAAK,QACxB,KAAI,OAAO,SAAS;MACN,YAAY,QAAQ,OAAO,cAC9B,QAAQ,OAAO,eACtB,YAAW,KAAK;GACd,UAAU;GACV,UAAU;GACV,YAAY,GAAG,OAAO,YAAY,GAAG,OAAO;GAC5C,UAAU,OAAO;GACjB,WAAW;GACX,SAAS,WAAW,OAAO,YAAY,GAAG,OAAO,cAAc;GAChE,CAAC;;AAKR,QAAO;;;;AC9GT,SAAgB,kBACd,UACA,SACA,SACA,MACsB;AAGtB,QAAO,EAAE,YADU,mBAAmB,UAAU,SAAS,SADvC,aAAa,KAAK,CACwC,MAAM,EAC7D;;;;ACPvB,MAAM,aAAa,cAAc,OAAO,KAAK,IAAI;AACjD,MAAM,YAAYC,OAAK,QAAQ,WAAW;AAE1C,SAAS,cAAc,eAAwD;CAC7E,MAAM,aAAaA,OAAK,QAAQ,WAAW,MAAM,MAAM,QAAQ,WAAW,cAAc,QAAQ,SAAS,OAAO,CAAC;AACjH,KAAI,WAAW,WAAW,CACxB,QAAO;EAAE,KAAK;EAAQ,QAAQ;EAAY;AAG5C,QAAO;EAAE,KAAK;EAAO,QADHA,OAAK,QAAQ,WAAW,MAAM,MAAM,WAAW,cAAc;EACvC;;AAG1C,SAAS,kBAAkB,eAAuB,MAAsB;CACtE,MAAM,EAAE,KAAK,WAAW,cAAc,cAAc;AAEpD,cAAa,KADI,QAAQ,QAAQ;EAAC;EAAO;EAAQ,GAAG;EAAK,GAAG,CAAC,QAAQ,GAAG,KAAK,EACjD;EAAE,OAAO;EAAW,KAAK,QAAQ;EAAK,CAAC;;AAGrE,SAAgB,cAAc,MAOT;CACnB,MAAM,EAAE,MAAM,MAAM,QAAQ,YAAY,aAAa,gBAAgB;CAErE,IAAI,eAAe,cAAc;CACjC,IAAI,oBAAoB;AAExB,KAAI,CAAC,cAAc,CAAC,WAAW,yBAAyB,EAAE;AACxD,MAAI,CAAC,KACH,OAAM,IAAI,aACR,6FACA,IACA,EACD;AAGH,MAAI;AACF,qBAAkB,qBAAqB,CAAC,UAAU,KAAK,CAAC;UAClD;AACN,SAAM,IAAI,aAAa,8BAA8B,IAAI,EAAE;;AAE7D,iBAAe;AACf,sBAAoB;;CAGtB,MAAM,YAAY;EAAC;EAAU;EAAM;EAAc;EAAQ;EAAiB;EAAa;AACvF,KAAI,KAAM,WAAU,KAAK,UAAU,KAAK;AACxC,KAAI,YAAa,WAAU,KAAK,kBAAkB,YAAY;AAE9D,KAAI;AACF,MAAI,aAAa;GACf,MAAM,MAAM,YAAY,SAAS,MAAM,GAAG,QAAQ;AAElD,gBAAa,KADI,QAAQ,QAAQ;IAAC;IAAO;IAAa,GAAG;IAAU,GAAG,CAAC,aAAa,GAAG,UAAU,EACrE;IAAE,OAAO;IAAW,KAAK,QAAQ;IAAK,CAAC;QAEnE,mBAAkB,qBAAqB,UAAU;AAGnD,SAAO;GAAE,QAAQ;GAAM;GAAc;GAAmB;SAClD;AACN,MAAI,WAAW,4BAA4B,CACzC,QAAO;GAAE,QAAQ;GAAO,eAAe;GAAM;GAAc;GAAmB;AAOhF,SAAO;GAAE,QAAQ;GAAO,eAJF,WAAW,2BAA2B,GACvD,KAAK,MAAM,aAAa,4BAA4B,QAAQ,CAAC,CAAe,SAC7E,KAAA;GAEmC;GAAc;GAAmB;;;;;AC5E5E,SAAgB,qBAAqB,QAA0E;CAC7G,MAAM,uBAA+C,EAAE;CACvD,MAAM,uBAA+C,EAAE;AACvD,MAAK,MAAM,KAAK,OAAO,KAAK,SAAS;AACnC,uBAAqB,EAAE,aAAa,qBAAqB,EAAE,aAAa,KAAK;AAC7E,uBAAqB,EAAE,aAAa,qBAAqB,EAAE,aAAa,KAAK;;CAG/E,MAAM,EAAE,UAAU,UAAU,aAAa,OAAO,KAAK;CAErD,MAAM,uBADe,WAAW,WAAW,WACC;CAC5C,MAAM,mBAAmB,uBAAuB,WAAW;AAI3D,QAAO;EACL;EACA;EACA,mBALA,uBAAuB,IAAI,KAAK,MAAO,mBAAmB,uBAAwB,IAAI,GAAG;EAMzF;EACA;EACA,WAAW;EACX,cAAc,OAAO;EACrB,GAAI,OAAO,sBAAsB,KAAA,IAAY,EAAE,mBAAmB,OAAO,mBAAmB,GAAG,EAAE;EAClG;;AAGH,SAAgB,oBACd,UACA,SACA,WACA,YACA,qBACM;AACN,UAAS,YAAY;EAAE,UAAU;EAAS;EAAW;EAAY;EAAqB;;AAGxF,SAAgB,iBAAiB,MAAyB,WAAmB,2BAAiC;AAC5G,eAAc,UAAU,KAAK,UAAU,MAAM,MAAM,EAAE,GAAG,KAAK;;;;ACvB/D,MAAM,YAAY,IAAI,OAAO,GAAG;AAEhC,SAAS,kBAAkB,QAAiD,UAA4B;AACtG,KAAI,OAAO,cAAc;EACvB,MAAM,cACJ,OAAO,KAAK,SAAS,WAAW,CAAC,SACjC,OAAO,KAAK,SAAS,QAAQ,CAAC,SAC9B,OAAO,KAAK,SAAS,YAAY,CAAC,SAClC,OAAO,KAAK,SAAS,MAAM,CAAC;AAC9B,UAAQ,IAAI,oBAAoB,OAAO,kBAAkB,GAAG,YAAY,6BAA6B;;AAGvG,SAAQ,IACN,WAAW,OAAO,kBAAkB,KAAK,OAAO,iBAAiB,GAAG,OAAO,qBAAqB,qBACjG;;AAGH,eAAsB,cAAc,MAqBlB;CAChB,MAAM,EACJ,MACA,SACA,MACA,QACA,YACA,YACA,aACA,aACA,OACA,aACA,sBACA,qBACA,eACA,cACA,cACA,kBACE;CACJ,MAAM,aAAa,KAAK,cAAc;CACtC,MAAM,WAA8B,EAAE;CAGtC,MAAM,kBACH,KAAK,gBAAgD,cAAc,UAAU;CAChF,MAAM,sBAAsB,gBAAgB,cAAc;CAC1D,MAAM,mBAAmB,iBAAiB,cAAc,WAAW;CAEnE,IAAI,UAAU;CACd,MAAM,WAAmC,aACpC,KAAK,MAAM,aAAa,YAAY,QAAQ,CAAC,GAC9C,KAAA;AAEJ,KAAI,cAAc,UAAU;AAC1B,UAAQ,IAAI,KAAK,YAAY;AAC7B,UAAQ,IAAI,QAAQ,QAAQ,uBAAuB;AACnD,UAAQ,IAAI,UAAU;EAEtB,MAAM,iBAAiB,UAAU,OAAO,cAAc;EACtD,IAAI;AACJ,MAAI,mBAAmB,eAAe,KACpC,cAAa,MAAM,UAAU,MAAM;GAAE;GAAsB;GAAqB;GAAe,CAAC;WACvF,mBAAmB,YAC5B,OAAM,IAAI,aAAa,mDAAmD,IAAI,EAAE;EAGlF,MAAM,aACJ,cAAc,aAAa,IACvB,MAAM,oBAAoB;GACxB;GACA;GACA,WAAW;GACX;GACA;GACA,WAAW,KAAK;GAChB,UAAU,eAAe,YAAY,mBAAmB;AACtD,YAAQ,IAAI,WAAW,cAAc,GAAG,WAAW,aAAa,eAAe,kBAAkB;;GAEpG,CAAC,GACF;GACE,QAAQ;GACR,UAAU;GACV,qBAAqB,EAAE;GACvB,cAAc,MAAM,eAAe,UAAU,QAAQ,MAAM,WAAW;GACvE;EAEP,MAAM,gBAAgB,qBAAqB,WAAW,aAAa;AACnE,oBAAkB,eAAe,SAAS;EAC1C,MAAM,iBAAiB,WAAW,aAAa;AAC/C,OAAK,MAAM,KAAK,eAAe,QAC7B,KAAI,EAAE,aAAa,WACjB,SAAQ,IAAI,MAAM,EAAE,SAAS,IAAI,EAAE,SAAS,IAAI,EAAE,OAAO,KAAK,EAAE,UAAU;EAG9E,MAAM,gBAAgB,eAAe,QAAQ;AAC7C,MAAI,gBAAgB,EAClB,SAAQ,IAAI,OAAO,cAAc,oBAAoB;AAGvD,MAAI,aAAa;AACf,YAAS,cAAc;AACvB,OAAI,cAAc,aAAa,EAC7B,qBACE,UACA,WAAW,UACX,WAAW,WAAW,UACtB,cAAc,mBACd,WAAW,oBACZ;;AAIL,MAAI,WAAW,WAAW,YAAY,WAAW,aAAa,OAC5D,KAAI,WAAW,WAAW,EACxB,SAAQ,IAAI,2BAA2B,WAAW,SAAS,qBAAqB;MAEhF,SAAQ,IAAI,iBAAiB;OAE1B;AACL,OAAI,aAAa;AACf,qBAAiB,SAAS;AAC1B,YAAQ,IAAI,iDAAiD;;AAG/D,OAAI,WAAW,WAAW,eACxB,SAAQ,IACN,oGACD;YACQ,WAAW,WAAW,UAC/B,SAAQ,IAAI,qDAAqD;AAGnE,SAAM,IAAI,aAAa,0EAA0E,IAAI,EAAE;;AAKzG,MAAI,uBAAuB,qBAAqB,cAAc,OAAO,UAAU,KAAK,GAAG;GACrF,MAAM,SAAS;GACf,MAAM,YAAY,cAAc,SAAS,EAAE;GAC3C,MAAM,YAAY,kBAAkB,eAAe,SAAS,WAAW,OAAO;GAC9E,MAAM,aAAa,UAAU,MAAM,MAAM,uBAAuB,EAAE,UAAU,gBAAgB,CAAC;AAE7F,OAAI,kBAAkB;AACpB,YAAQ,IAAI,GAAG;AACf,YAAQ,IAAI,mBAAmB,gBAAgB,EAAE,SAAS,MAAM,CAAC,CAAC;;AAGpE,OAAI,qBAAqB;IACvB,MAAM,SAAS,eAAe,eAAe;AAC7C,kBAAc,qBAAqB,KAAK,UAAU,QAAQ,MAAM,EAAE,GAAG,KAAK;AAC1E,YAAQ,IAAI,4BAA4B,sBAAsB;;AAGhE,OAAI,cAAc,oBAAoB,QAAQ;IAC5C,MAAM,qBAAqB,UAAU,QAAQ,MAAM,uBAAuB,EAAE,UAAU,gBAAgB,CAAC;AACvG,YAAQ,IAAI,KAAK,mBAAmB,OAAO,qCAAqC,gBAAgB,aAAa;;;AAIjH;;AAGF,KAAI,WAAW,QAAQ,cAAc,UAAU;AAC7C,UAAQ,IAAI,KAAK,YAAY;AAC7B,UAAQ,IAAI,QAAQ,QAAQ,uBAAuB;AACnD,UAAQ,IAAI,UAAU;EAItB,MAAM,kBAAkB,kBAAkB,UAFpB,MAAM,UAAU,SAAS;GAAE;GAAsB;GAAqB;GAAe,CAAC,EACtF,MAAM,UAAU,MAAM;GAAE;GAAsB;GAAqB;GAAe,CAAC,EACvB,KAAK;AAEvF,MAAI,gBAAgB,WAAW,SAAS,GAAG;AACzC,WAAQ,IAAI,SAAS,gBAAgB,WAAW,OAAO,mBAAmB;AAC1E,QAAK,MAAM,KAAK,gBAAgB,WAC9B,SAAQ,IAAI,MAAM,EAAE,SAAS,IAAI,EAAE,SAAS,IAAI,EAAE,WAAW,KAAK,EAAE,UAAU;QAGhF,SAAQ,IAAI,6BAA6B;AAG3C,MAAI,YACF,UAAS,iBAAiB;GACxB,kBAAkB,gBAAgB,WAAW;GAC7C,cAAc,gBAAgB,WAAW,KAAK,MAAM,EAAE,WAAW;GAClE;AAGH;;AAIF,KAD0B,CAAC,cAAc,CAAC,WAAW,yBAAyB,EACvD;AACrB,UAAQ,IAAI,KAAK,YAAY;AAC7B,UAAQ,IAAI,QAAQ,QAAQ,yDAAyD;AACrF,UAAQ,IAAI,UAAU;AACtB;;AAGF,SAAQ,IAAI,KAAK,YAAY;AAC7B,SAAQ,IAAI,QAAQ,QAAQ,qBAAqB;AACjD,SAAQ,IAAI,UAAU;CAEtB,MAAM,cAAc,cAAc;EAChC;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;AAEF,KAAI,aAAa;AACf,WAAS,aAAa;GACpB,QAAQ,YAAY;GACpB,GAAI,YAAY,kBAAkB,KAAA,IAAY,EAAE,eAAe,YAAY,eAAe,GAAG,EAAE;GAC/F,GAAI,YAAY,gBAAgB,EAAE,eAAe,MAAM,GAAG,EAAE;GAC7D;AACD,mBAAiB,SAAS;AAC1B,UAAQ,IAAI,iDAAiD;;AAG/D,KAAI,CAAC,YAAY,QAAQ;AACvB,MAAI,YAAY,cACd,OAAM,IAAI,aAAa,qEAAqE,IAAI,EAAE;AAGpG,QAAM,IAAI,aACR;;;;8CAEwC,KAAK;+CACJ,KAAK;+CACL,KAAK;+CACL,KAAK;yDACK,KAAK;yDACL,KAAK,2BACxD,IACA,EACD;;AAGH,SAAQ,IAAI,8BAA8B;;;;ACnR5C,SAAgB,aAAa,MAAsC;AACjE,QAAO;GACJ,gBAAgB,SAAS,yBAAyB,KAAK,mFAAmF,KAAK,iCAAiC,KAAK;GACrL,YAAY,SAAS,6EAA6E,KAAK,mCAAmC,KAAK,2BAA2B,KAAK;GAC/K,cAAc,SAAS,uBAAuB,KAAK,gEAAgE,KAAK;GACxH,eAAe,SAAS,wBAAwB,KAAK,sBAAsB,KAAK,sBAAsB,KAAK;EAC7G;;AAGH,SAAgB,YAAY,MAAsB;AAChD,QAAO,KAAK,UACV;EACE,MAAM;EACN,SAAS;EACT,MAAM;EACN,MAAM;EACN,OAAO;EACP,SAAS;GACP,KAAK;IAAE,OAAO;IAAqB,QAAQ;IAAmB;GAC9D,YAAY;IAAE,OAAO;IAAsB,QAAQ;IAAoB;GACxE;EACD,SAAS;GACP,OAAO;GACP,MAAM;GACN,cAAc;GACd,WAAW;GACX,GAAG,aAAa,KAAK;GACtB;EACD,cAAc,EACZ,iBAAiB,UAClB;EACD,iBAAiB;GACf,MAAM;GACN,KAAK;GACL,QAAQ;GACR,eAAe;GAChB;EACF,EACD,MACA,EACD;;AAGH,SAAgB,eAAuB;AACrC,QAAO,KAAK,UACV;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,kBAAkB;GAClB,QAAQ;GACR,aAAa;GACb,gBAAgB;GAChB,WAAW;GACX,QAAQ;GACR,SAAS;GACT,iBAAiB;GACjB,cAAc;GACd,kCAAkC;GAClC,mBAAmB;GACnB,iBAAiB;GAClB;EACD,SAAS,CAAC,OAAO,OAAO;EACxB,SAAS,CAAC,gBAAgB,OAAO;EAClC,EACD,MACA,EACD;;AAGH,SAAgB,eAAuB;AACrC,QAAO;;;;;;AAOT,SAAgB,aAAqB;AACnC,QAAO;;;;;;;;;;AAWT,SAAgB,cAAsB;AACpC,QAAO;;;;;;;;;;;;AAaT,SAAgB,UAAU,MAAsB;CAC9C,MAAM,UAAU,GAAG,YAAY,KAAK,CAAC;AACrC,QAAO;WACE,QAAQ,aAAa,KAAK;;;eAGtB,QAAQ;;;;;;AAOvB,SAAgB,SAAS,MAAsB;AAE7C,QAAO,YADS,GAAG,YAAY,KAAK,CAAC,SACV,aAAa,KAAK;;;;AAK/C,SAAgB,YAAoB;AAClC,QAAO;;;;;;;;AAST,SAAgB,YAAY,MAAsB;AAEhD,QAAO;;eADS,GAAG,YAAY,KAAK,CAAC,SAGhB;eACR,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/HpB,eAAsB,YAAY,MAAyD;CACzF,MAAM,aAAa,QAAQ,KAAK,WAAW,IAAI;CAC/C,MAAM,OAAO,KAAK;AAElB,KAAI,WAAW,QAAQ,YAAY,kBAAkB,CAAC,CACpD,OAAM,IAAI,MAAM,uDAAuD;CAIzE,MAAM,OAAO;EAAC,OAAO;EAAQ;EAAQ;EAAS;EAAwB;AACtE,MAAK,MAAM,OAAO,KAChB,WAAU,QAAQ,YAAY,IAAI,EAAE,EAAE,WAAW,MAAM,CAAC;CAI1D,MAAM,QAAiC;EACrC,CAAC,iBAAiB,cAAc,CAAC;EACjC,CAAC,oBAAoB,cAAc,CAAC;EACpC,CAAC,kBAAkB,YAAY,CAAC;EAChC,CAAC,mBAAmB,aAAa,CAAC;EAClC,CAAC,iBAAiB,UAAU,KAAK,CAAC;EAClC,CAAC,gBAAgB,SAAS,KAAK,CAAC;EAChC,CAAC,OAAO,KAAK,YAAY,YAAY,KAAK,CAAC;EAC5C;CAGD,MAAM,kBAAkB,QAAQ,YAAY,eAAe;CAC3D,IAAI;AACJ,KAAI,WAAW,gBAAgB,EAAE;EAC/B,MAAM,kBAAkB,aAAa,iBAAiB,QAAQ;EAC9D,MAAM,cAAc,KAAK,MAAM,gBAAgB;EAC/C,MAAM,SAAS,KAAK,MAAM,YAAY,KAAK,CAAC;AAE5C,cAAY,UAAU;GAAE,GAAG,OAAO;GAAS,GAAG,YAAY;GAAS;AACnE,cAAY,kBAAkB;GAAE,GAAG,OAAO;GAAiB,GAAG,YAAY;GAAiB;AAC3F,cAAY,eAAe;GAAE,GAAG,OAAO;GAAc,GAAG,YAAY;GAAc;AAElF,MAAI,CAAC,YAAY,QACf,aAAY,UAAU,OAAO;AAG/B,MAAI,CAAC,YAAY,KACf,aAAY,OAAO,OAAO;AAG5B,MAAI,CAAC,YAAY,KACf,aAAY,OAAO,OAAO;AAG5B,MAAI,CAAC,YAAY,MACf,aAAY,QAAQ,OAAO;AAE7B,uBAAqB,KAAK,UAAU,aAAa,MAAM,EAAE;OAEzD,sBAAqB,YAAY,KAAK;CAIxC,MAAM,gBAAgB,QAAQ,YAAY,aAAa;CACvD,IAAI;AACJ,KAAI,WAAW,cAAc,EAAE;EAC7B,MAAM,kBAAkB,aAAa,eAAe,QAAQ;EAC5D,MAAM,aAAa,WAAW;EAE9B,MAAM,gBAAgB,IAAI,IACxB,gBACG,MAAM,KAAK,CACX,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,QAAQ,SAAS,QAAQ,CAAC,KAAK,WAAW,IAAI,CAAC,CACnD;EACD,MAAM,WAAW,WAAW,MAAM,KAAK,CAAC,QAAQ,SAAS;GACvD,MAAM,UAAU,KAAK,MAAM;AAC3B,UAAO,WAAW,CAAC,cAAc,IAAI,QAAQ;IAC7C;AACF,qBAAmB,mBAAmB,gBAAgB,SAAS,KAAK,GAAG,KAAK,QAAQ,SAAS,KAAK,KAAK;OAEvG,oBAAmB,WAAW;AAGhC,MAAK,MAAM,CAAC,UAAU,YAAY,OAAO;EACvC,MAAM,WAAW,QAAQ,YAAY,SAAS;AAC9C,YAAU,QAAQ,UAAU,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACvD,gBAAc,UAAU,SAAS,QAAQ;;AAI3C,eAAc,iBAAiB,oBAAoB,QAAQ;AAG3D,eAAc,eAAe,kBAAkB,QAAQ;AAGvD,SAAQ,IAAI,oCAAoC,KAAK,OAAO,SAAS,QAAQ,KAAK,EAAE,WAAW,IAAI,MAAM;AACzG,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,WAAW;AACvB,MAAK,MAAM,CAAC,aAAa,MACvB,SAAQ,IAAI,KAAK,WAAW;AAE9B,MAAK,MAAM,OAAO,KAChB,SAAQ,IAAI,KAAK,IAAI,GAAG;AAI1B,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc;AAC1B,SAAQ,IAAI,qCAAqC,KAAK,WAAW;AACjE,SAAQ,IAAI,uEAAuE;AACnF,SAAQ,IAAI,kDAAkD;;;;ACpHhE,eAAsB,eAAe,MASnB;CAChB,IAAI,KAAK,MAAM,UAAU,KAAK,MAAM;EAClC,sBAAsB,KAAK;EAC3B,qBAAqB,KAAK;EAC1B,eAAe,KAAK;EACrB,CAAC;AACF,KAAI,KAAK,OACP,MAAK,cAAc,IAAI,KAAK,OAAO;CAGrC,MAAM,WAAW,kBAAkB,IAAI,KAAK,gBAAgB,KAAK,WAAW;AAG5E,MAFe,KAAK,UAAU,aAEf,QAAQ;EACrB,MAAM,SAAS,SAAS,IAAI,UAAU;AACtC,UAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAIF,YAAW,UAAU,KAAK,eAAe;;AAa3C,SAAS,UAAU,GAA+B;AAChD,QAAO;EACL,SAAS,EAAE,QAAQ;EACnB,QAAQ,EAAE,UAAU,WAAW,aAAa;EAC5C,MAAM,EAAE,UAAU;EAClB,aAAa,EAAE;EACf,aAAa,EAAE,eAAe,EAAE,UAAU;EAC1C,SAAS,EAAE;EACX,UAAU,EAAE,UAAU,KAAK,MAAM,EAAE,KAAK;EACzC;;AAGH,SAAS,WAAW,UAA+B,OAA6C;CAC9F,MAAM,UAAU,SAAS,EAAE;AAG3B,SAAQ,IAAI,gEAAgE;AAC5E,SAAQ,IAAI,4BAA4B;CAExC,MAAM,WAAgC,EAAE;AAExC,MAAK,MAAM,KAAK,UAAU;EAExB,MAAM,UADM,GAAG,EAAE,UAAU,WAAW,aAAa,CAAC,GAAG,EAAE,UAAU,UAC5C;EACvB,MAAM,aAAa,UAAU,QAAQ;EACrC,MAAM,eAAe,EAAE,YAAY,EAAE,QAAQ;EAC7C,MAAM,WAAW,eAAe,EAAE,UAAU;AAE5C,UAAQ,IACN,KAAK,EAAE,QAAQ,KAAK,KAAK,EAAE,UAAU,WAAW,aAAa,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,EAAE,WAAW,OAAO,WAAW,KAAK,SAAS,IACzI;AAGD,MAAI,EAAE,SACJ,MAAK,MAAM,KAAK,EAAE,SAChB,SAAQ,IAAI,cAAc,EAAE,KAAK,uBAAuB,SAAS,IAAI;AAIzE,MAAI,CAAC,WAAW,CAAC,aACf,UAAS,KAAK,EAAE;;AAIpB,SAAQ,IAAI,GAAG;AACf,SAAQ,IACN,UAAU,SAAS,OAAO,eAAe,SAAS,SAAS,SAAS,OAAO,sBAAsB,SAAS,OAAO,iBAClH;;;;ACNH,MAAM,eAAe;CAAC;CAAmB;CAAmB;CAAmB;;;;;;;;;AAU/E,eAAsB,WAAW,YAAqB,MAAc,QAAQ,KAAK,EAA+B;AAC9G,KAAI,YAAY;EACd,MAAM,WAAWC,OAAK,QAAQ,KAAK,WAAW;AAC9C,MAAI,CAAC,WAAW,SAAS,CACvB,OAAM,IAAI,gBAAgB,0BAA0B,YAAY,iDAAiD;AAEnH,MAAI;GACF,MAAM,MAAM,MAAM,OAAO,cAAc,SAAS,CAAC;AACjD,UAAQ,IAAI,WAAW;WAChB,KAAK;AAEZ,SAAM,IAAI,gBACR,kBAAkB,SAAS,IAFb,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IAG9D,SAAS,SAAS,MAAM,GACpB,4FACA,2CACL;;;AAIL,MAAK,MAAM,QAAQ,cAAc;EAC/B,MAAM,WAAWA,OAAK,QAAQ,KAAK,KAAK;AACxC,MAAI,CAAC,WAAW,SAAS,CAAE;AAC3B,MAAI;GACF,MAAM,MAAM,MAAM,OAAO,cAAc,SAAS,CAAC;AAEjD,UADgB,IAAI,WAAW;WAExB,KAAK;AAEZ,SAAM,IAAI,gBACR,kBAAkB,KAAK,IAFT,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IAG9D,KAAK,SAAS,MAAM,GAChB,4FACA,2CACL;;;AAGL,QAAO;;;;ACnIT,SAAgB,YAAY,QAA2B;AACrD,MAAK,MAAM,WAAW,OAAO,YAAY,EAAE,CACzC,iBAAgB,QAAQ;AAE1B,MAAK,MAAM,aAAa,OAAO,cAAc,EAAE,CAC7C,mBAAkB,UAAU;;;;ACOhC,SAAS,YAAY,KAAqB;CACxC,MAAM,WAAW,eAAe,eAAe,IAAI,WAAW;CAC9D,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAChE,KAAI,QAAS,SAAQ,MAAM,QAAQ;AACnC,SAAQ,KAAK,SAAS;;AAMxB,MAAM,eAAe,QAAQ,KAAK,QAAQ,WAAW;AACrD,MAAM,qBAAqB,iBAAiB,KAAK,QAAQ,KAAK,eAAe,KAAK,KAAA;AAKlF,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AAGJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;CACF,MAAM,SAAS,MAAM,WAAW,mBAAmB;AACnD,KAAI,QAAQ;AACV,cAAY,OAAO;AACnB,uBAAqB,OAAO;AAC5B,+BAA6B,OAAO;AACpC,8BAA4B,OAAO;AACnC,wBAAsB,OAAO;AAC7B,iBAAe,OAAO;AACtB,yBAAuB,OAAO;AAC9B,qBAAmB,OAAO;AAC1B,qBAAmB,OAAO;AAC1B,qBAAmB,OAAO;AAC1B,yBAAuB,OAAO;AAC9B,iBAAe,OAAO;;SAEjB,KAAK;AACZ,aAAY,IAAI;;AAGlB,MAAM,UAAU,IAAI,SAAS,CAC1B,KAAK,QAAQ,CACb,YAAY,8CAA8C,CAC1D,QAAQ,QAAQ,CAChB,OAAO,mBAAmB,8DAA8D;AAE3F,QACG,QAAQ,QAAQ,CAChB,YAAY,8CAA8C,CAC1D,OAAO,iBAAiB,uDAAuD,CAC/E,QAAQ,SAAS;AAChB,MAAK,SAAS,QAAQ,IAAI;AAC1B,KAAI,CAAC,KAAK,MAAM;AACd,UAAQ,MAAM,gEAAgE;AAC9E,UAAQ,KAAK,EAAE;;AAEjB,QAAO,aAAa;EAClB,GAAG;EACH,sBAAsB;EACtB,qBAAqB;EACrB,eAAe;EAChB,CAAC;EACF;AAEJ,QACG,QAAQ,WAAW,CACnB,YAAY,mDAAmD,CAC/D,OAAO,iBAAiB,uDAAuD,CAC/E,eAAe,qBAAqB,kBAAkB,CACtD,eAAe,kBAAkB,mBAAmB,CACpD,OAAO,kBAAkB,4DAA4D,CACrF,OAAO,sBAAsB,6BAA6B,CAC1D,OAAO,aAAa,gCAAgC,CACpD,OAAO,wBAAwB,uDAAuD,CACtF,OAAO,qBAAqB,wDAAwD,CACpF,OAAO,cAAc,6EAA6E,CAClG,OAAO,qBAAqB,sEAAsE,CAClG,QAAQ,SAAS;AAChB,MAAK,SAAS,QAAQ,IAAI;AAC1B,KAAI,CAAC,KAAK,MAAM;AACd,UAAQ,MAAM,gEAAgE;AAC9E,UAAQ,KAAK,EAAE;;AAEjB,iBAAgB;EACd,GAAG;EACH,sBAAsB;EACtB,qBAAqB;EACrB,eAAe;EACf,QAAQ;EACR,gBAAgB;EAChB,YAAY;EACZ,YAAY;EACZ,YAAY;EACZ,gBAAgB,uBAAuB,KAAK;EAC7C,CAAC,CAAC,MAAM,YAAY;EACrB;AAEJ,QACG,QAAQ,OAAO,CACf,YAAY,qDAAqD,CACjE,eAAe,gBAAgB,mBAAmB,CAClD,eAAe,gBAAgB,mBAAmB,CAClD,QAAQ,SAAS;AAChB,aAAY;EACV,GAAG;EACH,sBAAsB;EACtB,qBAAqB;EACrB,eAAe;EACf,QAAQ;EACT,CAAC,CAAC,MAAM,YAAY;EACrB;AAEJ,QACG,QAAQ,UAAU,CAClB,YAAY,6CAA6C,CACzD,eAAe,qBAAqB,uBAAuB,CAC3D,eAAe,qBAAqB,kBAAkB,CACtD,OAAO,mBAAmB,mBAAmB,CAC7C,QAAQ,SAAS;AAChB,MAAK,WAAW,OAAO,KAAK,KAAK;AACjC,gBAAe,KAAK,CAAC,MAAM,YAAY;EACvC;AAEJ,QACG,QAAQ,iBAAiB,CACzB,YAAY,kFAAkF,CAC9F,eAAe,qBAAqB,uBAAuB,CAC3D,eAAe,qBAAqB,kBAAkB,CACtD,eAAe,kBAAkB,sDAAsD,CACvF,OAAO,iBAAiB,+EAA+E,CACvG,QAAQ,SAAS;AAChB,MAAK,SAAS,QAAQ,IAAI;AAC1B,sBAAqB;EACnB,GAAG;EACH,qBAAqB;EACrB,eAAe;EAChB,CAAC,CAAC,MAAM,YAAY;EACrB;AAEJ,QACG,QAAQ,cAAc,CACtB,YAAY,wEAAwE,CACpF,eAAe,qBAAqB,4CAA4C,CAChF,eAAe,sBAAsB,6CAA6C,CAClF,OAAO,mBAAmB,6CAA6C,CACvE,OAAO,qBAAqB,gDAAgD,WAAW,CACvF,OAAO,aAAa,4CAA4C,CAChE,QAAQ,SAAS;AAChB,mBAAkB,KAAK,CAAC,MAAM,YAAY;EAC1C;AAEJ,QACG,QAAQ,iBAAiB,CACzB,YAAY,mDAAmD,CAC/D,eAAe,sBAAsB,6EAA6E,CAClH,OAAO,mBAAmB,gDAAgD,CAC1E,QAAQ,SAAS;AAChB,sBAAqB,KAAK,CAAC,MAAM,YAAY;EAC7C;AAEJ,QACG,QAAQ,SAAS,CACjB,YAAY,+EAA+E,CAC3F,OAAO,iBAAiB,uDAAuD,CAC/E,eAAe,qBAAqB,kBAAkB,CACtD,eAAe,kBAAkB,4BAA4B,CAC7D,OAAO,wBAAwB,0DAA0D,CACzF,OAAO,wBAAwB,0DAA0D,CACzF,OAAO,yBAAyB,gEAAgE,CAChG,OAAO,yBAAyB,wEAAwE,CACxG,OACC,kBACA,yKACD,CACA,OAAO,qBAAqB,kFAAkF,CAC9G,OAAO,sBAAsB,mEAAmE,CAChG,OAAO,iBAAiB,qEAAqE,CAC7F,OAAO,qBAAqB,sEAAsE,IAAI,CACtG,OAAO,0BAA0B,oDAAoD,CACrF,OAAO,4BAA4B,+CAA+C,CAClF,OAAO,4BAA4B,0CAA0C,CAC7E,OAAO,oBAAoB,mDAAmD,CAC9E,QAAQ,SAAS;AAChB,MAAK,SAAS,QAAQ,IAAI;AAI1B,MAAK,gBAAgB,qBAAqB,KAAK;AAC/C,eAAc;EACZ,GAAG;EACH,YAAY,SAAS,KAAK,YAAY,GAAG;EACzC,sBAAsB;EACtB,qBAAqB;EACrB,eAAe;EACf,cAAc;EACd,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,gBAAgB,KAAK;EACrB,eAAe,KAAK;EACrB,CAAC,CAAC,MAAM,YAAY;EACrB;AAEJ,QACG,QAAQ,UAAU,CAClB,YAAY,8DAA8D,CAC1E,OAAO,iBAAiB,uDAAuD,CAC/E,OAAO,qBAAqB,gCAAgC,QAAQ,CACpE,QAAQ,SAAS;AAChB,MAAK,SAAS,QAAQ,IAAI;AAC1B,KAAI,CAAC,KAAK,MAAM;AACd,UAAQ,MAAM,gEAAgE;AAC9E,UAAQ,KAAK,EAAE;;AAEjB,gBAAe;EACb,GAAG;EACH,sBAAsB;EACtB,qBAAqB;EACrB,eAAe;EACf,QAAQ;EACR,gBAAgB;EAChB,YAAY;EACb,CAAC,CAAC,MAAM,YAAY;EACrB;AAEJ,QACG,QAAQ,OAAO,CACf,YAAY,iCAAiC,CAC7C,eAAe,qBAAqB,kBAAkB,CACtD,OAAO,mBAAmB,qBAAqB,IAAI,CACnD,QAAQ,SAAS;AAChB,aAAY,KAAK,CAAC,MAAM,YAAY;EACpC;AAEJ,QAAQ,OAAO"}