@cellajs/cli 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cella-cli.ts","../src/cli.ts","../src/utils/colors.ts","../src/utils/env.ts","../src/utils/config.ts","../src/config/types.ts","../src/utils/errors.ts","../src/utils/managed-files.ts","../src/utils/module-territory.ts","../src/utils/display.ts","../package.json","../src/utils/overrides.ts","../src/utils/git.ts","../src/utils/manifest.ts","../src/utils/migration-notes.ts","../src/services/analyze.ts","../src/utils/diff.ts","../src/services/merge-engine.ts","../src/utils/cleanup.ts","../src/utils/versions.ts","../src/utils/cli-version.ts","../src/utils/upstream-overrides.ts","../src/services/analyze-core.ts","../src/services/migrate.ts","../src/services/audit.ts","../src/utils/audit-utils.ts","../src/utils/yaml.ts","../src/services/contributions.ts","../src/services/contrib-core.ts","../src/services/fork-utils.ts","../src/services/forks.ts","../src/services/sync.ts","../src/utils/gh.ts","../src/services/packages.ts","../src/services/package-usage.ts","../src/services/stats.ts","../src/utils/coverage-utils.ts","../src/services/stats-since.ts"],"sourcesContent":["#!/usr/bin/env tsx\n/**\n * Cella CLI main entry point: resolves the fork path, loads the config,\n * parses the command line and routes to the selected service.\n */\n\nimport { existsSync, statSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport process from 'node:process';\nimport { parseCli } from './cli';\nimport type { CellaCliConfig } from './config/types';\nimport { runAnalyze } from './services/analyze';\nimport { runAudit } from './services/audit';\nimport { runContributions } from './services/contributions';\nimport { runForks } from './services/forks';\nimport { runMigrate } from './services/migrate';\nimport { runStats } from './services/stats';\nimport { runBranchStats } from './services/stats-since';\nimport { runSyncCommand } from './services/sync';\nimport { registerSignalHandlers } from './utils/cleanup';\nimport pc from './utils/colors';\nimport { loadConfig } from './utils/config';\nimport { getEnv } from './utils/env';\nimport { errorMessage } from './utils/errors';\n\n/**\n * The fork path: the CELLA_FORK_PATH environment variable when set, else the current\n * working directory. A cwd inside cli/cella (pnpm --filter) resolves up to the fork root.\n */\nfunction getForkPath(): string {\n const envPath = getEnv('CELLA_FORK_PATH');\n if (envPath) {\n const resolved = resolve(envPath);\n if (!existsSync(resolved) || !statSync(resolved).isDirectory()) {\n throw new Error(`CELLA_FORK_PATH is not a valid directory: ${resolved}`);\n }\n return resolved;\n }\n\n let cwd = process.cwd();\n\n if (cwd.endsWith('/cli/cella') || cwd.endsWith('\\\\cli\\\\cella')) {\n cwd = resolve(cwd, '../..');\n }\n\n return cwd;\n}\n\n/**\n * Pre-flight check before running a service: verifies the path is a git repository.\n * The sync service cuts its own temporary branch from the trunk and owns its own\n * clean/resume state, so neither the current branch nor a dirty tree blocks a run.\n */\nfunction preflight(forkPath: string): void {\n if (!existsSync(join(forkPath, '.git'))) {\n throw new Error(`not a git repository: ${forkPath}`);\n }\n}\n\nfunction isHelpOrVersionRequest(): boolean {\n return (\n process.argv.slice(2).some((arg) => arg === '--help' || arg === '-h' || arg === '--version' || arg === '-v') ||\n process.argv[2] === 'help'\n );\n}\n\nasync function main(): Promise<void> {\n registerSignalHandlers();\n\n try {\n const forkPath = getForkPath();\n\n if (isHelpOrVersionRequest()) {\n await parseCli({ settings: { upstreamUrl: '', upstreamBranch: 'main' } } as CellaCliConfig, forkPath);\n return;\n }\n\n const userConfig = await loadConfig(forkPath);\n\n const config = await parseCli(userConfig, forkPath);\n\n // Services that operate on other fork paths skip the local-repo preflight.\n if (!['audit', 'forks', 'contributions', 'stats'].includes(config.service)) {\n preflight(forkPath);\n }\n\n switch (config.service) {\n case 'analyze': {\n await runAnalyze(config);\n break;\n }\n\n case 'sync': {\n await runSyncCommand(config);\n break;\n }\n\n case 'migrate': {\n await runMigrate(config);\n break;\n }\n\n case 'audit': {\n await runAudit(config);\n break;\n }\n\n case 'forks': {\n await runForks(config);\n break;\n }\n\n case 'contributions': {\n await runContributions(config);\n break;\n }\n\n case 'stats': {\n if (config.md && !config.since) throw new Error('--md goes with --since <ref>');\n if (config.since) {\n await runBranchStats(config.forkPath, { since: config.since, markdown: config.md, verbose: config.verbose });\n } else {\n await runStats(config);\n }\n break;\n }\n }\n\n console.info();\n } catch (error) {\n console.error();\n console.error(`${pc.red('✗')} ${errorMessage(error)}`);\n process.exit(1);\n }\n}\n\nmain();\n","/**\n * Command-line parsing: the service definitions, commander wiring, and the\n * interactive service menu, resolved into a RuntimeConfig.\n */\n\nimport process from 'node:process';\nimport { select } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport type { AnalyzeScope, CellaCliConfig, RuntimeConfig, SyncService } from './config/types';\nimport pc from './utils/colors';\nimport { isUpstreamRepo, resolveUpstream } from './utils/config';\nimport { MENU_DIVIDER, NAME, printHeader, setJsonMode, VERSION } from './utils/display';\nimport { printWarnings, validateOverrides } from './utils/overrides';\n\ntype CliServiceSelection = {\n service?: SyncService;\n options: CliOptionState;\n};\n\ntype CliOptionState = Pick<\n RuntimeConfig,\n | 'logFile'\n | 'verbose'\n | 'list'\n | 'json'\n | 'diff'\n | 'openDiff'\n | 'scope'\n | 'fork'\n | 'hard'\n | 'unpinned'\n | 'track'\n | 'ref'\n | 'keepConfig'\n | 'force'\n | 'checkOverrides'\n | 'coverage'\n | 'since'\n | 'md'\n | 'all'\n | 'show'\n | 'extract'\n | 'run'\n | 'script'\n | 'runArgs'\n | 'mark'\n>;\n\ntype MenuContext = {\n hasForks: boolean;\n isUpstreamRepo: boolean;\n};\n\ntype ServiceOptionDefinition = {\n flags: string;\n description: string;\n};\n\ntype ServiceDefinition = {\n name: SyncService;\n description: string;\n options?: ServiceOptionDefinition[];\n /** Arguments the service takes after its options, e.g. the ones `migrate --run` hands to the codemod. */\n operands?: ServiceOptionDefinition;\n includeInMenu?: (context: MenuContext) => boolean;\n};\n\n/** A string option's value, or undefined when it was not passed. */\nconst str = (value: unknown): string | undefined => (typeof value === 'string' ? value : undefined);\n\n/** A boolean flag's value: true only when it was passed. */\nconst flag = (value: unknown): boolean => value === true;\n\nfunction readOptions(opts: Record<string, unknown>, operands: string[] = []): CliOptionState {\n const scope = str(opts.scope);\n if (scope && scope !== 'all' && scope !== 'risk' && scope !== 'protected') {\n throw new Error(`invalid --scope '${scope}'. expected one of: all, risk, protected`);\n }\n const normalizedScope = scope as AnalyzeScope | undefined;\n\n const run = str(opts.run);\n if (operands.length > 0 && !run) {\n throw new Error(`unexpected argument '${operands[0]}'. arguments after the options only go with --run <id>`);\n }\n\n return {\n logFile: flag(opts.log),\n verbose: flag(opts.verbose),\n list: flag(opts.list),\n json: flag(opts.json),\n diff: str(opts.diff),\n openDiff: str(opts.openDiff),\n scope: normalizedScope,\n fork: str(opts.fork),\n hard: flag(opts.hard),\n unpinned: flag(opts.unpinned),\n track: opts.track === 'release' || opts.track === 'branch' ? opts.track : undefined,\n ref: str(opts.ref) || undefined,\n keepConfig: flag(opts.keepConfig),\n force: flag(opts.force),\n checkOverrides: flag(opts.checkOverrides),\n coverage: flag(opts.coverage),\n since: str(opts.since) || undefined,\n md: flag(opts.md),\n all: flag(opts.all),\n show: str(opts.show),\n extract: str(opts.extract),\n run,\n script: str(opts.script),\n runArgs: run ? operands : undefined,\n mark: Array.isArray(opts.mark) ? opts.mark.filter((id): id is string => typeof id === 'string') : undefined,\n };\n}\n\n// Option literals shared verbatim by more than one service.\nconst logOption: ServiceOptionDefinition = {\n flags: '--log',\n description: 'write complete file list to cella-sync.log',\n};\nconst jsonOption: ServiceOptionDefinition = {\n flags: '--json',\n description: 'machine-readable output for tooling/agents',\n};\nconst trackOption: ServiceOptionDefinition = {\n flags: '--track <mode>',\n description: 'override upstream tracking for this run: release|branch',\n};\nconst refOption: ServiceOptionDefinition = {\n flags: '--ref <ref>',\n description: 'pin the upstream commit for this run: sha, release tag or branch',\n};\nconst hardOption: ServiceOptionDefinition = {\n flags: '--hard',\n description: 'overwrite drifted files with upstream version (aggressive realignment)',\n};\nconst verboseOption: ServiceOptionDefinition = {\n flags: '-V, --verbose',\n description: 'show detailed output during operations',\n};\nconst forkOption: ServiceOptionDefinition = {\n flags: '--fork <name>',\n description: 'pre-select a fork by name (skips the fork selection prompt)',\n};\n\nconst serviceDefinitions: ServiceDefinition[] = [\n {\n name: 'analyze',\n description: 'dry run to see what would change on sync',\n options: [\n logOption,\n { flags: '--list', description: 'non-interactive output for tooling (one file per line)' },\n jsonOption,\n { flags: '--scope <scope>', description: 'analyze scope for --list/--json: all|risk|protected' },\n trackOption,\n refOption,\n { flags: '--diff <path>', description: 'print the unified diff for one file, then exit' },\n { flags: '--open-diff <path>', description: 'open a browser diff for one file, then exit' },\n ],\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'sync',\n description: 'merge upstream changes onto a fresh branch, sync package.json and open a squash-merge PR',\n options: [\n logOption,\n hardOption,\n { flags: '--unpinned', description: 'ignore pinned files (except package.json) to resurface upstream changes' },\n trackOption,\n refOption,\n { flags: '--keep-config', description: 'merge with your sync config as it stands when upstream changed its own' },\n ],\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'migrate',\n description: 'list the upstream migration notes this app has not handled yet',\n options: [\n { flags: '--all', description: 'list every upstream note, handled or not' },\n jsonOption,\n { flags: '--show <id>', description: \"print one note's README\" },\n { flags: '--extract <id>', description: \"write one note's folder under node_modules/.cache to run its codemod\" },\n { flags: '--run <id>', description: \"run one note's codemod; files identical to upstream stay as they are\" },\n { flags: '--script <file>', description: 'with --run: the script to run when the note folder holds several' },\n { flags: '--mark <ids...>', description: 'record notes as handled' },\n ],\n operands: {\n flags: '[codemodArgs...]',\n description: \"with --run, after `--`: arguments for the codemod (default: inventory and the note's roots)\",\n },\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'audit',\n description: 'check for outdated packages and vulnerabilities',\n options: [\n { flags: '--list', description: 'skip interactive update prompts after printing audit results' },\n { flags: '--force', description: 'bypass pnpm metadata cache for fresh registry data' },\n { flags: '--check-overrides', description: 'check which pnpm.overrides are still needed' },\n ],\n },\n {\n name: 'forks',\n description: 'run normal sync inside local fork repositories',\n options: [\n forkOption,\n { flags: '--log', description: 'write complete file list to cella-sync.log for each synced fork' },\n verboseOption,\n hardOption,\n {\n flags: '--keep-config',\n description: \"merge with the fork's sync config as it stands when upstream changed its own\",\n },\n ],\n includeInMenu: (context) => context.hasForks,\n },\n {\n name: 'contributions',\n description: 'pull and adopt changes from local forks',\n options: [\n forkOption,\n { flags: '--list', description: 'non-interactive output for tooling (tab-separated rows)' },\n jsonOption,\n { flags: '--diff <path>', description: 'print the unified diff for one contributed file, then exit' },\n ],\n includeInMenu: (context) => context.hasForks,\n },\n {\n name: 'stats',\n description: 'count files by category and workspace package',\n options: [\n verboseOption,\n { flags: '--coverage', description: 'regenerate test coverage before showing the stats summary' },\n {\n flags: '--since <ref>',\n description: 'count what the current branch changed since it left <ref>, by kind of file',\n },\n { flags: '--md', description: 'with --since: print the table as markdown for a pull request description' },\n ],\n },\n];\n\nfunction getMenuContext(userConfig: CellaCliConfig, forkPath: string): MenuContext {\n return {\n hasForks: (userConfig.forks?.length ?? 0) > 0,\n isUpstreamRepo: isUpstreamRepo(forkPath),\n };\n}\n\nfunction buildServiceChoices(context: MenuContext) {\n // Pad service labels to align descriptions (longest label is 'contributions').\n const label = (name: string) => name.padEnd(14);\n const baseChoices = serviceDefinitions\n .filter((service) => service.includeInMenu?.(context) ?? true)\n .map((service) => ({\n value: service.name,\n name: `${label(service.name)}${pc.dim(service.description)}`,\n }));\n\n return [\n ...baseChoices,\n { type: 'separator' as const, separator: MENU_DIVIDER },\n { value: 'exit' as const, name: pc.red(`${label('exit')}${pc.dim('quit without doing anything')}`) },\n ];\n}\n\nfunction addServiceCommand(\n program: Command,\n definition: ServiceDefinition,\n setSelection: (selection: CliServiceSelection) => void,\n) {\n const command = program.command(definition.name).description(definition.description);\n\n for (const option of definition.options ?? []) {\n command.option(option.flags, option.description);\n }\n if (definition.operands) command.argument(definition.operands.flags, definition.operands.description);\n\n // Commander hands declared arguments to the action before the options\n command.action((...args: unknown[]) => {\n const operands = definition.operands ? (args[0] as string[]) : [];\n const opts = (definition.operands ? args[1] : args[0]) as Record<string, unknown>;\n setSelection({\n service: definition.name,\n options: readOptions(opts, operands),\n });\n });\n}\n\nfunction buildProgram(setSelection: (selection: CliServiceSelection) => void): Command {\n const program = new Command(NAME)\n .name('cella')\n .version(VERSION, '-v, --version', 'output the current version')\n .usage('[service] [options]')\n .helpOption('-h, --help', 'display help for a command')\n .showHelpAfterError()\n .addHelpText(\n 'after',\n [\n '',\n 'Examples:',\n ' $ cella analyze',\n ' $ cella analyze --json --scope risk',\n ' $ cella analyze --open-diff frontend/src/routes/index.tsx',\n ' $ cella sync --hard',\n ' $ cella sync --unpinned',\n ' $ cella sync --track branch',\n ' $ cella sync --ref 4f7d87c',\n ' $ cella migrate --run 20261001T2116-tailwind-class-conventions -- rewrite frontend/src',\n ' $ cella migrate --mark 20261002T0614-config-switch',\n ' $ cella audit --check-overrides',\n ' $ cella stats --since origin/main --md',\n ' $ cella contributions --fork raak --json',\n ].join('\\n'),\n );\n\n for (const definition of serviceDefinitions) {\n addServiceCommand(program, definition, setSelection);\n }\n\n return program;\n}\n\nfunction parseCommandLine(argv: string[]): CliServiceSelection {\n if (argv.length <= 2) {\n return { options: readOptions({}) };\n }\n\n let selection: CliServiceSelection = { options: readOptions({}) };\n const program = buildProgram((nextSelection) => {\n selection = nextSelection;\n });\n\n program.parse(argv);\n return selection;\n}\n\nasync function promptForService(userConfig: CellaCliConfig, forkPath: string): Promise<SyncService> {\n const selected = await select<SyncService | 'exit'>({\n message: 'choose a service:',\n choices: buildServiceChoices(getMenuContext(userConfig, forkPath)),\n loop: false,\n });\n\n if (selected === 'exit') {\n console.info(pc.dim('exiting...'));\n console.info();\n process.exit(0);\n }\n\n console.info();\n return selected;\n}\n\nfunction buildRuntimeConfig(\n userConfig: CellaCliConfig,\n forkPath: string,\n selection: CliServiceSelection,\n): RuntimeConfig {\n // Static fallback ref (branch tip). For release tracking the merge engine resolves\n // the concrete release-tag ref after fetching and writes it back to config.upstreamRef.\n const { branchRef } = resolveUpstream(userConfig.settings);\n\n return {\n ...userConfig,\n forkPath,\n upstreamRef: branchRef,\n service: selection.service ?? 'analyze',\n ...selection.options,\n };\n}\n\nexport async function parseCli(userConfig: CellaCliConfig, forkPath: string): Promise<RuntimeConfig> {\n const selection = parseCommandLine(process.argv);\n\n // In machine-output modes (--json, --diff, --list, --md), reserve stdout for the payload/patch/rows/table\n // and route all human output (header, warnings, spinner) to stderr. Audit's --list only skips\n // its interactive prompts; its report is the human output and stays on stdout.\n const machineList = selection.options.list && selection.service !== 'audit';\n if (selection.options.json || selection.options.diff || selection.options.md || machineList) setJsonMode(true);\n\n printHeader();\n\n // Ignored entries are validated against the upstream branch as last fetched.\n const warnings = await validateOverrides(userConfig, forkPath, resolveUpstream(userConfig.settings).branchRef);\n if (warnings.length > 0) {\n printWarnings(warnings);\n console.info();\n }\n\n if (!selection.service) {\n selection.service = await promptForService(userConfig, forkPath);\n }\n\n return buildRuntimeConfig(userConfig, forkPath, selection);\n}\n","import process from 'node:process';\nimport { styleText } from 'node:util';\nimport { hasEnv } from './env';\n\ntype ColorStyle = 'blue' | 'bold' | 'cyan' | 'dim' | 'gray' | 'green' | 'magenta' | 'red' | 'white' | 'yellow';\n\nfunction colorsEnabled(): boolean {\n if (hasEnv('NO_COLOR')) return false;\n if (hasEnv('FORCE_COLOR')) return true;\n return !!process.stdout.isTTY;\n}\n\nfunction applyStyle(style: ColorStyle, text: string): string {\n if (!colorsEnabled()) return text;\n return styleText(style, text, { validateStream: false });\n}\n\nconst pc = {\n blue: (text: string) => applyStyle('blue', text),\n bold: (text: string) => applyStyle('bold', text),\n cyan: (text: string) => applyStyle('cyan', text),\n dim: (text: string) => applyStyle('dim', text),\n gray: (text: string) => applyStyle('gray', text),\n green: (text: string) => applyStyle('green', text),\n magenta: (text: string) => applyStyle('magenta', text),\n red: (text: string) => applyStyle('red', text),\n white: (text: string) => applyStyle('white', text),\n yellow: (text: string) => applyStyle('yellow', text),\n};\n\nexport default pc;\n","import process from 'node:process';\n\n/**\n * Centralized environment access for CLI/runtime integration points.\n */\nexport function getEnv(name: string): string | undefined {\n // biome-ignore lint/style/noProcessEnv: This module centralizes intentional CLI environment access.\n return process.env[name];\n}\n\n/** Whether the variable is set at all, even to an empty string. */\nexport function hasEnv(name: string): boolean {\n // biome-ignore lint/style/noProcessEnv: This module centralizes intentional CLI environment access.\n return name in process.env;\n}\n\n/** A mutable copy of the full environment, for passing to child processes. */\nexport function getEnvSnapshot(): NodeJS.ProcessEnv {\n // biome-ignore lint/style/noProcessEnv: This module centralizes intentional CLI environment access.\n return { ...process.env };\n}\n","/**\n * Config loading utilities for sync CLI.\n *\n * Shared between main entry point and forks service.\n */\n\nimport { existsSync, readFileSync, realpathSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { z } from 'zod';\nimport { type CellaCliConfig, cellaConfigSchema, type PackageJsonSyncKey, type SyncSettings } from '../config/types';\nimport { errorMessage } from './errors';\nimport { CONFIG_FILE } from './managed-files';\nimport { resolveAppModuleFolders } from './module-territory';\n\n/** Default git remote name used to point at the upstream repository. */\nexport const DEFAULT_UPSTREAM_REMOTE = 'cella-upstream';\n\n/** Default branch used when a config omits `upstreamBranch`; also cella's fork-compare base. */\nexport const DEFAULT_BRANCH = 'main';\n\n/**\n * Prefix for the temporary integration branches that `cella sync` cuts per run\n * (e.g. `cella/sync/20260702-1430`).\n *\n * The three-segment shape (`cella/sync/<stamp>`) means it can never collide with a real branch\n * named `cella` or `cella/sync`.\n */\nexport const DEFAULT_SYNC_PREFIX = 'cella/sync';\n\n/**\n * Default trunk branch that `cella sync` cuts from and opens PRs into.\n */\nconst DEFAULT_RELEASE_BASE = 'main';\n\n/** The package.json keys that sync when a config omits `packageJsonSync`. */\nexport const DEFAULT_PACKAGE_JSON_SYNC: PackageJsonSyncKey[] = ['dependencies', 'devDependencies'];\n\n/** Whether the repo at `repoPath` is upstream cella itself (its root package.json is named 'cella'). */\nexport function isUpstreamRepo(repoPath: string): boolean {\n return JSON.parse(readFileSync(join(repoPath, 'package.json'), 'utf8')).name === 'cella';\n}\n\n/**\n * Whether `branch` is one of the temporary integration branches `cella sync` cuts, i.e. it\n * lives under the internal `cella/sync/` namespace.\n */\nexport function isTemporarySyncBranch(branch: string): boolean {\n return branch.startsWith(`${DEFAULT_SYNC_PREFIX}/`);\n}\n\n/**\n * Resolve the trunk branch `cella sync` cuts the temporary branch from and PRs into.\n */\nexport function resolveReleaseBase(settings: SyncSettings): string {\n return settings.releaseBase ?? DEFAULT_RELEASE_BASE;\n}\n\n/**\n * Build a unique temporary integration branch name for a sync cycle, e.g.\n * `cella/sync/20260702-1430`. Cutting a fresh branch per cycle keeps each PR\n * scoped to that sync's upstream delta.\n */\nexport function buildTemporarySyncBranch(): string {\n const now = new Date();\n const pad = (n: number) => String(n).padStart(2, '0');\n const stamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}`;\n return `${DEFAULT_SYNC_PREFIX}/${stamp}`;\n}\n\n/**\n * Resolve the upstream tracking plan from sync settings.\n *\n * Single source of truth shared by the CLI entry point and the merge engine.\n * The concrete ref for release tracking (latest tag) can only be resolved after\n * fetching, so this returns a plan; the merge engine turns it into a ref.\n *\n * - `track`: 'release' (default) syncs to the latest release tag; 'branch' follows the tip.\n * - `branchRef`: `<DEFAULT_UPSTREAM_REMOTE>/<branch>`, the branch-track ref and static fallback.\n */\nexport function resolveUpstream(settings: SyncSettings): {\n track: 'release' | 'branch';\n branchRef: string;\n} {\n const track = settings.upstreamTrack ?? 'release';\n const branch = settings.upstreamBranch ?? DEFAULT_BRANCH;\n const branchRef = `${DEFAULT_UPSTREAM_REMOTE}/${branch}`;\n return { track, branchRef };\n}\n\n/**\n * Load cella/cella.config.ts from a fork/repo path.\n */\nexport async function loadConfig(forkPath: string): Promise<CellaCliConfig> {\n const configPath = join(forkPath, CONFIG_FILE);\n\n if (!existsSync(configPath)) {\n throw new Error(`config file not found: ${configPath}`);\n }\n\n // Resolve symlinks and validate path stays within fork directory\n const realConfigPath = realpathSync(configPath);\n const realForkPath = realpathSync(resolve(forkPath));\n if (!realConfigPath.startsWith(`${realForkPath}/`)) {\n throw new Error('config path resolves outside fork directory');\n }\n\n let configModule: { default?: unknown };\n try {\n configModule = await import(realConfigPath);\n } catch (error) {\n // Syntax/runtime errors while evaluating the config must fail closed: a config that\n // cannot be loaded means sync protections (ignored/pinned) are unknown.\n throw new Error(`failed to load ${configPath}: ${errorMessage(error)}`);\n }\n\n // Strict schema validation.\n const result = cellaConfigSchema.safeParse(configModule.default);\n if (!result.success) {\n throw new Error(`invalid ${configPath}:\\n${z.prettifyError(result.error)}`);\n }\n const config: CellaCliConfig = result.data;\n\n // Auto-derive fork-owned module folders (modules declaring `owner: 'app'`) and merge\n // them into ignored. This keeps app modules as fork territory: upstream never\n // adds/modifies/deletes them during sync, and the contributions service never offers\n // them back upstream. Derived entries always exist (they come from real files), so\n // config validation never warns about them.\n const appModuleFolders = resolveAppModuleFolders(realForkPath);\n if (appModuleFolders.length > 0) {\n const existing = config.overrides?.ignored ?? [];\n config.overrides = {\n ...config.overrides,\n ignored: [...new Set([...existing, ...appModuleFolders])],\n };\n }\n\n return config;\n}\n","/**\n * Configuration types: the public cella/cella.config.ts surface, its runtime\n * schema, and the internal types the services share.\n */\n\nimport { z } from 'zod';\n\n// Public API for cella/cella.config.ts.\n\nconst PACKAGE_JSON_SYNC_KEYS = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n 'scripts',\n 'engines',\n 'packageManager',\n 'overrides',\n 'exports',\n 'pnpm',\n] as const;\n\n/** Valid package.json keys that can be synced */\nexport type PackageJsonSyncKey = (typeof PACKAGE_JSON_SYNC_KEYS)[number];\n\n/**\n * Sync settings: all configurable options for the sync CLI.\n * Hover over each property for documentation.\n */\nexport interface SyncSettings {\n /** Upstream repository URL (e.g., 'git@github.com:cellajs/cella.git') */\n upstreamUrl: string;\n\n /**\n * Upstream branch, used for `upstreamTrack: 'branch'` and for GitHub file links.\n * Defaults to 'main'.\n */\n upstreamBranch?: string;\n\n /**\n * How to track upstream cella. Defaults to 'release'.\n * - 'release' (default): sync to a published cella release tag (`0.18.1`, with or without `v`). Stable and\n * reviewable: each bump maps to a changelog. Uses the latest release.\n * - 'branch': follow the bleeding-edge tip of `upstreamBranch`. For cella\n * maintainers and forks doing active development on top of unreleased changes.\n */\n upstreamTrack?: 'release' | 'branch';\n\n /**\n * Trunk branch that `pnpm cella sync` cuts the temporary branch from and that you open the\n * squash-merge PR into. Defaults to 'main'. Cutting fresh from trunk each cycle keeps every\n * PR limited to that cycle's upstream delta (no accumulation) and `main` linear.\n */\n releaseBase?: string;\n\n /** Which package.json keys to sync (default: ['dependencies', 'devDependencies']). `type` always syncs. */\n packageJsonSync?: PackageJsonSyncKey[];\n\n /** Automatic package.json sync after the sync service completes (default: true). Set to false to turn it off. */\n syncWithPackages?: boolean;\n\n /**\n * How to link files in CLI output.\n * - 'commit' (default): Link to the commit that changed the file on GitHub.\n * - 'file': Link to the file in the repo at the upstream branch on GitHub.\n * - 'local': Deprecated (the upstream view worktree was replaced by browser diffs); treated as 'file'.\n */\n fileLinkMode?: 'commit' | 'file' | 'local';\n}\n\n/**\n * Configuration for a downstream fork repository that cella interacts with.\n *\n * Cella is the upstream/source-of-truth. For each fork it can:\n * - pull contributions FROM the fork's `pullBranch` (contributions service)\n * - run the normal temporary-branch sync flow inside the fork (forks service)\n */\nexport interface ForkConfig {\n /** Display name for the fork (also used as the contrib/<name> branch slug) */\n name: string;\n /** Local path to the fork repository (relative to this config or absolute) */\n localPath: string;\n /**\n * Git remote URL of the fork (e.g. 'git@github.com:org/fork.git').\n * When set, the contributions service fetches the fork's `pullBranch` from this\n * remote (the authoritative committed ref), so the comparison does not depend on\n * the local checkout being up to date. The local clone is still used to read the\n * fork's owned-folder territory when available.\n */\n remoteUrl?: string;\n /** Fork branch that cella pulls contributions from (contributions service) */\n pullBranch: string;\n}\n\n/** User-configurable sync options for cella/cella.config.ts. */\nexport interface CellaCliConfig {\n /** Core sync settings */\n settings: SyncSettings;\n\n /**\n * File overrides for controlling sync behavior per folder/file.\n */\n overrides?: {\n /**\n * Paths the fork fully owns: never synced (existing or new).\n * Exact paths or directory prefixes, not globs: 'bench' matches 'bench/' and\n * everything under it, 'README.md' matches that exact file.\n * Local territory: upstream cannot add, modify, or delete anything under these.\n */\n ignored?: string[];\n\n /**\n * Paths pinned to the fork: fork wins on conflicts.\n * Exact paths or directory prefixes, not globs: 'bench' matches 'bench/' and\n * everything under it, 'README.md' matches that exact file.\n * Non-conflicting upstream changes merge normally.\n * If fork deleted a pinned file, deletion is respected.\n */\n pinned?: string[];\n };\n\n /**\n * Downstream fork repositories that cella interacts with (for upstream template repos).\n * When configured, the 'forks' and 'contributions' services appear in the CLI menu.\n */\n forks?: ForkConfig[];\n}\n\n/**\n * Helper function for defining cella/cella.config.ts with type checking.\n */\nexport function defineConfig(config: CellaCliConfig): CellaCliConfig {\n return config;\n}\n\n/**\n * Strict runtime schema mirroring {@link CellaCliConfig}.\n *\n * The TS interfaces above stay the source of truth (and keep their hover docs for\n * config authors). This schema is what's enforced at load time: `.strict()` rejects\n * unknown keys, so a typo like `ignoredFolders` for `ignored` fails closed; a silent\n * fallback would drop sync protection (tsx does not typecheck the config).\n *\n * The `satisfies z.ZodType<CellaCliConfig>` assertion keeps schema and interface in\n * lockstep: if either drifts (a renamed/removed/mis-typed field), TypeScript errors here.\n */\nexport const cellaConfigSchema = z\n .object({\n settings: z\n .object({\n upstreamUrl: z.string().min(1),\n upstreamBranch: z.string().min(1).optional(),\n upstreamTrack: z.enum(['release', 'branch']).optional(),\n releaseBase: z.string().min(1).optional(),\n packageJsonSync: z.array(z.enum(PACKAGE_JSON_SYNC_KEYS)).optional(),\n syncWithPackages: z.boolean().optional(),\n fileLinkMode: z.enum(['commit', 'file', 'local']).optional(),\n })\n .strict(),\n overrides: z\n .object({\n ignored: z.array(z.string()).optional(),\n pinned: z.array(z.string()).optional(),\n })\n .strict()\n .optional(),\n forks: z\n .array(\n z\n .object({\n name: z.string().min(1),\n localPath: z.string().min(1),\n remoteUrl: z.string().optional(),\n pullBranch: z.string().min(1),\n })\n .strict(),\n )\n .optional(),\n })\n .strict() satisfies z.ZodType<CellaCliConfig>;\n\n// Internal types for the services.\n\n/** Sync services available in the CLI */\nexport type SyncService = 'analyze' | 'sync' | 'migrate' | 'audit' | 'forks' | 'contributions' | 'stats';\n\n/** Analyze output scope for interactive and machine-readable flows */\nexport type AnalyzeScope = 'all' | 'risk' | 'protected';\n\n/** Runtime configuration with all resolved values */\nexport interface RuntimeConfig extends CellaCliConfig {\n /** Resolved fork repository path */\n forkPath: string;\n\n /** Full upstream remote ref (e.g., 'cella-upstream/development') */\n upstreamRef: string;\n\n /** Selected sync service */\n service: SyncService;\n\n /** Write full file list to log file */\n logFile: boolean;\n\n /** Non-interactive list output (for LLM/agent usage) */\n list: boolean;\n\n /** Machine-readable JSON output (for tooling/agent usage) */\n json: boolean;\n\n /** Print the unified diff for one file, then exit (analyze and contributions; for tooling/agents) */\n diff?: string;\n\n /** Open a browser diff for one file, then exit (analyze) */\n openDiff?: string;\n\n /** Scope of files returned in analyze list/json output */\n scope?: AnalyzeScope;\n\n /** Show verbose output */\n verbose: boolean;\n\n /** Pre-selected fork name (skips fork selection prompt) */\n fork?: string;\n\n /** Overwrite drifted files with upstream version (aggressive realignment) */\n hard?: boolean;\n\n /**\n * Disable pinned entries (cella/cella.config.ts overrides.pinned) for this sync so upstream\n * versions surface as behind/diverged. Managed files stay pinned because cella\n * handles them separately. Like --hard, uses the natural merge-base to resurface\n * full upstream history.\n */\n unpinned?: boolean;\n\n /**\n * Override upstream tracking for this run (analyze/sync), ignoring `settings.upstreamTrack`.\n * 'branch' follows the upstream branch tip (bleeding edge); 'release' uses a release tag.\n */\n track?: 'release' | 'branch';\n\n /**\n * Pin the upstream ref for this run (analyze/sync), overriding `track`: a commit sha, a release\n * tag or an upstream branch name. Must be on the upstream branch or in an upstream release.\n */\n ref?: string;\n\n /**\n * Merge with the fork's sync config as it stands (sync service). Without it, a new merge stops\n * before anything changes when upstream changed its own `overrides` or `packageJsonSync` in ways\n * the fork config does not follow.\n */\n keepConfig?: boolean;\n\n /** Bypass pnpm metadata cache for fresh registry data (audit service) */\n force?: boolean;\n\n /** Check which pnpm.overrides are still needed (audit service) */\n checkOverrides?: boolean;\n\n /** Regenerate test coverage before showing the stats summary (stats service) */\n coverage?: boolean;\n\n /** Count what the current branch changed since it left this ref, by kind of file (stats service) */\n since?: string;\n\n /** Print the `since` table as markdown for a pull request description (stats service) */\n md?: boolean;\n\n /** List every upstream migration note, not only the open ones (migrate service) */\n all?: boolean;\n\n /** Print one migration note's README (migrate service) */\n show?: string;\n\n /** Write one migration note's folder where its codemod can run (migrate service) */\n extract?: string;\n\n /** Run one migration note's codemod, keeping files identical to upstream as they are (migrate service) */\n run?: string;\n\n /** The script to run with `run`, when the note folder holds more than one (migrate service) */\n script?: string;\n\n /** Arguments after `--`, passed to the codemod as given (migrate service, with `run`) */\n runArgs?: string[];\n\n /** Migration note ids to record as handled (migrate service) */\n mark?: string[];\n}\n\n/** File status after analysis */\nexport type FileStatus =\n | 'identical' // No changes needed\n | 'ahead' // Fork is ahead, protected (pinned/ignored)\n | 'local' // Local file (never existed upstream)\n | 'drifted' // Fork is ahead, NOT protected (at risk)\n | 'behind' // Upstream has changes to sync\n | 'diverged' // Both changed, will merge\n | 'pinned' // Fork wins on conflict\n | 'ignored' // Excluded from sync entirely\n | 'deleted' // Fork deleted, will stay deleted\n | 'renamed'; // Upstream renamed file\n\n/** Statuses the sync applies changes for: a staged sync holds at least one file with one of these. */\nexport const SYNC_APPLIED_STATUSES: readonly FileStatus[] = ['behind', 'diverged', 'renamed', 'ignored', 'pinned'];\n\n/** Commit metadata for a single log entry */\nexport interface CommitRangeEntry {\n hash: string;\n message: string;\n date: string;\n}\n\n/** Analyzed file with status and metadata */\nexport interface AnalyzedFile {\n path: string;\n status: FileStatus;\n /** True if file is in ignored list */\n isIgnored: boolean;\n /** True if file is in pinned list */\n isPinned: boolean;\n /** True if file exists in fork */\n existsInFork: boolean;\n /** True if file exists in upstream */\n existsInUpstream: boolean;\n /** Relative date when file was last changed (since merge-base) */\n changedAt?: string;\n /** Unix epoch seconds of the last change, for sorting */\n changedTs?: number;\n /** Short commit hash of the last change */\n changedCommit?: string;\n /** For diverged files: relative date of upstream change */\n upstreamChangedAt?: string;\n /** For diverged files: Unix epoch seconds of the upstream change, for sorting */\n upstreamChangedTs?: number;\n /** For diverged files: short commit hash of the upstream change */\n upstreamCommit?: string;\n /** For renamed files: the original path before rename */\n renamedFrom?: string;\n /**\n * Protected (pinned/ignored) files only: both sides changed since the merge-base. The fork\n * side wins whole-file, so upstream's changes to this path are dropped by the sync.\n */\n upstreamChanged?: boolean;\n /** For `upstreamChanged` files: lines upstream changed since the merge-base (undefined for binary) */\n upstreamChangedLines?: number;\n /**\n * Ignored files only: upstream changed, added or deleted the file since the merge-base and the\n * fork did not touch it. Ignored paths never sync, so without this flag the change stays unseen\n * (new config keys, version bumps). Managed files and generated output (`isGeneratedFile`) are\n * never flagged.\n */\n upstreamOnly?: boolean;\n /**\n * Pinned `ahead` files only: lines present upstream but absent from the fork (undefined for\n * binary). Independent of the sync point, so it also shows upstream content dropped by an\n * earlier sync, or removed on purpose; only a diff can tell.\n */\n upstreamLinesAbsent?: number;\n}\n\n/** Summary counts by status */\nexport interface AnalysisSummary {\n /** Changed package/config files that are handled separately from normal sync categories */\n managed: number;\n identical: number;\n ahead: number;\n local: number;\n drifted: number;\n behind: number;\n diverged: number;\n pinned: number;\n ignored: number;\n deleted: number;\n renamed: number;\n}\n\n/** Merge result from merge-engine */\nexport interface MergeResult {\n success: boolean;\n /** Upstream branch name for file links */\n upstreamBranch?: string;\n /** Resolved concrete upstream ref that was merged (branch ref or release tag ref) */\n upstreamRef?: string;\n /** Upstream release tag synced (when tracking releases) */\n upstreamTag?: string;\n files: AnalyzedFile[];\n summary: AnalysisSummary;\n conflicts: string[];\n /** Upstream GitHub URL base for commit links */\n upstreamGitHubUrl?: string;\n /** Upstream commit info */\n upstreamCommit?: CommitRangeEntry;\n /** Commits included in this sync range (oldest-first when rendered) */\n upstreamCommits?: CommitRangeEntry[];\n /** Files that were auto-merged by git (diverged without remaining conflicts) */\n autoMergedFiles?: string[];\n /**\n * Protected (pinned/ignored) files resolved to the fork side although upstream also changed\n * them: upstream's hunks were dropped, not merged. Review each against upstream.\n */\n protectedConflicts?: string[];\n /** `protectedConflicts` grouped by the `pinned` or `ignored` entry they fall under, for one diff hint per entry. */\n protectedUpstreamChanges?: ProtectedUpstreamGroup[];\n /** Pasteable `<merge-base>..<upstream>` range of short SHAs, for `git diff` hints. */\n upstreamDiffRange?: string;\n /** How upstream's own sync config changed since the merge-base, where the fork config does not follow. */\n upstreamOverrides?: UpstreamOverridesReport;\n /** Files flagged `upstreamOnly`, grouped by the `ignored` entry they fall under (config order). */\n ignoredUpstreamChanges?: IgnoredUpstreamGroup[];\n /**\n * Upstream migration notes: how many the incoming ref holds, which ones upstream added since the\n * sync point, and how many stay open in the fork once those are added.\n */\n migrationNotes?: { total: number; arrived: string[]; open: number };\n}\n\n/** Entries of one sync config list (`pinned`, `ignored` or `packageJsonSync`) that the fork config does not mirror. */\nexport interface OverrideListChanges {\n /** Entries upstream added since the merge-base that the fork list lacks. */\n added: string[];\n /** Entries upstream removed since the merge-base that the fork list still carries. */\n removed: string[];\n}\n\n/**\n * Upstream sync config changes the fork should review. The sync config is managed (never merged),\n * so new upstream `pinned`/`ignored` entries and `packageJsonSync` keys only reach the fork by\n * hand. `unreadable` means upstream's config was missing or unparsable at one side (`base` =\n * merge-base, `incoming` = upstream ref), so nothing was compared.\n */\nexport type UpstreamOverridesReport =\n | {\n kind: 'changes';\n pinned: OverrideListChanges;\n ignored: OverrideListChanges;\n packageJsonSync: OverrideListChanges;\n }\n | { kind: 'unreadable'; side: 'base' | 'incoming' };\n\n/** Protected paths upstream also changed, under one `pinned` or `ignored` entry. */\nexport interface ProtectedUpstreamGroup {\n /** The `pinned` or `ignored` entry the paths fall under; the path itself when no entry covers it (a managed file). */\n entry: string;\n /** Paths under the entry, sorted. */\n paths: string[];\n}\n\n/** Upstream-only changes under one `ignored` entry. */\nexport interface IgnoredUpstreamGroup {\n /** The `ignored` entry (configured or derived from an app-owned module) the files fall under. */\n entry: string;\n /** Changed paths under the entry, sorted. */\n paths: string[];\n /** Paths the fork lacks (new upstream files). */\n added: number;\n /** Paths upstream deleted (the fork keeps them). */\n deleted: number;\n}\n","/**\n * Error helpers for sync CLI.\n */\n\n/** The message of an unknown thrown value: an Error's message, anything else via String(). */\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","/**\n * Files that cella manages outside the normal file sync categories.\n */\n\n/** Sync config path, relative to the fork repo root. Fork-owned, never synced from upstream. */\nexport const CONFIG_FILE = 'cella/cella.config.ts';\n\n/**\n * Legacy config path, before the config moved into `cella/`. Kept so the one sync that\n * performs the root→`cella/` move still recognizes the file as managed at its old path:\n * during that move git may present the change under the old path (or as a delete+add that\n * skips rename detection), and an exact match on the new path alone would let it fall\n * through to a normal (conflicting) merge. Harmless to match forever; it can only appear\n * on the move sync of a not-yet-migrated fork.\n */\nexport const LEGACY_CONFIG_FILE = 'cella.config.ts';\n\n/** Every path the sync config has lived at. Compared against to always-ignore across the move. */\nexport const CONFIG_FILE_PATHS: readonly string[] = [CONFIG_FILE, LEGACY_CONFIG_FILE];\n\n/**\n * Check if a file path is the sync config, at its current or legacy (pre-`cella/`) path.\n */\nexport function isConfigFile(filePath: string): boolean {\n return CONFIG_FILE_PATHS.includes(filePath);\n}\n\n/**\n * Check if a file path is a package.json file.\n */\nexport function isPackageJson(filePath: string): boolean {\n return filePath === 'package.json' || filePath.endsWith('/package.json');\n}\n\n/**\n * Check if a file path is generated output a fork regenerates itself: a `gen` path segment\n * (`sdk/gen/...`) or a `.gen.` file name (`routeTree.gen.ts`, `compose.gen.yml`). Upstream's\n * copy is never adopted, so upstream changes to it are not worth reporting.\n */\nexport function isGeneratedFile(filePath: string): boolean {\n const segments = filePath.split('/');\n return segments.includes('gen') || (segments.at(-1) ?? '').includes('.gen.');\n}\n\n/**\n * Check if a file path is managed by cella outside normal file sync categories.\n */\nexport function isManagedFile(filePath: string): boolean {\n return isPackageJson(filePath) || filePath === 'pnpm-lock.yaml' || isConfigFile(filePath);\n}\n","/**\n * Static analysis of module ownership for sync CLI.\n *\n * Each module declares ownership via a `registerModule`, `defineBackendModule`, or\n * `defineFrontendModule` call ({ owner, ... }) in its `*-module.ts` file.\n * Modules with `owner: 'app'` are fork-specific: their\n * source folders, plus matching frontend static asset folders when present, are\n * fork territory and must never be added, modified, or deleted by upstream during\n * sync, nor offered back upstream by the contributions service.\n *\n * Parsing is syntax-only (no type-checker), so it is fast and tolerant of\n * formatting, comments, and property order. Built on ts-morph so the same\n * project/AST approach can be reused for other source-introspection tasks.\n */\n\nimport { existsSync } from 'node:fs';\nimport { basename, join, relative, sep } from 'node:path';\nimport { Project, SyntaxKind } from 'ts-morph';\n\n/** Glob patterns (relative to repo root) for module definition files. */\nconst MODULE_FILE_GLOBS = [\n 'backend/src/modules/*/*-module.ts',\n 'frontend/src/modules/*/*-module.ts',\n 'frontend/src/modules/*/*-module.tsx',\n];\n\n/** Call names that register a module and carry its `owner` in the first argument. */\nconst MODULE_REGISTER_CALLS = new Set(['registerModule', 'defineBackendModule', 'defineFrontendModule']);\nconst FRONTEND_STATIC_ROOT = 'frontend/public/static';\n\n/**\n * Read the string value of an object literal's `owner` property, if present.\n */\nfunction readOwner(call: import('ts-morph').CallExpression): string | undefined {\n const arg = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);\n const initializer = arg?.getProperty('owner')?.asKind(SyntaxKind.PropertyAssignment)?.getInitializer();\n return initializer?.asKind(SyntaxKind.StringLiteral)?.getLiteralValue();\n}\n\n/**\n * Scan a repository for module territory owned by the app (`owner: 'app'`).\n *\n * @param repoPath - Absolute path to the repository root to scan.\n * @returns Repo-relative folder paths (POSIX separators), deduplicated.\n */\nexport function resolveAppModuleFolders(repoPath: string): string[] {\n const project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipFileDependencyResolution: true,\n skipLoadingLibFiles: true,\n });\n\n const sourceFiles = project.addSourceFilesAtPaths(MODULE_FILE_GLOBS.map((glob) => `${repoPath}/${glob}`));\n\n const folders = new Set<string>();\n const moduleNames = new Set<string>();\n\n for (const sourceFile of sourceFiles) {\n const ownsApp = sourceFile\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .some((call) => MODULE_REGISTER_CALLS.has(call.getExpression().getText()) && readOwner(call) === 'app');\n\n if (!ownsApp) continue;\n\n const folder = relative(repoPath, sourceFile.getDirectoryPath()).split(sep).join('/');\n folders.add(folder);\n moduleNames.add(basename(folder));\n }\n\n for (const moduleName of moduleNames) {\n const staticFolder = `${FRONTEND_STATIC_ROOT}/${moduleName}`;\n if (existsSync(join(repoPath, staticFolder))) {\n folders.add(staticFolder);\n }\n }\n\n return [...folders];\n}\n","/**\n * Display utilities: console output formatting, spinners, hyperlinks, and the\n * report blocks analyze and sync print.\n */\n\nimport { writeFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport process from 'node:process';\nimport packageJson from '../../package.json' with { type: 'json' };\nimport type {\n AnalysisSummary,\n AnalyzedFile,\n CommitRangeEntry,\n FileStatus,\n MergeResult,\n RuntimeConfig,\n} from '../config/types';\nimport pc from './colors';\nimport { getEnv } from './env';\nimport { CONFIG_FILE, isManagedFile } from './managed-files';\n\n/** CLI name */\nexport const NAME = 'cella cli';\n\n/** Version from package.json */\nexport const VERSION = packageJson.version;\n\n/** Options for generating links in CLI output */\nexport interface LinkOptions {\n /** Base GitHub URL for upstream (e.g., 'https://github.com/cellajs/cella') */\n upstreamGitHubUrl?: string;\n /** Upstream branch name for file links */\n upstreamBranch?: string;\n /** File link mode: 'commit' links to commit, 'file' links to file in repo ('local' is deprecated, treated as 'file') */\n fileLinkMode?: 'commit' | 'file' | 'local';\n /** Fork repository path for resolving file paths */\n forkPath?: string;\n}\n\n/** Line divider */\nexport const DIVIDER = '─'.repeat(60);\n\n/** Divider used above the exit entry of interactive menus */\nexport const MENU_DIVIDER = '─'.repeat(40);\n\n/** Most recent upstream commits shown per commit list (fetch detail, PR body) */\nexport const COMMIT_LIST_MAX = 50;\n\n/** Warning mark for non-fatal warnings */\nexport const warningMark = pc.yellow('⚠');\n\n/** Check mark for successful status lines */\nexport const checkMark = pc.green('✓');\n\ninterface Spinner {\n text: string;\n start(): Spinner;\n stop(): void;\n}\n\nclass TerminalSpinner implements Spinner {\n private readonly frames = ['-', '\\\\', '|', '/'];\n private frameIndex = 0;\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly enabled: boolean;\n\n constructor(\n public text: string,\n isSilent: boolean,\n ) {\n this.enabled = !isSilent && !!process.stdout.isTTY;\n }\n\n start(): Spinner {\n if (!this.enabled || this.timer) return this;\n\n this.render();\n this.timer = setInterval(() => {\n this.frameIndex = (this.frameIndex + 1) % this.frames.length;\n this.render();\n }, 80);\n\n return this;\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n\n if (!this.enabled) return;\n\n process.stdout.write('\\r\\x1b[2K');\n }\n\n private render(): void {\n process.stdout.write(`\\r${pc.cyan(this.frames[this.frameIndex])} ${this.text}`);\n }\n}\n\n/** Active spinner reference */\nlet activeSpinner: Spinner | null = null;\n\n/**\n * When true, stdout is reserved for machine-readable payloads (e.g. `--json`),\n * so all human-facing output (header, warnings, steps, spinner) is routed to stderr.\n */\nlet jsonMode = false;\n\n/**\n * Enable JSON mode: keep stdout clean for the JSON payload by sending every\n * human-facing line (console.info/console.warn, header, spinner) to stderr.\n * This makes `cella --json ... | jq` pipe cleanly.\n */\nexport function setJsonMode(enabled: boolean): void {\n jsonMode = enabled;\n if (!enabled) return;\n const toStderr = (...args: unknown[]) => {\n process.stderr.write(`${args.map((a) => (typeof a === 'string' ? a : String(a))).join(' ')}\\n`);\n };\n console.info = toStderr;\n console.log = toStderr;\n console.warn = toStderr;\n}\n\n/** Write a machine-readable payload to stdout (bypasses the stderr routing of JSON mode). */\nexport function writeStdout(text: string): void {\n process.stdout.write(text.endsWith('\\n') ? text : `${text}\\n`);\n}\n\nfunction getHeader(): string {\n const right = 'cellajs.com';\n // Account for ANSI codes when calculating padding\n const visibleLeft = `⧈ ${NAME} v${VERSION}`;\n const padding = Math.max(1, 60 - visibleLeft.length - right.length);\n return `${pc.cyan(`⧈ ${NAME}`)}${pc.dim(` · v${VERSION}`)}${pc.cyan(`${' '.repeat(padding)}${right}`)}`;\n}\n\nexport function printHeader(): void {\n console.info();\n console.info(getHeader());\n console.info(DIVIDER);\n console.info();\n}\n\n/** A completed step line with check mark; `detail` adds a dim line plus a trailing blank line. */\nfunction printStep(label: string, detail?: string): void {\n console.info(`${checkMark} ${label}`);\n if (detail) {\n console.info(` ${pc.dim(detail)}`);\n console.info(); // blank line after detail block\n }\n}\n\n/** Start a progress spinner; suppressed in test environments and JSON mode. */\nexport function createSpinner(text: string): Spinner {\n const isTestEnv = !!getEnv('VITEST') || getEnv('NODE_ENV') === 'test';\n activeSpinner = new TerminalSpinner(text, isTestEnv || jsonMode);\n activeSpinner.start();\n return activeSpinner;\n}\n\nexport function spinnerSuccess(message?: string, detail?: string): void {\n stopSpinner();\n if (message) {\n printStep(message, detail);\n }\n}\n\nexport function spinnerFail(message: string): void {\n stopSpinner();\n console.info(`${pc.red('✗')} ${message}`);\n}\n\nexport function spinnerText(text: string): void {\n if (activeSpinner) {\n activeSpinner.text = text;\n }\n}\n\nfunction stopSpinner(): void {\n if (activeSpinner) {\n activeSpinner.stop();\n activeSpinner = null;\n }\n}\n\n/**\n * Create a clickable hyperlink for terminals that support OSC 8.\n * Falls back to just the label if no URL provided.\n */\nexport function hyperlink(label: string, url?: string): string {\n if (!url) return label;\n // Strip control characters from URL to prevent terminal escape injection (CWE-116)\n // biome-ignore lint/suspicious/noControlCharactersInRegex: stripping control chars is the security purpose here.\n const safeUrl = url.replace(/[\\x00-\\x1f\\x7f]/g, '');\n // OSC 8 hyperlink format: \\x1b]8;;URL\\x07LABEL\\x1b]8;;\\x07\n return `\\x1b]8;;${safeUrl}\\x07${label}\\x1b]8;;\\x07`;\n}\n\n/** VS Code deep link that opens a file from the fork workspace. */\nfunction getVsCodeOpenFileLink(filePath: string, options: LinkOptions): string {\n const { forkPath } = options;\n if (!forkPath) return filePath;\n\n const absolutePath = resolve(forkPath, filePath);\n const url = `vscode://file${absolutePath}`;\n return hyperlink(filePath, url);\n}\n\n/** The fetched-upstream detail block, with clickable short commit hashes. */\nexport function formatFetchedUpstreamDetail(\n commitCount: number,\n commits: CommitRangeEntry[],\n upstreamGitHubUrl?: string,\n maxShownCommits = COMMIT_LIST_MAX,\n): string {\n const commitLabel = commitCount === 1 ? '1 new commit' : `${commitCount} new commits`;\n const lines = [`${commitLabel} since last merge`];\n\n const shown = commits.slice(0, maxShownCommits);\n for (const commit of shown) {\n const shortHash = commit.hash.slice(0, 7);\n const commitUrl = upstreamGitHubUrl ? `${upstreamGitHubUrl}/commit/${commit.hash}` : undefined;\n const hashLabel = hyperlink(shortHash, commitUrl);\n lines.push(` ${hashLabel} \"${commit.message}\" (${commit.date})`);\n }\n\n if (commitCount > shown.length) {\n lines.push(` ... and ${commitCount - shown.length} more`);\n }\n\n return lines.join('\\n');\n}\n\n/** Link parts (`{ label, url }`) for a file, per the configured fileLinkMode, for hyperlink(). */\nfunction getFileLink(\n filePath: string,\n commitHash: string | undefined,\n options: LinkOptions,\n): { label: string; url?: string } {\n const { upstreamGitHubUrl, upstreamBranch, fileLinkMode = 'commit' } = options;\n // The deprecated 'local' value maps to 'file'.\n const mode = fileLinkMode === 'local' ? 'file' : fileLinkMode;\n\n if (!upstreamGitHubUrl) {\n return { label: commitHash?.slice(0, 9) || '' };\n }\n\n if (mode === 'file' && upstreamBranch) {\n // Link to file in repo: https://github.com/org/repo/blob/branch/path/to/file\n const url = `${upstreamGitHubUrl}/blob/${upstreamBranch}/${filePath}`;\n return { label: filePath.split('/').pop() || filePath, url };\n }\n\n // Default: link to commit\n if (commitHash) {\n const url = `${upstreamGitHubUrl}/commit/${commitHash}`;\n return { label: commitHash.slice(0, 9), url };\n }\n\n return { label: '' };\n}\n\nfunction printSectionHeader(title: string): void {\n console.info();\n console.info(title);\n console.info(DIVIDER);\n console.info();\n}\n\nfunction formatFileDateInfo(\n filePath: string,\n commit: string | undefined,\n date: string | undefined,\n linkOptions: LinkOptions,\n): string {\n const link = getFileLink(filePath, commit, linkOptions);\n const linkLabel = link.label ? hyperlink(link.label, link.url) : '';\n return date ? pc.dim(` ≠ ${date} ${linkLabel}`) : '';\n}\n\nexport function formatMergeInProgressDetail(\n conflictCount: number,\n autoMergedFiles: string[],\n linkOptions: LinkOptions,\n maxFiles = 100,\n): string {\n const lines = [`${conflictCount} conflicts to resolve in IDE`];\n\n if (autoMergedFiles.length === 0) {\n return lines.join('\\n');\n }\n\n lines.push('');\n lines.push(` auto-merged files (${autoMergedFiles.length}):`);\n\n const shown = autoMergedFiles.slice(0, maxFiles);\n for (const filePath of shown) {\n const fileLink = getVsCodeOpenFileLink(filePath, linkOptions);\n lines.push(` - ${fileLink}`);\n }\n\n if (autoMergedFiles.length > shown.length) {\n lines.push(` ... + ${autoMergedFiles.length - shown.length} more`);\n }\n\n return lines.join('\\n');\n}\n\n/** Display configuration for a file status */\ninterface StatusConfig {\n icon: string;\n label: string;\n color: (text: string) => string;\n description?: string;\n}\n\ntype SummaryStatus = FileStatus | 'managed';\n\n/** Unified status display config: icon, label, color, and description for each status. Key order defines sort priority. */\nconst statusConfig: Record<FileStatus, StatusConfig> = {\n behind: { icon: pc.cyan('↓'), label: 'behind', color: pc.cyan, description: 'upstream changed, will sync' },\n diverged: { icon: pc.magenta('⇅'), label: 'diverged', color: pc.magenta, description: 'both changed, will merge' },\n drifted: { icon: pc.yellow('!'), label: 'drifted', color: pc.yellow, description: 'fork changed (at risk)' },\n ahead: { icon: pc.blue('↑'), label: 'ahead', color: pc.blue, description: 'fork changed (protected)' },\n local: { icon: pc.green('+'), label: 'local', color: pc.green, description: 'local file in cella folders' },\n pinned: { icon: pc.green('⨀'), label: 'pinned', color: pc.green, description: 'both changed, fork wins' },\n ignored: { icon: pc.gray('⨂'), label: 'ignored', color: pc.gray },\n identical: { icon: pc.gray('✓'), label: 'identical', color: pc.gray, description: 'no changes' },\n deleted: { icon: pc.red('✗'), label: 'deleted', color: pc.red },\n renamed: { icon: pc.blue('→'), label: 'renamed', color: pc.blue },\n};\n\nconst summaryStatusConfig: Record<SummaryStatus, StatusConfig> = {\n ...statusConfig,\n managed: {\n icon: pc.cyan('◇'),\n label: 'managed',\n color: pc.cyan,\n description: 'package.jsons & cella/cella.config.ts handled separately',\n },\n ignored: { ...statusConfig.ignored, description: 'protected by ignored config' },\n};\n\n/** Ordered status keys derived from statusConfig key order */\nconst statusOrder = Object.keys(statusConfig) as FileStatus[];\n\nfunction printSummary(summary: AnalysisSummary, title = 'summary'): void {\n printSectionHeader(pc.cyan(title));\n\n const maxCount = Math.max(...statusOrder.map((status) => summary[status]), summary.managed);\n const countWidth = String(maxCount).length + 1;\n\n const printLine = (status: SummaryStatus, count: number) => {\n const { icon, label, color, description } = summaryStatusConfig[status];\n const countStr = color(String(count).padStart(countWidth));\n const desc = description ? pc.dim(description) : '';\n console.info(` ${icon} ${countStr} ${label.padEnd(15)}${desc}`);\n };\n\n // Grouped layout with blank lines between groups\n printLine('managed', summary.managed);\n printLine('ignored', summary.ignored);\n\n console.info();\n printLine('identical', summary.identical);\n\n console.info();\n printLine('ahead', summary.ahead);\n printLine('local', summary.local);\n printLine('drifted', summary.drifted);\n\n console.info();\n printLine('diverged', summary.diverged);\n printLine('pinned', summary.pinned);\n\n console.info();\n printLine('behind', summary.behind);\n}\n\n/** Options shared by the file-list section printers. */\ninterface FileSectionOptions {\n /** Override section header title */\n title?: string;\n /** Footer hint text (dimmed), one line per entry */\n hint?: string | string[];\n /** Which commit/date fields to use: 'fork' or 'upstream' */\n dateSource?: 'fork' | 'upstream';\n /** Per-file detail appended after the date/link info */\n suffix?: (file: AnalyzedFile) => string;\n}\n\n/**\n * Print a list of files as a section: header, one line per file (capped), optional hint.\n * `icon` may vary per file (e.g. pinned vs ignored) and `suffix` appends per-file detail.\n */\nfunction printFileSection(\n files: AnalyzedFile[],\n title: string,\n linkOptions: LinkOptions,\n options: FileSectionOptions & { icon: string | ((file: AnalyzedFile) => string) },\n): void {\n if (files.length === 0) return;\n\n printSectionHeader(`${title} ${pc.dim(`· ${files.length} files`)}`);\n\n const useUpstream = options.dateSource === 'upstream';\n const maxLines = 100;\n const shown = files.length > maxLines ? files.slice(0, maxLines) : files;\n\n for (const file of shown) {\n const icon = typeof options.icon === 'string' ? options.icon : options.icon(file);\n const commit = useUpstream ? file.upstreamCommit : file.changedCommit;\n const date = useUpstream ? file.upstreamChangedAt : file.changedAt;\n const dateInfo = formatFileDateInfo(file.path, commit, date, linkOptions);\n console.info(` ${icon} ${file.path}${dateInfo}${options.suffix?.(file) ?? ''}`);\n }\n\n if (files.length > maxLines) {\n console.info(pc.dim(` ... + ${files.length - maxLines} more`));\n }\n\n if (options.hint) {\n console.info();\n for (const line of Array.isArray(options.hint) ? options.hint : [options.hint]) {\n console.info(pc.dim(` ${line}`));\n }\n }\n}\n\n/**\n * Print a group of files with a specific status, including section header and footer.\n */\nfunction printFileGroup(\n files: AnalyzedFile[],\n status: FileStatus,\n linkOptions: LinkOptions,\n options?: FileSectionOptions,\n): void {\n const filtered = files.filter((f) => f.status === status && !isManagedFile(f.path));\n const config = statusConfig[status];\n const title = options?.title ?? `${config.icon} ${config.label}`;\n printFileSection(filtered, title, linkOptions, { ...options, icon: config.icon });\n}\n\n/**\n * Protected (pinned/ignored) files that upstream also changed since the last sync. The fork\n * side wins whole-file on these, so upstream's hunks are dropped: the regression class where\n * a pinned stylesheet misses new upstream utilities that synced components rely on.\n */\nexport function findProtectedBehind(files: AnalyzedFile[]): AnalyzedFile[] {\n return files.filter((file) => file.upstreamChanged && !isManagedFile(file.path));\n}\n\n/** Shared hint for protected-but-behind output (analyze section and sync summary). */\nconst PROTECTED_BEHIND_HINT =\n 'pinned/ignored files where upstream also changed since the last sync; the fork side wins on conflict, ' +\n 'so diff each against upstream (analyze --open-diff <path>) and adopt what you need.';\n\n/** Icon by protection kind (⨂ ignored, ⨀ pinned) for protected-but-behind lines. */\nfunction protectionIcon(file: AnalyzedFile): string {\n return file.isIgnored ? statusConfig.ignored.icon : statusConfig.pinned.icon;\n}\n\n/** Per-file detail: how many lines upstream changed (dropped by the fork-wins resolution). */\nfunction formatUpstreamChangedLines(file: AnalyzedFile): string {\n if (file.upstreamChangedLines === undefined) return '';\n const n = file.upstreamChangedLines;\n return pc.yellow(` · ${n} ${n === 1 ? 'line' : 'lines'} changed upstream`);\n}\n\n/** What a protected-but-behind list needs for its `git diff` hints. */\ntype ProtectedDiffSource = Pick<MergeResult, 'upstreamDiffRange' | 'protectedUpstreamChanges'>;\n\n/**\n * Pasteable `git diff` lines for a protected-but-behind list: one per `pinned` or `ignored` entry\n * that holds a listed path, under a line that introduces them. The range runs from the last sync\n * point to upstream, so each shows only what upstream changed; a diff of the fork against upstream\n * would show the fork's own changes too. Empty without a range or a matching entry.\n */\nfunction protectedDiffHints(source: ProtectedDiffSource | undefined, paths: string[]): string[] {\n const range = source?.upstreamDiffRange;\n if (!range) return [];\n const listed = new Set(paths);\n const groups = (source?.protectedUpstreamChanges ?? []).filter((group) => group.paths.some((p) => listed.has(p)));\n if (groups.length === 0) return [];\n return [\n 'what upstream changed since the last sync, per pinned/ignored entry:',\n ...groups.map((group) => ` git diff ${range} -- ${shellPath(group.entry)}`),\n ];\n}\n\n/** Per-file detail for pinned `ahead` files: upstream lines the fork lacks (only when > 0). */\nfunction formatUpstreamLinesAbsent(file: AnalyzedFile): string {\n const n = file.upstreamLinesAbsent ?? 0;\n return n > 0 ? pc.yellow(` · ${n} upstream ${n === 1 ? 'line' : 'lines'} absent`) : '';\n}\n\n/**\n * Print all analyze-mode file group sections in review order:\n * behind, ahead (protected), protected-but-behind, drifted, and diverged.\n *\n * Protected-but-behind covers every `pinned`-status file (both changed, fork wins) plus\n * ignored files upstream also changed, so there is no separate `pinned` group. With `diffSource`\n * (the merge result) it ends with one `git diff` line per pinned/ignored entry.\n */\nexport function printAnalysisFileGroups(\n files: AnalyzedFile[],\n linkOptions: LinkOptions,\n diffSource?: ProtectedDiffSource,\n): void {\n const protectedBehind = findProtectedBehind(files);\n printFileGroup(files, 'behind', linkOptions, {\n title: pc.cyan('↓ behind on upstream'),\n });\n printFileGroup(files, 'ahead', linkOptions, {\n title: `${pc.blue('↑ protected in fork')}`,\n suffix: formatUpstreamLinesAbsent,\n hint: [\n 'these files have fork changes but are protected (pinned); upstream did not change them since the last sync.',\n 'pinned files keep the fork side on every conflict; a count here is upstream content the fork never received, ' +\n 'deliberately or not: diff and decide.',\n ],\n });\n printFileSection(protectedBehind, `${warningMark} ${pc.yellow('protected but behind upstream')}`, linkOptions, {\n icon: protectionIcon,\n suffix: formatUpstreamChangedLines,\n dateSource: 'upstream',\n hint: [\n PROTECTED_BEHIND_HINT,\n ...protectedDiffHints(\n diffSource,\n protectedBehind.map((file) => file.path),\n ),\n ],\n });\n printFileGroup(files, 'drifted', linkOptions, {\n title: `${warningMark} ${pc.yellow('drifted from upstream')}`,\n hint: 'these files have fork changes but are not pinned or ignored.',\n });\n printFileGroup(files, 'diverged', linkOptions, {\n title: `${pc.magenta('⇅ diverged')}`,\n hint: 'both fork and upstream changed.',\n dateSource: 'upstream',\n });\n}\n\nfunction writeLogFile(forkPath: string, files: AnalyzedFile[]): string {\n const logPath = join(forkPath, 'cella-sync.log');\n\n const lines: string[] = [\n `cella sync analysis: ${new Date().toISOString()}`,\n DIVIDER,\n '',\n `complete file list (${files.length} files)`,\n DIVIDER,\n '',\n ];\n\n const sortedFiles = [...files].sort((a, b) => {\n const aOrder = statusOrder.indexOf(a.status);\n const bOrder = statusOrder.indexOf(b.status);\n if (aOrder !== bOrder) return aOrder - bOrder;\n return a.path.localeCompare(b.path);\n });\n\n for (const file of sortedFiles) {\n const config = statusConfig[file.status];\n // biome-ignore lint/suspicious/noControlCharactersInRegex: stripping ANSI escape sequences requires \\x1b literal.\n const icon = config.icon.replace(/\\x1b\\[[0-9;]*m/g, ''); // Strip ANSI\n lines.push(` ${icon} ${config.label.padEnd(12)} ${file.path}`);\n }\n\n writeFileSync(logPath, lines.join('\\n'), 'utf8');\n return logPath;\n}\n\nexport function printSyncComplete(result: MergeResult, options: { stagedBranch?: string } = {}): void {\n const updated = result.files.filter((file) => file.status === 'behind' || file.status === 'diverged').length;\n const diverged = result.files.filter((file) => file.status === 'diverged').length;\n const merged = result.autoMergedFiles?.length ?? Math.max(0, diverged - result.conflicts.length);\n const conflicts = result.conflicts.length;\n\n console.info();\n if (options.stagedBranch) {\n console.info(`${checkMark} sync merge staged on '${options.stagedBranch}'`);\n console.info(\n pc.dim(` ${updated} files updated, ${merged} auto-merged, ${conflicts} conflicts. committing next...`),\n );\n } else {\n console.info(`${checkMark} sync complete`);\n console.info(pc.dim(` ${updated} files updated, ${merged} auto-merged, ${conflicts} conflicts`));\n }\n\n printProtectedConflicts(result);\n console.info();\n}\n\n/**\n * List protected files the sync resolved to the fork side although upstream changed them\n * (`MergeResult.protectedConflicts`). Printed right when the drop happens so it is not\n * discovered weeks later as a styling or behavior regression. Silent when empty.\n */\nfunction printProtectedConflicts(result: MergeResult): void {\n const paths = result.protectedConflicts ?? [];\n if (paths.length === 0) return;\n\n const byPath = new Map(result.files.map((file) => [file.path, file]));\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(\n `${paths.length} protected ${paths.length === 1 ? 'file kept' : 'files kept'} the fork version, dropping upstream changes:`,\n )}`,\n );\n for (const path of paths) {\n const file = byPath.get(path);\n const icon = file ? protectionIcon(file) : statusConfig.pinned.icon;\n console.info(` ${icon} ${path}${file ? formatUpstreamChangedLines(file) : ''}`);\n }\n for (const line of [PROTECTED_BEHIND_HINT, ...protectedDiffHints(result, paths)]) console.info(pc.dim(` ${line}`));\n}\n\n/** `1 file`, `2 files`: a count with its noun. */\nfunction plural(count: number, singular: string, pluralForm = `${singular}s`): string {\n return `${count} ${count === 1 ? singular : pluralForm}`;\n}\n\n/** Quote a path for a pasteable shell command when it holds characters the shell would interpret. */\nfunction shellPath(path: string): string {\n return /^[\\w./@+-]+$/.test(path) ? path : `'${path.replace(/'/g, `'\\\\''`)}'`;\n}\n\n/**\n * Ignored paths upstream changed since the last sync while the fork left them untouched\n * (`MergeResult.ignoredUpstreamChanges`). Ignored paths never sync, so this is where new config\n * keys or version bumps under e.g. `shared/config` surface. One line per `ignored` entry with a\n * file count, plus a pasteable `git diff` of upstream's side. Silent when empty.\n */\nexport function printIgnoredUpstreamChanges(result: MergeResult): void {\n const groups = result.ignoredUpstreamChanges ?? [];\n if (groups.length === 0) return;\n\n const total = groups.reduce((count, group) => count + group.paths.length, 0);\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(`ignored paths changed upstream · ${plural(total, 'file')} under ${plural(groups.length, 'entry', 'entries')}`)}`,\n );\n for (const group of groups) {\n const counts = [plural(group.paths.length, 'file')];\n if (group.added > 0) counts.push(`${group.added} new`);\n if (group.deleted > 0) counts.push(`${group.deleted} deleted`);\n console.info(` ${statusConfig.ignored.icon} ${group.entry} ${pc.dim(`· ${counts.join(', ')}`)}`);\n if (result.upstreamDiffRange) {\n console.info(pc.dim(` git diff ${result.upstreamDiffRange} -- ${shellPath(group.entry)}`));\n }\n }\n console.info(pc.dim(' the fork left these untouched and ignored paths never sync: diff and adopt what you need.'));\n}\n\n/**\n * Upstream sync config entries the fork config does not follow (`MergeResult.upstreamOverrides`):\n * `overrides` entries and `packageJsonSync` keys upstream added that the fork lacks, and ones\n * upstream dropped that the fork still has. The sync config is managed and never merges, so these\n * only reach the fork by hand. Silent when there is nothing to report; one dim line when upstream's\n * config was unreadable.\n */\nexport function printUpstreamOverrideChanges(result: Pick<MergeResult, 'upstreamOverrides'>): void {\n const report = result.upstreamOverrides;\n if (!report) return;\n\n console.info();\n if (report.kind === 'unreadable') {\n const side = report.side === 'base' ? 'the last sync point' : 'the incoming ref';\n console.info(\n pc.dim(`upstream sync config not compared: upstream ${CONFIG_FILE} is missing or unreadable at ${side}`),\n );\n return;\n }\n\n const lines: string[] = [];\n for (const list of ['pinned', 'ignored', 'packageJsonSync'] as const) {\n for (const entry of report[list].added) lines.push(` ${pc.green('+')} ${list}: ${entry}`);\n for (const entry of report[list].removed) {\n lines.push(` ${pc.red('−')} ${list}: ${entry}${pc.dim(' · dropped upstream, still in your config')}`);\n }\n }\n console.info(\n `${warningMark} ${pc.yellow(`upstream changed its sync config · ${plural(lines.length, 'entry', 'entries')} to review`)}`,\n );\n for (const line of lines) console.info(line);\n console.info(pc.dim(` ${CONFIG_FILE} never syncs: add or drop these by hand where they fit your app.`));\n}\n\n/**\n * A pinned file whose fork content is byte-identical to the previous upstream (status\n * `behind`) never actually diverged: the pin is silently freezing it at the old upstream\n * version and dropping upstream's new changes. Because the fork copy equals the old\n * upstream, this produces no merge conflict and no type error, so it slips through unseen\n * (e.g. a pinned nav-config losing new upstream entries). These are the pins worth a look.\n * Managed files (package.json, the lockfile, the sync config) are always pinned but stay out:\n * the package sync reconciles their keys, so the pin masks nothing there.\n */\nexport function findMaskingPins(files: AnalyzedFile[]): AnalyzedFile[] {\n return files.filter(\n (file) =>\n file.isPinned &&\n !isManagedFile(file.path) &&\n file.status === 'behind' &&\n file.existsInFork &&\n file.existsInUpstream,\n );\n}\n\n/**\n * Warn when pins are masking upstream changes (see `findMaskingPins`). Silent by design\n * when there is nothing to report, so it is safe to call unconditionally after a summary.\n */\nfunction printMaskingPinWarning(files: AnalyzedFile[]): void {\n const masking = findMaskingPins(files);\n if (masking.length === 0) return;\n\n const many = masking.length > 1;\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(\n `${masking.length} pinned ${many ? 'files match' : 'file matches'} the previous upstream but changed upstream:`,\n )}`,\n );\n console.info(pc.yellow(' the pin keeps the old fork copy and silently drops those upstream changes:'));\n for (const file of masking) {\n console.info(pc.dim(` ⨀ ${file.path}`));\n }\n console.info(\n pc.yellow(' if the fork never customized these, unpin them in cella/cella.config.ts to take upstream.'),\n );\n console.info();\n}\n\n/**\n * Print warnings for aggressive sync flags (--hard / --unpinned) after completion.\n *\n * Explains what each active flag did and its consequence, and adds a shared\n * caution to cherry-pick deliberately when either is used.\n */\nexport function printFlagWarnings(options: { hard?: boolean; unpinned?: boolean }): void {\n const { hard, unpinned } = options;\n if (!hard && !unpinned) return;\n\n if (hard) {\n console.info(pc.yellow('⚠ --hard used: drifted files were treated as behind, overwriting with incoming.'));\n }\n if (unpinned) {\n console.info(\n pc.yellow(\n '⚠ --unpinned used: pinned files in cella/cella.config.ts were ignored, this can result in more drifts.',\n ),\n );\n }\n console.info(pc.yellow(' be extra careful and cherry-pick what you want only.'));\n console.info();\n}\n\n/**\n * Print the post-engine report block shared by analyze and sync: the summary, then the upstream\n * changes the sync never brings in (ignored paths and upstream's own sync config), and pins that\n * silently freeze a file at the old upstream (no conflict, no type error).\n */\nexport function printEngineReports(result: MergeResult, title: string): void {\n printSummary(result.summary, title);\n printIgnoredUpstreamChanges(result);\n printUpstreamOverrideChanges(result);\n printMaskingPinWarning(result.files);\n}\n\n/** Write the full file list to cella-sync.log when --log was passed, and print where it landed. */\nexport function printLogFileReport(config: Pick<RuntimeConfig, 'forkPath' | 'logFile'>, files: AnalyzedFile[]): void {\n if (!config.logFile) return;\n const logPath = writeLogFile(config.forkPath, files);\n console.info();\n console.info(pc.dim(`full file list written to: ${logPath}`));\n}\n","{\n \"name\": \"@cellajs/cli\",\n \"version\": \"0.3.3\",\n \"private\": false,\n \"license\": \"MIT\",\n \"description\": \"CLI for managing your monorepo and syncing with upstream Cella.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/cellajs/cella-cli\"\n },\n \"homepage\": \"https://cellajs.com\",\n \"author\": \"CellaJS <info@cellajs.com>\",\n \"engines\": {\n \"node\": \"26.x\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"exports\": {\n \".\": \"./dist/index.js\",\n \"./config\": {\n \"types\": \"./dist/config.d.ts\",\n \"import\": \"./dist/config.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\",\n \"index.js\",\n \"README.md\"\n ],\n \"bin\": {\n \"cella\": \"index.js\"\n },\n \"imports\": {\n \"#/*\": \"./src/*\"\n },\n \"scripts\": {\n \"start\": \"tsx index.ts\",\n \"clean\": \"rimraf ./dist\",\n \"build\": \"tsup\",\n \"test-build\": \"pnpm run build && node index.js --help\",\n \"prepublishOnly\": \"pnpm run test:release\",\n \"check\": \"pnpm ts && pnpm biome check --write .\",\n \"ts\": \"tsgo --pretty\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"test\": \"vitest run\",\n \"test:release\": \"pnpm run build && vitest run --config vitest.release.config.ts\",\n \"test:watch\": \"vitest\",\n \"prepare\": \"lefthook install\"\n },\n \"dependencies\": {\n \"@inquirer/core\": \"^12.0.3\",\n \"@inquirer/prompts\": \"^8.7.2\",\n \"@pierre/diffs\": \"^1.5.1\",\n \"commander\": \"^15.0.0\",\n \"ts-morph\": \"^28.0.0\",\n \"zod\": \"^4.6.5\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.5.15\",\n \"@commitlint/cli\": \"^21.2.3\",\n \"@commitlint/config-conventional\": \"^21.2.3\",\n \"@evilmartians/lefthook\": \"^2.1.15\",\n \"@types/node\": \"26.6.3\",\n \"@typescript/native-preview\": \"7.0.0-dev.20260707.2\",\n \"rimraf\": \"^6.1.3\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.23.15\",\n \"typescript\": \"6.0.3\",\n \"vitest\": \"^5.0.3\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"cella\",\n \"cellajs\",\n \"cli\",\n \"sync\",\n \"template\"\n ],\n \"packageManager\": \"pnpm@11.8.0\",\n \"commitlint\": {\n \"extends\": [\n \"@commitlint/config-conventional\"\n ],\n \"rules\": {\n \"type-enum\": [\n 2,\n \"always\",\n [\n \"feat\",\n \"fix\",\n \"perf\",\n \"refactor\",\n \"revert\",\n \"docs\",\n \"chore\",\n \"build\",\n \"ci\",\n \"style\",\n \"test\"\n ]\n ],\n \"header-max-length\": [\n 2,\n \"always\",\n 120\n ],\n \"body-max-line-length\": [\n 0,\n \"always\",\n 200\n ],\n \"footer-max-line-length\": [\n 0,\n \"always\",\n 200\n ]\n }\n }\n}\n","/**\n * Override matching and validation: files matched against the ignored/pinned\n * paths, and config warnings for entries that cannot work.\n */\n\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { AnalyzedFile, CellaCliConfig, IgnoredUpstreamGroup, ProtectedUpstreamGroup } from '../config/types';\nimport { warningMark } from './display';\nimport { fileExistsAtRef } from './git';\nimport { isGeneratedFile, isManagedFile } from './managed-files';\nimport { isUpstreamOnly } from './migration-notes';\n\n/**\n * Whether a file path is owned by any of the given folders.\n *\n * Folders are directory prefixes (not globs): an entry matches the file when\n * the path equals the entry exactly or is nested under `entry + '/'`.\n *\n * @param filePath - The file path to test\n * @param folders - Folder prefixes (or exact paths) to match against\n */\nexport function isUnderAnyFolder(filePath: string, folders: string[]): boolean {\n return folders.some((folder) => {\n const entry = folder.replace(/\\/+$/, '');\n return filePath === entry || filePath.startsWith(`${entry}/`);\n });\n}\n\n/**\n * Whether a file is inside an ignored path, or an upstream-only one (migration notes),\n * which every fork ignores without listing it.\n */\nexport function isIgnored(filePath: string, config: CellaCliConfig): boolean {\n return isUpstreamOnly(filePath) || isUnderAnyFolder(filePath, config.overrides?.ignored || []);\n}\n\n/**\n * Whether a file is in the pinned list.\n * Managed files always count as pinned (handled separately by cella).\n */\nexport function isPinned(filePath: string, config: CellaCliConfig): boolean {\n if (isManagedFile(filePath)) return true;\n return isUnderAnyFolder(filePath, config.overrides?.pinned || []);\n}\n\n/**\n * Group `upstreamOnly` files by the `ignored` entry they fall under, so a report can name the\n * folder from the config (plus derived app-module folders) with one diff hint per entry.\n *\n * A file under nested entries lands on the most specific one. Groups follow the order of\n * `ignored`; managed files and generated output are left out.\n *\n * @param files - Analyzed files (only those flagged `upstreamOnly` count)\n * @param ignored - The fork's effective `ignored` entries\n */\nexport function groupIgnoredUpstreamChanges(files: AnalyzedFile[], ignored: string[]): IgnoredUpstreamGroup[] {\n const entries = [...new Set(ignored.map((entry) => entry.replace(/\\/+$/, '')).filter(Boolean))];\n const mostSpecificFirst = [...entries].sort((a, b) => b.length - a.length);\n const groups = new Map<string, IgnoredUpstreamGroup>();\n\n for (const file of files) {\n if (!file.upstreamOnly || isManagedFile(file.path) || isGeneratedFile(file.path)) continue;\n const entry = mostSpecificFirst.find((candidate) => isUnderAnyFolder(file.path, [candidate]));\n if (!entry) continue;\n\n const group = groups.get(entry) ?? { entry, paths: [], added: 0, deleted: 0 };\n group.paths.push(file.path);\n if (!file.existsInFork) group.added++;\n if (!file.existsInUpstream) group.deleted++;\n groups.set(entry, group);\n }\n\n for (const group of groups.values()) group.paths.sort();\n return entries.flatMap((entry) => groups.get(entry) ?? []);\n}\n\n/**\n * Group protected paths upstream also changed by the `pinned` or `ignored` entry they fall under,\n * so a report can print one diff hint per entry, not one per file.\n *\n * A path under nested entries lands on the most specific one; a path no entry covers (a managed\n * file) stands for itself. Groups follow the order the paths come in.\n *\n * @param paths - Protected paths upstream also changed (`MergeResult.protectedConflicts`)\n * @param config - The fork's sync config\n */\nexport function groupProtectedUpstreamChanges(paths: string[], config: CellaCliConfig): ProtectedUpstreamGroup[] {\n const entries = [...(config.overrides?.pinned ?? []), ...(config.overrides?.ignored ?? [])]\n .map((entry) => entry.replace(/\\/+$/, ''))\n .filter(Boolean);\n const mostSpecificFirst = [...new Set(entries)].sort((a, b) => b.length - a.length);\n const groups = new Map<string, ProtectedUpstreamGroup>();\n\n for (const path of paths) {\n const entry = mostSpecificFirst.find((candidate) => isUnderAnyFolder(path, [candidate])) ?? path;\n const group = groups.get(entry) ?? { entry, paths: [] };\n group.paths.push(path);\n groups.set(entry, group);\n }\n\n for (const group of groups.values()) group.paths.sort();\n return [...groups.values()];\n}\n\n/**\n * Resolve effective pin status for a sync run, honoring the --unpinned flag.\n *\n * When `unpinned` is true, configured pins are disabled so upstream versions\n * surface as behind/diverged; managed files stay pinned (their content is\n * reconciled separately by cella).\n */\nexport function isPinnedForSync(filePath: string, config: CellaCliConfig, unpinned?: boolean): boolean {\n if (isManagedFile(filePath)) return true;\n if (unpinned) return false;\n return isPinned(filePath, config);\n}\n\n/** Validation warning */\ninterface ConfigWarning {\n type: 'pinned-glob' | 'pinned-not-found' | 'ignored-not-found';\n pattern: string;\n message: string;\n}\n\n/** Whether an entry contains glob characters (not supported in overrides). */\nfunction hasGlobChars(entry: string): boolean {\n return entry.includes('*') || entry.includes('?');\n}\n\n/**\n * Validate config overrides and return warnings.\n *\n * Checks for:\n * - Pinned entries using glob patterns (not supported)\n * - Pinned entries that don't exist in fork\n * - Ignored entries that exist neither in the fork nor upstream\n *\n * A fork ignores some paths to keep them from arriving (a file upstream has and the fork deleted),\n * so an ignored entry missing from the fork is fine while upstream has the path. That is read at\n * `upstreamRef` as last fetched, without fetching: when the ref does not resolve (nothing fetched\n * yet), every ignored entry missing from the fork warns.\n *\n * @param config - The sync config to validate\n * @param forkPath - Path to the fork repository\n * @param upstreamRef - Upstream ref to look ignored entries up at (e.g. 'cella-upstream/main')\n */\nexport async function validateOverrides(\n config: CellaCliConfig,\n forkPath: string,\n upstreamRef?: string,\n): Promise<ConfigWarning[]> {\n const warnings: ConfigWarning[] = [];\n\n const pinned = config.overrides?.pinned || [];\n for (const entry of pinned) {\n if (hasGlobChars(entry)) {\n warnings.push({\n type: 'pinned-glob',\n pattern: entry,\n message: `pin uses glob (not supported, use a path or folder): ${entry}`,\n });\n } else if (!existsSync(join(forkPath, entry))) {\n warnings.push({\n type: 'pinned-not-found',\n pattern: entry,\n message: `pin not found: ${entry}`,\n });\n }\n }\n\n const ignored = config.overrides?.ignored || [];\n for (const entry of ignored) {\n if (hasGlobChars(entry)) {\n warnings.push({\n type: 'ignored-not-found',\n pattern: entry,\n message: `ignored entry uses glob (not supported, use a path or folder): ${entry}`,\n });\n } else if (!existsSync(join(forkPath, entry.replace(/\\/+$/, '')))) {\n if (upstreamRef && (await fileExistsAtRef(forkPath, upstreamRef, entry.replace(/\\/+$/, '')))) continue;\n warnings.push({\n type: 'ignored-not-found',\n pattern: entry,\n message: `ignored entry not found: ${entry}`,\n });\n }\n }\n\n return warnings;\n}\n\nexport function printWarnings(warnings: ConfigWarning[]): void {\n for (const warning of warnings) {\n console.info(`${warningMark} ${warning.message}`);\n }\n}\n","/**\n * Git command helpers: typed wrappers around common git operations, plus the\n * sync-point tracking and merge-base recovery machinery.\n */\n\nimport { execFile } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readdir, rmdir, unlink } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\nimport { promisify } from 'node:util';\nimport type { CommitRangeEntry } from '../config/types';\nimport { getEnvSnapshot } from './env';\nimport { MANIFEST_FILE, parseSyncManifest, readManifestBase, type SyncManifest } from './manifest';\n\nconst execFileAsync = promisify(execFile);\n\n/** Maximum stdout buffer for subprocess output (50MB). */\nexport const MAX_BUFFER = 50 * 1024 * 1024;\n\n/**\n * Replace the userinfo part of URLs in text (embedded tokens or passwords) with `***`.\n * Keeps secrets in git remote URLs out of error messages (CWE-532).\n */\nfunction redactUrlSecrets(text: string): string {\n return text.replace(/https?:\\/\\/[^@\\s]+@/g, (match) => {\n const protocol = match.startsWith('https') ? 'https' : 'http';\n return `${protocol}://***@`;\n });\n}\n\n/** Options for git command execution */\ninterface GitCommandOptions {\n /** Skip editor prompts (for merge commits, etc.) */\n skipEditor?: boolean;\n /** Maximum buffer size for stdout (default: 50MB) */\n maxBuffer?: number;\n /** Ignore command errors: a failed command returns an empty string. */\n ignoreErrors?: boolean;\n /** Additional environment variables for the git command */\n env?: Record<string, string>;\n}\n\n/**\n * Executes a git command and returns trimmed stdout.\n *\n * @param args - Git command arguments (e.g., ['status', '--porcelain'])\n * @param cwd - Working directory for the command\n * @param options - Command execution options\n * @returns Trimmed stdout from the command\n */\nexport async function git(args: string[], cwd: string, options: GitCommandOptions = {}): Promise<string> {\n const env = {\n ...getEnvSnapshot(),\n ...(options.skipEditor ? { GIT_EDITOR: 'true' } : {}),\n ...options.env,\n };\n\n const maxBuffer = options.maxBuffer ?? MAX_BUFFER;\n\n try {\n const { stdout } = await execFileAsync('git', args, { cwd, env, maxBuffer });\n return stdout.trim();\n } catch (error) {\n if (options.ignoreErrors) return '';\n // Tokens/passwords embedded in git remote URLs must not reach the error message.\n if (error instanceof Error) {\n error.message = redactUrlSecrets(error.message);\n }\n throw error;\n }\n}\n\nexport async function getCurrentBranch(cwd: string): Promise<string> {\n return git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd);\n}\n\nexport async function switchBranch(cwd: string, branch: string): Promise<void> {\n await git(['switch', branch], cwd);\n}\n\n/**\n * Detach HEAD at a commit or ref (`git switch --detach`), holding no branch.\n */\nexport async function switchDetached(cwd: string, ref: string): Promise<void> {\n await git(['switch', '--detach', ref], cwd);\n}\n\n/**\n * Create and check out a new branch from a specific start point (branch/ref).\n *\n * `--no-track` keeps a remote-tracking start point (`origin/main`) from becoming the new\n * branch's upstream, where a bare `git push` could then land on the trunk.\n */\nexport async function createBranchFrom(cwd: string, branch: string, startPoint: string): Promise<void> {\n await git(['switch', '-c', branch, '--no-track', startPoint], cwd);\n}\n\n/** Whether a local branch exists. */\nexport async function branchExists(cwd: string, branch: string): Promise<boolean> {\n return (await git(['rev-parse', '-q', '--verify', `refs/heads/${branch}`], cwd, { ignoreErrors: true })) !== '';\n}\n\n/**\n * The worktree that has `branch` checked out, or null when none has.\n *\n * Git refuses to switch to a branch another worktree has checked out (and to move its ref), so\n * callers that would switch to a shared branch such as the trunk check here first.\n */\nexport async function getBranchWorktree(cwd: string, branch: string): Promise<string | null> {\n const output = await git(['worktree', 'list', '--porcelain'], cwd, { ignoreErrors: true });\n let worktree: string | null = null;\n for (const line of output.split('\\n')) {\n if (line.startsWith('worktree ')) worktree = line.slice('worktree '.length);\n else if (line === `branch refs/heads/${branch}`) return worktree;\n }\n return null;\n}\n\n/**\n * Fast-forward a branch no worktree has checked out to `ref`, without checking it out.\n *\n * Fetching from the repository itself (`git fetch . <ref>:<branch>`) moves the branch ref only,\n * and git refuses when that is not a fast-forward or a worktree has the branch checked out.\n */\nexport async function fastForwardBranch(cwd: string, branch: string, ref: string): Promise<void> {\n await git(['fetch', '--quiet', '.', `${ref}:refs/heads/${branch}`], cwd);\n}\n\n/** Delete a local branch (force). No-op if it doesn't exist. */\nexport async function deleteBranch(cwd: string, branch: string): Promise<void> {\n await git(['branch', '-D', branch], cwd, { ignoreErrors: true });\n}\n\n/**\n * Fast-forward the current branch from its upstream tracking branch.\n * Best-effort: ignores errors (e.g. no origin, offline, or nothing to pull).\n */\nexport async function pullFastForward(cwd: string): Promise<void> {\n await git(['pull', '--ff-only'], cwd, { ignoreErrors: true, skipEditor: true });\n}\n\n/** How the current branch compares to its upstream tracking branch. */\ninterface UpstreamStatus {\n /** Upstream tracking ref (e.g. `origin/main`), or null when none is configured. */\n upstream: string | null;\n /** Commits the local branch has that its upstream doesn't. */\n ahead: number;\n /** Commits the upstream has that the local branch doesn't. */\n behind: number;\n}\n\n/**\n * A branch's upstream tracking ref (e.g. `origin/main`), or null when none is configured.\n * `branch` defaults to the current one.\n */\nexport async function getBranchUpstream(cwd: string, branch = ''): Promise<string | null> {\n const upstream = await git(['rev-parse', '--abbrev-ref', '--symbolic-full-name', `${branch}@{upstream}`], cwd, {\n ignoreErrors: true,\n });\n return upstream || null;\n}\n\n/**\n * Fetch a branch's upstream, then report how far ahead/behind the branch is.\n *\n * `branch` defaults to the current one. A named branch is compared by ref, without checking it\n * out, so this also works for a branch another worktree has checked out.\n *\n * The fetch is best-effort so an offline/no-remote run still returns whatever is already local.\n * Returns `upstream: null` when the branch has no tracking branch configured (local-only repo).\n */\nexport async function getUpstreamStatus(cwd: string, branch?: string): Promise<UpstreamStatus> {\n const local = branch ? `refs/heads/${branch}` : 'HEAD';\n const upstream = await getBranchUpstream(cwd, branch);\n if (!upstream) return { upstream: null, ahead: 0, behind: 0 };\n\n // Refresh the remote-tracking ref so the comparison reflects the remote's latest state.\n const remote = upstream.split('/')[0];\n await git(['fetch', remote], cwd, { ignoreErrors: true, skipEditor: true });\n\n const counts = await git(['rev-list', '--left-right', '--count', `${local}...${upstream}`], cwd, {\n ignoreErrors: true,\n });\n const [ahead, behind] = counts.split(/\\s+/).map((n) => Number.parseInt(n, 10) || 0);\n return { upstream, ahead: ahead ?? 0, behind: behind ?? 0 };\n}\n\n/**\n * Push a branch to a remote, setting upstream tracking.\n *\n * `forceWithLease` allows a rewritten branch (see `flattenBranch`) to replace the version\n * already on the remote, while still refusing to overwrite remote commits we haven't seen.\n */\nexport async function pushBranch(\n cwd: string,\n remote: string,\n branch: string,\n options: { forceWithLease?: boolean } = {},\n): Promise<void> {\n await git(['push', '-u', ...(options.forceWithLease ? ['--force-with-lease'] : []), remote, branch], cwd);\n}\n\n/**\n * List merge commits made on the current branch itself: commits with two parents on the\n * first-parent chain from HEAD down to where the branch forked off `baseRef` (newest first).\n *\n * `--first-parent` keeps the walk on the branch's own commits, so merge commits that merely\n * exist inside a merged-in history (e.g. upstream's internal merges) don't count.\n */\nexport async function listBranchMergeCommits(cwd: string, baseRef: string): Promise<string[]> {\n const out = await git(['rev-list', '--merges', '--first-parent', `${baseRef}..HEAD`], cwd, { ignoreErrors: true });\n return out ? out.split('\\n').filter(Boolean) : [];\n}\n\n/**\n * Rewrite the current branch as one commit with `message`, parented on the point where the\n * branch forked off `baseRef`. The tree (content) is kept exactly as-is; only the commit\n * graph changes, so the branch's diff against the base is untouched.\n *\n * Companion to `commitSquash` for commits that already happened: a manual `git commit` during\n * a sync merge records a two-parent merge commit, which makes the PR list the upstream\n * branch's entire (unshared) history. Flattening restores the single-commit shape.\n */\nexport async function flattenBranch(cwd: string, baseRef: string, message: string): Promise<void> {\n const parent = await getMergeBase(cwd, baseRef, 'HEAD');\n const tree = await git(['rev-parse', 'HEAD^{tree}'], cwd);\n const commit = await git(['commit-tree', tree, '-p', parent, '-m', message], cwd);\n await git(['reset', '--hard', commit], cwd);\n}\n\n/**\n * Commit the staged changes as a single-parent commit, discarding any in-progress merge state.\n *\n * A normal commit with `MERGE_HEAD` present records a two-parent merge commit. Because the fork\n * doesn't share pushed ancestry with upstream (the local `git replace` graft that makes merges\n * incremental is never pushed), such a merge commit makes the PR list the upstream branch's\n * entire history. Removing the merge state first collapses the staged delta into one clean\n * commit, so the PR shows a single commit with the incremental diff.\n */\nexport async function commitSquash(cwd: string, message: string): Promise<void> {\n for (const file of ['MERGE_HEAD', 'MERGE_MSG', 'MERGE_MODE']) {\n const path = await gitPath(cwd, file);\n if (existsSync(path)) await unlink(path);\n }\n await git(['commit', '-m', message], cwd, { skipEditor: true });\n}\n\n/**\n * Absolute path of a file in the current worktree's git dir. In a linked worktree `.git` is a\n * pointer file and the git dir lives under the main checkout's `.git/worktrees/<name>`.\n */\nasync function gitPath(cwd: string, file: string): Promise<string> {\n return resolve(cwd, await git(['rev-parse', '--git-path', file], cwd));\n}\n\n/**\n * Stage every change in the working tree (`git add -A`), including untracked and deleted files.\n */\nexport async function stageAll(cwd: string): Promise<void> {\n await git(['add', '-A'], cwd);\n}\n\n/**\n * Whether a merge is currently in progress (MERGE_HEAD present), in a linked worktree too.\n */\nexport async function mergeInProgress(cwd: string): Promise<boolean> {\n return (await git(['rev-parse', '-q', '--verify', 'MERGE_HEAD'], cwd, { ignoreErrors: true })) !== '';\n}\n\nexport async function getShortSha(cwd: string, ref: string): Promise<string> {\n return git(['rev-parse', '--short', ref], cwd);\n}\n\nexport async function getWorkingTreeChangeCount(cwd: string): Promise<number> {\n const status = await git(['status', '--porcelain'], cwd);\n if (!status) return 0;\n return status.split('\\n').filter(Boolean).length;\n}\n\nasync function remoteExists(cwd: string, remoteName: string): Promise<boolean> {\n const remotes = await git(['remote'], cwd);\n return remotes.split('\\n').includes(remoteName);\n}\n\n/** Add the remote, or point an existing one at `url`. */\nexport async function ensureRemote(cwd: string, remoteName: string, url: string): Promise<void> {\n if (await remoteExists(cwd, remoteName)) {\n await git(['remote', 'set-url', remoteName, url], cwd);\n } else {\n await git(['remote', 'add', remoteName, url], cwd);\n }\n}\n\nexport async function fetchRemote(cwd: string, remoteName: string): Promise<void> {\n await git(['fetch', remoteName], cwd);\n}\n\n/**\n * Fetch upstream tags into a remote-scoped namespace (`refs/<remoteName>/tags/*`),\n * never the local `refs/tags/*`. This keeps cella's release tags from\n * colliding with the fork's own release tags (forks run their own release-please).\n * `--no-tags` prevents git from also writing them into `refs/tags/*`.\n */\nexport async function fetchUpstreamTags(cwd: string, remoteName: string): Promise<void> {\n await git(['fetch', remoteName, '--no-tags', `+refs/tags/*:refs/${remoteName}/tags/*`], cwd);\n}\n\n/**\n * A template release tag is a version, with or without the `v` prefix (`0.18.1`, `v0.5.0`).\n * Component tags (`create-cella-0.2.3`) and other namespaces (`archive/pre-release`) start with a name.\n */\nconst releaseTagPattern = /^v?\\d[\\w.+-]*$/;\n\n/**\n * Resolve the latest upstream release tag (the highest version tag) from the\n * remote-scoped tag namespace. Returns the short tag name and its full ref, or null\n * when no release exists.\n */\nexport async function resolveLatestReleaseTag(\n cwd: string,\n remoteName: string,\n): Promise<{ tag: string; ref: string } | null> {\n const prefix = `refs/${remoteName}/tags/`;\n const output = await git(['for-each-ref', '--sort=-version:refname', '--format=%(refname)', prefix], cwd, {\n ignoreErrors: true,\n });\n if (!output) return null;\n for (const line of output.split('\\n')) {\n const ref = line.trim();\n if (!ref) continue;\n const tag = ref.slice(prefix.length);\n if (releaseTagPattern.test(tag)) return { tag, ref };\n }\n return null;\n}\n\n/**\n * Resolve a ref named for upstream (`--ref`) to a commit: a branch on the upstream remote, then a\n * tag from the remote-scoped tag namespace, then the ref as given (a sha). Upstream names come\n * first, so `main` means upstream's main and `1.0.0` upstream's release, never the fork's own.\n * Revision suffixes work too (`main~2`). Returns the commit sha, plus the release tag when the\n * ref is a release tag name itself (`1.2.3`, not `1.2.3~1`); null when nothing resolves.\n */\nexport async function resolveUpstreamCommit(\n cwd: string,\n remoteName: string,\n ref: string,\n): Promise<{ sha: string; release?: { tag: string; ref: string } } | null> {\n if (ref.startsWith('-')) return null;\n const tagRef = `refs/${remoteName}/tags/${ref}`;\n for (const candidate of [`refs/remotes/${remoteName}/${ref}`, tagRef, ref]) {\n const sha = await git(['rev-parse', '-q', '--verify', `${candidate}^{commit}`], cwd, { ignoreErrors: true });\n if (!sha) continue;\n const release = candidate === tagRef && releaseTagPattern.test(ref) ? { tag: ref, ref: tagRef } : undefined;\n return { sha, release };\n }\n return null;\n}\n\n/**\n * Whether upstream published `sha`: reachable from the upstream branch (`branchRef`, e.g.\n * `cella-upstream/main`) or from an upstream release tag (remote-scoped namespace).\n */\nexport async function isPublishedUpstream(\n cwd: string,\n remoteName: string,\n branchRef: string,\n sha: string,\n): Promise<boolean> {\n const containing = await git(\n [\n 'for-each-ref',\n '--count=1',\n '--format=%(refname)',\n '--contains',\n sha,\n `refs/remotes/${branchRef}`,\n `refs/${remoteName}/tags/[0-9]*`,\n `refs/${remoteName}/tags/v[0-9]*`,\n ],\n cwd,\n { ignoreErrors: true },\n );\n return containing !== '';\n}\n\nexport async function getCommitInfo(cwd: string, ref: string): Promise<CommitRangeEntry> {\n const format = '%H%n%s%n%ar'; // hash, subject, relative date\n const output = await git(['log', '-1', `--format=${format}`, ref], cwd);\n const [hash, message, date] = output.split('\\n');\n return { hash, message, date };\n}\n\n/** The number of commits in `toRef` that are not in `fromRef`. */\nexport async function countCommitsBetween(cwd: string, fromRef: string, toRef: string): Promise<number> {\n const output = await git(['rev-list', '--count', `${fromRef}..${toRef}`], cwd);\n return Number.parseInt(output.trim(), 10) || 0;\n}\n\n/**\n * List commits in a ref range, oldest-first to match GitHub compare ordering.\n *\n * Supports skip+limit pagination so callers can show only the most recent N commits\n * without fetching the entire range.\n */\nexport async function listCommitsBetween(\n cwd: string,\n fromRef: string,\n toRef: string,\n options: {\n skip?: number;\n limit?: number;\n } = {},\n): Promise<CommitRangeEntry[]> {\n const { skip, limit } = options;\n const args = ['log', '--format=%H%x1f%s%x1f%ar', '--reverse', `${fromRef}..${toRef}`];\n\n const output = await git(args, cwd, { ignoreErrors: true });\n if (!output) return [];\n\n const commits: CommitRangeEntry[] = [];\n for (const line of output.split('\\n')) {\n if (!line) continue;\n const [hash, message, date] = line.split('\\x1f');\n if (!hash || !message || !date) continue;\n commits.push({ hash, message, date });\n }\n\n const start = Math.max(0, skip ?? 0);\n return limit && limit > 0 ? commits.slice(start, start + limit) : commits.slice(start);\n}\n\ninterface FileChangeInfo {\n date: string;\n hash: string;\n /** Unix epoch seconds of the change, for sorting */\n timestamp: number;\n}\n\n/**\n * Relative date and commit hash of the last change for every file in a range,\n * as filePath -> { date, hash, timestamp }; one `git log` call for the whole range.\n */\nexport async function getFileChangeInfo(\n cwd: string,\n fromRef: string,\n toRef: string,\n): Promise<Map<string, FileChangeInfo>> {\n const info = new Map<string, FileChangeInfo>();\n\n try {\n // Per commit: hash, epoch timestamp, relative date, then the list of files changed.\n const output = await git(['log', '--name-only', '--format=%h %ct %ar', `${fromRef}..${toRef}`], cwd, {\n ignoreErrors: true,\n });\n\n if (!output.trim()) return info;\n\n const lines = output.split('\\n');\n let currentHash = '';\n let currentDate = '';\n let currentTimestamp = 0;\n\n for (const line of lines) {\n if (!line) continue;\n\n // A commit header line: short hash, epoch timestamp, relative date.\n const match = line.match(/^([a-f0-9]{7,})\\s+(\\d+)\\s+(.+)$/);\n if (match) {\n currentHash = match[1];\n currentTimestamp = Number(match[2]);\n currentDate = match[3];\n } else if (currentHash && currentDate && !info.has(line)) {\n // A file path line; first write wins, so the most recent commit's info is kept.\n info.set(line, { date: currentDate, hash: currentHash, timestamp: currentTimestamp });\n }\n }\n } catch {\n // Ignore errors, return empty map\n }\n\n return info;\n}\n\n/** Whether the working tree is clean (no uncommitted changes). */\nexport async function isClean(cwd: string): Promise<boolean> {\n const status = await git(['status', '--porcelain'], cwd);\n return !status;\n}\n\n/**\n * Throw if the working tree has uncommitted changes.\n * `subject` labels the repo in the error (e.g. 'working directory', 'fork').\n */\nexport async function assertClean(cwd: string, subject = 'working directory'): Promise<void> {\n if (!(await isClean(cwd))) {\n throw new Error(`${subject} has uncommitted changes. please commit or stash before syncing.`);\n }\n}\n\n/** Create a worktree detached at a commit; --detach avoids \"branch already checked out\" errors. */\nexport async function createWorktree(cwd: string, worktreePath: string, commitRef: string): Promise<void> {\n await git(['worktree', 'add', '--detach', worktreePath, commitRef], cwd);\n}\n\nexport async function removeWorktree(cwd: string, worktreePath: string): Promise<void> {\n await git(['worktree', 'remove', worktreePath, '--force'], cwd, { ignoreErrors: true });\n await git(['worktree', 'prune'], cwd, { ignoreErrors: true });\n}\n\nexport async function listWorktrees(cwd: string): Promise<string[]> {\n const output = await git(['worktree', 'list', '--porcelain'], cwd);\n const lines = output.split('\\n');\n const paths: string[] = [];\n for (const line of lines) {\n if (line.startsWith('worktree ')) {\n paths.push(line.slice(9));\n }\n }\n return paths;\n}\n\n/**\n * Perform a merge in the current directory, leaving it staged (--no-commit --no-edit).\n * Always uses --no-ff to prevent fast-forward, ensuring HEAD stays in place\n * and MERGE_HEAD is created for proper merge state tracking.\n */\nexport async function merge(cwd: string, ref: string): Promise<{ success: boolean; conflicts: string[] }> {\n try {\n await git(['merge', '--no-ff', '--no-commit', '--no-edit', ref], cwd, { skipEditor: true });\n return { success: true, conflicts: [] };\n } catch (error) {\n const conflicts = await getConflictedFiles(cwd);\n if (conflicts.length > 0) {\n return { success: false, conflicts };\n }\n throw error;\n }\n}\n\nexport async function getConflictedFiles(cwd: string): Promise<string[]> {\n const output = await git(['diff', '--name-only', '--diff-filter=U'], cwd, { ignoreErrors: true });\n if (!output) return [];\n return output.split('\\n').filter(Boolean);\n}\n\nexport async function mergeAbort(cwd: string): Promise<void> {\n await git(['merge', '--abort'], cwd, { ignoreErrors: true });\n}\n\nexport async function fileExistsAtRef(cwd: string, ref: string, filePath: string): Promise<boolean> {\n const result = await git(['ls-tree', '--name-only', ref, '--', filePath], cwd, { ignoreErrors: true });\n return result !== '';\n}\n\n/** Check out a file from a ref into index and worktree (restores upstream files missing in the fork). */\nexport async function checkoutFromRef(cwd: string, ref: string, filePath: string): Promise<void> {\n await git(['checkout', ref, '--', filePath], cwd);\n}\n\n/**\n * Restore a path from a ref into the working tree only, leaving the index untouched,\n * so adopted changes remain unstaged for review.\n */\nexport async function restoreWorktreeFromRef(cwd: string, ref: string, filePath: string): Promise<void> {\n await git(['restore', `--source=${ref}`, '--worktree', '--', filePath], cwd);\n}\n\n/**\n * Restore paths from a ref into the working tree only, in batches, leaving the index untouched.\n * Paths are taken literally, so a file name with glob characters (`[id].tsx`) restores that file.\n */\nexport async function batchRestoreWorktreeFromRef(cwd: string, ref: string, filePaths: string[]): Promise<void> {\n const batchSize = 200;\n for (let i = 0; i < filePaths.length; i += batchSize) {\n const batch = filePaths.slice(i, i + batchSize);\n await git(['--literal-pathspecs', 'restore', `--source=${ref}`, '--worktree', '--', ...batch], cwd);\n }\n}\n\n/**\n * Paths at `ref` whose working tree copy is byte-identical to it. Renames are not detected, so a\n * file the working tree moved away counts as changed at its old path.\n */\nexport async function listIdenticalToRef(cwd: string, ref: string): Promise<Set<string>> {\n const nulSeparated = (out: string) => out.split('\\0').filter(Boolean);\n const [tracked, changed] = await Promise.all([\n git(['ls-tree', '-r', '--name-only', '-z', ref], cwd),\n git(['diff', '--name-only', '--no-renames', '-z', ref, '--'], cwd),\n ]);\n const differs = new Set(nulSeparated(changed));\n return new Set(nulSeparated(tracked).filter((path) => !differs.has(path)));\n}\n\nexport async function getMergeBase(cwd: string, ref1: string, ref2: string): Promise<string> {\n return git(['merge-base', ref1, ref2], cwd);\n}\n\n/** File change status codes from git diff-tree */\ntype FileChangeStatus = 'A' | 'D' | 'M' | 'T' | 'R';\n\n/** File change info from git diff-tree */\ninterface FileChange {\n status: FileChangeStatus;\n baseHash: string | null;\n targetHash: string | null;\n /** For renames: the original path (before rename) */\n oldPath?: string;\n}\n\n/**\n * Files changed between two refs (`git diff-tree -r -M90%`), as filePath -> FileChange.\n * Status codes: A=added, D=deleted, M=modified, T=type-changed, R=renamed (90% similarity\n * threshold). A rename is keyed by its NEW path, with `oldPath` stored in the value.\n */\nexport async function getFileChanges(\n cwd: string,\n baseRef: string,\n targetRef: string,\n): Promise<Map<string, FileChange>> {\n // Format for non-renames: :oldmode newmode oldhash newhash status\\tpath\n // Format for renames: :oldmode newmode oldhash newhash Rxx\\toldpath\\tnewpath\n const output = await git(['diff-tree', '-r', '-M90%', '--no-commit-id', baseRef, targetRef], cwd, {\n ignoreErrors: true,\n });\n\n const changes = new Map<string, FileChange>();\n\n if (!output) return changes;\n\n // diff-tree prints the all-zero hash for a missing side (added/deleted files).\n const hashOrNull = (hash: string) => (hash === '0'.repeat(40) ? null : hash);\n\n for (const line of output.split('\\n')) {\n if (!line) continue;\n\n // Rename lines: a space after Rxx, then a tab between the old and new paths.\n const renameMatch = line.match(/^:\\d+ \\d+ ([a-f0-9]+) ([a-f0-9]+) R\\d*\\s+(.+)\\t(.+)$/);\n if (renameMatch) {\n const [, baseHash, targetHash, oldPath, newPath] = renameMatch;\n changes.set(newPath, {\n status: 'R',\n baseHash: hashOrNull(baseHash),\n targetHash: hashOrNull(targetHash),\n oldPath,\n });\n continue;\n }\n\n // Parse non-rename: :100644 100644 abc123... def456... M\\tpath/to/file\n const match = line.match(/^:\\d+ \\d+ ([a-f0-9]+) ([a-f0-9]+) ([ADMT])\\t(.+)$/);\n if (match) {\n const [, baseHash, targetHash, status, filePath] = match;\n changes.set(filePath, {\n status: status as 'A' | 'D' | 'M' | 'T',\n baseHash: hashOrNull(baseHash),\n targetHash: hashOrNull(targetHash),\n });\n }\n }\n\n return changes;\n}\n\n/** Lines added/removed for one path (`null` for binary files, where git reports `-`). */\ninterface DiffStat {\n additions: number | null;\n deletions: number | null;\n}\n\n/**\n * Lines added/removed per file between two refs (`git diff --numstat`), optionally limited\n * to `paths`. Renames are not detected (`--no-renames`) so every entry is keyed by its plain\n * path, never git's `old => new` notation.\n */\nexport async function getDiffStat(\n cwd: string,\n fromRef: string,\n toRef: string,\n paths: string[] = [],\n): Promise<Map<string, DiffStat>> {\n const args = ['diff', '--numstat', '--no-renames', fromRef, toRef];\n if (paths.length > 0) args.push('--', ...paths);\n const out = await git(args, cwd, { ignoreErrors: true });\n\n const stat = new Map<string, DiffStat>();\n for (const line of out.split('\\n')) {\n if (!line.trim()) continue;\n const [a, d, ...rest] = line.split('\\t');\n const path = rest.join('\\t');\n if (!path) continue;\n stat.set(path, {\n additions: a === '-' ? null : Number(a),\n deletions: d === '-' ? null : Number(d),\n });\n }\n return stat;\n}\n\n/** All file hashes at a ref (one `ls-tree -r` call), as filePath -> hash. */\nexport async function getFileHashesAtRef(cwd: string, ref: string): Promise<Map<string, string>> {\n const output = await git(['ls-tree', '-r', ref], cwd);\n const hashes = new Map<string, string>();\n\n if (!output) return hashes;\n\n for (const line of output.split('\\n')) {\n if (!line) continue;\n // Parse: <mode> <type> <hash>\\t<path>\n const match = line.match(/^\\d+ \\w+ ([a-f0-9]+)\\t(.+)$/);\n if (match) {\n const [, hash, filePath] = match;\n hashes.set(filePath, hash);\n }\n }\n\n return hashes;\n}\n\n/**\n * Restore a file to its HEAD version (our version during a merge), in both index and worktree.\n *\n * Uses `git checkout HEAD --` because `git restore --source=HEAD` fails on unmerged\n * (conflicted) paths during a merge; checkout resolves them by taking HEAD's version.\n */\nexport async function restoreToHead(cwd: string, filePath: string): Promise<void> {\n await git(['checkout', 'HEAD', '--', filePath], cwd);\n}\n\n/**\n * Restore multiple files to their HEAD version in a single git command, which also\n * keeps IDE file-watcher churn down.\n *\n * Uses `git checkout HEAD --` because `git restore --source=HEAD` fails on unmerged\n * (conflicted) paths during a merge; checkout resolves them by taking HEAD's version.\n */\nexport async function batchRestoreToHead(cwd: string, filePaths: string[]): Promise<void> {\n if (filePaths.length === 0) return;\n await git(['checkout', 'HEAD', '--', ...filePaths], cwd);\n}\n\n/** Tracked delete (`git rm -f`): records a deletion in the merge result. */\nasync function gitRm(cwd: string, filePath: string): Promise<void> {\n await git(['rm', '-f', '--', filePath], cwd, { ignoreErrors: true });\n}\n\n/** Tracked delete for multiple files in a single git command. */\nexport async function batchGitRm(cwd: string, filePaths: string[]): Promise<void> {\n if (filePaths.length === 0) return;\n await git(['rm', '-f', '--', ...filePaths], cwd, { ignoreErrors: true });\n}\n\n/** Files staged as new additions vs HEAD (diff-filter=A): absent at HEAD, brought in by a merge. */\nexport async function getStagedNewFiles(cwd: string): Promise<string[]> {\n const output = await git(['diff', '--cached', '--name-only', '--diff-filter=A'], cwd, { ignoreErrors: true });\n return output ? output.split('\\n').filter(Boolean) : [];\n}\n\n/**\n * Remove files from the index only (--cached), leaving the working tree untouched,\n * for files staged by a merge that shouldn't be committed.\n */\nexport async function batchUnstageFiles(cwd: string, filePaths: string[]): Promise<void> {\n if (filePaths.length === 0) return;\n await git(['rm', '--cached', '-f', '--', ...filePaths], cwd, { ignoreErrors: true });\n}\n\n/** Move a file (`git mv -f`), creating parent directories as needed. */\nexport async function gitMv(cwd: string, oldPath: string, newPath: string): Promise<void> {\n const newDir = dirname(join(cwd, newPath));\n await mkdir(newDir, { recursive: true });\n\n await git(['mv', '-f', oldPath, newPath], cwd);\n}\n\nexport async function fileExistsInWorktree(cwd: string, filePath: string): Promise<boolean> {\n return existsSync(join(cwd, filePath));\n}\n\n/**\n * Remove a file from the worktree filesystem if it exists.\n * Used to clean up files that git rm may not have removed (e.g., after squash merge).\n */\nexport async function removeFileFromWorktree(cwd: string, filePath: string): Promise<void> {\n const fullPath = join(cwd, filePath);\n try {\n await unlink(fullPath);\n await cleanupEmptyParentDirs(cwd, dirname(filePath));\n } catch {\n // File missing or not removable: ignore\n }\n}\n\n/**\n * Fully remove a file: tracked delete from the index (git rm) plus filesystem removal\n * for cases git rm leaves behind (e.g. during a merge), including empty parent dirs.\n */\nexport async function removeFileFully(cwd: string, filePath: string): Promise<void> {\n await gitRm(cwd, filePath);\n await removeFileFromWorktree(cwd, filePath);\n}\n\n/**\n * Recursively remove empty parent directories up to (but not including) the root.\n * Stops when encountering a non-empty directory or the root.\n */\nasync function cleanupEmptyParentDirs(cwd: string, relativePath: string): Promise<void> {\n if (!relativePath || relativePath === '.') return;\n\n const fullPath = join(cwd, relativePath);\n try {\n const entries = await readdir(fullPath);\n if (entries.length === 0) {\n await rmdir(fullPath);\n await cleanupEmptyParentDirs(cwd, dirname(relativePath));\n }\n } catch {\n // Directory missing, not empty, or not removable: stop\n }\n}\n\n// Sync ref tracking and merge-base recovery.\n\n/**\n * Store the upstream commit hash after a successful sync.\n * Used to recover correct merge-base when squash strategy creates single-parent commits.\n *\n * Also records the fork HEAD at store time as `refs/cella/last-sync-head`. The last-sync\n * ref is written while the merge is still staged (before the user commits), so it cannot be\n * trusted on its own: if the user runs `git merge --abort`, HEAD never advances and the ref\n * is left pointing at an upstream commit that was never actually integrated. Recording HEAD\n * lets `getEffectiveMergeBase` detect that an aborted/uncommitted merge produced a stale ref.\n */\nexport async function storeLastSyncRef(cwd: string, upstreamHash: string): Promise<void> {\n await git(['update-ref', 'refs/cella/last-sync', upstreamHash], cwd);\n const head = await git(['rev-parse', 'HEAD'], cwd, { ignoreErrors: true });\n if (head) {\n await git(['update-ref', 'refs/cella/last-sync-head', head], cwd);\n }\n}\n\n/** Stage a single path (git add). Best-effort: never throws. */\nexport async function stagePath(cwd: string, path: string): Promise<void> {\n await git(['add', '--', path], cwd, { ignoreErrors: true });\n}\n\n/** The stored last-sync upstream ref, or null when no sync has been recorded. */\nexport async function getStoredSyncRef(cwd: string): Promise<string | null> {\n const ref = await git(['rev-parse', 'refs/cella/last-sync'], cwd, { ignoreErrors: true });\n return ref || null;\n}\n\n/** The fork HEAD recorded when the last-sync ref was stored, or null. */\nasync function getStoredSyncHead(cwd: string): Promise<string | null> {\n const ref = await git(['rev-parse', 'refs/cella/last-sync-head'], cwd, { ignoreErrors: true });\n return ref || null;\n}\n\n/**\n * Read the sync manifest committed at a specific ref.\n *\n * This intentionally reads from git, not the working tree: a staged/aborted sync can leave the\n * worktree manifest ahead of the committed trunk, and that must not validate a sync point.\n */\nexport async function readManifestAtRef(cwd: string, ref: string): Promise<SyncManifest | null> {\n const raw = await git(['show', `${ref}:${MANIFEST_FILE}`], cwd, { ignoreErrors: true });\n if (!raw) return null;\n return parseSyncManifest(raw);\n}\n\n/** The upstream base commit SHA from the manifest committed at `ref`, or null. */\nexport async function readManifestBaseAtRef(cwd: string, ref: string): Promise<string | null> {\n const manifest = await readManifestAtRef(cwd, ref);\n return manifest ? manifest.upstream.commit.toLowerCase() : null;\n}\n\n/**\n * Read the `version` field of the root `package.json` committed at a ref.\n * Returns null when the file is absent or unparsable.\n */\nexport async function readPackageVersionAtRef(cwd: string, ref: string): Promise<string | null> {\n const raw = await git(['show', `${ref}:package.json`], cwd, { ignoreErrors: true });\n if (!raw) return null;\n\n try {\n const version = (JSON.parse(raw) as { version?: unknown }).version;\n return typeof version === 'string' && version ? version : null;\n } catch {\n return null;\n }\n}\n\n/** Whether a commit object is present in the local object store. */\nasync function commitObjectExists(cwd: string, sha: string): Promise<boolean> {\n try {\n await git(['cat-file', '-e', `${sha}^{commit}`], cwd);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The root (parentless) commit of a ref's history. A create-cella scaffold has a\n * single rootless \"Initial commit\" whose tree is a frozen snapshot of the upstream\n * template at scaffold time. Returns null when no root is found.\n */\nasync function getRootCommit(cwd: string, ref: string): Promise<string | null> {\n const out = await git(['rev-list', '--max-parents=0', ref], cwd, { ignoreErrors: true });\n const roots = out.split('\\n').filter(Boolean);\n return roots.length > 0 ? roots[roots.length - 1] : null;\n}\n\n/** Max upstream commits scored when inferring a scaffold base by tree similarity. */\nconst SCAFFOLD_CANDIDATE_LIMIT = 400;\n\n/** Concurrent diff-tree scoring calls during scaffold-base inference. */\nconst SCAFFOLD_SCORE_CONCURRENCY = 10;\n\n/**\n * Reject an inferred scaffold base when more than this fraction of the root snapshot's\n * paths differ from the best-matching upstream commit. The template cleaner rewrites a\n * fixed handful of files and deselected optional modules remove a few folders, so a real\n * scaffold stays far below this; a hand-rolled repo blows past it.\n */\nconst SCAFFOLD_MATCH_MAX_DIFF_RATIO = 0.3;\n\n/**\n * Infer the upstream commit a scaffold was created from, by tree similarity.\n *\n * A create-cella scaffold's root commit is a frozen snapshot of the upstream tree at\n * scaffold time: the template cleaner only rewrites a handful of files (project name,\n * ports, changelog) and drops deselected module folders, so the vast majority of paths\n * stay byte-identical to exactly one upstream commit. Diff the root tree against recent\n * upstream commits and take the closest match; no provenance file is needed.\n *\n * Candidates are bounded to upstream commits no newer than the root commit (plus a\n * clock-skew margin): the scaffold cannot come from a commit that didn't exist yet.\n * Neighboring candidates can tie when the commits between them only touch files the\n * scaffold rewrote anyway (upstream release commits do exactly this); either tie is a\n * correct base for the 3-way merge, and newest wins.\n *\n * Returns null when no candidate matches convincingly (see SCAFFOLD_MATCH_MAX_DIFF_RATIO).\n */\nasync function inferScaffoldBase(cwd: string, headRef: string, upstreamRef: string): Promise<string | null> {\n const root = await getRootCommit(cwd, headRef);\n if (!root) return null;\n\n const rootDate = await git(['show', '-s', '--format=%cI', root], cwd, { ignoreErrors: true });\n if (!rootDate) return null;\n // A day of margin absorbs clock skew between the scaffolding machine and upstream committers.\n const before = new Date(new Date(rootDate).getTime() + 24 * 60 * 60 * 1000).toISOString();\n\n const revList = await git(\n ['rev-list', `--max-count=${SCAFFOLD_CANDIDATE_LIMIT}`, `--before=${before}`, upstreamRef],\n cwd,\n { ignoreErrors: true },\n );\n const candidates = revList.split('\\n').filter(Boolean);\n if (candidates.length === 0) return null;\n\n const totalPaths = (await git(['ls-tree', '-r', '--name-only', root], cwd)).split('\\n').filter(Boolean).length;\n if (totalPaths === 0) return null;\n\n // Score = differing paths between candidate and root snapshot. rev-list is newest-first\n // and strict `<` keeps the first (newest) candidate on ties.\n let best: { sha: string; diff: number } | null = null;\n outer: for (let i = 0; i < candidates.length; i += SCAFFOLD_SCORE_CONCURRENCY) {\n const chunk = candidates.slice(i, i + SCAFFOLD_SCORE_CONCURRENCY);\n const scores = await Promise.all(\n chunk.map(async (sha) => {\n try {\n const out = await git(['diff-tree', '-r', '--name-only', sha, root], cwd);\n return { sha, diff: out ? out.split('\\n').length : 0 };\n } catch {\n return { sha, diff: Number.POSITIVE_INFINITY };\n }\n }),\n );\n for (const score of scores) {\n if (!best || score.diff < best.diff) best = score;\n if (best.diff === 0) break outer; // byte-identical snapshot, cannot do better\n }\n }\n\n if (!best || best.diff / totalPaths > SCAFFOLD_MATCH_MAX_DIFF_RATIO) return null;\n return best.sha;\n}\n\n/**\n * Read the scaffold provenance trailer from the fork's root commit message.\n *\n * create-cella stamps `Cella-Base: <sha>` on the initial commit, recording the exact\n * upstream commit the scaffold snapshot was taken from. Riding in commit history, it\n * travels with push/clone (a local ref does not) and needs no file in the worktree.\n */\nasync function readRootTrailerBase(cwd: string, headRef: string): Promise<string | null> {\n const root = await getRootCommit(cwd, headRef);\n if (!root) return null;\n const message = await git(['show', '-s', '--format=%B', root], cwd, { ignoreErrors: true });\n const match = message.match(/^cella-base:\\s*([0-9a-f]{40})$/im);\n return match ? match[1].toLowerCase() : null;\n}\n\n/**\n * Whether the repository is a shallow clone (created with `git clone --depth`, or otherwise\n * carrying a `.git/shallow` graft). Shallow history is truncated below the graft point, so the\n * real common ancestor with upstream is absent: `git merge-base` finds nothing even when one\n * exists in the full history, and the 3-way file analysis walks an incomplete commit graph.\n */\nasync function isShallowRepository(cwd: string): Promise<boolean> {\n const out = await git(['rev-parse', '--is-shallow-repository'], cwd, { ignoreErrors: true });\n return out === 'true';\n}\n\n/**\n * Restore full history on a shallow clone by fetching from its own origin, so merge-base and the\n * 3-way analysis see the real commit graph. Grafting cannot recover this case (the intermediate\n * commits are genuinely missing, not just disconnected), so the history is deepened for real.\n *\n * Throws an actionable error when the history cannot be restored (e.g. no reachable origin),\n * because sync cannot run correctly against truncated history.\n */\nasync function unshallowRepository(cwd: string): Promise<void> {\n try {\n await git(['fetch', '--unshallow'], cwd, { skipEditor: true });\n } catch (error) {\n const detail = error instanceof Error ? `\\n\\n${error.message}` : '';\n throw new Error(\n 'this is a shallow clone and its full history could not be restored automatically.\\n' +\n 'Sync needs the complete history to find the common ancestor with upstream. Restore it with:\\n\\n' +\n ' git fetch --unshallow\\n\\n' +\n `then re-run sync.${detail}`,\n );\n }\n}\n\n/**\n * Ensure a native git merge-base exists between the fork and upstream.\n *\n * A create-cella scaffold, or a fork whose upstream squashed its history, has unrelated\n * histories, so `git merge-base` finds nothing and every sync fails at the very first step.\n * This bootstraps ancestry non-destructively:\n * 0. If the repo is a shallow clone, restore its full history first: the real ancestor is\n * truncated away, so no graft can recover it; deepening the history brings it back.\n * 1. If a native merge-base already exists, do nothing (the common case).\n * 2. Otherwise resolve the logical base commit: sources are tried in order and the first\n * one whose commit actually exists after the upstream fetch wins: the sync-point\n * record (`refs/cella/last-sync` ref, then committed/worktree `cella/cella.manifest.json`),\n * then the scaffold origin (the root commit's `Cella-Base:` trailer, then tree-similarity\n * inference as reseed fallback for scaffolds whose trailer is absent or stale).\n * 3. Graft the fork's root commit onto that base with `git replace --graft`, so every native\n * git operation (merge-base and the 3-way merge itself) sees correct ancestry. The replace\n * ref is local-only and never pushed, so the fork's own published history stays clean.\n *\n * Throws an actionable error when no valid base can be determined.\n */\nexport async function ensureSyncBase(cwd: string, headRef: string, upstreamRef: string): Promise<void> {\n // A shallow clone has its history truncated below the graft point, so the real common ancestor\n // is absent and merge-base finds nothing. Restore the full history first: this is not unrelated\n // history to graft over, it is real history to bring back.\n if (await isShallowRepository(cwd)) {\n await unshallowRepository(cwd);\n }\n\n // Native ancestry already present: nothing to bootstrap.\n const nativeBase = await git(['merge-base', headRef, upstreamRef], cwd, { ignoreErrors: true });\n if (nativeBase) return;\n\n const sources: Array<() => Promise<string | null>> = [\n () => getStoredSyncRef(cwd),\n () => readManifestBaseAtRef(cwd, headRef),\n () => readManifestBase(cwd),\n () => readRootTrailerBase(cwd, headRef),\n () => inferScaffoldBase(cwd, headRef, upstreamRef),\n ];\n\n let baseSha: string | null = null;\n for (const source of sources) {\n const sha = await source();\n if (sha && (await commitObjectExists(cwd, sha))) {\n baseSha = sha;\n break;\n }\n }\n if (!baseSha) {\n throw new Error(\n `no common ancestor between the fork and '${upstreamRef}', and no sync base could be determined.\\n\\n` +\n 'This fork has unrelated history with upstream (typical for a create-cella scaffold, or after\\n' +\n 'upstream squashed its history) and no recorded or inferable base commit exists after fetching\\n' +\n 'upstream. Seed it manually with the upstream commit the fork was created from, then re-run sync:\\n\\n' +\n ' git update-ref refs/cella/last-sync <upstream-sha>\\n',\n );\n }\n\n const root = await getRootCommit(cwd, headRef);\n if (!root) throw new Error(\"could not determine the fork's root commit to bootstrap sync ancestry\");\n\n // Graft the fork root onto the base (idempotent via -f) so native git sees the ancestry.\n await git(['replace', '-f', '--graft', root, baseSha], cwd);\n\n // Record the base as the last-sync ref so future runs and the squash strategy stay consistent.\n await git(['update-ref', 'refs/cella/last-sync', baseSha], cwd);\n}\n\n/** Whether `ancestor` is an ancestor of `descendant`. */\nexport async function isAncestor(cwd: string, ancestor: string, descendant: string): Promise<boolean> {\n try {\n await git(['merge-base', '--is-ancestor', ancestor, descendant], cwd);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Legacy sync point for forks that last synced before the manifest was committed: the local\n * last-sync ref, guarded against aborted merges. The ref is written while the merge is still\n * staged; if the user ran `git merge --abort` without committing, HEAD never advanced past\n * the recorded sync HEAD and the upstream commits were never integrated, so the ref is discarded.\n */\nasync function getLegacySyncRef(cwd: string, headRef: string): Promise<string | null> {\n const storedRef = await getStoredSyncRef(cwd);\n if (!storedRef) return null;\n\n const storedHead = await getStoredSyncHead(cwd);\n if (storedHead) {\n const currentHead = await git(['rev-parse', headRef], cwd, { ignoreErrors: true });\n if (currentHead && currentHead === storedHead) return null;\n }\n\n return storedRef;\n}\n\n/**\n * The effective merge-base, preferring the recorded sync point when it's more recent.\n * This handles stale merge-base caused by previous squash syncs (single-parent commits\n * don't update git's merge-base graph).\n *\n * The manifest committed at `headRef` is the authoritative record: the sync engine stages it\n * inside every applied sync, so it lands iff the sync commit lands. That makes it immune to\n * aborted merges (never committed) and available on fresh clones and other machines (it\n * travels with the repo, unlike local refs). The local last-sync ref is only consulted as a\n * fallback for forks whose last sync predates the manifest.\n *\n * @returns The effective base commit, whether git's base was stale, and the recorded sync point\n */\nexport async function getEffectiveMergeBase(\n cwd: string,\n headRef: string,\n upstreamRef: string,\n): Promise<{ base: string; isStale: boolean; storedRef: string | null }> {\n const gitBase = await getMergeBase(cwd, headRef, upstreamRef);\n\n const recorded = (await readManifestBaseAtRef(cwd, headRef)) ?? (await getLegacySyncRef(cwd, headRef));\n if (!recorded) {\n return { base: gitBase, isStale: false, storedRef: null };\n }\n\n // Only prefer the recorded sync point when it is actually newer than git's own answer.\n const recordedIsNewer = await isAncestor(cwd, gitBase, recorded);\n if (recordedIsNewer && recorded !== gitBase) {\n return { base: recorded, isStale: true, storedRef: recorded };\n }\n\n return { base: gitBase, isStale: false, storedRef: recorded };\n}\n\n/**\n * Run `fn` with a temporary local graft that makes `baseSha` an ancestor of `headRef`, so\n * native git operations (merge-base resolution and the 3-way merge itself) see the recorded\n * sync point, not a stale historical ancestor.\n *\n * Squash syncs advance the recorded sync point (manifest + `refs/cella/last-sync`) without\n * advancing git's commit graph, so a plain `git merge` replays every upstream change since the\n * last true merge ancestor: hunks the fork already integrated (or deliberately resolved away)\n * re-apply as clean auto-merges or re-conflict on every sync. The graft adds `baseSha` as an\n * extra parent of the `headRef` commit via `git replace --graft`; replace refs are local-only\n * and the ref is deleted right after `fn`, so nothing ever leaks into pushed history.\n *\n * Runs `fn` without grafting when the graft is unnecessary or unsafe:\n * - `baseSha` is already an ancestor of `headRef` (git's own merge-base is not stale), or\n * - a replacement object already exists for the `headRef` commit (never clobber, e.g. the\n * scaffold root graft from {@link ensureSyncBase} when the root commit is HEAD).\n */\nexport async function withTemporarySyncBaseGraft<T>(\n cwd: string,\n headRef: string,\n baseSha: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const headSha = await git(['rev-parse', headRef], cwd, { ignoreErrors: true });\n if (!headSha || !(await commitObjectExists(cwd, baseSha))) return fn();\n\n // Native ancestry already covers the base: nothing to graft.\n if (await isAncestor(cwd, baseSha, headSha)) return fn();\n\n // Never clobber an existing replacement object for this commit.\n const existingReplacement = await git(['replace', '-l', headSha], cwd, { ignoreErrors: true });\n if (existingReplacement) return fn();\n\n const parentsRaw = await git(['log', '-1', '--format=%P', headSha], cwd, { ignoreErrors: true });\n const parents = parentsRaw ? parentsRaw.split(/\\s+/) : [];\n\n await git(['replace', '-f', '--graft', headSha, ...parents, baseSha], cwd);\n try {\n return await fn();\n } finally {\n await git(['replace', '-d', headSha], cwd, { ignoreErrors: true });\n }\n}\n","/**\n * Cella sync manifest.\n *\n * A committed record of the last upstream sync point, living in the fork's `cella/` folder as\n * `cella/cella.manifest.json`. It serves two purposes:\n * 1. Machine: `upstream.commit` is the bootstrap seed `ensureSyncBase` uses to reconstruct\n * the merge-base on a clone that has no local `refs/cella/last-sync` (fresh clone, CI, a\n * second maintainer). Committed, so it travels with the repo (a local ref does not).\n * 2. Human: records the upstream repo, tracking mode, release/commit and a GitHub link, so\n * each sync PR shows exactly which upstream point you moved to.\n *\n * Written and staged by the sync engine on every applied sync, so it stays in lockstep with\n * `refs/cella/last-sync` and rides along in the sync commit.\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\n/** Committed manifest path, relative to the fork repo root. */\nexport const MANIFEST_FILE = 'cella/cella.manifest.json';\n\n/** The last upstream sync point recorded in {@link MANIFEST_FILE}. */\nexport interface SyncManifest {\n upstream: {\n /** GitHub slug of the upstream repo, e.g. 'cellajs/cella'. */\n repo?: string;\n /** Tracking mode at sync time. */\n track?: 'release' | 'branch';\n /** Integrated upstream commit SHA: the merge-base bootstrap seed. */\n commit: string;\n /** Release tag when tracking releases, else null. */\n release?: string | null;\n /** Human-readable link to the commit or release on GitHub. */\n url?: string;\n /** UTC timestamp of the sync (ISO 8601). */\n syncedAt?: string;\n };\n}\n\n/** Parse and validate raw manifest JSON. Returns null when malformed or missing a 40-hex upstream commit. */\nexport function parseSyncManifest(raw: string): SyncManifest | null {\n try {\n const parsed = JSON.parse(raw) as SyncManifest;\n const commit = parsed?.upstream?.commit;\n if (typeof commit !== 'string' || !/^[0-9a-f]{40}$/i.test(commit)) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\n/** Read and validate the manifest. Returns null when absent or malformed. */\nexport async function readSyncManifest(cwd: string): Promise<SyncManifest | null> {\n try {\n return parseSyncManifest(await readFile(join(cwd, MANIFEST_FILE), 'utf8'));\n } catch {\n return null;\n }\n}\n\n/**\n * Return the recorded upstream base commit SHA, or null.\n * Bootstrap seed for {@link ensureSyncBase} when no local `refs/cella/last-sync` exists.\n */\nexport async function readManifestBase(cwd: string): Promise<string | null> {\n const manifest = await readSyncManifest(cwd);\n return manifest ? manifest.upstream.commit.toLowerCase() : null;\n}\n\n/** Write the manifest as pretty JSON with a trailing newline. */\nexport async function writeSyncManifest(cwd: string, manifest: SyncManifest): Promise<void> {\n const manifestPath = join(cwd, MANIFEST_FILE);\n // Ensure the cella/ folder exists (a fresh fork may not have it yet on first sync).\n await mkdir(dirname(manifestPath), { recursive: true });\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\n}\n","/**\n * Upstream migration notes, read from git.\n *\n * Upstream ships one note per sync-breaking change in `cella/migrations/<id>/`: a README.md that\n * opens with flat frontmatter, then the title and a summary paragraph, plus at most one codemod\n * (the one non-test `.ts` file). The folder is upstream-only: the sync never brings it into the\n * fork and removes a copy it finds. Notes are read from upstream commits the sync already fetched.\n *\n * The fork records only the notes it has not handled yet, in `cella/cella.migrations.json` as\n * `{ \"pending\": [...] }`. The sync adds the notes that arrive with it; `cella migrate --mark`\n * removes them. A missing file means nothing is pending, so a new app needs no seed. Notes are\n * information, never a gate: nothing blocks on a pending note.\n */\n\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { git } from './git';\n\n/** Upstream folder holding one subfolder per note. Upstream-only: never synced into a fork. */\nexport const NOTES_DIR = 'cella/migrations';\n\n/** The fork's record of notes still to handle. */\nexport const PENDING_FILE = 'cella/cella.migrations.json';\n\n/** A note folder name: `<YYYYMMDDThhmm>-<slug>`, UTC minute precision, so ids sort chronologically. */\nconst NOTE_ID = /^\\d{8}T\\d{4}-[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/** One note, as read at an upstream ref. */\nexport interface MigrationNote {\n id: string;\n /** The README's `# ` heading; the id when the README has none. */\n title: string;\n /** The paragraph under the title. */\n summary: string;\n /** Changes upstream in a way app-specific code must follow. */\n syncBreaking: boolean;\n /** Bumped `clientCacheVersion` or shipped a lens module. */\n clientCacheBump: boolean;\n /** Default scan roots for the codemod. */\n roots: string[];\n /** File name of the codemod inside the note folder, or null for a manual note. */\n codemod: string | null;\n}\n\n/** Whether a file in a note folder is a codemod script: a `.ts` file that is not a test. */\nexport function isCodemodFile(name: string): boolean {\n return name.endsWith('.ts') && !name.endsWith('.test.ts');\n}\n\n/** Whether a path is upstream-only: the sync never brings it in and removes a fork copy. */\nexport function isUpstreamOnly(filePath: string): boolean {\n return filePath === NOTES_DIR || filePath.startsWith(`${NOTES_DIR}/`);\n}\n\n/** The lines after the frontmatter, without HTML comment lines (a comment opens at the start of a line). */\nfunction bodyLines(lines: string[]): string[] {\n let inComment = false;\n return lines.filter((line) => {\n if (!inComment && !line.trimStart().startsWith('<!--')) return true;\n inComment = !line.includes('-->');\n return false;\n });\n}\n\n/** Parse a note README. Unreadable frontmatter values fall back to false/empty. */\nexport function parseNote(id: string, source: string, fileNames: string[]): MigrationNote {\n const lines = source.replace(/\\r\\n/g, '\\n').split('\\n');\n const close = lines[0] === '---' ? lines.indexOf('---', 1) : -1;\n const meta = new Map<string, string>();\n for (const line of lines.slice(1, Math.max(close, 1))) {\n const match = /^(\\w+):\\s*(.*)$/.exec(line);\n if (match) meta.set(match[1], match[2].trim());\n }\n\n const body = bodyLines(lines.slice(close + 1)).join('\\n');\n const blocks = body\n .split(/\\n\\s*\\n/)\n .map((block) => block.trim())\n .filter(Boolean);\n const title = /^# (.+)$/.exec(blocks[0] ?? '')?.[1].trim();\n const summary = title && blocks[1] && !/^(#|>|[-*|]|```)/.test(blocks[1]) ? blocks[1].replace(/\\s*\\n\\s*/g, ' ') : '';\n\n return {\n id,\n title: title || id,\n summary,\n syncBreaking: meta.get('syncBreaking') === 'true',\n clientCacheBump: meta.get('clientCacheBump') === 'true',\n roots: (meta.get('roots') ?? '')\n .split(',')\n .map((root) => root.trim())\n .filter(Boolean),\n codemod: fileNames.find(isCodemodFile) ?? null,\n };\n}\n\n/** Ids of every note at `ref`, oldest first; empty when the ref has no notes folder. */\nexport async function listNoteIds(cwd: string, ref: string): Promise<string[]> {\n const out = await git(['ls-tree', '--name-only', `${ref}:${NOTES_DIR}`], cwd, { ignoreErrors: true });\n return out\n .split('\\n')\n .filter((name) => NOTE_ID.test(name))\n .sort();\n}\n\n/** One note at `ref`, or null when its README is not there. */\nexport async function readNote(cwd: string, ref: string, id: string): Promise<MigrationNote | null> {\n const source = await git(['show', `${ref}:${NOTES_DIR}/${id}/README.md`], cwd, { ignoreErrors: true });\n if (!source) return null;\n const files = await git(['ls-tree', '--name-only', `${ref}:${NOTES_DIR}/${id}`], cwd, { ignoreErrors: true });\n return parseNote(id, source, files.split('\\n').filter(Boolean));\n}\n\n/** Notes upstream added between two commits: present at `to`, absent at `from`. */\nexport async function arrivedNoteIds(cwd: string, from: string, to: string): Promise<string[]> {\n const [before, after] = await Promise.all([listNoteIds(cwd, from), listNoteIds(cwd, to)]);\n const known = new Set(before);\n return after.filter((id) => !known.has(id));\n}\n\n/**\n * The fork's pending note ids. A missing file is an empty list. A file still in the older\n * `{ \"applied\": [...] }` shape converts once: pending = notes at `syncRef` minus applied.\n */\nexport async function readPending(cwd: string, syncRef: string | null): Promise<string[]> {\n const path = join(cwd, PENDING_FILE);\n if (!existsSync(path)) return [];\n const parsed = JSON.parse(await readFile(path, 'utf8')) as { pending?: unknown; applied?: unknown };\n if (Array.isArray(parsed.pending)) return parsed.pending.filter((id): id is string => typeof id === 'string');\n if (!Array.isArray(parsed.applied) || !syncRef) return [];\n const applied = new Set(parsed.applied);\n return (await listNoteIds(cwd, syncRef)).filter((id) => !applied.has(id));\n}\n\n/** Write the pending ids, sorted and de-duplicated; an empty list deletes the file. */\nexport async function writePending(cwd: string, ids: string[]): Promise<void> {\n const path = join(cwd, PENDING_FILE);\n const pending = [...new Set(ids)].sort();\n if (pending.length === 0) {\n await rm(path, { force: true });\n return;\n }\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify({ pending }, null, 2)}\\n`, 'utf8');\n}\n\n/** GitHub permalink to a note's README at a commit, when upstream is on GitHub. */\nexport function noteUrl(upstreamGitHubUrl: string | undefined, commit: string, id: string): string | undefined {\n return upstreamGitHubUrl ? `${upstreamGitHubUrl}/blob/${commit}/${NOTES_DIR}/${id}/README.md` : undefined;\n}\n\n/**\n * The one info line sync, analyze and migrate print, e.g.\n * `migration notes: 94 of 97 handled · 3 arrived with this sync · 3 open: pnpm cella migrate`.\n */\nexport function formatNotesLine(\n total: number,\n open: number,\n arrived?: number,\n options: { dryRun?: boolean } = {},\n): string {\n const parts = [open === 0 ? `all ${total} handled` : `${Math.max(0, total - open)} of ${total} handled`];\n if (arrived) parts.push(`${arrived} ${options.dryRun ? 'arrive' : 'arrived'} with this sync`);\n if (open > 0) parts.push(`${open} open: pnpm cella migrate`);\n return `migration notes: ${parts.join(' · ')}`;\n}\n","/**\n * Analyze service: a dry run of sync that shows what would change without applying.\n * Runs the same merge engine as sync and discards the result.\n */\n\nimport { basename } from 'node:path';\nimport type { MergeResult, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { gitDiffFile, openDiffInBrowser } from '../utils/diff';\nimport {\n checkMark,\n createSpinner,\n type LinkOptions,\n printAnalysisFileGroups,\n printEngineReports,\n printLogFileReport,\n spinnerSuccess,\n writeStdout,\n} from '../utils/display';\nimport { CONFIG_FILE } from '../utils/managed-files';\nimport { runEngineWithSpinner } from './merge-engine';\nimport { printMigrationNotesLine } from './migrate';\n\nconst scopeStatuses: Record<'all' | 'risk' | 'protected', Set<string>> = {\n all: new Set(['ahead', 'drifted', 'diverged']),\n risk: new Set(['drifted', 'diverged']),\n protected: new Set(['ahead']),\n};\n\n/**\n * Scope filter. Protected files upstream also changed (`upstreamChanged`, status `pinned` or\n * `ignored`) ride along in `all` and `protected`: they are the pins most worth reviewing. So do\n * ignored files only upstream changed (`upstreamOnly`), and the sync config when upstream's\n * overrides changed in ways the fork config does not follow.\n */\nfunction filterByScope(result: MergeResult, scope: 'all' | 'risk' | 'protected'): MergeResult['files'] {\n const statuses = scopeStatuses[scope];\n if (scope === 'risk') return result.files.filter((f) => statuses.has(f.status));\n const overridesChanged = result.upstreamOverrides?.kind === 'changes';\n return result.files.filter(\n (f) =>\n statuses.has(f.status) ||\n f.upstreamChanged === true ||\n f.upstreamOnly === true ||\n (overridesChanged && f.path === CONFIG_FILE),\n );\n}\n\nfunction findTargetFile(files: MergeResult['files'], targetPath: string) {\n const exact = files.find((f) => f.path === targetPath);\n if (exact) return exact;\n\n const normalized = targetPath.replace(/^\\.\\//, '');\n return files.find((f) => f.path === normalized);\n}\n\nfunction printUnifiedDiff(config: RuntimeConfig, filePath: string): void {\n // Label the upstream side 'cella/' and the local side with the repo's folder name\n // so the diff reads cella/<path> vs <fork>/<path>, not opaque a/ and b/.\n const diff = gitDiffFile(config.forkPath, `${config.upstreamRef}..HEAD`, filePath, {\n dstPrefix: basename(config.forkPath),\n });\n writeStdout(diff.toString());\n}\n\nexport async function runAnalyze(config: RuntimeConfig): Promise<MergeResult> {\n createSpinner('starting analysis...');\n\n const result = await runEngineWithSpinner(config, false);\n\n spinnerSuccess();\n\n const scopedFiles = filterByScope(result, config.scope ?? 'all');\n\n if (config.diff) {\n const file = findTargetFile(scopedFiles, config.diff) ?? findTargetFile(result.files, config.diff);\n if (!file) throw new Error(`file not found in analysis results: ${config.diff}`);\n printUnifiedDiff(config, file.path);\n return result;\n }\n\n if (config.json) {\n const overrides = result.upstreamOverrides?.kind === 'changes' ? result.upstreamOverrides : undefined;\n const out = scopedFiles.map((f) => ({\n path: f.path,\n status: f.status,\n changedAt: f.changedAt ?? null,\n changedCommit: f.changedCommit ?? null,\n upstreamChangedAt: f.upstreamChangedAt ?? null,\n upstreamCommit: f.upstreamCommit ?? null,\n upstreamChanged: f.upstreamChanged ?? false,\n upstreamChangedLines: f.upstreamChangedLines ?? null,\n upstreamLinesAbsent: f.upstreamLinesAbsent ?? null,\n upstreamOnly: f.upstreamOnly ?? false,\n // Only on the sync config: upstream override entries and packageJsonSync keys the fork config does not follow\n upstreamOverrides:\n overrides && f.path === CONFIG_FILE\n ? { pinned: overrides.pinned, ignored: overrides.ignored, packageJsonSync: overrides.packageJsonSync }\n : null,\n }));\n writeStdout(JSON.stringify(out, null, 2));\n return result;\n }\n\n if (config.list) {\n for (const file of scopedFiles) {\n writeStdout(file.path);\n }\n return result;\n }\n\n if (config.openDiff) {\n const file = findTargetFile(scopedFiles, config.openDiff) ?? findTargetFile(result.files, config.openDiff);\n if (!file) throw new Error(`file not found in analysis results: ${config.openDiff}`);\n\n // Diff the upstream ref against the working tree (single ref, no range) so the\n // rendered page includes uncommitted local changes: a live view of the file as it stands.\n const patch = gitDiffFile(config.forkPath, config.upstreamRef, file.path);\n if (patch.length === 0) {\n console.info(`${checkMark} ${file.path} is identical to upstream`);\n return result;\n }\n\n const pagePath = await openDiffInBrowser(\n patch.toString(),\n {\n filePath: file.path,\n srcLabel: 'cella',\n dstLabel: basename(config.forkPath),\n note: 'local working tree',\n },\n config.forkPath,\n );\n console.info(`${checkMark} opened browser diff for ${file.path}`);\n console.info(pc.dim(` ${pagePath}`));\n return result;\n }\n\n const linkOptions: LinkOptions = {\n upstreamGitHubUrl: result.upstreamGitHubUrl,\n upstreamBranch: result.upstreamBranch,\n fileLinkMode: config.settings.fileLinkMode,\n forkPath: config.forkPath,\n };\n\n // File lists first (analyze shows them for review); the summary and shared reports close the output.\n printAnalysisFileGroups(result.files, linkOptions, result);\n\n printEngineReports(result, 'analysis summary');\n\n await printMigrationNotesLine(config, result);\n\n printLogFileReport(config, result.files);\n\n console.info();\n\n return result;\n}\n","/**\n * Diff helpers: a single-file `git diff`, and a diff rendered as a self-contained\n * HTML page that opens in the default browser. Used by the analyze and\n * contributions services.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { basename, join } from 'node:path';\nimport process from 'node:process';\nimport { MAX_BUFFER } from './git';\n\n/**\n * Run `git diff` for a single file.\n *\n * With `dstPrefix`, the sides are labeled `cella/<path>` vs `<dstPrefix>/<path>`,\n * not opaque a/ and b/: used for the `--diff` stdout mode where the labels carry\n * meaning. Without it, standard a/ b/ prefixes are kept, which the HTML\n * renderer's patch parser requires.\n *\n * @param cwd - Repo to run the diff in\n * @param range - Ref range (e.g. 'upstreamRef..HEAD'), or a single ref to diff\n * that ref against the working tree\n * @param filePath - File to diff\n * @returns Raw diff output (empty when the file is identical)\n */\nexport function gitDiffFile(\n cwd: string,\n range: string,\n filePath: string,\n options: { dstPrefix?: string } = {},\n): Buffer {\n const args = ['diff', '--no-color'];\n if (options.dstPrefix) args.push('--src-prefix=cella/', `--dst-prefix=${options.dstPrefix}/`);\n args.push(range, '--', filePath);\n\n try {\n return execFileSync('git', args, { cwd, maxBuffer: MAX_BUFFER });\n } catch (error) {\n const stderr = (error as { stderr?: Buffer }).stderr?.toString().trim();\n throw new Error(stderr || `failed to diff ${filePath}`);\n }\n}\n\n/** Labels shown in the header of a rendered diff page. */\ninterface DiffPageMeta {\n /** File path shown in the page header and title */\n filePath: string;\n /** Label for the upstream side (e.g. 'cella') */\n srcLabel: string;\n /** Label for the local side (e.g. the fork name) */\n dstLabel: string;\n /** Extra context shown after the labels (e.g. 'includes uncommitted changes') */\n note?: string;\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\n\n/**\n * Render a unified diff as a complete, self-contained HTML document.\n *\n * Highlighting and diff layout come from `@pierre/diffs` (Shiki-based), rendered\n * server-side to static HTML: no scripts, no external requests, adapts to the\n * viewer's light/dark preference. The patch must use standard a/ b/ prefixes\n * (call `gitDiffFile` without `dstPrefix`); side labels belong in `meta`.\n */\nexport async function renderDiffPage(patch: string, meta: DiffPageMeta): Promise<string> {\n // Lazy import: the CLI is a short-lived process and most invocations never\n // render a diff, so startup shouldn't pay Shiki's module-load cost.\n const { preloadPatchDiff } = await import('@pierre/diffs/ssr');\n\n const { prerenderedHTML } = await preloadPatchDiff({\n patch,\n options: {\n diffStyle: 'split',\n themeType: 'system',\n lineDiffType: 'word-alt',\n hunkSeparators: 'line-info',\n overflow: 'wrap',\n disableFileHeader: true,\n },\n });\n\n const title = `${escapeHtml(meta.filePath)} · ${escapeHtml(meta.srcLabel)} vs ${escapeHtml(meta.dstLabel)}`;\n const note = meta.note ? `<span class=\"note\">· ${escapeHtml(meta.note)}</span>` : '';\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${title}</title>\n<style>\n :root { color-scheme: light dark; }\n * { box-sizing: border-box; }\n body {\n margin: 0;\n font-family: ui-sans-serif, system-ui, -apple-system, sans-serif;\n background: light-dark(#fafafa, #111);\n color: light-dark(#111, #eee);\n }\n header {\n display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap;\n padding: 0.9rem 1.25rem;\n border-bottom: 1px solid light-dark(#e2e2e2, #2a2a2a);\n position: sticky; top: 0;\n background: inherit;\n }\n header .brand { font-weight: 600; color: light-dark(#0891b2, #22d3ee); }\n header code { font-family: ui-monospace, monospace; font-size: 0.9rem; }\n header .sides { margin-left: auto; font-size: 0.8rem; opacity: 0.7; }\n main { max-width: 1400px; margin: 1rem auto; padding: 0 1rem 2rem; }\n .diff-shell {\n border: 1px solid light-dark(#e2e2e2, #2a2a2a);\n border-radius: 8px; overflow: hidden;\n background: light-dark(#fff, #161616);\n }\n</style>\n</head>\n<body>\n<header>\n <span class=\"brand\">⧈ cella diff</span>\n <code>${escapeHtml(meta.filePath)}</code>\n <span class=\"sides\">${escapeHtml(meta.srcLabel)} ← → ${escapeHtml(meta.dstLabel)} ${note}</span>\n</header>\n<main>\n <!-- Declarative shadow DOM: the library's CSS targets :host, which only\n matches inside a shadow root (its browser component renders into one). -->\n <div class=\"diff-shell\">\n <template shadowrootmode=\"open\">\n${prerenderedHTML}\n </template>\n </div>\n</main>\n</body>\n</html>`;\n}\n\n/** Open a file or URL with the platform's default handler (best-effort: a\n * missing or failing opener is not fatal; the page path is printed anyway). */\nfunction openWithDefaultApp(target: string): void {\n try {\n if (process.platform === 'win32') {\n execFileSync('rundll32', ['url.dll,FileProtocolHandler', target], { stdio: 'ignore' });\n } else {\n execFileSync(process.platform === 'darwin' ? 'open' : 'xdg-open', [target], { stdio: 'ignore' });\n }\n } catch {\n // e.g. headless environment without a browser/opener\n }\n}\n\n/**\n * Render a diff page, write it to a stable temp path, and open it in the browser.\n *\n * The output path is keyed by repo name and file path and overwritten on each\n * view, so repeat views don't litter tmp and a browser refresh shows the latest\n * render.\n *\n * @returns Absolute path of the written HTML file.\n */\nexport async function openDiffInBrowser(patch: string, meta: DiffPageMeta, repoPath: string): Promise<string> {\n const html = await renderDiffPage(patch, meta);\n\n const dir = join(tmpdir(), `cella-diff-${basename(repoPath)}`);\n mkdirSync(dir, { recursive: true });\n const outPath = join(dir, `${meta.filePath.replace(/[^\\w.-]+/g, '-')}.html`);\n\n writeFileSync(outPath, html);\n openWithDefaultApp(outPath);\n return outPath;\n}\n","/**\n * Merge engine, shared by analyze and sync.\n *\n * Two modes:\n * - Analyze (dry run): previews the merge in a temp worktree without touching the fork\n * - Sync: performs the real merge directly in the fork for full IDE support\n *\n * Sync mode:\n * 1. Start a real merge in the fork (git merge --no-commit)\n * 2. Apply resolutions directly (pinned→ours, ignored→rm, diverged→git's merge)\n * 3. Leave the fork in merge state: conflicts keep their markers for IDE 3-way resolution\n */\n\nimport { existsSync } from 'node:fs';\nimport { rm } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n type AnalysisSummary,\n type AnalyzedFile,\n type CommitRangeEntry,\n type MergeResult,\n type RuntimeConfig,\n SYNC_APPLIED_STATUSES,\n type UpstreamOverridesReport,\n} from '../config/types';\nimport { cleanupLeftoverWorktrees, cleanupWorktree, getWorktreePath, registerWorktree } from '../utils/cleanup';\nimport { cliVersionMismatch, readUpstreamCliRange } from '../utils/cli-version';\nimport { DEFAULT_UPSTREAM_REMOTE, resolveUpstream } from '../utils/config';\nimport {\n COMMIT_LIST_MAX,\n createSpinner,\n formatFetchedUpstreamDetail,\n formatMergeInProgressDetail,\n spinnerSuccess,\n spinnerText,\n VERSION,\n} from '../utils/display';\nimport {\n batchGitRm,\n batchRestoreToHead,\n batchUnstageFiles,\n checkoutFromRef,\n countCommitsBetween,\n createWorktree,\n ensureRemote,\n ensureSyncBase,\n fetchRemote,\n fetchUpstreamTags,\n fileExistsAtRef,\n fileExistsInWorktree,\n getCommitInfo,\n getConflictedFiles,\n getCurrentBranch,\n getEffectiveMergeBase,\n getMergeBase,\n getShortSha,\n getStagedNewFiles,\n getUpstreamStatus,\n getWorkingTreeChangeCount,\n git,\n gitMv,\n isAncestor,\n isPublishedUpstream,\n listCommitsBetween,\n merge,\n mergeAbort,\n removeFileFromWorktree,\n removeFileFully,\n resolveLatestReleaseTag,\n resolveUpstreamCommit,\n restoreToHead,\n stagePath,\n storeLastSyncRef,\n withTemporarySyncBaseGraft,\n} from '../utils/git';\nimport { CONFIG_FILE, isManagedFile } from '../utils/managed-files';\nimport { MANIFEST_FILE, type SyncManifest, writeSyncManifest } from '../utils/manifest';\nimport {\n arrivedNoteIds,\n listNoteIds,\n NOTES_DIR,\n PENDING_FILE,\n readPending,\n writePending,\n} from '../utils/migration-notes';\nimport {\n groupIgnoredUpstreamChanges,\n groupProtectedUpstreamChanges,\n isIgnored,\n isPinnedForSync,\n} from '../utils/overrides';\nimport { compareUpstreamOverrides } from '../utils/upstream-overrides';\nimport { type AnalyzePredicates, analyzeRefs, enrichChangeInfo } from './analyze-core';\n\ntype ProgressCallback = (message: string, detail?: string) => void;\n\ntype StepCallback = (label: string, detail?: string) => void;\n\n/**\n * Thrown when the upstream commit is behind the fork's last sync point: the fork already has it,\n * and merging it would stage a revert. `cella sync` ends as a no-op on it, unless the run pinned\n * the ref itself (`--ref`).\n */\nexport class BehindSyncPointError extends Error {}\n\n/**\n * Thrown before a new merge starts when upstream changed its sync config in ways the fork config\n * does not follow. Carries the report so the caller can print it.\n */\nexport class UpstreamConfigChangedError extends Error {\n readonly report: UpstreamOverridesReport;\n\n constructor(report: UpstreamOverridesReport) {\n super(\n [\n 'upstream changed its sync config and yours does not follow it: stopped before the merge, nothing changed.',\n ` add or drop the entries that fit your app in ${CONFIG_FILE}, commit, then rerun.`,\n ' to merge with your config as it stands, rerun with --keep-config.',\n ].join('\\n'),\n );\n this.report = report;\n }\n}\n\n/**\n * Convert a git remote URL to a GitHub base URL.\n * Supports both SSH (git@github.com:org/repo.git) and HTTPS formats.\n */\nexport function getGitHubBaseUrl(remoteUrl: string): string | null {\n // SSH format: git@github.com:cellajs/cella.git\n const sshMatch = remoteUrl.match(/git@github\\.com:([^/]+)\\/([^.]+)(?:\\.git)?$/);\n if (sshMatch) {\n return `https://github.com/${sshMatch[1]}/${sshMatch[2]}`;\n }\n\n // HTTPS format: https://github.com/cellajs/cella.git\n const httpsMatch = remoteUrl.match(/https:\\/\\/github\\.com\\/([^/]+)\\/([^/.]+)(?:\\.git)?$/);\n if (httpsMatch) {\n return `https://github.com/${httpsMatch[1]}/${httpsMatch[2]}`;\n }\n\n return null;\n}\n\n/** Protected whole-file resolution: the fork side wins outright (ignored or pinned). */\nfunction isProtectedFile(file: AnalyzedFile): boolean {\n return file.isIgnored || file.isPinned;\n}\n\n/** Build analyzer predicates for the sync direction (local = fork, incoming = upstream). */\nfunction syncPredicates(config: RuntimeConfig): AnalyzePredicates {\n return {\n isIgnored: (path) => isIgnored(path, config),\n isPinned: (path) => isPinnedForSync(path, config, config.unpinned),\n hard: config.hard,\n };\n}\n\n/**\n * Apply merge directly to fork with pre-analysis.\n *\n * Strategy: analyze BEFORE merge (uses git refs only, invisible to IDE),\n * then merge + immediate batch resolution to minimize working tree flickering.\n *\n * 1. Pre-analyze using git refs (no working tree changes)\n * 2. Collect batch resolution plan (which files to restore/remove)\n * 3. Start real merge in fork (git merge --no-commit)\n * 4. Immediately batch-restore pinned/ignored files (single git command)\n * 5. Apply remaining individual resolutions\n * 6. Leave fork in merge state for IDE 3-way conflict resolution\n */\nasync function applyDirectMerge(\n forkPath: string,\n upstreamRef: string,\n mergeBaseRef: string,\n config: RuntimeConfig,\n onProgress?: ProgressCallback,\n): Promise<{\n remainingConflicts: string[];\n analyzedFiles: AnalyzedFile[];\n autoMergedFiles: string[];\n protectedConflicts: string[];\n}> {\n // Phase 1: Pre-analyze using git refs (invisible to IDE).\n // analyzeRefs only uses git plumbing (ls-tree, diff-tree) on refs,\n // not the working tree, so results are identical before or after merge.\n onProgress?.('analyzing files...');\n const analyzedFiles = await analyzeRefs(\n forkPath,\n 'HEAD',\n upstreamRef,\n mergeBaseRef,\n syncPredicates(config),\n onProgress,\n );\n\n // Phase 2: Collect batch resolution plan for immediate post-merge application.\n // These files will be restored to HEAD in a single git command right after merge,\n // preventing the IDE from seeing upstream changes to pinned/ignored files.\n const batchRestorePaths: string[] = [];\n const batchRemovePaths: string[] = [];\n\n for (const file of analyzedFiles) {\n const { path: filePath, status, isPinned: pinned, isIgnored: ignored, existsInFork } = file;\n if (status === 'identical' || status === 'ahead') continue;\n if (!isProtectedFile(file)) continue;\n\n if (ignored && existsInFork) {\n batchRestorePaths.push(filePath);\n } else if (ignored && !existsInFork) {\n batchRemovePaths.push(filePath);\n } else if (pinned && !file.renamedFrom && existsInFork) {\n batchRestorePaths.push(filePath);\n } else if (pinned && !file.renamedFrom && !existsInFork) {\n // Pinned file absent in the fork: removed from the merge so the deletion stands.\n batchRemovePaths.push(filePath);\n }\n }\n\n // Phase 3: Start real merge in fork. Left staged with MERGE_HEAD intact so git and the IDE\n // treat it as a real in-progress merge (3-way conflict view, `git merge --abort` works).\n // The finishing rerun squashes the commit to a single parent (`commitSquash`); upstream\n // ancestry is tracked via the manifest, never via a pushed two-parent merge commit.\n // The temporary graft makes the merge 3-way against the recorded sync point, not git's\n // own (squash-stale) merge-base; without it, upstream hunks already integrated by\n // earlier syncs re-apply or re-conflict on every run.\n onProgress?.('starting merge in fork...');\n await withTemporarySyncBaseGraft(forkPath, 'HEAD', mergeBaseRef, () => merge(forkPath, upstreamRef));\n\n // Phase 4: Immediately batch-restore pinned/ignored files.\n // Single git command restores all files at once, minimizing the window\n // where the IDE sees upstream changes to protected files.\n if (batchRestorePaths.length > 0) {\n onProgress?.(`batch restoring ${batchRestorePaths.length} pinned/ignored files...`);\n await batchRestoreToHead(forkPath, batchRestorePaths);\n }\n if (batchRemovePaths.length > 0) {\n onProgress?.(`batch removing ${batchRemovePaths.length} ignored files...`);\n await batchGitRm(forkPath, batchRemovePaths);\n for (const filePath of batchRemovePaths) {\n await removeFileFromWorktree(forkPath, filePath);\n }\n }\n\n // Phase 5: Apply remaining individual resolutions.\n for (const file of analyzedFiles) {\n const { path: filePath, status, existsInFork } = file;\n\n if (status === 'identical' || status === 'ahead') {\n continue;\n }\n\n // Pinned/ignored already handled in the Phase-2/4 batch: skip them here.\n if (isProtectedFile(file)) continue;\n\n if (status === 'diverged') {\n // git's merge result stands for diverged files.\n onProgress?.(`→ ${filePath}: using git merge result (diverged)`);\n continue;\n }\n\n if (status === 'behind') {\n if (!existsInFork) {\n onProgress?.(`→ ${filePath}: adding from upstream (new file)`);\n await checkoutFromRef(forkPath, upstreamRef, filePath);\n } else if (!file.existsInUpstream) {\n // Upstream deleted the file: removed from the fork, including leftovers after a squash merge.\n onProgress?.(`→ ${filePath}: removing (deleted in upstream)`);\n await removeFileFully(forkPath, filePath);\n } else {\n // Both exist and only upstream changed: upstream's version is taken explicitly,\n // which resolves false conflicts from a stale merge-base (previous squash syncs).\n onProgress?.(`→ ${filePath}: accepting upstream (behind)`);\n await checkoutFromRef(forkPath, upstreamRef, filePath);\n }\n continue;\n }\n\n if (status === 'deleted') {\n await removeFileFully(forkPath, filePath);\n continue;\n }\n\n if (status === 'renamed' && file.renamedFrom) {\n // Upstream renames apply as git mv to preserve history.\n const oldPath = file.renamedFrom;\n const oldPathExists = await fileExistsInWorktree(forkPath, oldPath);\n const newPathExists = await fileExistsInWorktree(forkPath, filePath);\n\n if (oldPathExists && !newPathExists) {\n onProgress?.(`→ ${oldPath} → ${filePath}: moving (renamed in upstream)`);\n try {\n await gitMv(forkPath, oldPath, filePath);\n } catch {\n // git mv can fail mid-merge: fall back to remove plus checkout.\n await removeFileFully(forkPath, oldPath);\n await checkoutFromRef(forkPath, upstreamRef, filePath);\n }\n } else if (oldPathExists && newPathExists) {\n // Both exist (merge already staged the new file, but the old one is still in the worktree).\n onProgress?.(`→ ${oldPath} → ${filePath}: completing rename (removing old)`);\n await removeFileFully(forkPath, oldPath);\n await checkoutFromRef(forkPath, upstreamRef, filePath);\n } else {\n // Rename already applied (or neither path exists): the new path gets upstream's content.\n onProgress?.(`→ ${filePath}: updating from upstream (renamed)`);\n await checkoutFromRef(forkPath, upstreamRef, filePath);\n }\n }\n }\n\n // Protected files where upstream's changes were dropped by the fork-wins resolution above:\n // the batch-restored pinned/ignored files that upstream also changed since the merge-base.\n // Surfaced in the sync summary so the loss is visible right when it happens.\n const protectedConflicts = analyzedFiles.filter((file) => file.upstreamChanged).map((file) => file.path);\n // Membership test only: the array keeps the report's order (consumers group/print in path order).\n const protectedConflictSet = new Set(protectedConflicts);\n\n // Handle remaining git conflicts: auto-resolve only ignored/pinned (fork wins);\n // everything else keeps its markers for IDE 3-way resolution.\n const gitConflicts = await getConflictedFiles(forkPath);\n for (const filePath of gitConflicts) {\n const isProtected = isIgnored(filePath, config) || isPinnedForSync(filePath, config, config.unpinned);\n if (!isProtected) continue;\n\n if (await fileExistsAtRef(forkPath, 'HEAD', filePath)) {\n onProgress?.(`→ ${filePath}: keeping fork (protected conflict)`);\n await restoreToHead(forkPath, filePath);\n if (!protectedConflictSet.has(filePath)) {\n protectedConflictSet.add(filePath);\n protectedConflicts.push(filePath);\n }\n } else {\n onProgress?.(`→ ${filePath}: removing (protected conflict, not in fork)`);\n await removeFileFully(forkPath, filePath);\n }\n }\n\n const remainingConflicts = await getConflictedFiles(forkPath);\n const remainingConflictSet = new Set(remainingConflicts);\n const autoMergedFiles = analyzedFiles\n .filter((file) => file.status === 'diverged' && !remainingConflictSet.has(file.path))\n .map((file) => file.path);\n\n // Phase 6: safety net for ignored files still staged after the merge.\n // During a merge, batchGitRm can silently fail on newly-added files, leaving\n // them as \"Added in index, Deleted from working tree\" (AD status). This catches\n // any ignored files that slipped through the earlier resolution phases.\n const stagedNewFiles = await getStagedNewFiles(forkPath);\n const staleIgnoredFiles = stagedNewFiles.filter((f) => isIgnored(f, config));\n if (staleIgnoredFiles.length > 0) {\n onProgress?.(`cleaning up ${staleIgnoredFiles.length} ignored files still in index...`);\n await batchUnstageFiles(forkPath, staleIgnoredFiles);\n for (const filePath of staleIgnoredFiles) {\n await removeFileFromWorktree(forkPath, filePath);\n }\n }\n\n return { remainingConflicts, analyzedFiles, autoMergedFiles, protectedConflicts };\n}\n\nfunction calculateSummary(files: AnalyzedFile[]): AnalysisSummary {\n const summary: AnalysisSummary = {\n managed: 0,\n identical: 0,\n ahead: 0,\n local: 0,\n drifted: 0,\n behind: 0,\n diverged: 0,\n pinned: 0,\n ignored: 0,\n deleted: 0,\n renamed: 0,\n };\n\n for (const file of files) {\n if (file.status !== 'identical' && isManagedFile(file.path)) {\n summary.managed++;\n continue;\n }\n\n summary[file.status]++;\n }\n\n return summary;\n}\n\n/** Upstream context resolved once per run and shared by both engine modes. */\ninterface UpstreamContext {\n /** Concrete upstream ref merged from (branch tip, release-tag ref or a --ref commit sha) */\n upstreamRef: string;\n /** Release tag when tracking releases */\n releaseTag?: string;\n /** Effective merge-base used for the 3-way analysis */\n mergeBase: string;\n /** Recorded sync point. Same as `mergeBase`, except under --hard/--unpinned, which merge from the natural base */\n syncPoint: string;\n /** Upstream GitHub URL base for commit links */\n upstreamGitHubUrl?: string;\n /** Upstream HEAD commit info */\n upstreamCommit: CommitRangeEntry;\n /** Commits included in this sync range (oldest-first) */\n upstreamCommits: CommitRangeEntry[];\n}\n\nfunction formatLocalCheckoutDetail(\n forkPath: string,\n branch: string,\n headSha: string,\n changeCount: number,\n upstream: { upstream: string | null; ahead: number; behind: number },\n): string {\n const tracking = upstream.upstream\n ? `, tracking ${upstream.upstream} (${upstream.ahead} ahead, ${upstream.behind} behind)`\n : ', no tracking branch';\n const workingTree =\n changeCount === 0\n ? ' working tree clean'\n : ` ${changeCount} uncommitted change${changeCount === 1 ? '' : 's'} in working tree, not included in analysis`;\n\n return [`${forkPath}`, ` ${branch} @ ${headSha}${tracking}`, workingTree].join('\\n');\n}\n\n/**\n * Resolve a `--ref` to the upstream commit this run syncs to, after the fetch: an upstream branch\n * name, a release tag or a sha (see `resolveUpstreamCommit`). Refuses a ref that does not resolve,\n * or one upstream never published on its branch or in a release (a fork commit, an upstream\n * feature branch). A release tag syncs as that release; anything else as its commit sha, recorded\n * like branch tracking.\n */\nasync function resolvePinnedRef(\n forkPath: string,\n config: RuntimeConfig,\n remoteName: string,\n branchRef: string,\n ref: string,\n): Promise<{ ref: string; releaseTag?: string }> {\n const resolved = await resolveUpstreamCommit(forkPath, remoteName, ref);\n if (!resolved) {\n throw new Error(\n `--ref '${ref}' does not resolve to a commit. Pass a commit sha, a release tag or a branch on ` +\n `${config.settings.upstreamUrl}.`,\n );\n }\n if (!(await isPublishedUpstream(forkPath, remoteName, branchRef, resolved.sha))) {\n throw new Error(\n `--ref '${ref}' (${resolved.sha.slice(0, 7)}) is not on ${branchRef} or in an upstream release. ` +\n 'Sync only to commits upstream has published there.',\n );\n }\n return resolved.release ? { ref: resolved.release.ref, releaseTag: resolved.release.tag } : { ref: resolved.sha };\n}\n\n/**\n * Resolve everything both modes need from upstream: remote setup, the concrete\n * ref to merge (branch tip, latest release tag or a pinned --ref), sync ancestry bootstrap,\n * effective merge-base, and commit info for progress output.\n */\nasync function prepareUpstream(\n config: RuntimeConfig,\n onProgress?: ProgressCallback,\n onStep?: StepCallback,\n): Promise<UpstreamContext> {\n const { forkPath } = config;\n\n onProgress?.('checking local checkout...');\n const [branch, headSha, changeCount, upstreamStatus] = await Promise.all([\n getCurrentBranch(forkPath),\n getShortSha(forkPath, 'HEAD'),\n getWorkingTreeChangeCount(forkPath),\n getUpstreamStatus(forkPath),\n ]);\n onStep?.('local checkout', formatLocalCheckoutDetail(forkPath, branch, headSha, changeCount, upstreamStatus));\n\n onProgress?.('setting up upstream remote...');\n const { track: configTrack, branchRef } = resolveUpstream(config.settings);\n const remoteName = DEFAULT_UPSTREAM_REMOTE;\n // A per-run --track flag (config.track) overrides the configured tracking mode.\n const track = config.track ?? configTrack;\n await ensureRemote(forkPath, remoteName, config.settings.upstreamUrl);\n\n onProgress?.(`fetching upstream (${remoteName})...`);\n await fetchRemote(forkPath, remoteName);\n\n // Resolve the concrete ref to merge from. A per-run --ref pins it (and wins over --track);\n // otherwise release tracking (default) syncs to the latest published release tag and\n // branch tracking follows the upstream branch tip.\n let upstreamRef = branchRef;\n let releaseTag: string | undefined;\n if (config.ref) {\n await fetchUpstreamTags(forkPath, remoteName);\n const pinned = await resolvePinnedRef(forkPath, config, remoteName, branchRef, config.ref);\n upstreamRef = pinned.ref;\n releaseTag = pinned.releaseTag;\n } else if (track === 'release') {\n await fetchUpstreamTags(forkPath, remoteName);\n const latest = await resolveLatestReleaseTag(forkPath, remoteName);\n if (!latest) {\n throw new Error(\n `no upstream release tags found on '${remoteName}'. Set upstreamTrack: 'branch' to follow ${branchRef}, ` +\n `or check that ${config.settings.upstreamUrl} publishes release tags.`,\n );\n }\n upstreamRef = latest.ref;\n releaseTag = latest.tag;\n }\n const upstreamLabel = releaseTag ?? (config.ref ? `--ref ${config.ref}` : upstreamRef);\n\n // Expose the resolved ref to downstream steps (packages/analyze read config.upstreamRef\n // after the engine runs). The static fallback set at CLI parse time is the branch tip.\n config.upstreamRef = upstreamRef;\n onStep?.('remote configured', `${upstreamLabel} → ${config.settings.upstreamUrl}`);\n\n // Stop before anything merges when upstream was built with a newer CLI than this one.\n const cliRange = await readUpstreamCliRange(forkPath, upstreamRef);\n const cliMismatch = cliRange ? cliVersionMismatch(VERSION, cliRange) : null;\n if (cliMismatch) throw new Error(cliMismatch);\n\n // Bootstrap sync ancestry for forks with unrelated history (create-cella scaffold or an\n // upstream history squash). No-op once a native merge-base exists. Runs after fetch so the\n // base commit object is present, and after upstreamRef is finalized so release tags resolve.\n onProgress?.('checking sync base...');\n await ensureSyncBase(forkPath, 'HEAD', upstreamRef);\n\n const upstreamGitHubUrl = getGitHubBaseUrl(config.settings.upstreamUrl) ?? undefined;\n\n // Effective merge base (handles a stale base from previous squash syncs).\n // --hard and --unpinned use the natural merge-base, resurfacing the full upstream\n // history so drift and pins hidden below the sync point reappear consistently.\n const aggressive = config.hard === true || config.unpinned === true;\n const syncPoint = (await getEffectiveMergeBase(forkPath, 'HEAD', upstreamRef)).base;\n const mergeBase = aggressive ? await getMergeBase(forkPath, 'HEAD', upstreamRef) : syncPoint;\n\n const upstreamCommit = await getCommitInfo(forkPath, upstreamRef);\n\n // An upstream commit behind the sync point (an earlier run went further with --ref or --track\n // branch) would stage a revert of everything after it as if upstream had undone it: stop.\n if (upstreamCommit.hash !== syncPoint && (await isAncestor(forkPath, upstreamCommit.hash, syncPoint))) {\n const [upstreamShort, syncShort] = await Promise.all([\n getShortSha(forkPath, upstreamCommit.hash),\n getShortSha(forkPath, syncPoint),\n ]);\n const hint = config.ref\n ? 'Pick a newer --ref.'\n : releaseTag\n ? `Nothing to sync until a release past ${syncShort}; to follow the tip instead, run with --track branch.`\n : `Nothing to sync until '${branchRef}' moves past ${syncShort}.`;\n throw new BehindSyncPointError(\n `upstream ${upstreamLabel} (${upstreamShort}) is behind the last sync point ${syncShort}: the fork already ` +\n `has it, and syncing it would revert the upstream changes after it.\\n${hint}`,\n );\n }\n const commitCount = await countCommitsBetween(forkPath, mergeBase, upstreamRef);\n const commitSkip = commitCount > COMMIT_LIST_MAX ? commitCount - COMMIT_LIST_MAX : 0;\n const upstreamCommits =\n commitCount > 0\n ? await listCommitsBetween(forkPath, mergeBase, upstreamRef, { skip: commitSkip, limit: COMMIT_LIST_MAX })\n : [];\n\n onStep?.('fetched upstream', formatFetchedUpstreamDetail(commitCount, upstreamCommits, upstreamGitHubUrl));\n\n return { upstreamRef, releaseTag, mergeBase, syncPoint, upstreamGitHubUrl, upstreamCommit, upstreamCommits };\n}\n\n/**\n * Stop a new merge when upstream changed its sync config since the sync point in ways the fork\n * config does not follow. The merge runs on the fork's config, so a path upstream newly ignores or\n * pins would arrive as an ordinary synced file (upstream renamed an ignored folder, the fork's list\n * still names the old one). Compared from the sync point, under `--hard`/`--unpinned` too: older\n * changes were reported by the syncs they arrived with. `--keep-config` skips the gate; an\n * unreadable upstream config or a failed comparison never stops the run.\n */\nasync function assertSyncConfigFollowed(config: RuntimeConfig, ctx: UpstreamContext): Promise<void> {\n if (config.keepConfig) return;\n const report = await compareUpstreamOverrides(config.forkPath, ctx.syncPoint, ctx.upstreamRef, config).catch(\n () => undefined,\n );\n if (report?.kind === 'changes') throw new UpstreamConfigChangedError(report);\n}\n\n/** MergeResult fields shared by both engine modes. */\nfunction resultMeta(config: RuntimeConfig, ctx: UpstreamContext) {\n return {\n upstreamBranch: config.settings.upstreamBranch ?? 'main',\n upstreamRef: ctx.upstreamRef,\n upstreamTag: ctx.releaseTag,\n upstreamGitHubUrl: ctx.upstreamGitHubUrl,\n upstreamCommit: ctx.upstreamCommit,\n upstreamCommits: ctx.upstreamCommits,\n };\n}\n\n/**\n * Upstream changes the fork never receives, shared by both engine modes: the upstream config's\n * `overrides` entries and `packageJsonSync` keys the fork config does not follow (the config itself\n * never syncs), ignored files only upstream changed, and the protected files upstream also changed\n * (`protectedConflicts`) grouped by entry. Report only, read from refs (the merge state is\n * irrelevant); a failure here yields no report and never fails the run.\n */\nasync function upstreamOnlyReports(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n files: AnalyzedFile[],\n protectedConflicts: string[],\n): Promise<\n Pick<MergeResult, 'upstreamDiffRange' | 'upstreamOverrides' | 'ignoredUpstreamChanges' | 'protectedUpstreamChanges'>\n> {\n const { forkPath } = config;\n try {\n const [baseSha, upstreamSha, upstreamOverrides] = await Promise.all([\n getShortSha(forkPath, ctx.mergeBase),\n // the commit, not an annotated release tag object\n getShortSha(forkPath, ctx.upstreamCommit.hash),\n compareUpstreamOverrides(forkPath, ctx.mergeBase, ctx.upstreamRef, config),\n ]);\n return {\n upstreamDiffRange: `${baseSha}..${upstreamSha}`,\n upstreamOverrides,\n ignoredUpstreamChanges: groupIgnoredUpstreamChanges(files, config.overrides?.ignored ?? []),\n protectedUpstreamChanges: groupProtectedUpstreamChanges(protectedConflicts, config),\n };\n } catch {\n return {};\n }\n}\n\n/** Upstream migration notes for this sync range, plus the fork's pending list once the arrivals are added. */\ninterface NotesInRange {\n total: number;\n arrived: string[];\n pending: string[];\n}\n\n/**\n * Read the migration notes for this sync range: upstream's notes at the incoming ref and the ones\n * added since the recorded sync point. `--hard`/`--unpinned` merge from the natural merge-base,\n * but notes count from the sync point either way, so notes from earlier syncs are not added again.\n * Runs before the sync point moves. A failure yields no notes and never fails the run.\n */\nasync function readNotesInRange(config: RuntimeConfig, ctx: UpstreamContext): Promise<NotesInRange | undefined> {\n const { forkPath } = config;\n try {\n const [total, arrived, pending] = await Promise.all([\n listNoteIds(forkPath, ctx.upstreamRef),\n arrivedNoteIds(forkPath, ctx.syncPoint, ctx.upstreamRef),\n readPending(forkPath, ctx.syncPoint),\n ]);\n return { total: total.length, arrived, pending: [...new Set([...pending, ...arrived])] };\n } catch {\n return undefined;\n }\n}\n\n/** The {@link MergeResult} view of {@link NotesInRange}. */\nfunction notesResult(notes: NotesInRange | undefined): Pick<MergeResult, 'migrationNotes'> {\n return notes ? { migrationNotes: { total: notes.total, arrived: notes.arrived, open: notes.pending.length } } : {};\n}\n\n/**\n * Remove the fork's copy of the upstream-only notes folder (forks that synced it before it became\n * upstream-only, and new apps whose scaffold cloned it). Staged with the sync.\n */\nasync function removeUpstreamOnlyCopy(forkPath: string, onStep?: StepCallback): Promise<void> {\n if (!existsSync(join(forkPath, NOTES_DIR))) return;\n await git(['rm', '-r', '-q', '--ignore-unmatch', '--', NOTES_DIR], forkPath);\n await rm(join(forkPath, NOTES_DIR), { recursive: true, force: true });\n onStep?.('migration notes', `removed ${NOTES_DIR}/: notes stay upstream, list them with pnpm cella migrate`);\n}\n\n/**\n * SYNC MODE: merge, analyze, and resolve directly in the fork, then record the\n * sync point (local ref + committed manifest) and leave the merge staged.\n */\nasync function runSyncMerge(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n onProgress?: ProgressCallback,\n onStep?: StepCallback,\n): Promise<MergeResult> {\n const { forkPath } = config;\n const { upstreamRef, releaseTag, mergeBase, upstreamGitHubUrl, upstreamCommit } = ctx;\n\n // Last gate before anything merges (the CLI version gate runs in prepareUpstream)\n await assertSyncConfigFollowed(config, ctx);\n\n const notes = await readNotesInRange(config, ctx);\n\n const { remainingConflicts, analyzedFiles, autoMergedFiles, protectedConflicts } = await applyDirectMerge(\n forkPath,\n upstreamRef,\n mergeBase,\n config,\n onProgress,\n );\n\n const summary = calculateSummary(analyzedFiles);\n const synced = analyzedFiles.filter((file) => ['behind', 'diverged', 'renamed'].includes(file.status)).length;\n\n const totalResolved = analyzedFiles.filter((file) => SYNC_APPLIED_STATUSES.includes(file.status)).length;\n\n // Record the upstream sync point in lockstep: the local `refs/cella/last-sync` ref plus\n // the committed `cella/cella.manifest.json` (staged so it rides in the sync commit and travels\n // with the repo for fresh-clone bootstrap).\n const syncManifest: SyncManifest = {\n upstream: {\n repo: upstreamGitHubUrl ? upstreamGitHubUrl.replace('https://github.com/', '') : undefined,\n track: releaseTag ? 'release' : 'branch',\n commit: upstreamCommit.hash,\n release: releaseTag ?? null,\n url: upstreamGitHubUrl\n ? releaseTag\n ? `${upstreamGitHubUrl}/releases/tag/${releaseTag}`\n : `${upstreamGitHubUrl}/commit/${upstreamCommit.hash}`\n : undefined,\n syncedAt: new Date().toISOString(),\n },\n };\n const recordSyncPoint = async () => {\n await storeLastSyncRef(forkPath, upstreamCommit.hash);\n await writeSyncManifest(forkPath, syncManifest);\n await stagePath(forkPath, MANIFEST_FILE);\n // Notes that arrived join the fork's pending list; an empty list deletes the file.\n if (notes) {\n await writePending(forkPath, notes.pending);\n await stagePath(forkPath, PENDING_FILE);\n }\n await removeUpstreamOnlyCopy(forkPath, onStep);\n };\n\n if (remainingConflicts.length > 0) {\n // Conflicts: leave MERGE_HEAD intact for IDE 3-way merge resolution. The finishing\n // `cella sync` rerun commits single-parent (`commitSquash`); if the user commits manually\n // instead, the resulting merge commit is flattened away before the branch is pushed\n // (`flattenSyncBranch`) so the PR never lists the whole upstream history.\n await recordSyncPoint();\n onStep?.(\n 'merge in progress',\n formatMergeInProgressDetail(remainingConflicts.length, autoMergedFiles, { forkPath }, 100),\n );\n } else if (totalResolved > 0) {\n const label = synced > 0 ? `${synced} files from upstream` : 'upstream changes';\n // Keep MERGE_HEAD so the finishing rerun can tell a staged sync from a plain dirty\n // tree (`mergeInProgress`) and `git merge --abort` still works. The commit itself is\n // made single-parent at commit time (`commitSquash`).\n await recordSyncPoint();\n onStep?.('synced', `${label} (staged, commit to finish)`);\n } else {\n // Nothing changed: clean up the merge state.\n await mergeAbort(forkPath);\n onStep?.('up to date', 'no upstream changes to sync');\n }\n\n return {\n success: remainingConflicts.length === 0,\n files: analyzedFiles,\n summary,\n conflicts: remainingConflicts,\n autoMergedFiles,\n protectedConflicts,\n ...resultMeta(config, ctx),\n ...(await upstreamOnlyReports(config, ctx, analyzedFiles, protectedConflicts)),\n ...notesResult(notes),\n };\n}\n\n/**\n * ANALYZE MODE: preview the merge in a temp worktree (invisible to the IDE),\n * classify all files, and discard the worktree; the fork is never touched.\n */\nasync function runAnalyzePreview(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n onProgress?: ProgressCallback,\n onStep?: StepCallback,\n): Promise<MergeResult> {\n const { forkPath } = config;\n const worktreePath = getWorktreePath(forkPath);\n const notes = await readNotesInRange(config, ctx);\n\n onProgress?.('creating worktree in temp directory...');\n await createWorktree(forkPath, worktreePath, 'HEAD');\n onStep?.('worktree created', worktreePath);\n\n // Perform merge in worktree (always real merge, never --squash, for correct 3-way).\n // Replace refs are shared across worktrees, so the temporary graft on the fork's HEAD\n // commit steers this worktree merge to the recorded sync point too.\n onProgress?.('performing merge in worktree...');\n await withTemporarySyncBaseGraft(worktreePath, 'HEAD', ctx.mergeBase, () => merge(worktreePath, ctx.upstreamRef));\n onStep?.('merge complete', 'upstream merged into worktree');\n\n onProgress?.('analyzing files...');\n const analyzedFiles = await analyzeRefs(\n forkPath,\n 'HEAD',\n ctx.upstreamRef,\n ctx.mergeBase,\n syncPredicates(config),\n onProgress,\n );\n await enrichChangeInfo(forkPath, analyzedFiles, ctx.mergeBase, 'HEAD', ctx.upstreamRef);\n const protectedConflicts = analyzedFiles.filter((f) => f.upstreamChanged).map((f) => f.path);\n const reports = await upstreamOnlyReports(config, ctx, analyzedFiles, protectedConflicts);\n onStep?.('analysis complete', `${analyzedFiles.length} files analyzed, dry run, no changes applied`);\n\n onProgress?.('cleaning up worktree...');\n await cleanupWorktree(forkPath, worktreePath);\n\n return {\n success: true,\n files: analyzedFiles,\n summary: calculateSummary(analyzedFiles),\n // For analyze mode, count diverged files as potential conflicts\n conflicts: analyzedFiles.filter((f) => f.status === 'diverged').map((f) => f.path),\n protectedConflicts,\n ...resultMeta(config, ctx),\n ...reports,\n ...notesResult(notes),\n };\n}\n\n/** Merge engine entry point: prepare upstream once, then run the requested mode. */\nexport async function runMergeEngine(\n config: RuntimeConfig,\n options: {\n apply: boolean;\n onProgress?: ProgressCallback;\n onStep?: StepCallback;\n },\n): Promise<MergeResult> {\n const { forkPath } = config;\n const worktreePath = getWorktreePath(forkPath);\n const { apply, onProgress, onStep } = options;\n\n await cleanupLeftoverWorktrees(forkPath);\n\n registerWorktree(forkPath, worktreePath);\n\n try {\n const ctx = await prepareUpstream(config, onProgress, onStep);\n return apply\n ? await runSyncMerge(config, ctx, onProgress, onStep)\n : await runAnalyzePreview(config, ctx, onProgress, onStep);\n } catch (error) {\n await cleanupWorktree(forkPath, worktreePath);\n throw error;\n }\n}\n\n/**\n * Run the merge engine with the standard spinner wiring shared by analyze and sync:\n * progress updates the spinner text, each completed step prints with its detail and\n * starts a fresh spinner.\n */\nexport async function runEngineWithSpinner(config: RuntimeConfig, apply: boolean): Promise<MergeResult> {\n return runMergeEngine(config, {\n apply,\n onProgress: (message) => {\n spinnerText(message);\n },\n onStep: (label, detail) => {\n spinnerSuccess(label, detail);\n createSpinner('...');\n },\n });\n}\n","/**\n * Worktree cleanup and signal handlers for graceful abort. Worktrees live in a\n * temp directory outside the repo so they never appear in the IDE.\n */\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, rmSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { basename, join, resolve } from 'node:path';\nimport process from 'node:process';\nimport pc from './colors';\nimport { checkMark, warningMark } from './display';\nimport { errorMessage } from './errors';\nimport { listWorktrees, mergeAbort, removeWorktree } from './git';\n\n/**\n * Managed worktree kinds and their system-temp directory prefixes.\n *\n * - `sync`: temporary merge preview worktree. Registered for signal cleanup and\n * removed when the process exits.\n * - `view`: legacy \"upstream view\" worktree that backed VS Code diff links in\n * older CLI versions (before browser diffs). No longer created; the prefix is\n * kept so leftovers from previous versions are removed on the next run.\n */\nconst WORKTREE_PREFIXES = {\n sync: 'cella-sync-',\n view: 'cella-view-',\n} as const;\n\ntype WorktreeKind = keyof typeof WORKTREE_PREFIXES;\n\n/**\n * Build the system-temp worktree path for a kind: the repo folder name plus a hash of its full\n * path, so two repos with the same folder name (or parallel test runs) never share one.\n */\nfunction buildWorktreePath(kind: WorktreeKind, repoPath: string): string {\n const key = createHash('sha256').update(resolve(repoPath)).digest('hex').slice(0, 8);\n return join(tmpdir(), `${WORKTREE_PREFIXES[kind]}${basename(repoPath)}-${key}`);\n}\n\n/** The path earlier CLI versions used, the repo folder name alone. Cleaned up, never created. */\nfunction legacyWorktreePath(kind: WorktreeKind, repoPath: string): string {\n return join(tmpdir(), `${WORKTREE_PREFIXES[kind]}${basename(repoPath)}`);\n}\n\n/** The temporary sync worktree path in the system temp directory (invisible to the IDE). */\nexport function getWorktreePath(repoPath: string): string {\n return buildWorktreePath('sync', repoPath);\n}\n\nlet cleanupRegistered = false;\n\nlet currentWorktreePath: string | null = null;\nlet currentRepoPath: string | null = null;\n\n/** Register a worktree for cleanup on exit/abort. */\nexport function registerWorktree(repoPath: string, worktreePath: string): void {\n currentRepoPath = repoPath;\n currentWorktreePath = worktreePath;\n}\n\n/** Unregister the worktree (call after successful cleanup). */\nfunction unregisterWorktree(): void {\n currentRepoPath = null;\n currentWorktreePath = null;\n}\n\nexport async function cleanupWorktree(repoPath: string, worktreePath: string): Promise<void> {\n await removeWorktree(repoPath, worktreePath);\n\n // git worktree remove can leave the directory; force-remove what remains.\n if (existsSync(worktreePath)) {\n rmSync(worktreePath, { recursive: true, force: true });\n }\n\n unregisterWorktree();\n}\n\n/**\n * Clean up any leftover worktrees from a previous (interrupted) run, including\n * the legacy upstream-view worktree created by older CLI versions.\n * No-op when no leftovers exist (the common case).\n */\nexport async function cleanupLeftoverWorktrees(repoPath: string): Promise<void> {\n for (const kind of Object.keys(WORKTREE_PREFIXES) as WorktreeKind[]) {\n for (const worktreePath of [buildWorktreePath(kind, repoPath), legacyWorktreePath(kind, repoPath)]) {\n if (existsSync(worktreePath)) await cleanupWorktree(repoPath, worktreePath);\n }\n }\n\n // Also prune any orphaned git worktree references for our managed prefixes.\n const prefixes = Object.values(WORKTREE_PREFIXES);\n const worktrees = await listWorktrees(repoPath);\n for (const wt of worktrees) {\n if (prefixes.some((prefix) => wt.includes(prefix)) && !existsSync(wt)) {\n await removeWorktree(repoPath, wt);\n }\n }\n}\n\nasync function handleAbort(signal: string): Promise<void> {\n console.info();\n console.info(`${warningMark} interrupted (${signal}): cleaning up...`);\n\n if (currentRepoPath && currentWorktreePath) {\n try {\n await mergeAbort(currentWorktreePath);\n } catch {\n // Ignore: merge may not be in progress\n }\n\n try {\n await cleanupWorktree(currentRepoPath, currentWorktreePath);\n console.info(`${checkMark} no changes were made to your repository.`);\n } catch (error) {\n console.error(`${pc.red('✗')} failed to clean up worktree: ${errorMessage(error)}`);\n }\n }\n\n process.exit(1);\n}\n\nexport function registerSignalHandlers(): void {\n if (cleanupRegistered) return;\n\n process.on('SIGINT', () => handleAbort('SIGINT'));\n process.on('SIGTERM', () => handleAbort('SIGTERM'));\n\n cleanupRegistered = true;\n}\n","/**\n * Version parsing shared by package.json merging and the CLI version check.\n */\n\ninterface ComparableVersion {\n major: number;\n minor: number;\n patch: number;\n}\n\n/**\n * The version a plain version or simple range names (`1.2.3`, `^1.2`, `>=1.2.3`), or null for\n * anything else: protocols (`workspace:`, `link:`, `file:`, git and URLs), `*` and `||` unions.\n */\nexport function parseComparableVersion(version: string): ComparableVersion | null {\n const trimmed = version.trim();\n\n if (\n trimmed === '' ||\n trimmed === '*' ||\n trimmed.includes('workspace:') ||\n trimmed.includes('catalog:') ||\n trimmed.includes('file:') ||\n trimmed.includes('link:') ||\n trimmed.includes('git+') ||\n trimmed.includes('github:') ||\n trimmed.includes('http://') ||\n trimmed.includes('https://') ||\n trimmed.includes('||')\n ) {\n return null;\n }\n\n const match = trimmed.match(\n /^(?:\\^|~|>=|<=|>|<|=)?\\s*v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/,\n );\n\n if (!match) return null;\n\n return {\n major: Number(match[1]),\n minor: Number(match[2] ?? 0),\n patch: Number(match[3] ?? 0),\n };\n}\n\n/** Standard comparator: negative when `left` is lower, zero when equal, positive when higher. */\nexport function compareVersions(left: ComparableVersion, right: ComparableVersion): number {\n if (left.major !== right.major) return left.major - right.major;\n if (left.minor !== right.minor) return left.minor - right.minor;\n return left.patch - right.patch;\n}\n","/**\n * The CLI version upstream asks for.\n *\n * A sync bumps the fork's `@cellajs/cli` along with its other packages, so each sync runs on the\n * CLI from before it. A fix to analyze or sync would reach a fork one sync late, and that run\n * would silently miss what the fix reports. Upstream's root package.json names the CLI it was\n * built with; a run on an older CLI stops before it touches the fork.\n */\n\nimport { git } from './git';\nimport { compareVersions, parseComparableVersion } from './versions';\n\nconst CLI_PACKAGE = '@cellajs/cli';\n\n/** The `@cellajs/cli` range in upstream's root package.json at `ref`, or null when it names none. */\nexport async function readUpstreamCliRange(repoPath: string, ref: string): Promise<string | null> {\n const source = await git(['show', `${ref}:package.json`], repoPath, { ignoreErrors: true });\n if (!source) return null;\n try {\n const pkg = JSON.parse(source) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n return pkg.devDependencies?.[CLI_PACKAGE] ?? pkg.dependencies?.[CLI_PACKAGE] ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * The error message when `running` is older than the lowest version `range` admits, else null.\n * A range with no lower bound (`<1.0.0`, `workspace:*`, `link:…`, `a || b`) never blocks.\n */\nexport function cliVersionMismatch(running: string, range: string): string | null {\n if (/^\\s*(<|>(?!=))/.test(range)) return null;\n const required = parseComparableVersion(range);\n const current = parseComparableVersion(running);\n if (!required || !current || compareVersions(current, required) >= 0) return null;\n return [\n `upstream needs ${CLI_PACKAGE} ${range}, this is ${running}: an older CLI misses fixes to the sync itself.`,\n ` update it, commit, then rerun: pnpm add -D -w '${CLI_PACKAGE}@${range}'`,\n ].join('\\n');\n}\n","/**\n * Upstream override changes for sync CLI.\n *\n * The fork's `cella/cella.config.ts` is a managed file: the sync never merges it, so entries\n * upstream adds to (or drops from) its own `overrides.pinned`/`overrides.ignored`, and keys it\n * adds to or drops from `settings.packageJsonSync`, never reach the fork on their own. This module\n * reads upstream's config at the merge-base and at the incoming ref, extracts the lists without\n * evaluating the file (ts-morph, syntax only), and keeps the entries the fork config does not\n * follow: upstream additions the fork lacks, and upstream removals the fork still carries. Report\n * only: the fork config is never written.\n */\n\nimport { Node, type ObjectLiteralExpression, Project, type SourceFile, SyntaxKind } from 'ts-morph';\nimport type { CellaCliConfig, OverrideListChanges, UpstreamOverridesReport } from '../config/types';\nimport { DEFAULT_PACKAGE_JSON_SYNC } from './config';\nimport { git } from './git';\nimport { CONFIG_FILE_PATHS } from './managed-files';\nimport { isUnderAnyFolder } from './overrides';\n\n/** The lists the comparison reads from a sync config, as plain string entries. */\ninterface OverrideLists {\n pinned: string[];\n ignored: string[];\n /** `settings.packageJsonSync`, the default when the config names none; null when it cannot be read statically. */\n packageJsonSync: string[] | null;\n}\n\nconst LIST_KEYS = ['pinned', 'ignored'] as const;\n\n/** Resolve wrappers (`(x)`, `x as T`, `x satisfies T`) and same-file identifiers to the underlying expression. */\nfunction resolveExpression(node: Node | undefined, sourceFile: SourceFile, depth = 0): Node | undefined {\n if (!node || depth > 8) return node;\n if (Node.isParenthesizedExpression(node) || Node.isAsExpression(node) || Node.isSatisfiesExpression(node)) {\n return resolveExpression(node.getExpression(), sourceFile, depth + 1);\n }\n if (Node.isIdentifier(node)) {\n return resolveExpression(\n sourceFile.getVariableDeclaration(node.getText())?.getInitializer(),\n sourceFile,\n depth + 1,\n );\n }\n return node;\n}\n\n/** The config object: the `defineConfig({...})` argument, else a plain `export default {...}`. */\nfunction findConfigObject(sourceFile: SourceFile): ObjectLiteralExpression | undefined {\n for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n if (call.getExpression().getText() !== 'defineConfig') continue;\n const arg = resolveExpression(call.getArguments()[0], sourceFile);\n if (Node.isObjectLiteralExpression(arg)) return arg;\n }\n const exported = sourceFile.getExportAssignment((assignment) => !assignment.isExportEquals());\n const value = resolveExpression(exported?.getExpression(), sourceFile);\n return Node.isObjectLiteralExpression(value) ? value : undefined;\n}\n\n/**\n * Resolved value of a named property in an object literal: `undefined` when absent (spreads and\n * methods are not followed), `null` when present without a readable value.\n */\nfunction readProperty(object: ObjectLiteralExpression, name: string, sourceFile: SourceFile): Node | null | undefined {\n for (const property of object.getProperties()) {\n if (Node.isPropertyAssignment(property)) {\n if (property.getName().replace(/^['\"`]|['\"`]$/g, '') !== name) continue;\n return resolveExpression(property.getInitializer(), sourceFile) ?? null;\n }\n if (Node.isShorthandPropertyAssignment(property) && property.getName() === name) {\n return resolveExpression(property.getNameNode(), sourceFile) ?? null;\n }\n }\n return undefined;\n}\n\n/** String entries of an array literal; null when `node` is not one. Other elements (spreads, variables) are skipped. */\nfunction readStringEntries(node: Node): string[] | null {\n if (!Node.isArrayLiteralExpression(node)) return null;\n const entries: string[] = [];\n for (const element of node.getElements()) {\n if (Node.isStringLiteral(element) || Node.isNoSubstitutionTemplateLiteral(element)) {\n entries.push(element.getLiteralValue());\n }\n }\n return entries;\n}\n\n/**\n * `settings.packageJsonSync` of a config object: the default keys when `settings` or the list is\n * absent, null when either is present without a statically readable value.\n */\nfunction readPackageJsonSync(config: ObjectLiteralExpression, sourceFile: SourceFile): string[] | null {\n const settings = readProperty(config, 'settings', sourceFile);\n if (settings === undefined) return [...DEFAULT_PACKAGE_JSON_SYNC];\n if (!settings || !Node.isObjectLiteralExpression(settings)) return null;\n const keys = readProperty(settings, 'packageJsonSync', sourceFile);\n if (keys === undefined) return [...DEFAULT_PACKAGE_JSON_SYNC];\n return keys ? readStringEntries(keys) : null;\n}\n\n/**\n * Extract `overrides.pinned`, `overrides.ignored` and `settings.packageJsonSync` from config source\n * without evaluating it.\n *\n * Only string literals count; other array elements (spreads, variables) are skipped. A missing\n * `overrides` or list reads as empty, a missing `packageJsonSync` as the default keys. Returns null\n * when the config object or a present `overrides`/list cannot be read statically; an unreadable\n * `packageJsonSync` alone reads as null, so the override lists still compare.\n */\nexport function parseOverrideLists(source: string): OverrideLists | null {\n try {\n const project = new Project({ useInMemoryFileSystem: true, skipLoadingLibFiles: true });\n const sourceFile = project.createSourceFile('cella.config.ts', source);\n const config = findConfigObject(sourceFile);\n if (!config) return null;\n\n const lists: OverrideLists = {\n pinned: [],\n ignored: [],\n packageJsonSync: readPackageJsonSync(config, sourceFile),\n };\n const overrides = readProperty(config, 'overrides', sourceFile);\n if (overrides === undefined) return lists;\n if (!overrides || !Node.isObjectLiteralExpression(overrides)) return null;\n\n for (const key of LIST_KEYS) {\n const list = readProperty(overrides, key, sourceFile);\n if (list === undefined) continue;\n const entries = list ? readStringEntries(list) : null;\n if (!entries) return null;\n lists[key] = entries;\n }\n return lists;\n } catch {\n return null;\n }\n}\n\n/** Normalize an entry for comparison: trimmed, no leading `./`, no trailing slash. */\nfunction normalizeEntry(entry: string): string {\n return entry.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n}\n\n/**\n * Compare upstream's lists at the merge-base and at the incoming ref against the fork's lists.\n *\n * - added: new upstream entries the fork list lacks (an exact entry or a parent folder covers it).\n * - removed: entries upstream dropped that the fork list still carries verbatim.\n *\n * `packageJsonSync` keys compare by name, and not at all when a side could not be read. Entries\n * upstream had all along are never reported, whether or not the fork has them.\n */\nexport function diffOverrideLists(\n base: OverrideLists,\n incoming: OverrideLists,\n fork: OverrideLists,\n): Record<(typeof LIST_KEYS)[number] | 'packageJsonSync', OverrideListChanges> {\n const diff = (key: (typeof LIST_KEYS)[number]): OverrideListChanges => {\n const baseSet = new Set(base[key].map(normalizeEntry).filter(Boolean));\n const incomingSet = new Set(incoming[key].map(normalizeEntry).filter(Boolean));\n const forkEntries = fork[key].map(normalizeEntry).filter(Boolean);\n return {\n added: [...incomingSet].filter((entry) => !baseSet.has(entry) && !isUnderAnyFolder(entry, forkEntries)),\n removed: [...baseSet].filter((entry) => !incomingSet.has(entry) && forkEntries.includes(entry)),\n };\n };\n const diffKeys = (): OverrideListChanges => {\n const [baseKeys, incomingKeys, forkKeys] = [base.packageJsonSync, incoming.packageJsonSync, fork.packageJsonSync];\n if (!baseKeys || !incomingKeys || !forkKeys) return { added: [], removed: [] };\n return {\n added: [...new Set(incomingKeys)].filter((key) => !baseKeys.includes(key) && !forkKeys.includes(key)),\n removed: [...new Set(baseKeys)].filter((key) => !incomingKeys.includes(key) && forkKeys.includes(key)),\n };\n };\n return { pinned: diff('pinned'), ignored: diff('ignored'), packageJsonSync: diffKeys() };\n}\n\n/** Upstream's config source at a ref (current path first, then the legacy root path), or null. */\nasync function readConfigSourceAtRef(repoPath: string, ref: string): Promise<string | null> {\n for (const path of CONFIG_FILE_PATHS) {\n const source = await git(['show', `${ref}:${path}`], repoPath, { ignoreErrors: true });\n if (source) return source;\n }\n return null;\n}\n\n/**\n * Report how upstream's `overrides` and `packageJsonSync` changed between the merge-base and the\n * incoming ref, limited to entries the fork config does not follow (see {@link diffOverrideLists}).\n *\n * Returns undefined when there is nothing to report: upstream has no config at either ref, the\n * config is unchanged, or every change is already mirrored in the fork. Returns `unreadable`\n * when the config is missing or unparsable at one side only.\n */\nexport async function compareUpstreamOverrides(\n repoPath: string,\n mergeBaseRef: string,\n incomingRef: string,\n forkConfig: CellaCliConfig,\n): Promise<UpstreamOverridesReport | undefined> {\n const [baseSource, incomingSource] = await Promise.all([\n readConfigSourceAtRef(repoPath, mergeBaseRef),\n readConfigSourceAtRef(repoPath, incomingRef),\n ]);\n if (baseSource === incomingSource) return undefined;\n\n const base = baseSource === null ? null : parseOverrideLists(baseSource);\n if (!base) return { kind: 'unreadable', side: 'base' };\n const incoming = incomingSource === null ? null : parseOverrideLists(incomingSource);\n if (!incoming) return { kind: 'unreadable', side: 'incoming' };\n\n const fork: OverrideLists = {\n pinned: forkConfig.overrides?.pinned ?? [],\n ignored: forkConfig.overrides?.ignored ?? [],\n packageJsonSync: forkConfig.settings.packageJsonSync ?? DEFAULT_PACKAGE_JSON_SYNC,\n };\n const changes = diffOverrideLists(base, incoming, fork);\n const count = Object.values(changes).reduce((n, list) => n + list.added.length + list.removed.length, 0);\n return count > 0 ? { kind: 'changes', ...changes } : undefined;\n}\n","/**\n * Direction-agnostic ref analyzer for sync CLI.\n *\n * Compares a \"local\" ref against an \"incoming\" ref using a shared merge-base,\n * classifying every changed file (identical / ahead / local / drifted / behind /\n * diverged / pinned / ignored / deleted / renamed). It works purely on git\n * plumbing (ls-tree, diff-tree, log) against refs, never the working tree.\n *\n * Both directions reuse it:\n * - sync (merge-engine): local = fork HEAD, incoming = upstream\n * - contributions: local = cella branch, incoming = fork branch\n *\n * The result fields `existsInFork`/`existsInUpstream` map to local/incoming\n * respectively (named for the sync direction, reused as-is for contributions).\n *\n * Protected files (pinned/ignored) additionally get `upstreamChanged` when both sides\n * changed since the merge-base: the local side wins whole-file there, so incoming's hunks\n * are dropped silently unless surfaced. Ignored files only incoming changed get\n * `upstreamOnly`: nothing local is at stake, but the change never syncs. Managed files and\n * generated output (regenerated locally, never adopted) are left out of that flag.\n */\n\nimport type { AnalyzedFile, FileStatus } from '../config/types';\nimport { getDiffStat, getFileChangeInfo, getFileChanges, getFileHashesAtRef } from '../utils/git';\nimport { isGeneratedFile, isManagedFile } from '../utils/managed-files';\n\n/** Predicates and options that steer classification (direction-specific). */\nexport interface AnalyzePredicates {\n /** True if the file is inside owned/ignored territory (never synced). */\n isIgnored: (path: string) => boolean;\n /** True if the file is pinned (local wins on conflict). */\n isPinned: (path: string) => boolean;\n /** Treat drifted files as behind (overwrite local with incoming). */\n hard?: boolean;\n}\n\n/** Whether an ignored path can carry `upstreamOnly`: not managed and not generated output. */\nfunction isReportableIgnored(filePath: string): boolean {\n return !isManagedFile(filePath) && !isGeneratedFile(filePath);\n}\n\ntype ProgressCallback = (message: string) => void;\n\n/**\n * Analyze files between a local and an incoming ref using a merge-base.\n *\n * @param repoPath - Repo where all refs are reachable (git ops run here)\n * @param localRef - The \"ours\" ref (e.g. fork HEAD, or cella branch)\n * @param incomingRef - The \"theirs\" ref (e.g. upstream, or fork branch)\n * @param mergeBaseRef - Common ancestor ref used for 3-way comparison\n * @param predicates - Direction-specific ignore/pin/hard behavior\n */\nexport async function analyzeRefs(\n repoPath: string,\n localRef: string,\n incomingRef: string,\n mergeBaseRef: string,\n predicates: AnalyzePredicates,\n onProgress?: ProgressCallback,\n): Promise<AnalyzedFile[]> {\n onProgress?.('collecting file hashes (batch)...');\n\n const [forkHashes, upstreamHashes, baseHashes] = await Promise.all([\n getFileHashesAtRef(repoPath, localRef),\n getFileHashesAtRef(repoPath, incomingRef),\n getFileHashesAtRef(repoPath, mergeBaseRef),\n ]);\n\n // Changes between base and each tip; rename detection runs at -M90%.\n const upstreamChanges = await getFileChanges(repoPath, mergeBaseRef, incomingRef);\n const forkChanges = await getFileChanges(repoPath, mergeBaseRef, localRef);\n\n // oldPath -> newPath for renames in incoming.\n const upstreamRenames = new Map<string, string>();\n for (const [newPath, change] of upstreamChanges) {\n if (change.status === 'R' && change.oldPath) {\n upstreamRenames.set(change.oldPath, newPath);\n }\n }\n\n const allFiles = new Set([...forkHashes.keys(), ...upstreamHashes.keys(), ...upstreamRenames.keys()]);\n\n const changedFiles = new Set([...upstreamChanges.keys(), ...forkChanges.keys(), ...upstreamRenames.keys()]);\n\n // Content hashes present anywhere in incoming, for O(1) rename-source lookups below.\n const upstreamHashSet = new Set(upstreamHashes.values());\n\n onProgress?.(\n `analyzing ${changedFiles.size} changed files (${allFiles.size - changedFiles.size} identical skipped)...`,\n );\n\n const analyzedFiles: AnalyzedFile[] = [];\n const handledOldPaths = new Set<string>();\n // Protected files flagged `upstreamChanged` via a rename: their numstat at the new path\n // would count the whole file as added, so they get no line count.\n const renamedProtected = new Set<string>();\n let processed = 0;\n\n for (const filePath of allFiles) {\n if (handledOldPaths.has(filePath)) continue;\n\n const inFork = forkHashes.has(filePath);\n const inUpstream = upstreamHashes.has(filePath);\n\n const fileIsIgnored = predicates.isIgnored(filePath);\n const fileIsPinned = predicates.isPinned(filePath);\n\n const upstreamChange = upstreamChanges.get(filePath);\n const isUpstreamRename = upstreamChange?.status === 'R' && upstreamChange.oldPath;\n\n const renamedToPath = upstreamRenames.get(filePath);\n\n if (!changedFiles.has(filePath) && inFork && inUpstream) {\n analyzedFiles.push({\n path: filePath,\n status: 'identical',\n isIgnored: fileIsIgnored,\n isPinned: fileIsPinned,\n existsInFork: true,\n existsInUpstream: true,\n });\n continue;\n }\n\n processed++;\n if (processed % 100 === 0) {\n onProgress?.(`analyzing ${processed}/${changedFiles.size} changed files...`);\n }\n\n const forkHash = forkHashes.get(filePath) ?? null;\n const upstreamHash = upstreamHashes.get(filePath) ?? null;\n const baseHash = baseHashes.get(filePath) ?? null;\n\n let status: FileStatus;\n let renamedFrom: string | undefined;\n\n if (isUpstreamRename && upstreamChange.oldPath) {\n const oldPath = upstreamChange.oldPath;\n const oldPathInFork = forkHashes.has(oldPath);\n const forkOldHash = forkHashes.get(oldPath) ?? null;\n const baseOldHash = baseHashes.get(oldPath) ?? null;\n\n handledOldPaths.add(oldPath);\n\n const forkModifiedOld = forkOldHash !== baseOldHash;\n\n // A renamed directory (e.g. config/ → shared/) can leave the local pinned\n // list referencing the old path, so both paths count for pinned/ignored.\n const oldPathPinned = predicates.isPinned(oldPath);\n\n let upstreamChanged: boolean | undefined;\n if (fileIsPinned || oldPathPinned || predicates.isIgnored(oldPath)) {\n // Protected: local's version is kept at the new path.\n status = 'pinned';\n // Local edited the old file and incoming changed its content beyond the rename.\n if (forkModifiedOld && upstreamHash !== baseOldHash) {\n upstreamChanged = true;\n renamedProtected.add(filePath);\n }\n } else if (!oldPathInFork) {\n // Old path absent locally (deleted or moved): plain behind, git's merge handles it.\n status = 'behind';\n } else if (forkModifiedOld) {\n // Local modified the old file: diverged, git's merge surfaces the conflict.\n status = 'diverged';\n renamedFrom = oldPath;\n } else {\n // Unmodified old file locally: a clean rename to apply.\n status = 'renamed';\n renamedFrom = oldPath;\n }\n\n // Incoming moved a file into (or within) ignored territory and the local side never\n // touched the source: an upstream-only change at the new path.\n const upstreamOnly = fileIsIgnored && !forkModifiedOld && isReportableIgnored(filePath);\n\n analyzedFiles.push({\n path: filePath,\n status,\n isIgnored: fileIsIgnored,\n isPinned: fileIsPinned,\n existsInFork: inFork,\n existsInUpstream: true,\n renamedFrom,\n upstreamChanged,\n upstreamOnly: upstreamOnly || undefined,\n });\n continue;\n }\n\n // Old paths of incoming renames are handled at the new path.\n if (renamedToPath) {\n handledOldPaths.add(filePath);\n continue;\n }\n\n if (fileIsIgnored) {\n status = 'ignored';\n } else if (!inFork && inUpstream) {\n // File is missing locally but present in incoming. Distinguish a genuinely new\n // incoming file from a file the local side deliberately deleted, by consulting\n // the merge-base (the symmetric `inFork && !inUpstream` branch does the same):\n // - pinned: local owns the path, keep it removed.\n // - existed at base and incoming hasn't touched it since (upstreamHash === baseHash):\n // the absence is a deliberate local deletion that stays deleted; re-adding it\n // as if incoming introduced a new file would resurface it every sync.\n // - otherwise (never in base = truly new, or incoming modified a file the local side\n // deleted = delete/modify): surface incoming's version.\n const locallyDeleted = baseHash !== null && upstreamHash === baseHash;\n status = fileIsPinned || locallyDeleted ? 'deleted' : 'behind';\n } else if (inFork && !inUpstream) {\n if (baseHash !== null) {\n // In base, deleted by incoming: sync the deletion unless pinned.\n status = fileIsPinned ? 'ahead' : 'behind';\n } else {\n // Local file (never existed in merge-base). If its exact content exists at a\n // different path in incoming, it is likely the source of a rename we couldn't\n // detect due to a squash merge-base: treated as behind so the rename applies.\n // (This file is absent from incoming, so any hash match is at another path.)\n status = forkHash && upstreamHashSet.has(forkHash) ? 'behind' : 'local';\n }\n } else if (forkHash === upstreamHash) {\n status = 'identical';\n } else {\n const forkChanged = forkHash !== baseHash;\n const upstreamChanged = upstreamHash !== baseHash;\n\n if (forkChanged && upstreamChanged) {\n status = fileIsPinned ? 'pinned' : 'diverged';\n } else if (forkChanged && !upstreamChanged) {\n // --hard treats drifted as behind (incoming overwrites).\n status = fileIsPinned ? 'ahead' : predicates.hard ? 'behind' : 'drifted';\n } else {\n status = 'behind';\n }\n }\n\n // Protected file where BOTH sides changed since the merge-base (a local edit or deletion,\n // and incoming content that differs from base). Local wins whole-file, so incoming's\n // hunks are dropped; the flag lets analyze/sync surface the loss. A protected file\n // that only changed locally is plain `ahead`; one that only changed incoming (`behind`\n // with the local copy still equal to base) is reported separately as a masking pin.\n const upstreamChanged =\n (fileIsPinned || fileIsIgnored) && inUpstream && upstreamHash !== baseHash && forkHash !== baseHash;\n\n // Ignored file only incoming changed, added or deleted since the merge-base (the local copy,\n // or its absence, still equals base). Nothing local is dropped, but ignored paths never sync,\n // so the change would stay unseen. The pinned counterpart is the masking pin (`behind`).\n const upstreamOnly =\n fileIsIgnored && isReportableIgnored(filePath) && upstreamHash !== baseHash && forkHash === baseHash;\n\n analyzedFiles.push({\n path: filePath,\n status,\n isIgnored: fileIsIgnored,\n isPinned: fileIsPinned,\n existsInFork: inFork,\n existsInUpstream: inUpstream,\n upstreamChanged: upstreamChanged || undefined,\n upstreamOnly: upstreamOnly || undefined,\n });\n }\n\n // Size the dropped incoming changes: one numstat call limited to the flagged paths.\n const flagged = analyzedFiles.filter((file) => file.upstreamChanged && !renamedProtected.has(file.path));\n if (flagged.length > 0) {\n const stat = await getDiffStat(\n repoPath,\n mergeBaseRef,\n incomingRef,\n flagged.map((file) => file.path),\n );\n for (const file of flagged) {\n const entry = stat.get(file.path);\n if (entry && entry.additions !== null && entry.deletions !== null) {\n file.upstreamChangedLines = entry.additions + entry.deletions;\n }\n }\n }\n\n // Retroactive signal for pinned `ahead` files (incoming untouched since the merge-base, so\n // the check above cannot fire): count lines incoming has that local lacks, relative to\n // the tips, not the sync point. Pinned only; ignored territory is noise by design.\n const stale = analyzedFiles.filter(\n (file) =>\n file.status === 'ahead' &&\n file.isPinned &&\n !file.isIgnored &&\n file.existsInFork &&\n file.existsInUpstream &&\n forkHashes.get(file.path) !== upstreamHashes.get(file.path),\n );\n if (stale.length > 0) {\n // from = incoming, to = local: numstat deletions are incoming lines absent locally\n const stat = await getDiffStat(\n repoPath,\n incomingRef,\n localRef,\n stale.map((file) => file.path),\n );\n for (const file of stale) {\n const deletions = stat.get(file.path)?.deletions;\n if (deletions !== null && deletions !== undefined) file.upstreamLinesAbsent = deletions;\n }\n }\n\n return analyzedFiles;\n}\n\n/**\n * Enrich analyzed files with change dates and commit hashes.\n *\n * Mutates each non-identical file in place: local-side dates for ahead/drifted,\n * incoming-side dates for behind, and both sides for diverged/pinned.\n *\n * @param repoPath - Repo where the refs are reachable\n * @param files - Files to enrich (mutated in place)\n * @param mergeBaseRef - Common ancestor ref\n * @param localRef - The \"ours\" ref\n * @param incomingRef - The \"theirs\" ref\n */\nexport async function enrichChangeInfo(\n repoPath: string,\n files: AnalyzedFile[],\n mergeBaseRef: string,\n localRef: string,\n incomingRef: string,\n): Promise<void> {\n const forkInfo = await getFileChangeInfo(repoPath, mergeBaseRef, localRef);\n const upstreamInfo = await getFileChangeInfo(repoPath, mergeBaseRef, incomingRef);\n\n for (const file of files) {\n if (file.status === 'identical') continue;\n\n if (file.status === 'ahead' || file.status === 'drifted') {\n const info = forkInfo.get(file.path);\n if (info) {\n file.changedAt = info.date;\n file.changedTs = info.timestamp;\n file.changedCommit = info.hash;\n }\n } else if (file.status === 'behind') {\n const info = upstreamInfo.get(file.path);\n if (info) {\n file.changedAt = info.date;\n file.changedTs = info.timestamp;\n file.changedCommit = info.hash;\n }\n } else if (file.status === 'diverged' || file.status === 'pinned' || file.upstreamChanged) {\n // Diverged/pinned (and protected files incoming also changed) carry both sides.\n const forkFileInfo = forkInfo.get(file.path);\n const upstreamFileInfo = upstreamInfo.get(file.path);\n if (forkFileInfo) {\n file.changedAt = forkFileInfo.date;\n file.changedTs = forkFileInfo.timestamp;\n file.changedCommit = forkFileInfo.hash;\n }\n if (upstreamFileInfo) {\n file.upstreamChangedAt = upstreamFileInfo.date;\n file.upstreamChangedTs = upstreamFileInfo.timestamp;\n file.upstreamCommit = upstreamFileInfo.hash;\n }\n }\n }\n}\n","/**\n * Migrate service: the upstream migration notes this fork has not handled yet.\n *\n * Notes live upstream only (see `utils/migration-notes`). They are read at the upstream commit the\n * fork last synced to, which the sync already fetched, so this works offline after a sync and\n * while a conflicted sync is still open. Each note also gets a GitHub permalink for readers\n * without the upstream remote. Nothing here blocks: the list is information to act on.\n *\n * `--run` runs a note's codemod from an extracted copy and puts back the files it changed that\n * were identical to upstream (see `runNote`).\n */\n\nimport { execFileSync, spawnSync } from 'node:child_process';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport type { MergeResult, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { DEFAULT_UPSTREAM_REMOTE } from '../utils/config';\nimport { checkMark, writeStdout } from '../utils/display';\nimport {\n batchRestoreWorktreeFromRef,\n ensureRemote,\n fetchRemote,\n getStoredSyncRef,\n git,\n listIdenticalToRef,\n MAX_BUFFER,\n readManifestBaseAtRef,\n} from '../utils/git';\nimport { readManifestBase } from '../utils/manifest';\nimport {\n formatNotesLine,\n isCodemodFile,\n listNoteIds,\n type MigrationNote,\n NOTES_DIR,\n noteUrl,\n readNote,\n readPending,\n writePending,\n} from '../utils/migration-notes';\nimport { getGitHubBaseUrl } from './merge-engine';\n\n/** Where `--extract` writes a note folder: inside the fork, so a codemod resolves the fork's packages. */\nconst EXTRACT_DIR = 'node_modules/.cache/cella/migrations';\n\n/** How many restored paths `--run` lists before it cuts the list short. */\nconst RESTORED_LIST_MAX = 20;\n\n/** Make sure an upstream commit is in this clone, fetching upstream once when it is not. */\nasync function ensureUpstreamCommit(config: RuntimeConfig, sha: string): Promise<void> {\n const { forkPath } = config;\n const present = async () =>\n !!(await git(['rev-parse', '--verify', '--quiet', `${sha}^{commit}`], forkPath, { ignoreErrors: true }));\n if (await present()) return;\n await ensureRemote(forkPath, DEFAULT_UPSTREAM_REMOTE, config.settings.upstreamUrl);\n await fetchRemote(forkPath, DEFAULT_UPSTREAM_REMOTE);\n if (!(await present()))\n throw new Error(`upstream commit ${sha.slice(0, 7)} is not reachable from '${DEFAULT_UPSTREAM_REMOTE}'`);\n}\n\n/** The upstream commit the fork last synced to, fetched if this clone lacks it; null before any sync. */\nasync function resolveNotesRef(config: RuntimeConfig): Promise<string | null> {\n const { forkPath } = config;\n const ref = (await getStoredSyncRef(forkPath)) ?? (await readManifestBaseAtRef(forkPath, 'HEAD'));\n if (!ref) return null;\n await ensureUpstreamCommit(config, ref);\n return ref;\n}\n\n/** Open and total note counts at the fork's sync point, for the info line; null before any sync. */\nasync function readNotesStatus(config: RuntimeConfig): Promise<{ total: number; open: number } | null> {\n try {\n const ref = await resolveNotesRef(config);\n if (!ref) return null;\n const [ids, pending] = await Promise.all([listNoteIds(config.forkPath, ref), readPending(config.forkPath, ref)]);\n return ids.length > 0 || pending.length > 0 ? { total: ids.length, open: pending.length } : null;\n } catch {\n return null;\n }\n}\n\n/** Print the dim info line at the end of a sync or analyze run. Never fails the run. */\nexport async function printMigrationNotesLine(config: RuntimeConfig, result?: MergeResult): Promise<void> {\n const notes = result?.migrationNotes;\n if (notes) {\n if (notes.total === 0) return;\n console.info();\n console.info(\n pc.dim(formatNotesLine(notes.total, notes.open, notes.arrived.length, { dryRun: config.service === 'analyze' })),\n );\n return;\n }\n const status = await readNotesStatus(config);\n if (!status) return;\n console.info();\n console.info(pc.dim(formatNotesLine(status.total, status.open)));\n}\n\n/** One note as `--json` reports it. */\nfunction toJson(note: MigrationNote, url: string | undefined, open: boolean) {\n return { ...note, kind: note.codemod ? 'codemod' : 'manual', open, url: url ?? null };\n}\n\n/** Print one note in the human list. */\nfunction printNote(index: number, note: MigrationNote, url: string | undefined): void {\n const tags = [\n note.codemod ? 'codemod' : 'manual',\n note.syncBreaking ? 'sync-breaking' : null,\n note.clientCacheBump ? 'cache-bump' : null,\n ]\n .filter(Boolean)\n .join(', ');\n console.info(`${index}. ${note.title} ${pc.dim(`[${tags}]`)}`);\n console.info(pc.dim(` id: ${note.id}`));\n if (note.summary) console.info(` ${note.summary}`);\n console.info(pc.dim(` read: pnpm cella migrate --show ${note.id}`));\n if (url) console.info(pc.dim(` ${url}`));\n if (note.codemod) console.info(pc.dim(` codemod: pnpm cella migrate --run ${note.id}`));\n console.info();\n}\n\n/**\n * Write a note's folder under {@link EXTRACT_DIR}, byte for byte. Returns the note, the folder\n * (relative to the fork) and its files.\n */\nasync function writeNoteFolder(\n config: RuntimeConfig,\n ref: string,\n id: string,\n): Promise<{ note: MigrationNote; target: string; files: string[] }> {\n const { forkPath } = config;\n const note = await readNote(forkPath, ref, id);\n if (!note) throw new Error(`no migration note '${id}' at upstream ${ref.slice(0, 7)}`);\n\n const files = (await git(['ls-tree', '-r', '--name-only', `${ref}:${NOTES_DIR}/${id}`], forkPath))\n .split('\\n')\n .filter(Boolean);\n const target = join(EXTRACT_DIR, id);\n for (const file of files) {\n // Byte for byte: the git helper trims its output.\n const content = execFileSync('git', ['show', `${ref}:${NOTES_DIR}/${id}/${file}`], {\n cwd: forkPath,\n maxBuffer: MAX_BUFFER,\n });\n const path = join(forkPath, target, file);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content);\n }\n return { note, target, files };\n}\n\n/** `--extract <id>`: write the note folder under {@link EXTRACT_DIR} and print how to run its codemod. */\nasync function extractNote(config: RuntimeConfig, ref: string, id: string): Promise<void> {\n const { note, target, files } = await writeNoteFolder(config, ref, id);\n\n console.info(`${checkMark} extracted ${files.length} file(s) to ${target}/`);\n console.info(pc.dim(` the README's ${NOTES_DIR}/${id}/ paths are this folder.`));\n if (note.codemod) {\n console.info(pc.dim(` pnpm exec tsx ${target}/${note.codemod} inventory ${note.roots.join(' ')}`));\n console.info(pc.dim(` or, keeping files identical to upstream as they are: pnpm cella migrate --run ${id}`));\n }\n}\n\n/**\n * The codemod of an extracted note: the file named with `--script`, else the one script in the\n * folder itself. Throws when the folder holds no script or several.\n */\nfunction resolveCodemod(id: string, files: string[], script?: string): string {\n if (script) {\n const name = script.replace(/^\\.\\//, '');\n if (!files.includes(name)) {\n throw new Error(`migration note '${id}' has no file '${script}'. its files: ${files.join(', ')}`);\n }\n return name;\n }\n const scripts = files.filter((file) => !file.includes('/') && isCodemodFile(file));\n if (scripts.length === 0) {\n throw new Error(\n `migration note '${id}' ships no codemod script: its steps are manual, read them with \\`pnpm cella migrate --show ${id}\\`.`,\n );\n }\n if (scripts.length > 1) {\n throw new Error(\n `migration note '${id}' ships ${scripts.length} scripts (${scripts.join(', ')}): name the one to run with --script <file>.`,\n );\n }\n return scripts[0];\n}\n\n/**\n * `--run <id>`: extract the note and run its codemod with `tsx` from the fork root, with the\n * arguments given after `--`, else `inventory` (report only) and the note's roots.\n *\n * A codemod's roots cover template-owned files too. A file identical to upstream already is the way\n * upstream wants it, so a rewrite there is drift (upstream may have changed the file after writing\n * the codemod). Files identical to the last synced upstream commit before the run, and changed by\n * it, get their upstream content back. That commit is `upstream.commit` in the working tree's\n * manifest, during a staged sync the incoming commit. The whole working tree is compared, so the\n * roots named after `--` are covered whichever they are.\n */\nasync function runNote(config: RuntimeConfig, ref: string, id: string): Promise<void> {\n const { forkPath } = config;\n const { note, target, files } = await writeNoteFolder(config, ref, id);\n const script = join(target, resolveCodemod(id, files, config.script));\n const args = config.runArgs?.length ? config.runArgs : ['inventory', ...note.roots];\n\n const upstreamCommit = (await readManifestBase(forkPath)) ?? ref;\n await ensureUpstreamCommit(config, upstreamCommit);\n const identical = await listIdenticalToRef(forkPath, upstreamCommit);\n\n console.info(pc.dim(`running pnpm exec tsx ${script} ${args.join(' ')}`));\n console.info();\n const child = spawnSync('pnpm', ['exec', 'tsx', script, ...args], { cwd: forkPath, stdio: 'inherit' });\n if (child.error) throw new Error(`could not run the codemod: ${child.error.message}`);\n\n // Also after a failed run: a codemod that stopped halfway may have rewritten files already.\n const stillIdentical = await listIdenticalToRef(forkPath, upstreamCommit);\n const restored = [...identical].filter((path) => !stillIdentical.has(path)).sort();\n await batchRestoreWorktreeFromRef(forkPath, upstreamCommit, restored);\n\n const upstreamShort = upstreamCommit.slice(0, 9);\n console.info();\n if (restored.length > 0) {\n console.info(`${checkMark} restored ${restored.length} file(s) to upstream ${upstreamShort}`);\n console.info(pc.dim(' the codemod changed them, and they were identical to upstream before the run:'));\n for (const path of restored.slice(0, RESTORED_LIST_MAX)) console.info(pc.dim(` ${path}`));\n if (restored.length > RESTORED_LIST_MAX) {\n console.info(pc.dim(` ... + ${restored.length - RESTORED_LIST_MAX} more`));\n }\n } else {\n console.info(pc.dim(`no file identical to upstream ${upstreamShort} was changed by the codemod.`));\n }\n\n if (child.status !== 0) throw new Error(`the codemod exited with code ${child.status ?? 'unknown'}`);\n if (!config.runArgs?.length) {\n const apply = ['rewrite', ...note.roots].join(' ');\n console.info(pc.dim(`report only. to apply: pnpm cella migrate --run ${id} -- ${apply}`));\n }\n}\n\n/** `--mark <ids…>`: drop handled notes from the pending list. */\nasync function markNotes(config: RuntimeConfig, ref: string, pending: string[], ids: string[]): Promise<void> {\n const open = new Set(pending);\n const unknown = ids.filter((id) => !open.has(id));\n for (const id of ids) open.delete(id);\n await writePending(config.forkPath, [...open]);\n const marked = ids.length - unknown.length;\n if (marked > 0) console.info(`${checkMark} recorded ${marked} note(s) as handled`);\n if (unknown.length > 0) console.info(pc.dim(`not pending, left as is: ${unknown.join(', ')}`));\n console.info(pc.dim(formatNotesLine((await listNoteIds(config.forkPath, ref)).length, open.size)));\n}\n\n/** Run the migrate service. */\nexport async function runMigrate(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n const ref = await resolveNotesRef(config);\n if (!ref) {\n console.info(pc.dim('no sync point recorded yet: migration notes start with the first `pnpm cella sync`.'));\n return;\n }\n\n const pending = await readPending(forkPath, ref);\n const githubUrl = getGitHubBaseUrl(config.settings.upstreamUrl) ?? undefined;\n const urlOf = (id: string) => noteUrl(githubUrl, ref, id);\n\n if (config.mark?.length) return markNotes(config, ref, pending, config.mark);\n if (config.run) return runNote(config, ref, config.run);\n if (config.extract) return extractNote(config, ref, config.extract);\n\n if (config.show) {\n const source = await git(['show', `${ref}:${NOTES_DIR}/${config.show}/README.md`], forkPath, {\n ignoreErrors: true,\n });\n if (!source) throw new Error(`no migration note '${config.show}' at upstream ${ref.slice(0, 7)}`);\n const url = urlOf(config.show);\n if (url) console.info(pc.dim(url));\n console.info(source);\n return;\n }\n\n const ids = config.all ? await listNoteIds(forkPath, ref) : pending;\n const notes = (await Promise.all(ids.map((id) => readNote(forkPath, ref, id)))).map(\n (note, i) =>\n note ?? {\n id: ids[i],\n title: `${ids[i]} (no longer upstream)`,\n summary: '',\n syncBreaking: false,\n clientCacheBump: false,\n roots: [],\n codemod: null,\n },\n );\n const total = (await listNoteIds(forkPath, ref)).length;\n\n if (config.json) {\n const open = new Set(pending);\n const out = {\n upstreamCommit: ref,\n total,\n open: pending.length,\n notes: notes.map((note) => toJson(note, urlOf(note.id), open.has(note.id))),\n };\n writeStdout(JSON.stringify(out, null, 2));\n return;\n }\n\n console.info(pc.dim(formatNotesLine(total, pending.length)));\n if (notes.length === 0) return;\n console.info();\n for (const [i, note] of notes.entries()) printNote(i + 1, note, urlOf(note.id));\n if (pending.length > 0) {\n console.info(pc.dim(\"work each note's README, check with `pnpm check`, then record it:\"));\n console.info(pc.dim(` pnpm cella migrate --mark ${pending.join(' ')}`));\n }\n}\n","/**\n * Audit service for the Cella CLI.\n *\n * Checks for outdated packages and security vulnerabilities across the monorepo.\n */\n\nimport { spawnSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { basename, join, relative } from 'node:path';\nimport { checkbox, confirm, Separator } from '@inquirer/prompts';\nimport type { RuntimeConfig } from '../config/types';\nimport {\n type AuditResult,\n buildVulnerabilityMap,\n clearCache,\n type EnhancedPackageInfo,\n fetchNpmMetadata,\n findChangelogUrl,\n formatDependents,\n getHighestSeverity,\n getOutdatedPackages,\n getReleasesUrl,\n getRepoUrl,\n getVulnIcon,\n isMajorVersionChange,\n loadCache,\n middleTruncate,\n runPnpmAudit,\n saveCache,\n type VulnerabilityInfo,\n} from '../utils/audit-utils';\nimport pc from '../utils/colors';\nimport {\n checkMark,\n createSpinner,\n DIVIDER,\n hyperlink,\n spinnerSuccess,\n spinnerText,\n warningMark,\n} from '../utils/display';\nimport { parseYamlBlockMap } from '../utils/yaml';\n\n/** Sentinel value for the audit --fix checkbox */\nconst AUDIT_FIX_VALUE = '__audit_fix__';\n\n/** A dependent workspace's package.json: its name plus dependency maps, for display names and pin detection. */\ntype DependentPkgJson = { name?: string } & Partial<Record<'dependencies' | 'devDependencies', Record<string, string>>>;\n\n/** Reader for dependents' package.jsons that loads each one once, caching by location. */\nfunction createDependentPkgReader(): (location: string) => DependentPkgJson | null {\n const cache = new Map<string, DependentPkgJson | null>();\n return (location) => {\n let cached = cache.get(location);\n if (cached === undefined) {\n try {\n cached = JSON.parse(readFileSync(join(location, 'package.json'), 'utf8'));\n } catch {\n cached = null;\n }\n cache.set(location, cached ?? null);\n }\n return cached ?? null;\n };\n}\n\n/** Vulnerability counts per severity, as `pnpm audit` reports them in its metadata. */\ntype SeverityCounts = Partial<AuditResult['metadata']['vulnerabilities']>;\n\n/**\n * Colored `N <severity>` parts for the severities with a non-zero count, in display order.\n * `suffix` rides inside each colored part except `low`, which always ends a summary.\n */\nfunction formatSeverityCounts(counts: SeverityCounts, suffix = ''): string[] {\n const parts: string[] = [];\n if (counts.critical) parts.push(pc.red(`${counts.critical} critical${suffix}`));\n if (counts.high) parts.push(pc.red(`${counts.high} high${suffix}`));\n if (counts.moderate) parts.push(pc.yellow(`${counts.moderate} moderate${suffix}`));\n if (counts.low) parts.push(pc.blue(`${counts.low} low`));\n return parts;\n}\n\nexport async function runAudit(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n\n if (config.checkOverrides) {\n await checkOverrides(forkPath);\n return;\n }\n\n const spinner = createSpinner('checking for outdated packages & vulnerabilities...');\n try {\n // --force drops both caches so registry data is fetched fresh.\n if (config.force) {\n spinnerText('clearing pnpm metadata cache...');\n clearCache();\n spawnSync('pnpm', ['cache', 'delete', '*'], {\n cwd: forkPath,\n stdio: 'ignore',\n });\n spinnerText('checking for outdated packages & vulnerabilities...');\n }\n\n const [outdatedPackages, auditResult] = await Promise.all([getOutdatedPackages(forkPath), runPnpmAudit(forkPath)]);\n\n const packageNames = Object.keys(outdatedPackages);\n const vulnMap = buildVulnerabilityMap(auditResult);\n\n if (packageNames.length === 0 && vulnMap.size === 0) {\n spinnerSuccess('all packages are up to date and secure');\n return;\n }\n\n // The cache holds resolved changelog URLs.\n const cache = loadCache();\n\n spinnerText(`found ${packageNames.length} outdated package(s), fetching metadata...`);\n\n const readDependentPkg = createDependentPkgReader();\n\n const dependentNameCache = new Map<string, string>();\n for (const name of packageNames) {\n for (const dep of outdatedPackages[name].dependentPackages) {\n if (!dependentNameCache.has(dep.location)) {\n dependentNameCache.set(dep.location, readDependentPkg(dep.location)?.name || basename(dep.location));\n }\n }\n }\n\n const enhancedPackages: EnhancedPackageInfo[] = [];\n const batchSize = 10;\n\n for (let i = 0; i < packageNames.length; i += batchSize) {\n const batch = packageNames.slice(i, i + batchSize);\n const results = await Promise.all(\n batch.map(async (name) => {\n const pkg = outdatedPackages[name];\n const metadata = await fetchNpmMetadata(name);\n const repoUrl = getRepoUrl(metadata);\n const changelogUrl = await findChangelogUrl(repoUrl, name, cache);\n\n // Workspaces that pin this package to an exact version.\n const pinnedIn: string[] = [];\n for (const d of pkg.dependentPackages) {\n const spec = readDependentPkg(d.location)?.[pkg.dependencyType]?.[name] || '';\n if (spec && !spec.startsWith('^') && !spec.startsWith('~') && !spec.startsWith('>')) {\n pinnedIn.push(d.name);\n }\n }\n\n return {\n name,\n current: pkg.current,\n latest: pkg.latest,\n dependents: pkg.dependentPackages.map((d) => d.name),\n dependentLocations: pkg.dependentPackages.map((d) => d.location),\n isDev: pkg.dependencyType === 'devDependencies',\n isMajorUpdate: isMajorVersionChange(pkg.current, pkg.latest),\n pinnedIn,\n repoUrl,\n changelogUrl,\n releasesUrl: getReleasesUrl(repoUrl),\n vulnerabilities: vulnMap.get(name) || [],\n };\n }),\n );\n enhancedPackages.push(...results);\n }\n\n saveCache(cache);\n\n enhancedPackages.sort((a, b) => {\n const depA = formatDependents(a.dependents);\n const depB = formatDependents(b.dependents);\n const depCompare = depA.localeCompare(depB);\n if (depCompare !== 0) return depCompare;\n return a.name.localeCompare(b.name);\n });\n\n spinner.stop();\n\n if (enhancedPackages.length > 0) {\n printOutdatedResults(enhancedPackages, dependentNameCache, forkPath);\n }\n printVulnerabilityResults(auditResult, vulnMap);\n\n // --list is the non-interactive mode: report only, no update prompt.\n const hasVulns = vulnMap.size > 0;\n if ((enhancedPackages.length > 0 || hasVulns) && !config.list) {\n await promptForUpdates(enhancedPackages, forkPath, auditResult);\n }\n } finally {\n spinner.stop();\n }\n}\n\nfunction printOutdatedResults(\n enhancedPackages: EnhancedPackageInfo[],\n dependentNameCache: Map<string, string>,\n forkPath: string,\n): void {\n const DEV_TAG = ' (dev)';\n const MAX_NAME_LEN = 35;\n const MAX_DEPENDENTS_LEN = 15;\n const maxNameLen = Math.min(\n MAX_NAME_LEN,\n Math.max(7, ...enhancedPackages.map((p) => p.name.length + (p.isDev ? DEV_TAG.length : 0))),\n );\n const maxCurrentLen = Math.max(7, ...enhancedPackages.map((p) => p.current.length));\n const maxLatestLen = Math.max(6, ...enhancedPackages.map((p) => p.latest.length));\n const maxDependentsLen = Math.min(\n MAX_DEPENDENTS_LEN,\n Math.max(10, ...enhancedPackages.map((p) => formatDependents(p.dependents).length)),\n );\n\n // The vuln column is a single dot, so it gets no width budget.\n const header = [\n ' ',\n pc.bold('package'.padEnd(maxNameLen)),\n pc.bold('current'.padEnd(maxCurrentLen)),\n pc.bold('latest'.padEnd(maxLatestLen)),\n pc.bold('in'.padEnd(maxDependentsLen)),\n pc.bold('links'),\n ].join(' ');\n\n console.info(header);\n\n for (const pkg of enhancedPackages) {\n const highestSeverity = getHighestSeverity(pkg.vulnerabilities);\n const vulnIndicator = highestSeverity ? getVulnIcon(highestSeverity) : ' ';\n\n const fullName = pkg.isDev ? `${pkg.name}${DEV_TAG}` : pkg.name;\n const displayName = middleTruncate(fullName, maxNameLen);\n const name = pc.white(displayName.padEnd(maxNameLen));\n\n const current = pc.red(pkg.current.padEnd(maxCurrentLen));\n const latestText = pkg.latest.padEnd(maxLatestLen);\n const latest = pkg.isMajorUpdate ? pc.bold(pc.green(latestText)) : pc.green(latestText);\n\n const dependentsText = formatDependents(pkg.dependents);\n const dependents = pc.dim(middleTruncate(dependentsText, maxDependentsLen).padEnd(maxDependentsLen));\n\n const links: string[] = [];\n if (pkg.changelogUrl) {\n links.push(hyperlink(pc.magenta('log'), pkg.changelogUrl));\n }\n if (pkg.releasesUrl) {\n links.push(hyperlink(pc.blue('rel'), pkg.releasesUrl));\n }\n if (pkg.repoUrl) {\n links.push(hyperlink(pc.cyan('repo'), pkg.repoUrl));\n }\n\n const linksStr = links.length > 0 ? links.join(' ') : pc.dim('n/a');\n\n console.info(`${vulnIndicator} ${name} ${current} ${latest} ${dependents} ${linksStr}`);\n }\n\n // Package.json links with counts by dependent name.\n console.info();\n const dependentMap = new Map<string, { location: string; count: number }>();\n for (const pkg of enhancedPackages) {\n for (const loc of pkg.dependentLocations) {\n const dependentName = dependentNameCache.get(loc) || basename(loc);\n const existing = dependentMap.get(dependentName);\n if (existing) {\n existing.count++;\n } else {\n dependentMap.set(dependentName, { location: loc, count: 1 });\n }\n }\n }\n const sortedDependents = [...dependentMap.entries()].sort((a, b) => a[0].localeCompare(b[0]));\n const maxDependentNameLen = Math.max(0, ...sortedDependents.map(([name]) => name.length));\n for (const [dependentName, { location, count }] of sortedDependents) {\n const packageJsonPath = join(location, 'package.json');\n const relativePath = relative(forkPath, packageJsonPath);\n const paddedName = dependentName.padEnd(maxDependentNameLen);\n console.info(\n ` ${pc.dim('•')} ${paddedName} ${hyperlink(relativePath, `file://${packageJsonPath}`)} ${pc.dim(`${count}`)}`,\n );\n }\n}\n\n/**\n * Build the grouped checkbox choices for the update prompt: the audit --fix entry when\n * vulnerabilities exist, then pinned packages, then the regular ones, with separators.\n */\nfunction buildUpdateChoices(\n packages: EnhancedPackageInfo[],\n auditResult: AuditResult | null,\n hasVulnerabilities: boolean,\n): Array<{ name: string; value: string; checked: boolean } | Separator> {\n const makeChoice = (pkg: EnhancedPackageInfo) => {\n const devTag = pkg.isDev ? pc.dim(' (dev)') : '';\n const version = `${pc.red(pkg.current)} → ${pc.green(pkg.latest)}`;\n const pinnedWarning =\n pkg.pinnedIn.length > 0 ? ` ${warningMark} ${pc.dim(`pinned in ${pkg.pinnedIn.join(', ')}`)}` : '';\n return {\n name: `${pkg.name}${devTag} ${version}${pinnedWarning}`,\n value: pkg.name,\n checked: false,\n };\n };\n\n const pinned = packages.filter((p) => p.pinnedIn.length > 0);\n const regular = packages.filter((p) => p.pinnedIn.length === 0);\n\n const choices: Array<{ name: string; value: string; checked: boolean } | Separator> = [];\n\n if (hasVulnerabilities) {\n const parts = formatSeverityCounts(auditResult?.metadata?.vulnerabilities || {});\n const vulnSummary = parts.length > 0 ? ` ${pc.dim('·')} ${parts.join(' ')}` : '';\n choices.push(new Separator(pc.red(`── vulnerabilities${vulnSummary} ──`)));\n choices.push({\n name: `${pc.cyan('pnpm audit --fix override')} ${pc.dim('add overrides for non-vulnerable versions')}`,\n value: AUDIT_FIX_VALUE,\n checked: false,\n });\n }\n\n if (pinned.length > 0) {\n choices.push(new Separator(pc.yellow(`── pinned (${pinned.length}) ──`)));\n choices.push(...pinned.map(makeChoice));\n }\n if (regular.length > 0) {\n if (pinned.length > 0 || hasVulnerabilities) {\n choices.push(new Separator(pc.dim(`── packages (${regular.length}) ──`)));\n }\n choices.push(...regular.map(makeChoice));\n }\n\n return choices;\n}\n\n/** Package-selection prompt; the chosen updates run through {@link executeUpdates}. */\nasync function promptForUpdates(\n packages: EnhancedPackageInfo[],\n forkPath: string,\n auditResult: AuditResult | null,\n): Promise<void> {\n const hasVulnerabilities =\n auditResult !== null && Object.values(auditResult.metadata?.vulnerabilities || {}).some((c) => c > 0);\n const hasPackages = packages.length > 0;\n\n let confirmMessage = 'update packages?';\n if (hasVulnerabilities && hasPackages) {\n confirmMessage = 'update packages and fix vulnerabilities?';\n } else if (hasVulnerabilities) {\n confirmMessage = 'fix vulnerabilities?';\n }\n\n let wantsUpdate: boolean;\n try {\n wantsUpdate = await confirm({\n message: confirmMessage,\n default: true,\n });\n } catch {\n return;\n }\n if (!wantsUpdate) return;\n\n console.info();\n\n const choices = buildUpdateChoices(packages, auditResult, hasVulnerabilities);\n\n let selected: string[];\n try {\n selected = await checkbox({\n message: 'toggle packages to update',\n choices,\n required: true,\n pageSize: 20,\n loop: false,\n theme: {\n icon: {\n cursor: '❯ ',\n },\n style: {\n highlight: (text: string) => text,\n keysHelpTip: (keys: [string, string][]) => {\n const tips = keys.map(([key, action]: [string, string]) => `${pc.dim(key)} ${action}`);\n return tips.join(' ');\n },\n renderSelectedChoices: (selectedChoices: Array<{ value?: string }>) =>\n pc.dim(`${selectedChoices.length} package${selectedChoices.length !== 1 ? 's' : ''} selected`),\n },\n },\n });\n } catch {\n // User pressed Ctrl+C or escaped\n return;\n }\n\n const runAuditFix = selected.includes(AUDIT_FIX_VALUE);\n const selectedPackages = selected.filter((s) => s !== AUDIT_FIX_VALUE);\n\n await executeUpdates(packages, forkPath, selectedPackages, runAuditFix);\n}\n\n/**\n * The selected updates: major bumps confirmed first, `pnpm audit --fix override` when chosen,\n * then one recursive `pnpm up` (catalog consumers normalized first).\n */\nasync function executeUpdates(\n packages: EnhancedPackageInfo[],\n forkPath: string,\n selectedPackages: string[],\n runAuditFix: boolean,\n): Promise<void> {\n const summaryParts: string[] = [];\n if (selectedPackages.length > 0) {\n summaryParts.push(`updating ${selectedPackages.length} package${selectedPackages.length !== 1 ? 's' : ''}`);\n }\n if (runAuditFix) {\n summaryParts.push('then updating dependencies');\n }\n console.info();\n console.info(pc.green(`✓ ${summaryParts.join(' ')}`));\n console.info();\n\n const selectedMajor = packages.filter((p) => selectedPackages.includes(p.name) && p.isMajorUpdate);\n if (selectedMajor.length > 0) {\n const majorNames = selectedMajor.map((p) => pc.bold(p.name)).join(', ');\n try {\n const proceed = await confirm({\n message: `${selectedMajor.length} major update${selectedMajor.length > 1 ? 's' : ''} selected (${majorNames}). proceed?`,\n default: true,\n });\n if (!proceed) {\n console.info(pc.dim(' update cancelled'));\n return;\n }\n } catch {\n return;\n }\n }\n\n const catalogPackages = readCatalogPackageNames(forkPath);\n\n const workspacePackages = new Map<string, string[]>();\n for (const pkgName of selectedPackages) {\n const pkg = packages.find((p) => p.name === pkgName);\n if (!pkg) continue;\n\n for (const dependent of pkg.dependents) {\n const group = workspacePackages.get(dependent);\n if (group) group.push(pkgName);\n else workspacePackages.set(dependent, [pkgName]);\n }\n }\n\n // Audit --fix runs before the package updates so its overrides apply during install.\n if (runAuditFix) {\n console.info(pc.dim('running pnpm audit --fix override...'));\n const auditFixResult = spawnSync('pnpm', ['audit', '--fix', 'override'], {\n cwd: forkPath,\n stdio: 'inherit',\n });\n\n console.info();\n if (auditFixResult.status === 0) {\n console.info(pc.green('✓ pnpm audit --fix override completed'));\n } else {\n console.error(pc.red(`✗ pnpm audit --fix override failed (exit code ${auditFixResult.status})`));\n }\n }\n\n // Summarize impacted workspaces before running a single workspace-wide update.\n // Catalog consumers are normalized before the recursive update so a strict\n // catalogMode cannot fail it with ERR_PNPM_CATALOG_VERSION_MISMATCH.\n for (const [workspace, pkgs] of workspacePackages) {\n const pkgList = pkgs.join(', ');\n console.info(`${pc.cyan('↑')} ${pc.bold(workspace)}: ${pc.dim(pkgList)}`);\n }\n\n if (selectedPackages.length > 0) {\n console.info();\n\n const selectedCatalogPackages = selectedPackages.filter((pkgName) => catalogPackages.has(pkgName));\n\n if (selectedCatalogPackages.length > 0) {\n console.info(pc.dim(`normalizing catalog consumers: ${selectedCatalogPackages.join(', ')}`));\n const normalizeResult = spawnSync('pnpm', ['-r', 'up', ...selectedCatalogPackages], {\n cwd: forkPath,\n stdio: 'inherit',\n });\n\n console.info();\n if (normalizeResult.status !== 0) {\n console.error(pc.red(`✗ catalog normalization failed (exit code ${normalizeResult.status})`));\n return;\n }\n }\n\n // Run one recursive update so pnpm can rewrite catalogs and direct consumers atomically.\n const result = spawnSync('pnpm', ['-r', 'up', '--latest', ...selectedPackages], {\n cwd: forkPath,\n stdio: 'inherit',\n });\n\n console.info();\n if (result.status === 0) {\n console.info(pc.green(`✓ ${selectedPackages.length} package${selectedPackages.length > 1 ? 's' : ''} updated`));\n } else {\n console.error(pc.red(`✗ update failed (exit code ${result.status})`));\n }\n }\n}\n\nfunction printVulnerabilityResults(auditResult: AuditResult | null, vulnMap: Map<string, VulnerabilityInfo[]>): void {\n if (auditResult && vulnMap.size > 0) {\n const vulnMeta = auditResult.metadata?.vulnerabilities || {};\n\n console.info();\n console.info(\n `${pc.red('⚠')} ${pc.bold('vulnerabilities')} ${pc.dim('·')} ${formatSeverityCounts(vulnMeta, ' ').join('')}`,\n );\n console.info(DIVIDER);\n\n for (const [pkgName, vulns] of vulnMap.entries()) {\n for (const vuln of vulns) {\n const severityIcon = getVulnIcon(vuln.severity);\n const cveStr = vuln.cves.length > 0 ? pc.dim(` ${vuln.cves[0]}`) : '';\n // Source info renders as \"in <workspace> via <direct-dep>\" or just \"in <workspace>\".\n let sourceStr = '';\n if (vuln.workspace) {\n sourceStr = pc.dim(` in ${vuln.workspace}`);\n if (vuln.directDependency) {\n sourceStr += pc.dim(` via ${vuln.directDependency}`);\n }\n }\n const title = middleTruncate(vuln.title, 60);\n console.info(\n `${severityIcon} ${pc.white(pkgName)} ${pc.dim(vuln.vulnerableVersions)}${sourceStr} ${pc.dim('·')} ${title}${cveStr}`,\n );\n }\n }\n } else {\n console.info();\n console.info(`${checkMark} no vulnerabilities found`);\n }\n\n console.info();\n}\n\nfunction readCatalogPackageNames(forkPath: string): Set<string> {\n const workspacePath = join(forkPath, 'pnpm-workspace.yaml');\n try {\n const content = readFileSync(workspacePath, 'utf8');\n return new Set(Object.keys(parseYamlBlockMap(content, 'catalog')));\n } catch {\n return new Set();\n }\n}\n\n/** All pnpm.overrides from package.json and pnpm-workspace.yaml, keyed by override key with target version and source file. */\nfunction readOverrides(forkPath: string): Map<string, { target: string; source: string }> {\n const overrides = new Map<string, { target: string; source: string }>();\n\n const pkgJsonPath = join(forkPath, 'package.json');\n try {\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8'));\n const pnpmOverrides = pkgJson.pnpm?.overrides || {};\n for (const [key, value] of Object.entries(pnpmOverrides)) {\n overrides.set(key, { target: value as string, source: 'package.json' });\n }\n } catch {\n // skip\n }\n\n const workspacePath = join(forkPath, 'pnpm-workspace.yaml');\n try {\n const content = readFileSync(workspacePath, 'utf8');\n const wsOverrides = parseYamlBlockMap(content, 'overrides');\n for (const [key, value] of Object.entries(wsOverrides)) {\n overrides.set(key, { target: value, source: 'pnpm-workspace.yaml' });\n }\n } catch {\n // skip\n }\n\n return overrides;\n}\n\n/** The --check-overrides report: each pnpm.override cross-referenced with the current audit. */\nasync function checkOverrides(forkPath: string): Promise<void> {\n const spinner = createSpinner('checking overrides against current audit...');\n\n const overrides = readOverrides(forkPath);\n\n if (overrides.size === 0) {\n spinnerSuccess('no pnpm.overrides found');\n return;\n }\n\n const auditResult = await runPnpmAudit(forkPath);\n\n const activeAdvisoryPackages = new Set<string>();\n if (auditResult?.advisories) {\n for (const advisory of Object.values(auditResult.advisories)) {\n activeAdvisoryPackages.add(advisory.module_name);\n }\n }\n\n spinner.stop();\n\n const securityOverrides: Array<{ key: string; pkg: string; target: string; source: string; status: string }> = [];\n const pinOverrides: Array<{ key: string; target: string; source: string }> = [];\n\n for (const [key, { target, source }] of overrides) {\n // Security overrides have version selectors like \"pkg@<=1.0.0\" or \"pkg@>=1.0.0 <2.0.0\"\n const atIndex = key.indexOf('@', key.startsWith('@') ? 1 : 0);\n if (atIndex > 0) {\n const pkg = key.slice(0, atIndex);\n const hasActiveAdvisory = activeAdvisoryPackages.has(pkg);\n const status = hasActiveAdvisory ? 'active' : 'likely stale';\n securityOverrides.push({ key, pkg, target, source, status });\n } else {\n pinOverrides.push({ key, target, source });\n }\n }\n\n const allKeys = Array.from(overrides.keys());\n const allValues = Array.from(overrides.values());\n const maxKeyLen = Math.max(8, ...allKeys.map((k) => k.length));\n const maxTargetLen = Math.max(6, ...allValues.map((v) => v.target.length));\n\n if (securityOverrides.length > 0) {\n console.info(pc.bold(`security overrides (${securityOverrides.length})`));\n console.info(DIVIDER);\n\n for (const o of securityOverrides) {\n const icon = o.status === 'active' ? pc.red('●') : pc.green('○');\n const statusText = o.status === 'active' ? pc.red('active') : pc.green('likely stale');\n const keyText = pc.white(o.key.padEnd(maxKeyLen));\n const targetText = pc.dim(o.target.padEnd(maxTargetLen));\n const sourceText = pc.dim(o.source);\n console.info(` ${icon} ${keyText} → ${targetText} ${statusText} ${sourceText}`);\n }\n console.info();\n }\n\n if (pinOverrides.length > 0) {\n console.info(pc.bold(`version pins (${pinOverrides.length})`));\n console.info(DIVIDER);\n\n for (const o of pinOverrides) {\n const keyText = pc.white(o.key.padEnd(maxKeyLen));\n const targetText = pc.dim(o.target.padEnd(maxTargetLen));\n const sourceText = pc.dim(o.source);\n console.info(` ${pc.blue('◆')} ${keyText} → ${targetText} ${sourceText}`);\n }\n console.info();\n }\n\n const staleCount = securityOverrides.filter((o) => o.status === 'likely stale').length;\n const activeCount = securityOverrides.filter((o) => o.status === 'active').length;\n\n if (staleCount > 0) {\n console.info(\n `${pc.green('○')} ${staleCount} override${staleCount !== 1 ? 's' : ''} likely stale: no matching advisory found in current audit`,\n );\n console.info(pc.dim(' overrides mask vulnerabilities: verify by temporarily removing and running pnpm audit'));\n }\n if (activeCount > 0) {\n console.info(\n `${pc.red('●')} ${activeCount} override${activeCount !== 1 ? 's' : ''} still active: advisory present without override`,\n );\n }\n if (pinOverrides.length > 0) {\n console.info(\n `${pc.blue('◆')} ${pinOverrides.length} version pin${pinOverrides.length !== 1 ? 's' : ''}: not security-related, review manually`,\n );\n }\n console.info();\n}\n","/**\n * Audit utilities: npm registry fetching, changelog detection, vulnerability\n * parsing, and caching for the audit service.\n */\n\nimport { execFile } from 'node:child_process';\nimport { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\nimport pc from './colors';\n\nconst execFileAsync = promisify(execFile);\n\ninterface OutdatedPackage {\n current: string;\n latest: string;\n dependencyType: 'dependencies' | 'devDependencies';\n dependentPackages: Array<{ name: string; location: string }>;\n}\n\nexport interface NpmRegistryData {\n repository?: { url: string };\n}\n\ninterface CachedPackageData {\n repoUrl: string | null;\n changelogUrl: string | null;\n fetchedAt: number;\n}\n\ninterface ChangelogCache {\n [packageName: string]: CachedPackageData;\n}\n\nexport interface EnhancedPackageInfo {\n name: string;\n current: string;\n latest: string;\n dependents: string[];\n dependentLocations: string[];\n isDev: boolean;\n isMajorUpdate: boolean;\n /** Workspace names where this package is pinned to an exact version (no ^ or ~) */\n pinnedIn: string[];\n repoUrl: string | null;\n changelogUrl: string | null;\n releasesUrl: string | null;\n vulnerabilities: VulnerabilityInfo[];\n}\n\n/** Vulnerability severity levels */\ntype VulnerabilitySeverity = 'critical' | 'high' | 'moderate' | 'low' | 'info';\n\n/** Vulnerability info for a package */\nexport interface VulnerabilityInfo {\n title: string;\n severity: VulnerabilitySeverity;\n vulnerableVersions: string;\n cves: string[];\n /** The workspace/dependent containing this vulnerability (e.g., 'frontend', 'backend') */\n workspace: string | null;\n /** The direct dependency in the workspace that brought in this vulnerable package */\n directDependency: string | null;\n}\n\n/** Audit result from pnpm audit --json */\nexport interface AuditResult {\n advisories: Record<string, AuditAdvisory>;\n metadata: {\n vulnerabilities: Record<VulnerabilitySeverity, number>;\n };\n}\n\ninterface AuditAdvisory {\n id: number;\n title: string;\n module_name: string;\n severity: VulnerabilitySeverity;\n vulnerable_versions: string;\n patched_versions: string;\n cves: string[];\n url: string;\n findings: Array<{ version: string; paths: string[] }>;\n}\n\n/** Parsed dependency path info from pnpm audit */\ninterface DependencyPathInfo {\n /** The workspace name (e.g., 'frontend', 'backend') */\n workspace: string | null;\n /** The direct dependency in the workspace that starts the chain */\n directDependency: string | null;\n}\n\n/** Cache file location (in cli/cella directory) */\nexport const CACHE_FILE = join(import.meta.dirname, '..', '..', '.audit.cache.json');\n\n/** Cache TTL: 7 days in ms */\nconst CACHE_TTL = 7 * 24 * 60 * 60 * 1000;\n\n/** Common changelog file paths to check in GitHub repos */\nexport const CHANGELOG_PATHS = ['CHANGELOG.md', 'CHANGELOG', 'changelog.md', 'HISTORY.md', 'CHANGES.md', 'NEWS.md'];\n\n/** Default branches to check for changelog files */\nexport const DEFAULT_BRANCHES = ['main', 'master'] as const;\n\n/** The changelog cache from disk; read errors yield an empty cache. */\nexport function loadCache(): ChangelogCache {\n try {\n if (existsSync(CACHE_FILE)) {\n return JSON.parse(readFileSync(CACHE_FILE, 'utf8'));\n }\n } catch {\n // Ignore cache read errors\n }\n return {};\n}\n\n/** Best-effort write of the changelog cache to disk. */\nexport function saveCache(cache: ChangelogCache): void {\n try {\n writeFileSync(CACHE_FILE, `${JSON.stringify(cache, null, 2)}\\n`);\n } catch {\n // Ignore cache write errors\n }\n}\n\n/** Removal of the changelog cache file, reported on the console. */\nexport function clearCache(): void {\n try {\n if (existsSync(CACHE_FILE)) {\n unlinkSync(CACHE_FILE);\n console.info(pc.green('✓ cache cleared successfully'));\n } else {\n console.info(pc.yellow('no cache file found'));\n }\n } catch (err) {\n console.error(pc.red('failed to clear cache:'), err);\n }\n}\n\n/** Package metadata from the npm registry, or null on any failure. */\nexport async function fetchNpmMetadata(packageName: string): Promise<NpmRegistryData | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${packageName}`);\n if (!response.ok) return null;\n return (await response.json()) as NpmRegistryData;\n } catch {\n return null;\n }\n}\n\n/** The repo URL from npm registry data, normalized to a plain https:// form. */\nexport function getRepoUrl(data: NpmRegistryData | null): string | null {\n if (!data?.repository?.url) return null;\n\n let url = data.repository.url;\n\n if (url.startsWith('git+')) {\n url = url.slice(4);\n }\n\n if (url.endsWith('.git')) {\n url = url.slice(0, -4);\n }\n\n if (url.startsWith('git://')) {\n url = url.replace('git://', 'https://');\n }\n\n return url;\n}\n\n/** Whether the URL points to a GitHub repository. */\nfunction isGitHubRepoUrl(repoUrl: string | null): repoUrl is string {\n if (!repoUrl) return false;\n try {\n const parsed = new URL(repoUrl);\n return parsed.hostname === 'github.com' || parsed.hostname === 'www.github.com';\n } catch {\n return false;\n }\n}\n\n/** The branch holding `filePath` in a GitHub repo, or null when no default branch has it. */\nasync function findGitHubFile(repoUrl: string, filePath: string): Promise<string | null> {\n if (!isGitHubRepoUrl(repoUrl)) return null;\n\n for (const branch of DEFAULT_BRANCHES) {\n const rawUrl = repoUrl.replace('github.com', 'raw.githubusercontent.com').concat(`/${branch}/${filePath}`);\n\n try {\n const response = await fetch(rawUrl, { method: 'HEAD' });\n if (response.ok) return branch;\n } catch {\n // Continue to next branch\n }\n }\n return null;\n}\n\n/**\n * The changelog URL for a package, found by probing common locations.\n * Results are cached to avoid repeated GitHub requests.\n */\nexport async function findChangelogUrl(\n repoUrl: string | null,\n packageName: string,\n cache: ChangelogCache,\n): Promise<string | null> {\n if (!isGitHubRepoUrl(repoUrl)) return null;\n\n const cached = cache[packageName];\n if (cached && Date.now() - cached.fetchedAt < CACHE_TTL) {\n return cached.changelogUrl;\n }\n\n for (const changelogPath of CHANGELOG_PATHS) {\n const branch = await findGitHubFile(repoUrl, changelogPath);\n if (branch) {\n const blobUrl = `${repoUrl}/blob/${branch}/${changelogPath}`;\n cache[packageName] = {\n repoUrl,\n changelogUrl: blobUrl,\n fetchedAt: Date.now(),\n };\n return blobUrl;\n }\n }\n\n // Cache the negative result too.\n cache[packageName] = {\n repoUrl,\n changelogUrl: null,\n fetchedAt: Date.now(),\n };\n\n return null;\n}\n\n/** The GitHub releases URL, or null for a non-GitHub repo. */\nexport function getReleasesUrl(repoUrl: string | null): string | null {\n if (!isGitHubRepoUrl(repoUrl)) return null;\n return `${repoUrl}/releases`;\n}\n\n/** Whether the update is a major version change. */\nexport function isMajorVersionChange(current: string, latest: string): boolean {\n const currentMajor = current.split('.')[0]?.replace(/^\\D+/, '');\n const latestMajor = latest.split('.')[0]?.replace(/^\\D+/, '');\n if (!currentMajor || !latestMajor) return false;\n return Number.parseInt(latestMajor, 10) > Number.parseInt(currentMajor, 10);\n}\n\n/**\n * Runs a pnpm command and parses its JSON stdout. pnpm exits non-zero when it finds outdated\n * packages or vulnerabilities (expected output, not an error), so the JSON is also rescued\n * from the error's stdout. Returns null for empty or unparsable output; never throws.\n */\nasync function runPnpmJson(args: string[], cwd: string): Promise<unknown> {\n const parse = (stdout?: string): unknown => {\n if (!stdout || stdout.trim() === '') return null;\n try {\n return JSON.parse(stdout);\n } catch {\n return null;\n }\n };\n\n try {\n const { stdout } = await execFileAsync('pnpm', args, {\n encoding: 'utf8',\n maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large outputs\n cwd,\n });\n return parse(stdout);\n } catch (error) {\n return parse(error instanceof Error && 'stdout' in error ? (error as { stdout: string }).stdout : undefined);\n }\n}\n\n/** Parsed `pnpm -r outdated --json`; an empty record when nothing is outdated or the check fails. */\nexport async function getOutdatedPackages(cwd: string): Promise<Record<string, OutdatedPackage>> {\n return ((await runPnpmJson(['-r', 'outdated', '--json'], cwd)) ?? {}) as Record<string, OutdatedPackage>;\n}\n\n/** Parsed `pnpm audit --json`; null when the audit fails or finds nothing. */\nexport async function runPnpmAudit(cwd: string): Promise<AuditResult | null> {\n return (await runPnpmJson(['audit', '--json'], cwd)) as AuditResult | null;\n}\n\n/**\n * Workspace and direct dependency extracted from vulnerability paths shaped like\n * \"workspace>direct-dep>transitive>vulnerable-pkg\". Examples:\n * - \"frontend>virtua>solid-js>seroval\" -> { workspace: 'frontend', directDependency: 'virtua' }\n * - \"backend>jsx-email>esbuild\" -> { workspace: 'backend', directDependency: 'jsx-email' }\n * - \"esbuild\" (direct) -> { workspace: null, directDependency: null }\n */\nfunction parseDependencyPath(paths: string[]): DependencyPathInfo {\n for (const pathStr of paths) {\n const parts = pathStr.split('>');\n if (parts.length >= 2) {\n return {\n workspace: parts[0],\n directDependency: parts.length > 2 ? parts[1] : null,\n };\n }\n }\n return { workspace: null, directDependency: null };\n}\n\n/** Map of package name -> vulnerabilities from an audit result. */\nexport function buildVulnerabilityMap(auditResult: AuditResult | null): Map<string, VulnerabilityInfo[]> {\n const map = new Map<string, VulnerabilityInfo[]>();\n if (!auditResult?.advisories) return map;\n\n for (const advisory of Object.values(auditResult.advisories)) {\n const allPaths = advisory.findings?.flatMap((f) => f.paths) || [];\n const { workspace, directDependency } = parseDependencyPath(allPaths);\n\n const existing = map.get(advisory.module_name) || [];\n existing.push({\n title: advisory.title,\n severity: advisory.severity,\n vulnerableVersions: advisory.vulnerable_versions,\n cves: advisory.cves || [],\n workspace,\n directDependency,\n });\n map.set(advisory.module_name, existing);\n }\n\n return map;\n}\n\n/** Severity dot per vulnerability level. */\nconst vulnIcons: Record<VulnerabilitySeverity, string> = {\n critical: pc.red('●'),\n high: pc.red('●'),\n moderate: pc.yellow('●'),\n low: pc.blue('●'),\n info: pc.gray('●'),\n};\n\nexport function getVulnIcon(severity: VulnerabilitySeverity): string {\n return vulnIcons[severity] ?? pc.gray('●');\n}\n\n/** The highest severity present in a list of vulnerabilities, or null. */\nexport function getHighestSeverity(vulns: VulnerabilityInfo[]): VulnerabilitySeverity | null {\n if (vulns.length === 0) return null;\n const order: VulnerabilitySeverity[] = ['critical', 'high', 'moderate', 'low', 'info'];\n for (const severity of order) {\n if (vulns.some((v) => v.severity === severity)) return severity;\n }\n return null;\n}\n\n/** Middle-truncation to maxLen, e.g. \"very-long-package-name\" -> \"very-lo…e-name\". */\nexport function middleTruncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n const ellipsis = '…';\n const charsToShow = maxLen - ellipsis.length;\n const frontChars = Math.ceil(charsToShow / 2);\n const backChars = Math.floor(charsToShow / 2);\n return str.slice(0, frontChars) + ellipsis + str.slice(-backChars);\n}\n\n/** Dependents as \"first +N\" when multiple. */\nexport function formatDependents(dependents: string[]): string {\n if (dependents.length === 0) return '';\n if (dependents.length === 1) return dependents[0];\n return `${dependents[0]} +${dependents.length - 1}`;\n}\n","/**\n * Extract the indented lines of a top-level YAML block (e.g. `overrides:`).\n * Stops at the next non-indented, non-empty line. Comment lines are skipped.\n */\nfunction yamlBlockLines(content: string, key: string): string[] {\n const lines: string[] = [];\n let inBlock = false;\n\n for (const line of content.split('\\n')) {\n if (new RegExp(`^${key}:\\\\s*$`).test(line)) {\n inBlock = true;\n continue;\n }\n if (!inBlock) continue;\n\n const trimmed = line.trim();\n if (trimmed.startsWith('#')) continue;\n // End of block: non-indented non-empty line (next top-level key)\n if (trimmed !== '' && !line.startsWith(' ') && !line.startsWith('\\t')) break;\n lines.push(line);\n }\n\n return lines;\n}\n\n/**\n * Parse a top-level YAML block of flat `key: value` entries into a record.\n * Quotes around keys and values are stripped.\n */\nexport function parseYamlBlockMap(content: string, key: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (const line of yamlBlockLines(content, key)) {\n const match = line.match(/^\\s+(.+?):\\s+['\"]?([^'\"]+)['\"]?\\s*$/);\n if (match) {\n result[match[1].replace(/^['\"]|['\"]$/g, '')] = match[2];\n }\n }\n return result;\n}\n\n/**\n * Parse a top-level YAML block of `- item` list entries into an array.\n */\nexport function parseYamlBlockList(content: string, key: string): string[] {\n const items: string[] = [];\n for (const line of yamlBlockLines(content, key)) {\n const trimmed = line.trim();\n if (trimmed.startsWith('- ')) items.push(trimmed.slice(2).trim());\n }\n return items;\n}\n","/**\n * Contributions service for sync CLI.\n *\n * Upstream-side (cella): based on the configured `forks`, lets the user pick a\n * single fork, pulls its `pullBranch` and builds a clean local `contrib/<fork>`\n * branch with only that fork's contributed files. Then shows an interactive TUI\n * to review and adopt individual files into the working tree.\n */\n\nimport {\n createPrompt,\n isDownKey,\n isEnterKey,\n isSpaceKey,\n isUpKey,\n useKeypress,\n usePagination,\n useState,\n} from '@inquirer/core';\nimport { select } from '@inquirer/prompts';\nimport type { FileStatus, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { DEFAULT_BRANCH, isUpstreamRepo, loadConfig } from '../utils/config';\nimport { gitDiffFile, openDiffInBrowser } from '../utils/diff';\nimport {\n checkMark,\n createSpinner,\n DIVIDER,\n spinnerFail,\n spinnerSuccess,\n warningMark,\n writeStdout,\n} from '../utils/display';\nimport { errorMessage } from '../utils/errors';\nimport { getCurrentBranch, getDiffStat, git, removeFileFromWorktree, restoreWorktreeFromRef } from '../utils/git';\nimport { buildContribBranch, countDetection, detectContributableFiles } from './contrib-core';\nimport { printNoForksHint, resolveForkBasePath, type ValidatedFork, validateForkPath } from './fork-utils';\n\ninterface ContribItem {\n /** File path relative to repo root */\n path: string;\n /** Local contrib branch ref (e.g., contrib/myfork) */\n ref: string;\n /** True if adopting this means deleting the file in cella */\n deleted: boolean;\n /** True if the file does not exist in cella yet (adopting it creates a new file) */\n created?: boolean;\n /** Analyzer status from cella's POV (behind = fork ahead, diverged = both changed) */\n status?: FileStatus;\n /** Relative date of the fork's change (e.g. '3 days ago') */\n changedAt?: string;\n /** Unix epoch seconds of the fork's change, for sorting */\n changedTs?: number;\n /** Lines added in the fork vs cella base (null for binary files) */\n additions?: number | null;\n /** Lines removed in the fork vs cella base (null for binary files) */\n deletions?: number | null;\n /** Whether file is selected for acceptance */\n checked: boolean;\n}\n\ninterface ContribPromptConfig {\n message: string;\n items: ContribItem[];\n /** Name of the fork being reviewed (used to label diffs cella/ vs <fork>/) */\n forkName: string;\n /** Base ref the contrib branches were built on (for diffing) */\n baseRef: string;\n /** Repo path where contrib branches live */\n cwd: string;\n pageSize?: number;\n}\n\n/**\n * Browser diff for a contrib file (cella base vs the fork's version).\n * Returns the written page path, or null when the file has no changes.\n */\nasync function showContribDiff(\n item: ContribItem,\n baseRef: string,\n cwd: string,\n forkName: string,\n): Promise<string | null> {\n const patch = gitDiffFile(cwd, `${baseRef}..${item.ref}`, item.path);\n if (patch.length === 0) return null;\n return openDiffInBrowser(patch.toString(), { filePath: item.path, srcLabel: 'cella', dstLabel: forkName }, cwd);\n}\n\n/**\n * Interactive prompt for reviewing contributed files.\n * Returns items selected for acceptance.\n */\nconst contribPrompt = createPrompt<ContribItem[], ContribPromptConfig>((config, done) => {\n const { pageSize = 20, baseRef, cwd, forkName } = config;\n\n const [items, setItems] = useState<ContribItem[]>(config.items);\n const [active, setActive] = useState(0);\n const [statusMsg, setStatusMsg] = useState('');\n const [promptStatus, setPromptStatus] = useState<'idle' | 'done'>('idle');\n\n useKeypress(async (key) => {\n const last = items.length - 1;\n\n if (items.length === 0) {\n if (isEnterKey(key) || key.name === 'q') {\n setPromptStatus('done');\n done([]);\n }\n return;\n }\n\n if (key.name === 'q') {\n setPromptStatus('done');\n done([]);\n return;\n }\n\n if (isEnterKey(key)) {\n const selected = items.filter((i) => i.checked);\n if (selected.length === 0) {\n setStatusMsg('select files with space first, or q to quit');\n return;\n }\n setPromptStatus('done');\n done(selected);\n return;\n }\n\n // Navigation\n if (key.ctrl && isUpKey(key)) {\n setActive(0);\n setStatusMsg('');\n return;\n }\n if (key.ctrl && isDownKey(key)) {\n setActive(last);\n setStatusMsg('');\n return;\n }\n if (isUpKey(key)) {\n setActive(active <= 0 ? 0 : active - 1);\n setStatusMsg('');\n return;\n }\n if (isDownKey(key)) {\n setActive(active >= last ? last : active + 1);\n setStatusMsg('');\n return;\n }\n\n if (isSpaceKey(key)) {\n setItems(items.map((item, i) => (i === active ? { ...item, checked: !item.checked } : item)));\n return;\n }\n\n // d = open diff in browser (non-blocking, the list stays up)\n if (key.name === 'd') {\n try {\n const pagePath = await showContribDiff(items[active], baseRef, cwd, forkName);\n setStatusMsg(pagePath ? `opened ${items[active].path} in browser` : `no changes for ${items[active].path}`);\n } catch (error) {\n setStatusMsg(`diff failed: ${errorMessage(error)}`);\n }\n return;\n }\n\n if (key.name === 'a') {\n const allChecked = items.every((item) => item.checked);\n setItems(items.map((item) => ({ ...item, checked: !allChecked })));\n setStatusMsg(allChecked ? 'deselected all' : 'selected all');\n return;\n }\n });\n\n // Render: done state\n if (promptStatus === 'done') {\n const checked = items.filter((i) => i.checked);\n if (checked.length > 0) {\n return `${checkMark} ${checked.length} files accepted`;\n }\n return `${checkMark} done`;\n }\n\n // Render: empty\n if (items.length === 0) {\n return `${checkMark} no contributions: press enter`;\n }\n\n // Render: paginated list\n const checkedCount = items.filter((i) => i.checked).length;\n\n const page = usePagination({\n items,\n active,\n renderItem({ item, isActive }) {\n const checkbox = item.checked ? pc.green('●') : pc.dim('○');\n const cursor = isActive ? pc.cyan('❯') : ' ';\n const newLabel = item.created ? pc.yellow(' · not in cella') : '';\n const delLabel = item.deleted ? pc.yellow(' [del]') : '';\n const statusTag = item.status === 'diverged' ? pc.yellow(' ⚠ diverged') : '';\n const dateLabel = item.changedAt ? pc.dim(` · ${item.changedAt}`) : '';\n const line = `${cursor} ${checkbox} ${item.path}${delLabel}${statusTag}${newLabel}${dateLabel}`;\n return isActive ? pc.cyan(line) : line;\n },\n pageSize,\n loop: false,\n });\n\n const countInfo =\n checkedCount > 0 ? `${items.length} files, ${pc.green(`${checkedCount} selected`)}` : `${items.length} files`;\n const header = `${pc.cyan('⬇')} ${config.message} ${pc.dim(`(${countInfo})`)}`;\n\n const keys: [string, string][] = [\n ['↑↓', 'navigate'],\n ['d', 'diff in browser'],\n ['a', '(de)select all'],\n ['space', 'select'],\n ['⏎', 'accept'],\n ['q', 'quit'],\n ];\n const helpLine = keys.map(([k, a]) => `${pc.bold(k)} ${pc.dim(a)}`).join(pc.dim(' · '));\n\n const statusLine = statusMsg ? ` ${pc.dim(statusMsg)}` : '';\n\n const lines = [header, page, statusLine, helpLine].filter(Boolean).join('\\n').trimEnd();\n return `${lines}\\x1B[?25l`;\n});\n\n/**\n * Resolve the fork to pull from: the explicit --fork by name, the single valid fork in\n * non-interactive modes (--list/--json/--diff), or an interactive prompt. Throws when no\n * fork can be selected (main's handler prints the message and exits 1); returns undefined\n * only when the interactive prompt selects nothing.\n */\nasync function selectFork(config: RuntimeConfig, validated: ValidatedFork[]): Promise<ValidatedFork | undefined> {\n if (config.fork) {\n const match = validated.find((v) => v.fork.name === config.fork);\n if (!match?.valid) {\n throw new Error(`fork '${config.fork}' not found or invalid in config`);\n }\n return match;\n }\n\n const validForks = validated.filter((v) => v.valid);\n if (config.list || config.json || config.diff) {\n if (validForks.length === 0) {\n throw new Error('no valid forks configured');\n }\n if (validForks.length > 1) {\n throw new Error('multiple forks configured; pass --fork <name> to choose one');\n }\n return validForks[0];\n }\n\n const choices = validated.map((v) => ({\n value: v.fork.name,\n name: v.valid\n ? `${v.fork.name} ${pc.dim(`[${v.fork.pullBranch}] ${v.fork.localPath}`)}`\n : `${v.fork.name} ${pc.dim(v.fork.localPath)}`,\n disabled: v.valid ? false : (v.error ?? 'invalid'),\n }));\n const picked = await select<string>({\n message: 'select fork to pull contributions from:',\n choices,\n loop: false,\n });\n const selected = validated.find((v) => v.fork.name === picked);\n if (!selected) console.info(pc.dim('no fork selected.'));\n return selected;\n}\n\n/** Fetch a fork's pullBranch into cella's object store and return the commit sha. */\nasync function fetchForkBranch(cellaPath: string, fetchSource: string, pullBranch: string): Promise<string> {\n await git(['fetch', fetchSource, pullBranch], cellaPath);\n return git(['rev-parse', 'FETCH_HEAD'], cellaPath);\n}\n\n/** Short sha + relative date of the fork's committed pullBranch HEAD (for the comparison banner). */\nasync function forkRefMeta(cellaPath: string, forkRef: string): Promise<{ sha: string; date: string }> {\n const out = await git(['log', '-1', '--format=%h%x09%cr', forkRef], cellaPath, { ignoreErrors: true });\n const [sha = forkRef.slice(0, 7), date = 'unknown'] = out.split('\\t');\n return { sha, date };\n}\n\n/**\n * Run the contributions service.\n *\n * Based on the configured `forks`, lets the user select one fork, pulls its\n * `pullBranch`, builds a clean local `contrib/<fork>` branch, then presents\n * an interactive TUI to review and adopt individual files.\n */\nexport async function runContributions(config: RuntimeConfig): Promise<void> {\n const forks = config.forks ?? [];\n\n if (forks.length === 0) {\n printNoForksHint('add forks to pull contributions from:');\n return;\n }\n\n // Compare forks against cella's currently checked-out branch, not a fixed\n // configured branch, so contributions reflect the branch you're working on.\n const baseRef = await getCurrentBranch(config.forkPath);\n\n // Warn when not on cella's base branch. The comparison is a 3-way analysis against\n // merge-base(baseRef, fork), so a long-lived feature branch has an older merge-base\n // than 'main' and may surface extra 'diverged' files that would show clean from main.\n if (baseRef !== DEFAULT_BRANCH) {\n console.info(\n `${warningMark} ${pc.yellow(`not on base branch '${DEFAULT_BRANCH}'`)} ${pc.dim(`comparing forks against '${baseRef}'`)}`,\n );\n console.info(\n ` ${pc.dim(`older merge-base may show extra 'diverged' files; switch to '${DEFAULT_BRANCH}' for the cleanest result`)}`,\n );\n console.info('');\n }\n\n const forkBasePath = await resolveForkBasePath(config.forkPath);\n const validated = forks.map((fork) => validateForkPath(fork, forkBasePath));\n\n const selectedFork = await selectFork(config, validated);\n if (!selectedFork) return;\n\n const { fork, resolvedPath } = selectedFork;\n const forkName = fork.name;\n\n createSpinner('pulling fork contributions...');\n const allItems: ContribItem[] = [];\n let forkBanner: { pullBranch: string; sha: string; date: string } | null = null;\n\n try {\n // Prefer the fork's remote (authoritative committed ref) over the local clone.\n const fetchSource = fork.remoteUrl ?? resolvedPath;\n const forkRef = await fetchForkBranch(config.forkPath, fetchSource, fork.pullBranch);\n const meta = await forkRefMeta(config.forkPath, forkRef);\n forkBanner = { pullBranch: fork.pullBranch, sha: meta.sha, date: meta.date };\n\n // Read the fork's own owned folders so its fork-specific modules aren't offered back\n let forkTerritory: string[] = [];\n try {\n const forkConfig = await loadConfig(resolvedPath);\n forkTerritory = forkConfig.overrides?.ignored ?? [];\n } catch {\n // Fork may not have a cella/cella.config.ts: no extra territory to exclude\n }\n\n const detection = await detectContributableFiles(config.forkPath, baseRef, forkRef, config, forkTerritory);\n if (countDetection(detection) > 0) {\n const { branch, appliedFiles } = await buildContribBranch(config.forkPath, baseRef, forkRef, detection, forkName);\n if (appliedFiles.length > 0) {\n const stat = await getDiffStat(config.forkPath, baseRef, branch);\n const metaByPath = new Map(detection.files.map((f) => [f.path, f]));\n const toItem = (path: string, deleted: boolean): ContribItem => {\n const fileMeta = metaByPath.get(path);\n return {\n path,\n ref: branch,\n deleted,\n ...(deleted ? {} : { created: fileMeta?.kind === 'created' }),\n status: fileMeta?.status,\n changedAt: fileMeta?.changedAt,\n changedTs: fileMeta?.changedTs,\n additions: stat.get(path)?.additions ?? null,\n deletions: stat.get(path)?.deletions ?? null,\n checked: false,\n };\n };\n for (const path of [...detection.modified, ...detection.created]) allItems.push(toItem(path, false));\n for (const path of detection.deleted) allItems.push(toItem(path, true));\n }\n }\n } catch (error) {\n spinnerFail(`failed to pull ${forkName}`);\n console.info(pc.red(` ✗ ${errorMessage(error)}`));\n return;\n }\n\n if (allItems.length === 0) {\n spinnerSuccess('no contributions found');\n return;\n }\n\n // Sort by most recent fork change first (undated files last), path as tie-breaker,\n // so the top of the list shows where the fork last drifted (further) apart.\n allItems.sort((a, b) => (b.changedTs ?? 0) - (a.changedTs ?? 0) || a.path.localeCompare(b.path));\n\n spinnerSuccess(`${allItems.length} files from ${forkName}`);\n\n // Make the comparison basis explicit: the fork is compared at its committed pullBranch HEAD,\n // not its working tree, so uncommitted fork edits never appear here. Still skipped for\n // --list/--diff: their human output goes to stderr, and the banner is noise there too.\n if (!config.list && !config.diff && forkBanner) {\n console.info(\n ` ${pc.dim(`${forkName}: comparing committed '${forkBanner.pullBranch}' @ ${forkBanner.sha} (${forkBanner.date}); uncommitted fork changes are not included`)}`,\n );\n }\n\n // Print the unified diff for a single file, then exit (tooling/agent usage).\n if (config.diff) {\n const matches = allItems.filter((i) => i.path === config.diff);\n if (matches.length === 0) {\n throw new Error(`no contribution found for path: ${config.diff}`);\n }\n for (const item of matches) {\n const diff = gitDiffFile(config.forkPath, `${baseRef}..${item.ref}`, item.path, { dstPrefix: forkName });\n writeStdout(diff.toString());\n }\n return;\n }\n\n // Machine-readable JSON output for tooling/agent usage\n if (config.json) {\n const out = allItems.map((item) => ({\n fork: forkName,\n path: item.path,\n status: item.status ?? null,\n kind: item.deleted ? 'deleted' : 'modified',\n changedAt: item.changedAt ?? null,\n changedTs: item.changedTs ?? null,\n additions: item.additions ?? null,\n deletions: item.deletions ?? null,\n }));\n writeStdout(JSON.stringify(out, null, 2));\n return;\n }\n\n // Non-interactive mode: output enriched list for LLM/agent usage.\n // Columns are tab-separated: fork, status, kind, changedAt, path.\n // Note: status reflects the fork's committed pullBranch HEAD vs cella's base\n // (behind = fork ahead, diverged = both changed), not the fork's working tree.\n if (config.list) {\n for (const item of allItems) {\n const status = item.status ?? 'behind';\n const kind = item.deleted ? 'deleted' : 'modified';\n const changedAt = item.changedAt ?? '-';\n writeStdout(`${forkName}\\t${status}\\t${kind}\\t${changedAt}\\t${item.path}`);\n }\n return;\n }\n\n console.info();\n console.info(DIVIDER);\n\n const selected = await contribPrompt({\n message: `contributions from ${forkName}`,\n items: allItems,\n forkName,\n baseRef,\n cwd: config.forkPath,\n pageSize: 20,\n });\n\n if (selected.length === 0) {\n console.info();\n return;\n }\n\n // Apply selected files into the working tree (unstaged in upstream cella, staged in a fork)\n createSpinner(`applying ${selected.length} files...`);\n const applyUnstaged = isUpstreamRepo(config.forkPath);\n\n let applied = 0;\n const errors: string[] = [];\n\n for (const item of selected) {\n try {\n // Reject paths with traversal components (CWE-22)\n if (item.path.includes('..') || item.path.startsWith('/')) {\n errors.push(`${item.path}: rejected (path traversal)`);\n continue;\n }\n if (item.deleted) {\n if (applyUnstaged) {\n await removeFileFromWorktree(config.forkPath, item.path);\n } else {\n await git(['rm', '-f', '--', item.path], config.forkPath, { ignoreErrors: true });\n }\n } else {\n if (applyUnstaged) {\n await restoreWorktreeFromRef(config.forkPath, item.ref, item.path);\n } else {\n await git(['checkout', item.ref, '--', item.path], config.forkPath);\n }\n }\n applied++;\n } catch (error) {\n errors.push(`${item.path}: ${errorMessage(error)}`);\n }\n }\n\n if (errors.length > 0) {\n spinnerFail(`applied ${applied}/${selected.length} files (${errors.length} errors)`);\n for (const err of errors) {\n console.info(pc.red(` ✗ ${err}`));\n }\n } else {\n spinnerSuccess(`applied ${applied} files ${pc.dim(applyUnstaged ? '(unstaged)' : '(staged)')}`);\n }\n\n // No per-file summary: the applied files are visible in the IDE's source control view.\n console.info();\n console.info(\n pc.dim(\n applyUnstaged\n ? ' files are unstaged: review, stage what you want, and commit when ready'\n : ' files are staged: review and commit when ready',\n ),\n );\n console.info();\n}\n","/**\n * Shared contribution engine.\n *\n * Cella (upstream) pulls a fork's branch and detects which files the fork\n * changed, created, or deleted relative to cella's base branch. It then builds\n * a clean local `contrib/<fork>` branch (the base branch plus only the fork's\n * file overlays) so the changes can be reviewed and adopted without a\n * working-tree checkout.\n *\n * The fork's blobs are read directly from the fetched ref (already in cella's\n * object store), never from the filesystem.\n */\n\nimport { dirname, join, resolve } from 'node:path';\nimport type { CellaCliConfig, FileStatus } from '../config/types';\nimport { git } from '../utils/git';\nimport { isIgnored, isPinned, isUnderAnyFolder } from '../utils/overrides';\nimport { analyzeRefs, enrichChangeInfo } from './analyze-core';\n\n/** A single contributable file with classification and metadata. */\ninterface ContribFile {\n /** File path relative to repo root */\n path: string;\n /** How adopting this file changes cella */\n kind: 'modified' | 'created' | 'deleted';\n /** Analyzer status from cella's POV (behind = fork ahead, diverged = both changed) */\n status: FileStatus;\n /** Relative date of the fork's change (e.g. '3 days ago') */\n changedAt?: string;\n /** Unix epoch seconds of the fork's change, for sorting */\n changedTs?: number;\n}\n\n/** Files a fork contributes relative to the base branch. */\ninterface ContribDetection {\n /** Files changed in fork that also exist in base */\n modified: string[];\n /** New fork files in directories that exist in base (sibling heuristic) */\n created: string[];\n /** Files that exist in base but were removed in fork */\n deleted: string[];\n /** Enriched per-file metadata for the union of the above */\n files: ContribFile[];\n}\n\nasync function listFilesAtRef(repoPath: string, ref: string): Promise<Set<string>> {\n const raw = await git(['ls-tree', '-r', '--name-only', ref], repoPath);\n return new Set(raw.split('\\n').filter(Boolean));\n}\n\n/**\n * Detect the files a fork contributes relative to cella's base branch.\n *\n * Uses a merge-base 3-way analysis (cella = local, fork = incoming) so the\n * result distinguishes fork-ahead changes from cella's own drift. Only files\n * where the fork is ahead (status `behind`) or both sides changed (`diverged`)\n * are contributable.\n *\n * @param repoPath - Cella repo path (where the fork ref has been fetched)\n * @param baseRef - Cella's base branch ref (e.g. 'development')\n * @param forkRef - Fetched fork commit (e.g. a resolved FETCH_HEAD sha)\n * @param config - Cella's config, used to exclude ignored/pinned files\n * @param forkTerritory - Paths the fork owns (from the fork's own\n * `ignored` list); excluded so fork-specific modules aren't offered back\n */\nexport async function detectContributableFiles(\n repoPath: string,\n baseRef: string,\n forkRef: string,\n config: CellaCliConfig,\n forkTerritory: string[] = [],\n): Promise<ContribDetection> {\n // Common ancestor for 3-way comparison; fall back to baseRef if histories are unrelated\n const mergeBase = (await git(['merge-base', baseRef, forkRef], repoPath, { ignoreErrors: true })).trim() || baseRef;\n\n const predicates = {\n isIgnored: (path: string) => isIgnored(path, config) || isUnderAnyFolder(path, forkTerritory),\n isPinned: (path: string) => isPinned(path, config),\n };\n\n // local = cella (baseRef), incoming = fork (forkRef)\n const analyzed = await analyzeRefs(repoPath, baseRef, forkRef, mergeBase, predicates);\n await enrichChangeInfo(repoPath, analyzed, mergeBase, baseRef, forkRef);\n\n // Base directory set for the sibling heuristic on created files.\n // Seed with '.' because the repo root always exists in cella, so new fork\n // files at the root (e.g. a shared config) are offered, not silently skipped.\n const baseFiles = await listFilesAtRef(repoPath, baseRef);\n const baseDirs = new Set<string>(['.']);\n for (const f of baseFiles) {\n let dir = dirname(f);\n while (dir !== '.') {\n baseDirs.add(dir);\n dir = dirname(dir);\n }\n }\n\n const files: ContribFile[] = [];\n for (const file of analyzed) {\n // Only files where the fork is ahead of cella are contributable\n if (file.status !== 'behind' && file.status !== 'diverged') continue;\n if (file.isIgnored || file.isPinned) continue;\n\n const inCella = file.existsInFork; // local side\n const inFork = file.existsInUpstream; // incoming side\n\n let kind: ContribFile['kind'];\n if (inCella && !inFork) {\n kind = 'deleted';\n } else if (!inCella && inFork) {\n // New fork file: only offer it when its directory already exists in cella,\n // so fork-specific modules don't flood the list (territory handles the rest)\n if (!baseDirs.has(dirname(file.path))) continue;\n kind = 'created';\n } else {\n kind = 'modified';\n }\n\n // Fork-side change date: 'behind' stores it in changedAt, 'diverged' in upstreamChangedAt\n const changedAt = file.status === 'diverged' ? file.upstreamChangedAt : file.changedAt;\n const changedTs = file.status === 'diverged' ? file.upstreamChangedTs : file.changedTs;\n files.push({ path: file.path, kind, status: file.status, changedAt, changedTs });\n }\n\n return {\n modified: files.filter((f) => f.kind === 'modified').map((f) => f.path),\n created: files.filter((f) => f.kind === 'created').map((f) => f.path),\n deleted: files.filter((f) => f.kind === 'deleted').map((f) => f.path),\n files,\n };\n}\n\n/** Total number of files in a detection result. */\nexport function countDetection(detection: ContribDetection): number {\n return detection.modified.length + detection.created.length + detection.deleted.length;\n}\n\n/**\n * Read mode and blob hash for a file at a ref.\n * Returns null if the path is not a regular blob at the ref.\n */\nasync function readBlobInfo(\n repoPath: string,\n ref: string,\n filePath: string,\n): Promise<{ mode: string; hash: string } | null> {\n const line = await git(['ls-tree', ref, '--', filePath], repoPath, { ignoreErrors: true });\n if (!line) return null;\n // Format: \"<mode> <type> <hash>\\t<path>\"\n const match = line.match(/^(\\d{6}) (\\w+) ([0-9a-f]+)\\t/);\n if (!match) return null;\n const [, mode, type, hash] = match;\n if (type !== 'blob') return null;\n // Only allow regular (100644) and executable (100755) file modes; skip symlinks/gitlinks\n if (mode !== '100644' && mode !== '100755') return null;\n return { mode, hash };\n}\n\n/**\n * Build a clean local `contrib/<fork>` branch from a fork's contributed files.\n *\n * The branch is created on top of `baseRef` with only the fork's file overlays\n * applied via a temporary index; the working tree is never touched.\n *\n * @returns The branch name and number of files applied.\n */\nexport async function buildContribBranch(\n repoPath: string,\n baseRef: string,\n forkRef: string,\n detection: ContribDetection,\n forkName: string,\n): Promise<{ branch: string; appliedFiles: string[] }> {\n const branch = `contrib/${forkName}`;\n // Resolve the actual git dir: in a linked worktree `.git` is a pointer file, and the\n // worktree's git dir lives under the main checkout's `.git/worktrees/<name>`.\n const gitDir = resolve(repoPath, await git(['rev-parse', '--git-dir'], repoPath));\n const tmpIndex = join(gitDir, `tmp-contrib-index-${forkName.replace(/[^\\w.-]/g, '_')}`);\n const indexEnv = { GIT_INDEX_FILE: tmpIndex };\n\n try {\n // Seed the temp index with cella's base tree\n await git(['read-tree', baseRef], repoPath, { env: indexEnv });\n\n const appliedFiles: string[] = [];\n\n // Overlay modified + created fork files (blobs already in object store via fetch)\n for (const filePath of [...detection.modified, ...detection.created]) {\n const blob = await readBlobInfo(repoPath, forkRef, filePath);\n if (!blob) continue;\n await git(\n ['update-index', '--add', '--replace', '--cacheinfo', `${blob.mode},${blob.hash},${filePath}`],\n repoPath,\n {\n env: indexEnv,\n },\n );\n appliedFiles.push(filePath);\n }\n\n // Remove deleted files from the index\n for (const filePath of detection.deleted) {\n await git(['update-index', '--remove', filePath], repoPath, { env: indexEnv, ignoreErrors: true });\n appliedFiles.push(`(deleted) ${filePath}`);\n }\n\n if (appliedFiles.length === 0) {\n return { branch, appliedFiles };\n }\n\n // Write tree and commit on top of base\n const treeHash = await git(['write-tree'], repoPath, { env: indexEnv });\n const parentHash = await git(['rev-parse', baseRef], repoPath);\n const commitBody = appliedFiles.map((f) => `- ${f}`).join('\\n');\n const commitMessage = `contrib(${forkName}): ${appliedFiles.length} files\\n\\n${commitBody}`;\n const commitHash = await git(['commit-tree', treeHash, '-p', parentHash, '-m', commitMessage], repoPath);\n\n // Create/update the local branch ref without checkout\n await git(['update-ref', `refs/heads/${branch}`, commitHash], repoPath);\n\n return { branch, appliedFiles };\n } finally {\n try {\n const { unlinkSync } = await import('node:fs');\n unlinkSync(tmpIndex);\n } catch {\n // Best effort\n }\n }\n}\n","/**\n * Shared helpers for the fork-aware services (`forks` and `contributions`).\n */\n\nimport { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport type { ForkConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { git } from '../utils/git';\nimport { CONFIG_FILE } from '../utils/managed-files';\n\n/**\n * Base directory that relative fork `localPath` values resolve against.\n *\n * A `localPath` like `../my-app` is written relative to the repository's main checkout. When\n * the CLI runs inside a linked worktree (e.g. `.claude/worktrees/x`), resolving against the\n * worktree would point inside the worktrees directory, so resolve against the main repository\n * root: the parent of the shared git common dir. Falls back to `repoPath` outside a repository.\n */\nexport async function resolveForkBasePath(repoPath: string): Promise<string> {\n const commonDir = await git(['rev-parse', '--git-common-dir'], repoPath, { ignoreErrors: true });\n return commonDir ? dirname(resolve(repoPath, commonDir)) : repoPath;\n}\n\n/** A fork config paired with its validation result. */\nexport interface ValidatedFork {\n fork: ForkConfig;\n resolvedPath: string;\n valid: boolean;\n error?: string;\n}\n\n/**\n * Validate a fork's local path resolves safely and points at a git repository.\n *\n * @param requireConfig when true, the fork must also contain a `cella/cella.config.ts`.\n */\nexport function validateForkPath(fork: ForkConfig, basePath: string, requireConfig = false): ValidatedFork {\n const resolvedPath = resolve(basePath, fork.localPath);\n\n // Validate resolved path doesn't escape the parent directory via traversal (CWE-22)\n if (!resolvedPath.startsWith(resolve(basePath, '..'))) {\n return { fork, resolvedPath, valid: false, error: 'path resolves outside parent directory' };\n }\n if (!existsSync(resolvedPath)) return { fork, resolvedPath, valid: false, error: 'path does not exist' };\n if (!existsSync(`${resolvedPath}/.git`)) return { fork, resolvedPath, valid: false, error: 'not a git repository' };\n if (requireConfig && !existsSync(`${resolvedPath}/${CONFIG_FILE}`)) {\n return { fork, resolvedPath, valid: false, error: `missing ${CONFIG_FILE}` };\n }\n\n return { fork, resolvedPath, valid: true };\n}\n\n/**\n * Print the \"no forks configured\" empty-state with a config example.\n *\n * @param action a short dim line describing what forks enable (e.g. 'add forks to your config:').\n */\nexport function printNoForksHint(action: string): void {\n console.info(pc.yellow('no forks configured in cella/cella.config.ts'));\n console.info(pc.dim(action));\n console.info(pc.dim(` forks: [{ name: 'my-app', localPath: '../my-app', pullBranch: 'development' }]`));\n}\n","/**\n * Forks service: runs the sync service inside configured local fork repositories\n * from the upstream template. Selecting a fork runs sync immediately (plus\n * packages when enabled), then returns to the selection menu.\n */\n\nimport { resolve } from 'node:path';\nimport process from 'node:process';\nimport { Separator, select } from '@inquirer/prompts';\nimport type { ForkConfig, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { loadConfig, resolveUpstream } from '../utils/config';\nimport { MENU_DIVIDER } from '../utils/display';\nimport { getCommitInfo, getCurrentBranch, getStoredSyncRef, getWorkingTreeChangeCount } from '../utils/git';\nimport { printNoForksHint, resolveForkBasePath, validateForkPath } from './fork-utils';\nimport { runSyncCommand } from './sync';\n\n/** Status info gathered from a fork repository */\ninterface ForkStatus {\n branch: string;\n dirty: number;\n lastSync: { date: string; message: string } | null;\n}\n\n/** Git status info for a fork: branch, dirty state, last sync. */\nasync function gatherForkStatus(forkPath: string): Promise<ForkStatus> {\n const [branch, dirty, syncRef] = await Promise.all([\n getCurrentBranch(forkPath).catch(() => 'unknown'),\n getWorkingTreeChangeCount(forkPath).catch(() => 0),\n getStoredSyncRef(forkPath),\n ]);\n\n let lastSync: { date: string; message: string } | null = null;\n if (syncRef) {\n const commitInfo = await getCommitInfo(forkPath, syncRef).catch(() => null);\n lastSync = { date: commitInfo?.date ?? 'unknown', message: commitInfo?.message ?? '' };\n }\n\n return { branch, dirty, lastSync };\n}\n\nfunction formatForkChoice(name: string, status: ForkStatus | null): string {\n if (!status) return name;\n\n // Sync: date and truncated commit message.\n let syncPart: string;\n if (status.lastSync) {\n const msg =\n status.lastSync.message.length > 36 ? `${status.lastSync.message.slice(0, 36)}…` : status.lastSync.message;\n syncPart = pc.dim(`${status.lastSync.date}`);\n if (msg) syncPart += pc.dim(` '${msg}'`);\n } else {\n syncPart = pc.dim('never synced');\n }\n\n const dirtyPart = status.dirty > 0 ? pc.yellow(`${status.dirty} uncommitted`) : '';\n\n const parts = [name, pc.dim(`[${status.branch}]`), syncPart];\n if (dirtyPart) parts.push(dirtyPart);\n\n return parts.join(pc.dim(' · '));\n}\n\n/** Fork choices with live status info, gathered in parallel. */\nasync function buildForkChoices(\n forks: ForkConfig[],\n basePath: string,\n): Promise<Array<{ value: string; name: string; disabled?: string }>> {\n const validated = forks.map((fork) => validateForkPath(fork, basePath, true));\n\n const statusEntries = await Promise.all(\n validated\n .filter((v) => v.valid)\n .map(async (v) => {\n const status = await gatherForkStatus(v.resolvedPath);\n return { path: v.fork.localPath, status };\n }),\n );\n const statusMap = new Map(statusEntries.map((e) => [e.path, e.status]));\n\n return validated.map((v) => {\n if (!v.valid) {\n return {\n value: v.fork.localPath,\n name: `${v.fork.name} ${pc.dim(v.fork.localPath)}`,\n disabled: v.error,\n };\n }\n return {\n value: v.fork.localPath,\n name: formatForkChoice(v.fork.name, statusMap.get(v.fork.localPath) ?? null),\n };\n });\n}\n\n/** Sync a single fork by running the same service flow the fork owner would run locally. */\nasync function syncFork(config: RuntimeConfig, fork: ForkConfig, forkPath: string): Promise<void> {\n console.info();\n console.info(pc.cyan(`syncing to ${fork.name}...`));\n console.info(pc.dim(`path: ${forkPath}`));\n console.info();\n\n const forkConfig = await loadConfig(forkPath);\n\n const { branchRef } = resolveUpstream(forkConfig.settings);\n const upstreamRef = branchRef;\n\n const forkRuntimeConfig: RuntimeConfig = {\n ...forkConfig,\n forkPath,\n upstreamRef,\n service: 'sync',\n logFile: config.logFile,\n list: false,\n json: false,\n verbose: config.verbose,\n hard: config.hard,\n keepConfig: config.keepConfig,\n };\n\n await runSyncCommand(forkRuntimeConfig);\n}\n\nexport async function runForks(config: RuntimeConfig): Promise<void> {\n const forks = config.forks ?? [];\n\n if (forks.length === 0) {\n printNoForksHint('add forks to your config:');\n return;\n }\n\n // --fork is the non-interactive mode.\n if (config.fork) {\n const match = forks.find((f) => f.name === config.fork);\n if (!match) {\n throw new Error(`fork '${config.fork}' not found in config`);\n }\n const resolvedPath = resolve(await resolveForkBasePath(config.forkPath), match.localPath);\n await syncFork(config, match, resolvedPath);\n return;\n }\n\n // Choices are rebuilt each iteration so the menu reflects updated status.\n const forkBasePath = await resolveForkBasePath(config.forkPath);\n while (true) {\n const choices = await buildForkChoices(forks, forkBasePath);\n const forkChoices = [...choices, new Separator(MENU_DIVIDER), { value: '_exit', name: pc.dim('exit') }];\n\n const selectedPath = await select<string>({\n message: 'select fork to sync:',\n choices: forkChoices,\n loop: false,\n });\n\n if (selectedPath === '_exit') {\n process.exit(0);\n }\n\n const resolvedForkPath = resolve(forkBasePath, selectedPath);\n const selectedFork = forks.find((f) => f.localPath === selectedPath);\n if (!selectedFork) {\n console.error(pc.red(`fork '${selectedPath}' not found in config`));\n continue;\n }\n\n await syncFork(config, selectedFork, resolvedForkPath);\n\n console.info();\n }\n}\n","/**\n * Sync service for the cella CLI.\n *\n * Runs the merge engine directly in the fork (no worktree) so conflicts surface in the IDE, on\n * a fresh temporary branch cut from the trunk. The service is idempotent: if a run stops at\n * conflicts, resolve them and run `cella sync` again to finish the same merge.\n */\n\nimport { spawnSync } from 'node:child_process';\nimport { select } from '@inquirer/prompts';\nimport { type CommitRangeEntry, type MergeResult, type RuntimeConfig, SYNC_APPLIED_STATUSES } from '../config/types';\nimport pc from '../utils/colors';\nimport {\n buildTemporarySyncBranch,\n DEFAULT_SYNC_PREFIX,\n isTemporarySyncBranch,\n resolveReleaseBase,\n} from '../utils/config';\nimport {\n COMMIT_LIST_MAX,\n checkMark,\n createSpinner,\n printEngineReports,\n printFlagWarnings,\n printLogFileReport,\n printSyncComplete,\n printUpstreamOverrideChanges,\n spinnerFail,\n spinnerSuccess,\n warningMark,\n} from '../utils/display';\nimport { errorMessage } from '../utils/errors';\nimport { closePr, type GhPullRequest, ghAvailable, listOpenSyncPrs, mergePrSquash } from '../utils/gh';\nimport {\n assertClean,\n branchExists,\n commitSquash,\n countCommitsBetween,\n createBranchFrom,\n deleteBranch,\n fastForwardBranch,\n fetchRemote,\n flattenBranch,\n getBranchUpstream,\n getBranchWorktree,\n getCommitInfo,\n getConflictedFiles,\n getCurrentBranch,\n getMergeBase,\n getShortSha,\n getUpstreamStatus,\n isAncestor,\n isClean,\n listBranchMergeCommits,\n listCommitsBetween,\n mergeInProgress,\n pullFastForward,\n pushBranch,\n readManifestAtRef,\n readManifestBaseAtRef,\n readPackageVersionAtRef,\n stageAll,\n switchBranch,\n switchDetached,\n} from '../utils/git';\nimport { readSyncManifest } from '../utils/manifest';\nimport { listNoteIds, noteUrl, readNote, readPending } from '../utils/migration-notes';\nimport { BehindSyncPointError, runEngineWithSpinner, UpstreamConfigChangedError } from './merge-engine';\nimport { printMigrationNotesLine } from './migrate';\nimport { runPackages } from './packages';\n\n/** Context for the temporary branch a sync cycle runs on. */\ninterface TemporarySyncBranch {\n /** The freshly cut temporary branch, e.g. `cella/sync/20260702-1430`. */\n temporaryBranch: string;\n /** The trunk the branch was cut from and PRs land into (`releaseBase`, default `main`). */\n base: string;\n /** The branch the user was on before the cycle started, 'HEAD' when detached (for cleanup on no-op). */\n startBranch: string;\n /** The commit the user was on before the cycle started (to return to a detached start). */\n startCommit: string;\n}\n\n/**\n * Make sure the trunk is current with its remote and return the ref a sync cycle cuts its branch\n * from. Compares refs and never checks the trunk out, so this also works from a linked worktree\n * while another worktree has the trunk checked out.\n *\n * Fetches the trunk's upstream and reacts to how local compares:\n * - behind (fast-forwardable): fast-forward it so the branch is cut from the latest trunk. When\n * another worktree has the trunk checked out, its ref can't move under that checkout: cut from\n * the remote-tracking ref instead and leave the trunk as it is.\n * - diverged (local commits the remote lacks *and* vice versa): abort with guidance, since\n * syncing onto a stale/diverged trunk produces a PR against an out-of-date base and avoidable\n * conflicts.\n * - ahead-only / up to date / no upstream (local-only repo): fine, just note it and continue.\n */\nasync function resolveCycleStart(forkPath: string, base: string, currentBranch: string): Promise<string> {\n // No local trunk branch to compare: cut from origin's, which `git switch` would have created it from.\n if (!(await branchExists(forkPath, base))) {\n await fetchRemote(forkPath, 'origin').catch(() => {});\n console.info(pc.dim(`'${base}' has no local branch: cutting from 'origin/${base}'.`));\n return `origin/${base}`;\n }\n\n const { upstream, ahead, behind } = await getUpstreamStatus(forkPath, base);\n\n if (!upstream) {\n console.info(pc.dim(`'${base}' has no upstream: skipping the up-to-date check.`));\n return base;\n }\n\n if (ahead > 0 && behind > 0) {\n throw new Error(\n `'${base}' has diverged from '${upstream}' (${ahead} ahead, ${behind} behind).\\n` +\n `Reconcile '${base}' with '${upstream}' first (e.g. rebase or reset it), then re-run sync.`,\n );\n }\n\n if (behind > 0) {\n const worktree = currentBranch === base ? null : await getBranchWorktree(forkPath, base);\n if (worktree) {\n console.info(\n pc.dim(`'${base}' is ${behind} behind '${upstream}' but checked out at ${worktree}; leaving it as it is.`),\n );\n return upstream;\n }\n console.info(pc.dim(`fast-forwarding '${base}' to '${upstream}' (${behind} behind)...`));\n if (currentBranch === base) await pullFastForward(forkPath);\n else await fastForwardBranch(forkPath, base, upstream);\n return base;\n }\n\n if (ahead > 0) {\n console.info(pc.dim(`'${base}' is ${ahead} commit(s) ahead of '${upstream}' (unpushed); continuing.`));\n }\n return base;\n}\n\n/**\n * Cut a fresh temporary sync branch from the trunk.\n *\n * Brings `releaseBase` up to date, then creates `cella/sync/<stamp>` from it (`git switch -c`\n * from wherever the run started) so the merge lands on an isolated throwaway branch, never a\n * long-lived integration branch.\n */\nasync function setupTemporarySyncBranch(config: RuntimeConfig): Promise<TemporarySyncBranch> {\n const { forkPath, settings } = config;\n const base = resolveReleaseBase(settings);\n const startBranch = await getCurrentBranch(forkPath);\n const startCommit = (await getCommitInfo(forkPath, 'HEAD')).hash;\n\n console.info(pc.dim(`updating '${base}'...`));\n const startPoint = await resolveCycleStart(forkPath, base, startBranch);\n\n const temporaryBranch = buildTemporarySyncBranch();\n\n console.info(pc.dim(`creating temporary sync branch '${temporaryBranch}' from '${startPoint}'...`));\n console.info();\n await createBranchFrom(forkPath, temporaryBranch, startPoint);\n\n return { temporaryBranch, base, startBranch, startCommit };\n}\n\n/**\n * The trunk ref a sync branch was cut from, to read its own commits against (`<ref>..HEAD`): the\n * trunk, or its remote-tracking ref when the trunk is behind it. `resolveCycleStart` cuts from\n * `origin` when another worktree holds a stale trunk, and that stale trunk would count origin's\n * newer commits as part of the sync branch.\n */\nasync function resolveCutBase(forkPath: string, base: string): Promise<string> {\n if (!(await branchExists(forkPath, base))) return `origin/${base}`;\n const upstream = await getBranchUpstream(forkPath, base);\n return upstream && (await isAncestor(forkPath, base, upstream)) ? upstream : base;\n}\n\n/**\n * Leave the sync branch for the trunk, after shipping it. When another worktree has the trunk\n * checked out, git refuses to switch to it: detach at the trunk instead, so this worktree holds\n * no branch and the sync branch can be deleted once its PR lands. Returns where it left HEAD.\n */\nasync function returnToBase(forkPath: string, base: string): Promise<string> {\n const worktree = await getBranchWorktree(forkPath, base);\n if (worktree) {\n console.info(pc.dim(`'${base}' is checked out at ${worktree}; detaching at '${base}' here instead...`));\n await switchDetached(forkPath, base);\n return `detached at '${base}'`;\n }\n\n console.info(pc.dim(`switching back to '${base}'...`));\n await switchBranch(forkPath, base);\n await pullFastForward(forkPath).catch(() => {});\n return `back on '${base}'`;\n}\n\n/**\n * Run the merge engine against the current branch (the core merge step).\n *\n * Performs the merge directly in the fork and leaves it staged: conflicted files keep their\n * markers for IDE 3-way resolution, everything else is resolved per the override rules. Called\n * by `runSyncCycle`.\n */\nexport async function runSync(\n config: RuntimeConfig,\n options?: {\n stagedBranch?: string;\n },\n): Promise<MergeResult> {\n createSpinner('starting sync...');\n\n let result: MergeResult;\n try {\n result = await runEngineWithSpinner(config, true);\n } catch (error) {\n // The engine threw, usually a stop before the merge: end the spinner, and when the sync config\n // gate stopped it, show what upstream changed.\n spinnerSuccess();\n if (error instanceof UpstreamConfigChangedError) {\n printUpstreamOverrideChanges({ upstreamOverrides: error.report });\n console.info();\n }\n throw error;\n }\n\n if (result.success) {\n spinnerSuccess();\n } else {\n spinnerFail('sync completed with conflicts');\n }\n\n // Print summary (no file lists for sync) plus the shared upstream-changes reports\n printEngineReports(result, 'merge summary');\n\n printLogFileReport(config, result.files);\n\n const stagedBranch =\n options?.stagedBranch && result.conflicts.length === 0 && hasStagedSyncChanges(result)\n ? options.stagedBranch\n : undefined;\n printSyncComplete(result, { stagedBranch });\n\n printFlagWarnings({ hard: config.hard, unpinned: config.unpinned });\n\n await printMigrationNotesLine(config, result);\n\n return result;\n}\n\n/** Conventional PR title prefix required by release-please. */\nconst SYNC_PR_TITLE = 'chore: sync upstream cella';\n\n/**\n * Build the sync commit subject, e.g. `chore: sync upstream cella v0.2.2 (4f7d87c)`.\n *\n * The upstream version comes from the manifest's release tag when tracking releases, else from\n * upstream's root package.json at the merged commit. Falls back to the bare title (+ short sha)\n * when a lookup fails, so committing never blocks on cosmetics.\n */\nasync function buildSyncCommitMessage(forkPath: string, upstreamRef: string): Promise<string> {\n const shortSha = await getShortSha(forkPath, upstreamRef).catch(() => '');\n if (!shortSha) return SYNC_PR_TITLE;\n\n const manifest = await readSyncManifest(forkPath);\n const version =\n manifest?.upstream.release ?? (await readPackageVersionAtRef(forkPath, upstreamRef).catch(() => null));\n return version ? `${SYNC_PR_TITLE} v${version.replace(/^v/, '')} (${shortSha})` : `${SYNC_PR_TITLE} ${shortSha}`;\n}\n\n/**\n * Qualify bare `#123` references in an upstream commit subject with the upstream repo slug.\n * Left bare, GitHub would auto-link them to the fork's own issue/PR #123 in the PR body.\n */\nfunction qualifyPrRefs(subject: string, repoSlug?: string): string {\n if (!repoSlug) return subject;\n return subject.replace(/(^|[^\\w/])#(\\d+)\\b/g, `$1${repoSlug}#$2`);\n}\n\n/** Inputs for {@link buildSyncPrBody}, recovered from the committed sync manifests. */\ninterface SyncPrBodyInput {\n /** GitHub slug of the upstream repo, e.g. 'cellajs/cella'. */\n repoSlug?: string;\n /** Upstream version or release tag at the sync point (leading `v` optional). */\n version?: string | null;\n /** Previous upstream sync point (full sha), when known. */\n fromSha?: string | null;\n /** Upstream commit this sync moved to (full sha). */\n toSha: string;\n /** Upstream commits in the range, oldest first (possibly truncated to the newest N). */\n commits: CommitRangeEntry[];\n /** Total commits in the range (may exceed `commits.length` when truncated). */\n totalCount: number;\n /** Upstream migration notes at the sync point: the total, and the ones the app has not handled yet. */\n notes?: { total: number; open: Array<{ id: string; title: string; url?: string }> };\n}\n\n/** Render the sync PR body: where the sync moved to, plus the upstream commits it brought in. */\nexport function buildSyncPrBody(input: SyncPrBodyInput): string {\n const { repoSlug, version, fromSha, toSha, commits, totalCount, notes } = input;\n const githubUrl = repoSlug ? `https://github.com/${repoSlug}` : undefined;\n const short = (sha: string) => sha.slice(0, 7);\n const commitRef = (sha: string) =>\n githubUrl ? `[\\`${short(sha)}\\`](${githubUrl}/commit/${sha})` : `\\`${short(sha)}\\``;\n\n const upstreamName = githubUrl ? `[${repoSlug}](${githubUrl})` : 'cella';\n const versionSuffix = version ? ` (v${version.replace(/^v/, '')})` : '';\n const lines = [`Syncs upstream ${upstreamName} to ${commitRef(toSha)}${versionSuffix}.`];\n\n if (totalCount > 0 && fromSha) {\n const compare = githubUrl ? ` ([compare](${githubUrl}/compare/${short(fromSha)}...${short(toSha)}))` : '';\n lines.push('', `**${totalCount} upstream commit${totalCount === 1 ? '' : 's'} since last sync**${compare}:`, '');\n if (totalCount > commits.length) lines.push(`- …${totalCount - commits.length} earlier commit(s) not shown`);\n for (const commit of commits) {\n lines.push(`- ${commitRef(commit.hash)} ${qualifyPrRefs(commit.message, repoSlug)}`);\n }\n }\n\n if (notes && notes.total > 0) {\n const { total, open } = notes;\n if (open.length === 0) lines.push('', `**Migration notes**: all ${total} handled.`);\n else {\n lines.push(\n '',\n `**Migration notes**: ${Math.max(0, total - open.length)} of ${total} handled, open (\\`pnpm cella migrate\\`):`,\n '',\n );\n for (const note of open)\n lines.push(`- ${note.url ? `[${note.title}](${note.url})` : note.title} (\\`${note.id}\\`)`);\n }\n }\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/**\n * Build the PR body for a finished sync branch: the upstream commits between the trunk's last\n * recorded sync point and the one this branch moves to (both read from committed manifests, so\n * this works on the rerun that ships the branch, long after the merge engine ran).\n *\n * Returns undefined when the branch has no committed manifest: the caller falls back to `--fill`.\n */\nasync function buildSyncPrBodyForBranch(forkPath: string, base: string): Promise<string | undefined> {\n const manifest = await readManifestAtRef(forkPath, 'HEAD');\n if (!manifest) return undefined;\n\n const toSha = manifest.upstream.commit.toLowerCase();\n // The trunk's committed manifest is the previous sync point; merge-base covers forks whose\n // last sync predates the manifest. `refs/cella/last-sync` is no help here: the merge already\n // moved it to `toSha`.\n const fromSha =\n (await readManifestBaseAtRef(forkPath, base)) ?? (await getMergeBase(forkPath, base, toSha).catch(() => null));\n const version = manifest.upstream.release ?? (await readPackageVersionAtRef(forkPath, toSha).catch(() => null));\n\n const totalCount = fromSha ? await countCommitsBetween(forkPath, fromSha, toSha).catch(() => 0) : 0;\n const commits =\n fromSha && totalCount > 0\n ? await listCommitsBetween(forkPath, fromSha, toSha, {\n skip: totalCount > COMMIT_LIST_MAX ? totalCount - COMMIT_LIST_MAX : 0,\n limit: COMMIT_LIST_MAX,\n })\n : [];\n\n const notes = await readPrBodyNotes(forkPath, toSha, manifest.upstream.repo).catch(() => undefined);\n return buildSyncPrBody({ repoSlug: manifest.upstream.repo, version, fromSha, toSha, commits, totalCount, notes });\n}\n\n/** Migration notes for the PR body: the total at the sync point and the app's open ones, with permalinks. */\nasync function readPrBodyNotes(forkPath: string, toSha: string, repoSlug?: string): Promise<SyncPrBodyInput['notes']> {\n const githubUrl = repoSlug ? `https://github.com/${repoSlug}` : undefined;\n const [ids, pending] = await Promise.all([listNoteIds(forkPath, toSha), readPending(forkPath, toSha)]);\n const open = await Promise.all(\n pending.map(async (id) => ({\n id,\n title: (await readNote(forkPath, toSha, id))?.title ?? id,\n url: noteUrl(githubUrl, toSha, id),\n })),\n );\n return { total: ids.length, open };\n}\n\n/** Print the GitHub CLI command for opening the finished sync PR. */\nfunction printPrCreateStep(branch: string, base: string, title = SYNC_PR_TITLE): void {\n console.info(pc.dim(` gh pr create --base ${base} --head ${branch} --title \"${title}\" --fill`));\n}\n\n/** Print the \"push + open a PR\" steps for a sync branch whose merge is already committed. */\nfunction printShipSteps(temporaryBranch: string, base: string, title?: string): void {\n console.info(pc.dim(` git push -u origin ${temporaryBranch}`));\n printPrCreateStep(temporaryBranch, base, title);\n}\n\n/** Whether sync applied changes that need a finishing rerun. */\nfunction hasStagedSyncChanges(result: MergeResult): boolean {\n return result.files.some((file) => SYNC_APPLIED_STATUSES.includes(file.status));\n}\n\n/** Extract the first URL from command output, usually the PR URL emitted by GitHub CLI. */\nfunction extractFirstUrl(output: string): string | undefined {\n return output.match(/https?:\\/\\/\\S+/)?.[0];\n}\n\n/**\n * Safety net run before a sync branch goes public: flatten away merge commits.\n *\n * The finishing rerun commits the sync as a single-parent commit (`commitSquash`), but a manual\n * `git commit` while the merge is staged records a two-parent merge commit instead. Upstream's\n * history isn't shared with `origin` (sync PRs are squash-merged), so such a commit makes the PR\n * list every upstream commit ever made, and that list grows with every upstream release.\n *\n * When the branch contains merge commits, rewrite it as one commit with identical content\n * (the PR diff is unchanged). Returns true if the branch was rewritten, so the caller can\n * force-push over the version already on the remote.\n */\nasync function flattenSyncBranch(forkPath: string, branch: string, base: string): Promise<boolean> {\n const mergeCommits = await listBranchMergeCommits(forkPath, base);\n if (mergeCommits.length === 0) return false;\n\n // The most recent merge's second parent is the upstream tip that was merged in.\n const message = await buildSyncCommitMessage(forkPath, `${mergeCommits[0]}^2`);\n\n console.info(\n pc.yellow(\n `'${branch}' contains ${mergeCommits.length} merge commit(s): the PR would list the entire upstream history.`,\n ),\n );\n console.info(pc.dim(`flattening '${branch}' to a single commit (same content)...`));\n await flattenBranch(forkPath, base, message);\n return true;\n}\n\n/** Indent every line of `text` by two spaces, for nesting captured `gh` output under a message. */\nfunction indentLines(text: string): string {\n return text\n .split('\\n')\n .map((line) => ` ${line}`)\n .join('\\n');\n}\n\n/**\n * Push the finished sync branch to `origin`, open a PR into the trunk, and switch back to the\n * trunk (or detach at it when another worktree has it checked out, see `returnToBase`). Runs when\n * `cella sync` is invoked on a sync branch whose merge is already committed:\n * shipping is always its own run, after the commit stage stopped for drift triage.\n *\n * Before pushing, any merge commits on the branch are flattened away (see `flattenSyncBranch`)\n * so the PR never lists the upstream branch's entire history.\n *\n * Every step degrades gracefully: a failed push (no `origin`, auth) prints the manual steps and\n * leaves you on the branch; a missing/failed `gh` (or an existing PR) prints the `gh` command but\n * still returns you to the trunk since the branch is already pushed.\n */\nasync function shipSyncBranch(config: RuntimeConfig, branch: string): Promise<void> {\n const { forkPath, settings } = config;\n const base = resolveReleaseBase(settings);\n // The PR targets `base`; its commits and body are read against the trunk the branch was cut from.\n const cutBase = await resolveCutBase(forkPath, base);\n\n const flattened = await flattenSyncBranch(forkPath, branch, cutBase);\n let prUrl: string | undefined;\n let prOpened = false;\n\n // The squash commit's subject is the versioned sync message; reused as the PR title so the\n // PR name carries the upstream version and commit id (release-please only needs the prefix).\n const headSubject = (await getCommitInfo(forkPath, 'HEAD').catch(() => null))?.message;\n const prTitle = headSubject?.startsWith(SYNC_PR_TITLE) ? headSubject : SYNC_PR_TITLE;\n\n console.info(pc.dim(`pushing '${branch}' to origin...`));\n try {\n await pushBranch(forkPath, 'origin', branch, { forceWithLease: flattened });\n } catch (error) {\n console.info(pc.yellow(`push failed (${errorMessage(error).split('\\n')[0]}). finish manually:`));\n printShipSteps(branch, base, prTitle);\n return;\n }\n\n if (ghAvailable()) {\n console.info(pc.dim('opening a pull request...'));\n const prBody = await buildSyncPrBodyForBranch(forkPath, cutBase);\n const bodyArgs = prBody ? ['--body', prBody] : ['--fill'];\n const pr = spawnSync('gh', ['pr', 'create', '--base', base, '--head', branch, '--title', prTitle, ...bodyArgs], {\n cwd: forkPath,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n prUrl = extractFirstUrl(`${pr.stdout ?? ''}\\n${pr.stderr ?? ''}`);\n prOpened = pr.status === 0;\n if (!prOpened) {\n console.info(pc.yellow('could not open the PR automatically (it may already exist). open it with:'));\n if (prUrl) console.info(pc.dim(` ${prUrl}`));\n printPrCreateStep(branch, base, prTitle);\n }\n } else {\n console.info(pc.yellow('`gh` not found, open the PR manually:'));\n printPrCreateStep(branch, base, prTitle);\n }\n\n const position = await returnToBase(forkPath, base);\n\n console.info();\n if (prUrl) {\n console.info(`${checkMark} sync pull request ${prOpened ? 'opened' : 'ready'}`);\n console.info(pc.dim(` ${prUrl} · branch pushed, ${position}`));\n } else {\n console.info(`${checkMark} sync branch pushed`);\n console.info(pc.dim(` '${branch}' is on origin, ${position}`));\n }\n await printMigrationNotesLine(config);\n}\n\n/**\n * Reconcile dependencies and regenerate derived files before committing a resumed merge.\n *\n * A sync merge (plus package.json key-sync) changes `package.json`, which leaves the lockfile\n * and generated files (SDK, etc.) stale and often unstaged. Mirroring what lefthook would do,\n * but up front, we run `pnpm install` then `pnpm check`, so the merge commit is complete and\n * consistent. Returns false if a step fails (the merge is left in progress to retry).\n */\nfunction finalizeWorkspace(forkPath: string): boolean {\n for (const args of [['install'], ['check']]) {\n console.info(pc.dim(`running pnpm ${args.join(' ')}...`));\n const result = spawnSync('pnpm', args, { cwd: forkPath, stdio: 'inherit' });\n if (result.status !== 0) return false;\n }\n return true;\n}\n\n/** Outcome of a sync cycle run on a fresh temporary branch. */\ntype SyncCycleOutcome =\n | { status: 'conflicts'; branch: TemporarySyncBranch }\n | { status: 'staged'; branch: TemporarySyncBranch }\n | { status: 'noop'; behind?: string };\n\n/**\n * Return to where the cycle started and drop the throwaway branch. Only for a branch that holds\n * nothing: an up-to-date run, or one that stopped before the merge.\n */\nasync function discardTemporarySyncBranch(forkPath: string, branch: TemporarySyncBranch): Promise<void> {\n if (branch.startBranch === 'HEAD') await switchDetached(forkPath, branch.startCommit);\n else await switchBranch(forkPath, branch.startBranch);\n await deleteBranch(forkPath, branch.temporaryBranch);\n}\n\n/**\n * After the merge step threw: drop the throwaway branch when the run stopped before the merge (a\n * gate, an unreachable upstream, a ref that does not resolve), so nothing changed and a rerun\n * starts a fresh cycle (an empty sync branch is never shipped). A branch that holds a merge or\n * changes stays as it is. Returns whether the branch was dropped.\n */\nasync function discardUnusedSyncBranch(forkPath: string, branch: TemporarySyncBranch): Promise<boolean> {\n const unused =\n (await getCurrentBranch(forkPath)) === branch.temporaryBranch &&\n !(await mergeInProgress(forkPath)) &&\n (await isClean(forkPath));\n if (!unused) return false;\n\n await discardTemporarySyncBranch(forkPath, branch);\n const start = branch.startBranch === 'HEAD' ? `at ${branch.startCommit.slice(0, 7)}` : `on '${branch.startBranch}'`;\n console.info(pc.dim(`removed the unused '${branch.temporaryBranch}', back ${start}.`));\n return true;\n}\n\n/**\n * Run one sync cycle on a fresh temporary branch: cut the branch, merge upstream (+ packages),\n * and report the resulting state.\n *\n * - `conflicts`: merge staged with unresolved conflicts, left for IDE resolution.\n * - `staged`: clean merge staged, ready to commit.\n * - `noop`: upstream had nothing new, or (`behind`) only a point the last sync already went past;\n * the throwaway branch was deleted and the original branch restored.\n *\n * A run that stops before the merge throws, after the throwaway branch is dropped the same way.\n */\nasync function runSyncCycle(config: RuntimeConfig): Promise<SyncCycleOutcome> {\n const { forkPath } = config;\n const branch = await setupTemporarySyncBranch(config);\n\n let result: MergeResult;\n try {\n result = await runSync(config, { stagedBranch: branch.temporaryBranch });\n } catch (error) {\n const discarded = await discardUnusedSyncBranch(forkPath, branch).catch(() => false);\n // Tracking a release or branch the last sync went past is nothing to sync, not a failure.\n // A pinned --ref behind the sync point stays an error: the run cannot do what it was asked.\n if (discarded && error instanceof BehindSyncPointError && !config.ref) {\n return { status: 'noop', behind: error.message };\n }\n throw error;\n }\n\n if (config.settings.syncWithPackages !== false) {\n // Run package sync even when the merge left conflicts: package.json files that are\n // themselves conflicted are skipped and reported; all others are still synced.\n await runPackages(config, { conflictedFiles: result.conflicts });\n }\n\n if (result.conflicts.length > 0) return { status: 'conflicts', branch };\n\n // Nothing staged: already up to date. Return to where the run started and drop the throwaway\n // branch (a fresh cycle never starts on a sync branch: those resume or ship instead).\n if (!(await mergeInProgress(forkPath))) {\n await discardTemporarySyncBranch(forkPath, branch);\n return { status: 'noop' };\n }\n\n return { status: 'staged', branch };\n}\n\n/**\n * Commit an in-progress merge on the temporary sync branch, never shipping in the same run.\n *\n * Runs directly after a clean merge, or on a rerun once a conflicted merge is resolved and\n * staged. If conflicts remain we point them out and stop; once none remain we reconcile\n * dependencies (`pnpm install` + `pnpm check`), stage everything, and commit the staged delta\n * as a single squashed commit (see `commitSquash`). It then stops on the committed branch:\n * that is the window for drift triage (`cella analyze` diffs committed HEAD) and follow-up\n * commits. Shipping (push + PR) is always its own rerun (see `runSyncCommand`).\n */\nasync function commitSyncMerge(config: RuntimeConfig, branch: string): Promise<void> {\n const { forkPath } = config;\n const conflicts = await getConflictedFiles(forkPath);\n\n console.info();\n if (conflicts.length > 0) {\n console.info(pc.yellow(`${conflicts.length} file(s) still conflict on '${branch}':`));\n for (const file of conflicts) console.info(pc.dim(` ${file}`));\n console.info(pc.dim('resolve and stage them, then re-run `pnpm cella sync` to finish (it commits for you).'));\n return;\n }\n\n // Stage everything up front (resolved conflicts + any manual edits) before running tooling that\n // may fail: `finalizeWorkspace` returns early on a failing `pnpm check`, so staging afterwards\n // would never happen and the edits would never be recorded in the merge.\n await stageAll(forkPath);\n\n // Reconcile deps + regenerate derived files (package.json key-sync and the merge both touch\n // package.json, leaving the lockfile and generated files stale/unstaged).\n if (!finalizeWorkspace(forkPath)) {\n console.info();\n console.info(\n pc.yellow('`pnpm install`/`pnpm check` failed. fix the issues, then re-run `pnpm cella sync` to finish.'),\n );\n return;\n }\n\n // Build the commit subject before squashing (commitSquash clears MERGE_HEAD), re-stage (the\n // install/check step may have touched files), then commit the staged delta as a single-parent\n // commit so the PR shows one clean commit, not the whole upstream history (the merge's\n // upstream ancestry isn't shared on the remote).\n const message = await buildSyncCommitMessage(forkPath, 'MERGE_HEAD');\n await stageAll(forkPath);\n await commitSquash(forkPath, message);\n console.info();\n console.info(pc.green(`committed the sync on '${branch}' as '${message}'.`));\n printTriageSteps(branch);\n await printMigrationNotesLine(config);\n}\n\n/** Guidance after the commit stage stops on the committed sync branch. */\nfunction printTriageSteps(branch: string): void {\n console.info(pc.dim(`staying on '${branch}' without pushing.`));\n console.info(pc.dim(' run drift triage (`pnpm cella analyze`), commit any follow-ups, then:'));\n console.info(pc.dim(' pnpm cella sync (pushes the branch and opens the PR)'));\n}\n\n/**\n * Merge the open sync PR(s) so the trunk carries the recorded sync point before a new cycle cuts\n * from it. The newest PR is a content superset of any older ones (each cycle re-syncs from the\n * same stale trunk base), so the newest is squash-merged and the rest are closed.\n *\n * A merge GitHub refuses (conflicts with the trunk, or failing required checks, the \"breaking\n * changes\" to fix first) stops the run: those must be resolved on the PR before syncing again.\n * On success the fresh cycle cuts from the merged trunk: `resolveCycleStart` fetches it and\n * fast-forwards the local trunk (or cuts from `origin`'s when another worktree has it checked out).\n */\nasync function mergeOpenSyncPrs(config: RuntimeConfig, open: GhPullRequest[]): Promise<'continue' | 'cancel'> {\n const { forkPath, settings } = config;\n const base = resolveReleaseBase(settings);\n const [newest, ...superseded] = open;\n\n console.info();\n console.info(pc.dim(`squash-merging #${newest.number} into '${base}'...`));\n const merged = mergePrSquash(forkPath, newest.number, { deleteBranch: true });\n if (!merged.ok) {\n console.info();\n console.info(pc.yellow(`could not merge #${newest.number}: resolve it first, then re-run \\`pnpm cella sync\\`:`));\n if (merged.output) console.info(pc.dim(indentLines(merged.output)));\n console.info(pc.dim(` ${newest.url}`));\n return 'cancel';\n }\n console.info(`${checkMark} merged #${newest.number}`);\n // Drop the stale local branch that tracked the merged PR (the remote one went with --delete-branch).\n await deleteBranch(forkPath, newest.headRefName);\n\n for (const pr of superseded) {\n console.info(pc.dim(`closing #${pr.number}: its changes are included in #${newest.number}...`));\n closePr(forkPath, pr.number);\n await deleteBranch(forkPath, pr.headRefName);\n }\n\n return 'continue';\n}\n\n/**\n * Before cutting a fresh sync branch, warn when an earlier sync PR is still open and unmerged.\n *\n * The last-sync point is recorded in the manifest committed *on the sync branch*, not on the\n * trunk. So a new cycle cut from a trunk that still lacks a merged sync PR re-includes that PR's\n * whole delta on top of the new upstream commits: the \"why are there suddenly so many changes\"\n * surprise. This offers to squash-merge the open PR first (so the new cycle cuts from an\n * up-to-date trunk), continue anyway, or cancel.\n *\n * Degrades to a silent no-op (`continue`) when it can't help: no `gh`, no open sync PR, or a\n * non-interactive session (no TTY to prompt on).\n */\nasync function guardAgainstOpenSyncPr(config: RuntimeConfig): Promise<'continue' | 'cancel'> {\n const { forkPath } = config;\n\n if (!ghAvailable() || !process.stdout.isTTY) return 'continue';\n\n const open = listOpenSyncPrs(forkPath, DEFAULT_SYNC_PREFIX);\n if (open.length === 0) return 'continue';\n\n const many = open.length > 1;\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(`${many ? `${open.length} earlier sync PRs are` : 'an earlier sync PR is'} still open and unmerged:`)}`,\n );\n for (const pr of open) {\n console.info(pc.dim(` #${pr.number} ${pr.title}`));\n console.info(pc.dim(` ${pr.url}`));\n }\n console.info(pc.dim(` starting a new sync now produces a PR that re-includes ${many ? 'these' : 'those'} changes.`));\n console.info();\n\n const choice = await select<'merge' | 'continue' | 'cancel'>({\n message: 'how do you want to proceed?',\n choices: [\n {\n value: 'merge',\n name: `merge ${many ? 'them' : `#${open[0].number}`} first, then sync ${pc.dim('(recommended)')}`,\n },\n { value: 'continue', name: `continue anyway ${pc.dim('(new PR will re-include the unmerged changes)')}` },\n { value: 'cancel', name: pc.red('cancel') },\n ],\n loop: false,\n });\n\n if (choice === 'cancel') return 'cancel';\n if (choice === 'continue') return 'continue';\n return mergeOpenSyncPrs(config, open);\n}\n\n/**\n * Run the standalone `cella sync` command.\n *\n * Idempotent. Each run advances the sync one stage and never commits and ships in the same run:\n * - Anywhere else: require a clean tree, cut a fresh temporary branch and merge upstream; a\n * clean merge is committed right away (the run stops there, for drift triage), a conflicted\n * one stops for IDE resolution. A run that stops before the merge (upstream needs a newer CLI,\n * upstream changed its sync config, upstream is behind the last sync point) drops the branch\n * again and leaves everything as it was.\n * - On a sync branch with a merge in progress: commit it (resume after conflicts), then stop.\n * - On a sync branch with the merge already committed: push and open the PR, then switch back\n * to the trunk (detach at it when another worktree has it checked out). Shipping is\n * deliberately its own run: the pause before it is where drift triage and follow-up commits\n * happen.\n */\nexport async function runSyncCommand(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n const currentBranch = await getCurrentBranch(forkPath);\n const onSyncBranch = isTemporarySyncBranch(currentBranch);\n\n // Resume path: an earlier run left a merge staged on this temporary branch (e.g. after\n // conflicts). Re-running finishes that merge; it never starts over.\n if (onSyncBranch && (await mergeInProgress(forkPath))) {\n await commitSyncMerge(config, currentBranch);\n return;\n }\n\n // On a sync branch with the merge already committed: ship it (push + PR + back to trunk).\n if (onSyncBranch) {\n // shipSyncBranch only pushes HEAD, so any edits made after the squash commit would be silently\n // left out of the pushed branch/PR. Refuse to ship over a dirty tree and make them commit.\n if (!(await isClean(forkPath))) {\n console.info();\n console.info(\n pc.yellow(\n `sync branch '${currentBranch}' has uncommitted changes.\\n` +\n 'commit them first (`git commit --amend --no-edit` or a new commit).',\n ),\n );\n return;\n }\n await shipSyncBranch(config, currentBranch);\n return;\n }\n\n // Fresh cycle: only ever cut the temporary branch from a clean tree.\n await assertClean(forkPath);\n\n // Guard against stacking: if an earlier sync PR is still open, its delta would re-appear in\n // this cycle's PR. Offer to merge it first (or bail) before cutting a new branch.\n if ((await guardAgainstOpenSyncPr(config)) === 'cancel') return;\n\n const outcome = await runSyncCycle(config);\n console.info();\n\n if (outcome.status === 'noop') {\n if (outcome.behind) {\n console.info(pc.green('nothing to sync: the last sync already went past this upstream point.'));\n for (const line of outcome.behind.split('\\n')) console.info(pc.dim(` ${line}`));\n } else {\n console.info(pc.green('already up to date with upstream, nothing to sync.'));\n }\n return;\n }\n\n const { temporaryBranch } = outcome.branch;\n if (outcome.status === 'conflicts') {\n console.info(`${warningMark} ${pc.yellow(`conflicts on '${temporaryBranch}'. Resolve and stage them, then:`)}`);\n console.info(pc.dim(' pnpm cella sync'));\n console.info(pc.dim(' rerun commits the sync and stops for drift triage; a further rerun ships (push + PR).'));\n console.info(pc.dim(' let the rerun commit: a manual `git commit` records a merge commit that bloats the PR.'));\n return;\n }\n\n // Clean merge: commit it in the same run (never shipping; that stays a separate rerun).\n await commitSyncMerge(config, temporaryBranch);\n}\n","/**\n * GitHub CLI (`gh`) helpers for the cella CLI.\n *\n * Thin wrappers around `gh` used by the sync service to list, merge, and close the sync pull\n * requests. Every wrapper degrades gracefully when `gh` is missing or a call fails, so a sync\n * run on a repo without `gh`/`origin` still works; it just skips the PR automation.\n */\n\nimport { spawnSync } from 'node:child_process';\n\n/** An open pull request, as returned by `gh pr list --json`. */\nexport interface GhPullRequest {\n number: number;\n title: string;\n headRefName: string;\n url: string;\n}\n\n/** Result of a `gh` invocation: whether it exited 0, plus its combined stdout+stderr. */\ninterface GhResult {\n ok: boolean;\n output: string;\n}\n\n/** Whether the GitHub CLI is available on PATH. */\nexport function ghAvailable(): boolean {\n return spawnSync('gh', ['--version'], { stdio: 'ignore' }).status === 0;\n}\n\n/** Run `gh` in `cwd`, capturing stdout+stderr. Never throws. */\nfunction runGh(cwd: string, args: string[]): GhResult {\n const result = spawnSync('gh', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });\n const output = `${result.stdout ?? ''}${result.stderr ?? ''}`.trim();\n return { ok: result.status === 0, output };\n}\n\n/**\n * Keep only the pull requests whose head branch is one of cella's temporary sync branches\n * (under the `<prefix>/` namespace, e.g. `cella/sync/`). Pure, unit-tested.\n */\nexport function filterSyncPrs(prs: GhPullRequest[], prefix: string): GhPullRequest[] {\n return prs.filter((pr) => pr.headRefName.startsWith(`${prefix}/`));\n}\n\n/**\n * List open sync PRs (head branch under `<prefix>/`), newest first (highest PR number).\n * Returns an empty array when `gh` fails (no auth, no origin) so callers degrade to a no-op.\n */\nexport function listOpenSyncPrs(cwd: string, prefix: string): GhPullRequest[] {\n const { ok, output } = runGh(cwd, [\n 'pr',\n 'list',\n '--state',\n 'open',\n '--json',\n 'number,title,headRefName,url',\n '--limit',\n '50',\n ]);\n if (!ok || !output) return [];\n\n let parsed: GhPullRequest[];\n try {\n parsed = JSON.parse(output) as GhPullRequest[];\n } catch {\n return [];\n }\n\n return filterSyncPrs(parsed, prefix).sort((a, b) => b.number - a.number);\n}\n\n/**\n * Build the argv for `gh pr merge`. Pure, unit-tested.\n *\n * The merge is attempted immediately and fails when the PR is not mergeable.\n */\nexport function buildMergeArgs(ref: string, options: { deleteBranch?: boolean } = {}): string[] {\n const args = ['pr', 'merge', ref, '--squash'];\n if (options.deleteBranch) args.push('--delete-branch');\n return args;\n}\n\n/** Squash-merge a PR (by number, branch, or URL). See {@link buildMergeArgs}. */\nexport function mergePrSquash(cwd: string, ref: string | number, options: { deleteBranch?: boolean } = {}): GhResult {\n return runGh(cwd, buildMergeArgs(String(ref), options));\n}\n\n/** Close a PR without merging (used to discard superseded sync PRs). */\nexport function closePr(cwd: string, ref: string | number): GhResult {\n return runGh(cwd, ['pr', 'close', String(ref)]);\n}\n","/**\n * Packages service: package.json keys synced between fork and upstream, three-way against the merge-base\n * package.json (upstream as of the previous sync):\n * - Add: entries that are new upstream are added\n * - Follow: an entry the fork never touched (still equal to its base value) follows upstream,\n * whether upstream rewrote a script, changed a range, or dropped the entry\n * - Keep: an entry the fork added or changed stays, except that a strictly higher upstream\n * version still bumps it; an entry the fork removed is not re-added\n * - Still used: a dependency or script upstream dropped stays while fork-authored code still\n * imports it, runs its CLI or runs the script (see package-usage.ts)\n * - Supports nested `pnpm` key (overrides, patchedDependencies, packageExtensions)\n * - `type` always syncs, whatever `packageJsonSync` lists (see mergeModuleType)\n * - A workspace package.json upstream added since the base arrives verbatim\n * Without a base (first sync, unrelated history) every upstream entry is added or bumped and\n * nothing is removed.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { PackageJsonSyncKey, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { DEFAULT_PACKAGE_JSON_SYNC } from '../utils/config';\nimport { createSpinner, spinnerSuccess, spinnerText, warningMark } from '../utils/display';\nimport { getEffectiveMergeBase, git } from '../utils/git';\nimport { isIgnored } from '../utils/overrides';\nimport { compareVersions, parseComparableVersion } from '../utils/versions';\nimport { type ForkUsage, loadForkUsage } from './package-usage';\n\n/** Package.json structure */\ninterface PackageJson {\n name?: string;\n version?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n engines?: Record<string, string>;\n packageManager?: string;\n overrides?: Record<string, string>;\n pnpm?: {\n overrides?: Record<string, string>;\n patchedDependencies?: Record<string, string>;\n packageExtensions?: Record<string, Record<string, unknown>>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\n/**\n * Whether the upstream version is strictly higher than the fork's; never downgrades.\n * For non-parseable values (workspace:*, etc.), false (the fork's value stays).\n */\nfunction isHigherVersion(upstreamVersion: string, forkVersion: string): boolean {\n if (upstreamVersion === forkVersion) return false;\n\n const upCoerced = parseComparableVersion(upstreamVersion);\n const forkCoerced = parseComparableVersion(forkVersion);\n\n if (!upCoerced || !forkCoerced) return false;\n\n return compareVersions(upCoerced, forkCoerced) > 0;\n}\n\ninterface RecordMergeResult {\n merged: Record<string, string>;\n changed: boolean;\n added: string[];\n updated: string[];\n removed: string[];\n /** Entries upstream dropped that stay because the fork still uses them */\n kept: { name: string; usedAt: string }[];\n}\n\ninterface RecordMergeOptions {\n /** Let a strictly higher upstream version win over the fork's own value (false for scripts, patch paths) */\n bumpHigher?: boolean;\n /** Where the fork still uses an entry, so upstream dropping it does not remove it */\n findUse?: (name: string) => string | undefined;\n}\n\n/** Keys whose entries are packages the code imports or whose CLIs it runs. */\nconst DEPENDENCY_KEYS: readonly PackageJsonSyncKey[] = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n];\n\n/**\n * Three-way merge for a Record<string, string> key (dependencies, scripts, overrides, ...).\n * `baseRecord` is the key at the merge-base: an entry whose fork value still equals its base\n * value was never touched by the fork and follows upstream, an update or a removal alike. An\n * entry the fork changed stays, unless `bumpHigher` and upstream carries a strictly higher\n * version. An entry the fork removed (in base, absent in fork) is not re-added, and one upstream\n * dropped stays while `findUse` finds it in use. Without a base every upstream entry is added or\n * bumped and nothing is removed.\n * Returns the merged record sorted alphabetically, plus the keys added, updated, removed and kept.\n */\nfunction mergeRecord(\n forkRecord: Record<string, string> | undefined,\n upstreamRecord: Record<string, string> | undefined,\n baseRecord: Record<string, string> | undefined,\n { bumpHigher = true, findUse }: RecordMergeOptions = {},\n): RecordMergeResult | undefined {\n if (!upstreamRecord) return undefined;\n\n const merged = { ...(forkRecord || {}) };\n const base = baseRecord || {};\n const added: string[] = [];\n const updated: string[] = [];\n const removed: string[] = [];\n const kept: RecordMergeResult['kept'] = [];\n\n for (const [name, upstreamValue] of Object.entries(upstreamRecord)) {\n const forkValue = merged[name];\n\n if (forkValue === undefined) {\n // In base but not in fork: the fork removed it on purpose\n if (name in base) continue;\n merged[name] = upstreamValue;\n added.push(name);\n } else if (forkValue === upstreamValue) {\n } else if (base[name] === forkValue) {\n // Untouched by the fork: follow upstream, a downgrade or a rewritten script included\n merged[name] = upstreamValue;\n updated.push(name);\n } else if (bumpHigher && isHigherVersion(upstreamValue, forkValue)) {\n // Both sides changed it: a strictly higher upstream version wins (with upstream's range prefix)\n merged[name] = upstreamValue;\n updated.push(name);\n }\n // Otherwise the fork's own value stays\n }\n\n // Entries upstream dropped: removed when the fork never touched them and does not use them\n for (const [name, forkValue] of Object.entries(merged)) {\n if (name in upstreamRecord) continue;\n if (base[name] === undefined || base[name] !== forkValue) continue;\n const usedAt = findUse?.(name);\n if (usedAt) {\n kept.push({ name, usedAt });\n continue;\n }\n delete merged[name];\n removed.push(name);\n }\n\n const sorted = Object.fromEntries(Object.entries(merged).sort(([a], [b]) => a.localeCompare(b)));\n const changed = added.length + updated.length + removed.length > 0;\n return { merged: sorted, changed, added, updated, removed, kept };\n}\n\n/** A subpath map (`{ \".\": …, \"./config\": … }`), not a string or a conditions object. */\nfunction isSubpathMap(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n return Object.keys(value).every((name) => name.startsWith('.'));\n}\n\n/**\n * Safe merge for the `exports` key: upstream subpaths the fork lacks are added, the\n * fork's own never touched. Only merges when both sides are subpath maps: a string or conditions object\n * can't take extra subpaths, and condition order is significant. Keeps the fork's key order.\n */\nfunction safeMergeExports(\n forkExports: unknown,\n upstreamExports: unknown,\n): { merged: Record<string, unknown>; changed: boolean; added: string[] } | undefined {\n if (!isSubpathMap(upstreamExports)) return undefined;\n if (forkExports !== undefined && !isSubpathMap(forkExports)) return undefined;\n\n const merged = { ...(forkExports || {}) };\n const added = Object.keys(upstreamExports).filter((name) => !(name in merged));\n for (const name of added) merged[name] = upstreamExports[name];\n\n return { merged, changed: added.length > 0, added };\n}\n\n/**\n * Merge for the `pnpm` key: `overrides` and `patchedDependencies` merge three-way like any\n * record; `packageExtensions` and other sub-keys are add-only.\n */\nfunction safeMergePnpm(\n forkPnpm: PackageJson['pnpm'],\n upstreamPnpm: PackageJson['pnpm'],\n basePnpm: PackageJson['pnpm'],\n): { merged: PackageJson['pnpm']; changed: boolean } | undefined {\n if (!upstreamPnpm) return undefined;\n\n const merged: NonNullable<PackageJson['pnpm']> = { ...(forkPnpm || {}) };\n let changed = false;\n\n // pnpm.overrides: same as dependency overrides (add, follow, bump versions)\n if (upstreamPnpm.overrides) {\n const result = mergeRecord(\n merged.overrides as Record<string, string> | undefined,\n upstreamPnpm.overrides as Record<string, string>,\n basePnpm?.overrides as Record<string, string> | undefined,\n );\n if (result?.changed) {\n merged.overrides = result.merged;\n changed = true;\n }\n }\n\n // pnpm.patchedDependencies: patch paths carry no version to compare, so equality only\n if (upstreamPnpm.patchedDependencies) {\n const result = mergeRecord(\n merged.patchedDependencies as Record<string, string> | undefined,\n upstreamPnpm.patchedDependencies as Record<string, string>,\n basePnpm?.patchedDependencies as Record<string, string> | undefined,\n { bumpHigher: false },\n );\n if (result?.changed) {\n merged.patchedDependencies = result.merged;\n changed = true;\n }\n }\n\n // pnpm.packageExtensions: new packages and new sub-keys are added, never removed\n if (upstreamPnpm.packageExtensions) {\n const forkExts = (merged.packageExtensions || {}) as Record<string, Record<string, unknown>>;\n const upstreamExts = upstreamPnpm.packageExtensions as Record<string, Record<string, unknown>>;\n\n for (const [pkg, upstreamExt] of Object.entries(upstreamExts)) {\n if (!(pkg in forkExts)) {\n forkExts[pkg] = upstreamExt;\n changed = true;\n } else {\n for (const [subKey, subValue] of Object.entries(upstreamExt)) {\n if (!(subKey in forkExts[pkg])) {\n forkExts[pkg][subKey] = subValue;\n changed = true;\n }\n }\n }\n }\n\n merged.packageExtensions = forkExts;\n }\n\n // Other pnpm sub-keys are added when missing in the fork.\n for (const [key, value] of Object.entries(upstreamPnpm)) {\n if (['overrides', 'patchedDependencies', 'packageExtensions'].includes(key)) continue;\n if (!(key in merged)) {\n merged[key] = value;\n changed = true;\n }\n }\n\n return { merged, changed };\n}\n\n/**\n * Three-way merge for `type`, which decides how Node loads the package's `.js` files, so it syncs\n * whatever `packageJsonSync` lists. Follows upstream where the fork still has the merge-base value\n * (an update or a removal alike) and keeps a value the fork set itself; never version-bumped.\n * A fork without `type` gets upstream's even when the base had one: `type` never synced before,\n * so a missing one is a missed upstream change, not a removal (to opt out, set \"commonjs\").\n * Returns the fork's new value and the change, or null when the fork's value stays.\n */\nfunction mergeModuleType(\n forkType: unknown,\n upstreamType: unknown,\n baseType: unknown,\n): { value: string | undefined; change: 'added' | 'updated' | 'removed' } | null {\n const asString = (value: unknown) => (typeof value === 'string' ? value : undefined);\n const fork = asString(forkType);\n const upstream = asString(upstreamType);\n if (fork === upstream) return null;\n if (fork === undefined) return { value: upstream, change: 'added' };\n if (fork !== asString(baseType)) return null;\n return { value: upstream, change: upstream === undefined ? 'removed' : 'updated' };\n}\n\n/**\n * Set a top-level key in place. A key the file already has keeps its position; a new one goes\n * where cella's own package.json files keep it, after `name`, `version` and `private` (whichever\n * comes last), else first.\n */\nfunction setTopLevelKey(pkg: PackageJson, key: string, value: unknown): void {\n if (key in pkg) {\n pkg[key] = value;\n return;\n }\n const entries = Object.entries(pkg);\n const after = Math.max(...['name', 'version', 'private'].map((name) => entries.findIndex(([k]) => k === name)));\n entries.splice(after + 1, 0, [key, value]);\n for (const name of Object.keys(pkg)) delete pkg[name];\n Object.assign(pkg, Object.fromEntries(entries));\n}\n\nfunction readPackageJson(filePath: string): PackageJson | null {\n if (!existsSync(filePath)) return null;\n try {\n return JSON.parse(readFileSync(filePath, 'utf8'));\n } catch {\n return null;\n }\n}\n\nfunction writePackageJson(filePath: string, data: PackageJson): void {\n writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\\n`, 'utf8');\n}\n\n/** The package.json path of a workspace location ('' is the root). */\nfunction packageJsonPath(relativePath: string): string {\n return relativePath ? `${relativePath}/package.json` : 'package.json';\n}\n\n/** A package.json at a git ref, raw and parsed; null when the ref has no such file. */\nasync function readPackageJsonAtRef(\n forkPath: string,\n ref: string,\n relativePath: string,\n): Promise<{ raw: string; data: PackageJson } | null> {\n try {\n const raw = await git(['show', `${ref}:${packageJsonPath(relativePath)}`], forkPath);\n return { raw, data: JSON.parse(raw) };\n } catch {\n return null;\n }\n}\n\n/** Every package.json location upstream has; the fork side is judged per location. */\nasync function discoverPackageLocations(forkPath: string, upstreamRef: string): Promise<string[]> {\n const stdout = await git(['ls-tree', '-r', '--name-only', upstreamRef], forkPath, { ignoreErrors: true });\n return stdout\n .split('\\n')\n .filter((p) => p.endsWith('/package.json') || p === 'package.json')\n .map((p) => (p === 'package.json' ? '' : p.replace('/package.json', '')));\n}\n\n/**\n * The upstream commit the fork last synced (the recorded sync point, else git's merge-base);\n * null when neither resolves, which turns every key merge into add-only.\n */\nasync function resolveMergeBase(forkPath: string, upstreamRef: string): Promise<string | null> {\n try {\n return (await getEffectiveMergeBase(forkPath, 'HEAD', upstreamRef)).base || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Sync a single package.json file three-way (fork, upstream, merge-base).\n *\n * A location the fork lacks is a workspace upstream added since the base: its package.json\n * lands verbatim when the merge brought the directory (and the location is not ignored). A\n * package.json the base had and the fork removed stays removed.\n *\n * Returns the change lines, plus the entries upstream dropped that stay because `usage` found\n * the fork still using them.\n */\nasync function syncPackageJson(\n config: RuntimeConfig,\n baseRef: string | null,\n usage: ForkUsage | null,\n relativePath: string,\n keysToSync: PackageJsonSyncKey[],\n): Promise<{ updated: boolean; changes: string[]; kept: string[] }> {\n const { forkPath, upstreamRef } = config;\n const changes: string[] = [];\n const kept: string[] = [];\n const pkgRelPath = packageJsonPath(relativePath);\n const pkgPath = join(forkPath, pkgRelPath);\n\n const forkPkg = readPackageJson(pkgPath);\n const upstream = await readPackageJsonAtRef(forkPath, upstreamRef, relativePath);\n const basePkg = baseRef ? (await readPackageJsonAtRef(forkPath, baseRef, relativePath))?.data : undefined;\n\n if (!upstream) return { updated: false, changes, kept };\n\n if (!forkPkg) {\n const workspaceArrived = relativePath !== '' && existsSync(join(forkPath, relativePath));\n if (basePkg || !workspaceArrived || isIgnored(pkgRelPath, config)) return { updated: false, changes, kept };\n writeFileSync(pkgPath, upstream.raw.endsWith('\\n') ? upstream.raw : `${upstream.raw}\\n`, 'utf8');\n return { updated: true, changes: ['copied from upstream (new workspace)'], kept };\n }\n\n const upstreamPkg = upstream.data;\n let updated = false;\n\n const type = mergeModuleType(forkPkg.type, upstreamPkg.type, basePkg?.type);\n if (type) {\n if (type.value === undefined) delete forkPkg.type;\n else setTopLevelKey(forkPkg, 'type', type.value);\n updated = true;\n changes.push(`type: ${type.change}`);\n }\n\n for (const key of keysToSync) {\n if (key === 'pnpm') {\n const result = safeMergePnpm(forkPkg.pnpm, upstreamPkg.pnpm, basePkg?.pnpm);\n if (result?.changed) {\n forkPkg.pnpm = result.merged;\n updated = true;\n changes.push('pnpm: merged');\n }\n continue;\n }\n\n if (key === 'packageManager') {\n // String key: follow upstream when the fork never touched it, else only bump higher\n const upstreamValue = upstreamPkg[key] as string | undefined;\n const forkValue = forkPkg[key] as string | undefined;\n const baseValue = basePkg?.[key] as string | undefined;\n\n if (upstreamValue && !forkValue) {\n if (baseValue) continue;\n forkPkg[key] = upstreamValue;\n updated = true;\n changes.push(`${key}: added`);\n } else if (\n upstreamValue &&\n forkValue &&\n upstreamValue !== forkValue &&\n (forkValue === baseValue || isHigherVersion(upstreamValue, forkValue))\n ) {\n forkPkg[key] = upstreamValue;\n updated = true;\n changes.push(`${key}: updated`);\n }\n continue;\n }\n\n if (key === 'exports') {\n // Add-only, subpath maps only: the fork gains new upstream subpaths, keeps any it defines\n // itself, and a subpath it has repointed stays repointed.\n const result = safeMergeExports(forkPkg.exports, upstreamPkg.exports);\n if (result?.changed) {\n forkPkg.exports = result.merged;\n updated = true;\n changes.push(...result.added.map((name) => `exports.${name}: added`));\n }\n continue;\n }\n\n // All Record<string, string> keys merge three-way; scripts carry no version to compare.\n const forkValue = forkPkg[key] as Record<string, string> | undefined;\n const upstreamValue = upstreamPkg[key] as Record<string, string> | undefined;\n const baseValue = basePkg?.[key] as Record<string, string> | undefined;\n\n let findUse: RecordMergeOptions['findUse'];\n if (usage && key === 'scripts') findUse = (name) => usage.findScript(name);\n else if (usage && DEPENDENCY_KEYS.includes(key)) findUse = (name) => usage.findPackage(relativePath, name);\n const result = mergeRecord(forkValue, upstreamValue, baseValue, { bumpHigher: key !== 'scripts', findUse });\n kept.push(...(result?.kept ?? []).map(({ name, usedAt }) => `${key}.${name}: used in ${usedAt}`));\n if (result?.changed) {\n (forkPkg as Record<string, unknown>)[key] = result.merged;\n updated = true;\n changes.push(\n ...result.added.map((name) => `${key}.${name}: added`),\n ...result.updated.map((name) => `${key}.${name}: updated`),\n ...result.removed.map((name) => `${key}.${name}: removed`),\n );\n }\n }\n\n if (updated) {\n writePackageJson(pkgPath, forkPkg);\n }\n\n return { updated, changes, kept };\n}\n\n/**\n * Run the packages sync service.\n *\n * Discovers every package.json location upstream has, then merges the configured keys three-way\n * against the merge-base (see the file header for the rules).\n *\n * When `conflictedFiles` is provided (e.g. after a sync that left conflicts),\n * any package.json that is itself unmerged is skipped to avoid clobbering\n * conflict markers; all other package.json files are still synced.\n */\nexport async function runPackages(config: RuntimeConfig, options: { conflictedFiles?: string[] } = {}): Promise<void> {\n createSpinner('syncing package.json files...');\n\n const keysToSync = config.settings.packageJsonSync || DEFAULT_PACKAGE_JSON_SYNC;\n const conflictedSet = new Set(options.conflictedFiles ?? []);\n\n const baseRef = await resolveMergeBase(config.forkPath, config.upstreamRef);\n // Before any package.json is rewritten: the fork-authored scripts are judged on the fork's own copy\n const usage = baseRef ? await loadForkUsage(config.forkPath, config.upstreamRef, baseRef) : null;\n const locations = await discoverPackageLocations(config.forkPath, config.upstreamRef);\n const reports: { path: string; changes: string[]; kept: string[] }[] = [];\n const skipped: string[] = [];\n\n for (const location of locations) {\n const pkgRelPath = packageJsonPath(location);\n\n // Skip package.json files that are themselves conflicted from the merge:\n // writing to them would clobber the conflict markers the user must resolve.\n if (conflictedSet.has(pkgRelPath)) {\n skipped.push(pkgRelPath);\n continue;\n }\n\n spinnerText(`syncing ${location || 'root'}/package.json...`);\n\n const { updated, changes, kept } = await syncPackageJson(config, baseRef, usage, location, keysToSync);\n if (updated || kept.length > 0) reports.push({ path: pkgRelPath, changes, kept });\n }\n\n const changedCount = reports.filter(({ changes }) => changes.length > 0).length;\n spinnerSuccess(\n 'package sync complete',\n `${changedCount} package.json${changedCount === 1 ? ' was' : 's were'} changed`,\n );\n\n for (const { path, changes } of reports) {\n if (changes.length === 0) continue;\n console.info(` ${path}`);\n for (const change of changes) console.info(` ${pc.dim(change)}`);\n }\n\n // Entries upstream dropped that the fork still uses: the user decides when they can go\n const kept = reports.flatMap(({ path, kept }) => kept.map((entry) => `${path} ${entry}`));\n if (kept.length > 0) {\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(`kept ${kept.length} ${kept.length === 1 ? 'entry' : 'entries'} upstream dropped, the fork still uses ${kept.length === 1 ? 'it' : 'them'}:`)}`,\n );\n for (const entry of kept) console.info(` ${pc.dim('→')} ${entry}`);\n }\n\n if (skipped.length > 0) {\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(`skipped ${skipped.length} conflicted package.json file(s): resolve the conflicts, commit the merge, then rerun \\`pnpm cella sync\\`:`)}`,\n );\n for (const path of skipped) {\n console.info(` ${pc.dim('→')} ${path}`);\n }\n }\n}\n","/**\n * Where the fork's own code still uses a package or a script.\n *\n * The package sync removes an entry upstream dropped when the fork never touched it in\n * package.json, but a fork can use an inherited entry without touching it: an import in a\n * fork-only module, a CLI in a fork script, a script name in a fork workflow. Only fork-authored\n * content is searched: files that differ from upstream after the file merge, and package.json\n * scripts the fork added or changed. Upstream no longer uses what it dropped, so a reference in\n * that content is the fork's own. A false match keeps the entry, which is the safe side: a stale\n * entry costs an install, a missing one breaks the fork.\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { git } from '../utils/git';\nimport { isManagedFile, isPackageJson } from '../utils/managed-files';\nimport { isUnderAnyFolder } from '../utils/overrides';\n\n/** Fork-authored content: a file, or one package.json script. */\ninterface ForkSource {\n /** Repo-relative path, which scopes a workspace's packages to its directory */\n path: string;\n /** Where the reference is, as reported to the user */\n label: string;\n /** The content, read on first use */\n text: () => string;\n}\n\n/** Answers where the fork still uses an entry upstream dropped; undefined when nowhere. */\nexport interface ForkUsage {\n /** A fork-authored place inside `location` that imports `name` or runs one of its CLIs */\n findPackage(location: string, name: string): string | undefined;\n /** A fork-authored place anywhere in the repo that runs script `name` through a package manager */\n findScript(name: string): string | undefined;\n}\n\n/** Larger files are generated or binary and are not searched. */\nconst MAX_FILE_BYTES = 1024 * 1024;\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** A file's text, or '' when it is missing, too large or binary. */\nfunction readSearchable(filePath: string): string {\n try {\n if (statSync(filePath).size > MAX_FILE_BYTES) return '';\n const text = readFileSync(filePath, 'utf8');\n return text.includes('\\0') ? '' : text;\n } catch {\n return '';\n }\n}\n\nfunction fileSource(forkPath: string, path: string): ForkSource {\n let text: string | undefined;\n return { path, label: path, text: () => (text ??= readSearchable(join(forkPath, path))) };\n}\n\nasync function readScriptsAtRef(forkPath: string, ref: string, path: string): Promise<Record<string, string>> {\n try {\n return JSON.parse(await git(['show', `${ref}:${path}`], forkPath)).scripts ?? {};\n } catch {\n return {};\n }\n}\n\n/** The scripts of a fork package.json that differ from both the merge-base and upstream. */\nasync function scriptSources(\n forkPath: string,\n upstreamRef: string,\n baseRef: string,\n path: string,\n): Promise<ForkSource[]> {\n let forkScripts: Record<string, string>;\n try {\n forkScripts = JSON.parse(readFileSync(join(forkPath, path), 'utf8')).scripts ?? {};\n } catch {\n return [];\n }\n const baseScripts = await readScriptsAtRef(forkPath, baseRef, path);\n const upstreamScripts = await readScriptsAtRef(forkPath, upstreamRef, path);\n\n return Object.entries(forkScripts)\n .filter(([name, value]) => value !== baseScripts[name] && value !== upstreamScripts[name])\n .map(([name, value]) => ({ path, label: `${path} (scripts.${name})`, text: () => value }));\n}\n\n/** The CLI names a package installs, from its installed package.json; its bare name when not installed. */\nfunction binNames(forkPath: string, location: string, name: string): string[] {\n const bareName = name.split('/').pop() as string;\n for (const dir of [join(forkPath, location), forkPath]) {\n const manifest = join(dir, 'node_modules', name, 'package.json');\n if (!existsSync(manifest)) continue;\n try {\n const { bin } = JSON.parse(readFileSync(manifest, 'utf8'));\n if (typeof bin === 'string') return [bareName];\n return bin && typeof bin === 'object' ? Object.keys(bin) : [];\n } catch {\n return [];\n }\n }\n return [bareName];\n}\n\n/**\n * How code refers to a package: a quoted specifier or subpath (imports, requires, config\n * strings), the package an `@types/*` entry types, and its CLI names as whole words.\n */\nfunction packagePatterns(forkPath: string, location: string, name: string): RegExp[] {\n const specifiers = [name];\n const typed = name.match(/^@types\\/(.+)$/);\n if (typed) specifiers.push(typed[1].includes('__') ? `@${typed[1].replace('__', '/')}` : typed[1]);\n\n const patterns = specifiers.map((specifier) => new RegExp(`(['\"\\`])${escapeRegExp(specifier)}(?:/[^'\"\\`\\\\s]*)?\\\\1`));\n for (const bin of binNames(forkPath, location, name)) {\n patterns.push(new RegExp(`(?:^|[\\\\s'\"\\`(;&|=])${escapeRegExp(bin)}(?=$|[\\\\s'\"\\`);&|])`, 'm'));\n }\n return patterns;\n}\n\n/** A package manager command that names the script as a whole word, e.g. `pnpm --filter backend geoip:download`. */\nfunction scriptPattern(name: string): RegExp {\n return new RegExp(`\\\\b(?:pnpm|npm|yarn|bun)\\\\s+(?:[^\\\\n;&|]*?\\\\s)?${escapeRegExp(name)}(?=$|[\\\\s'\"\\`);&|])`, 'm');\n}\n\n/**\n * Collect the fork-authored content: files in the working tree (the merge result) that differ\n * from upstream, minus managed files, plus the scripts the fork added or changed. Call before\n * any package.json is rewritten.\n */\nexport async function loadForkUsage(forkPath: string, upstreamRef: string, baseRef: string): Promise<ForkUsage> {\n const diff = await git(['diff', '--name-only', '-z', '--diff-filter=d', upstreamRef], forkPath);\n const sources: ForkSource[] = [];\n\n for (const path of diff.split('\\0').filter(Boolean)) {\n if (isPackageJson(path)) sources.push(...(await scriptSources(forkPath, upstreamRef, baseRef, path)));\n else if (!isManagedFile(path)) sources.push(fileSource(forkPath, path));\n }\n\n const findIn = (scoped: ForkSource[], patterns: RegExp[]) =>\n scoped.find((source) => patterns.some((pattern) => pattern.test(source.text())))?.label;\n\n return {\n findPackage: (location, name) =>\n findIn(\n location ? sources.filter((source) => isUnderAnyFolder(source.path, [location])) : sources,\n packagePatterns(forkPath, location, name),\n ),\n findScript: (name) => findIn(sources, [scriptPattern(name)]),\n };\n}\n","/**\n * Stats service for cella CLI.\n *\n * Counts files in the codebase using `git ls-files` (fast, respects .gitignore).\n * Categorizes by type and workspace package.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { printCoverageSummary } from '../utils/coverage-utils';\nimport { createSpinner, DIVIDER, spinnerSuccess } from '../utils/display';\nimport { git } from '../utils/git';\nimport { parseYamlBlockList } from '../utils/yaml';\n\n/** Extensions Biome can check (source code, config, styles) */\nexport const sourceExtensions = new Set(['ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs', 'json', 'jsonc', 'css', 'html']);\n\n/** File category for classification */\ntype FileCategory = 'test' | 'stories' | 'generated' | 'json' | 'other';\n\n/** Per-package file and LOC counts, broken down by category */\ninterface PackageStats {\n total: number;\n loc: number;\n categories: Record<FileCategory, { files: number; loc: number }>;\n}\n\n/** Stats result for display or JSON output */\ninterface StatsResult {\n total: number;\n totalLoc: number;\n skipped: number;\n categories: Record<FileCategory, { files: number; loc: number }>;\n packages: Record<string, PackageStats>;\n}\n\n/** Workspace package definition from pnpm-workspace.yaml */\nexport interface WorkspacePackage {\n /** Display name (e.g., 'backend', 'cli/cella') */\n name: string;\n /** Path prefix to match (e.g., 'backend/', 'cli/cella/') */\n prefix: string;\n}\n\n/** Workspace package names and path prefixes from pnpm-workspace.yaml. */\nexport async function getWorkspacePackages(forkPath: string): Promise<WorkspacePackage[]> {\n const content = await readFile(join(forkPath, 'pnpm-workspace.yaml'), 'utf8');\n\n return parseYamlBlockList(content, 'packages').map((pattern) => {\n // Wildcard patterns like 'cli/*' are resolved per file when matching.\n if (pattern.endsWith('/*')) {\n const base = pattern.slice(0, -2);\n return { name: `${base}/*`, prefix: `${base}/` };\n }\n return { name: pattern, prefix: `${pattern}/` };\n });\n}\n\nexport function classifyFile(filePath: string): FileCategory {\n if (\n filePath.includes('.test.') ||\n filePath.includes('.spec.') ||\n filePath.includes('/tests/') ||\n filePath.includes('/test/') ||\n filePath.startsWith('tests/') ||\n filePath.includes('/__tests__/')\n ) {\n return 'test';\n }\n\n if (filePath.includes('.stories.')) {\n return 'stories';\n }\n\n if (\n filePath.includes('.gen.') ||\n filePath.includes('.gen/') ||\n filePath.includes('/gen/') ||\n filePath.startsWith('drizzle/') ||\n filePath.includes('/drizzle/') ||\n filePath.endsWith('.d.ts') ||\n filePath.includes('.tsbuildinfo')\n ) {\n return 'generated';\n }\n\n if (filePath.endsWith('.json') || filePath.endsWith('.jsonc')) {\n return 'json';\n }\n\n return 'other';\n}\n\n/** The workspace package owning a file, with wildcard patterns resolved per file. */\nexport function matchPackage(filePath: string, packages: WorkspacePackage[]): string {\n for (const pkg of packages) {\n if (pkg.name.endsWith('/*')) {\n if (filePath.startsWith(pkg.prefix)) {\n // Extract the actual subpackage name (e.g., 'cli/cella' from 'cli/cella/src/foo.ts')\n const rest = filePath.slice(pkg.prefix.length);\n const subDir = rest.split('/')[0];\n if (subDir) {\n return `${pkg.prefix}${subDir}`;\n }\n }\n } else if (filePath.startsWith(pkg.prefix)) {\n return pkg.name;\n }\n }\n return '(root)';\n}\n\n/** Pathspec patterns for source extensions */\nconst sourcePathspecs = [...sourceExtensions].map((ext) => `*.${ext}`);\n\n/** File and LOC stats for the repository; one `git grep -c ''` call yields paths and line counts. */\nasync function collectStats(forkPath: string): Promise<StatsResult> {\n // Tracked source files with line counts (respects .gitignore, ~15ms).\n const output = await git(['grep', '-c', '', '--', ...sourcePathspecs], forkPath, { ignoreErrors: true });\n const allFilesOutput = await git(['ls-files', '--cached'], forkPath);\n const allFilesCount = allFilesOutput.split('\\n').filter(Boolean).length;\n\n const packages = await getWorkspacePackages(forkPath);\n\n // Parse \"path:count\" lines\n const entries: { path: string; loc: number }[] = [];\n for (const line of output.split('\\n')) {\n if (!line) continue;\n const sep = line.lastIndexOf(':');\n if (sep === -1) continue;\n entries.push({ path: line.slice(0, sep), loc: Number.parseInt(line.slice(sep + 1), 10) });\n }\n\n const skipped = allFilesCount - entries.length;\n const emptyCat = () => ({\n test: { files: 0, loc: 0 },\n stories: { files: 0, loc: 0 },\n generated: { files: 0, loc: 0 },\n json: { files: 0, loc: 0 },\n other: { files: 0, loc: 0 },\n });\n const categories = emptyCat();\n const pkgStats = new Map<string, PackageStats>();\n let totalLoc = 0;\n\n for (const { path, loc } of entries) {\n const category = classifyFile(path);\n categories[category].files++;\n categories[category].loc += loc;\n totalLoc += loc;\n\n const pkg = matchPackage(path, packages);\n let entry = pkgStats.get(pkg);\n if (!entry) {\n entry = { total: 0, loc: 0, categories: emptyCat() };\n pkgStats.set(pkg, entry);\n }\n entry.total++;\n entry.loc += loc;\n entry.categories[category].files++;\n entry.categories[category].loc += loc;\n }\n\n const sortedPackages = Object.fromEntries(\n [...pkgStats.entries()].sort((a, b) => b[1].categories.other.loc - a[1].categories.other.loc),\n );\n\n return { total: entries.length, totalLoc, skipped, categories, packages: sortedPackages };\n}\n\nfunction pad(n: number, width = 6): string {\n return String(n).padStart(width);\n}\n\nfunction formatLoc(n: number): string {\n if (n >= 1000) return `${(n / 1000).toFixed(1)}k`;\n return String(n);\n}\n\nfunction formatLocColumn(n: number, width = 8): string {\n return formatLoc(n).padStart(width);\n}\n\nfunction fmtPct(value: number, total: number): string {\n const pct = ((value / total) * 100).toFixed(1);\n return `${pct.padStart(5)}%`;\n}\n\nfunction printStats(stats: StatsResult, verbose: boolean): void {\n console.info();\n console.info(\n ` ${pc.bold('code files'.padEnd(13))} ${String(stats.total)} ${pc.dim(`(${[...sourceExtensions].join(' ')})`)}`,\n );\n console.info(` ${pc.bold('lines of code')} ${pc.cyan(formatLoc(stats.totalLoc))}`);\n console.info();\n\n const catEntries: [string, { files: number; loc: number }][] = [\n ['source & config', stats.categories.other],\n ['test', stats.categories.test],\n ['stories', stats.categories.stories],\n ['generated', stats.categories.generated],\n ['json', stats.categories.json],\n ];\n for (const [label, data] of catEntries) {\n console.info(\n ` ${pad(data.files)} ${pc.dim(fmtPct(data.files, stats.total))} ${label.padEnd(18)} ${pc.cyan(formatLocColumn(data.loc))} ${pc.dim(fmtPct(data.loc, stats.totalLoc))}`,\n );\n }\n\n console.info();\n console.info(DIVIDER);\n console.info();\n\n if (verbose) {\n const header = ` ${''.padEnd(6)} ${'package'.padEnd(18)} ${'loc'.padStart(8)} ${'test'.padStart(6)} ${'story'.padStart(6)} ${'gen'.padStart(6)} ${'json'.padStart(6)} ${'src'.padStart(6)}`;\n console.info(pc.dim(header));\n for (const [name, data] of Object.entries(stats.packages)) {\n const c = data.categories;\n const srcFiles = c.other.files;\n const srcLoc = c.other.loc;\n if (srcFiles === 0) continue;\n console.info(\n ` ${pc.dim(pad(srcFiles))} ${name.padEnd(18)} ${pc.cyan(formatLocColumn(srcLoc))} ${pc.dim(pad(c.test.files))} ${pc.dim(pad(c.stories.files))} ${pc.dim(pad(c.generated.files))} ${pc.dim(pad(c.json.files))} ${pc.dim(pad(srcFiles))}`,\n );\n }\n } else {\n console.info(pc.dim(' source & config by package'));\n for (const [name, data] of Object.entries(stats.packages)) {\n const srcFiles = data.categories.other.files;\n const srcLoc = data.categories.other.loc;\n if (srcFiles === 0) continue;\n console.info(\n ` ${pad(srcFiles)} ${pc.dim(fmtPct(srcFiles, stats.categories.other.files))} ${name.padEnd(18)} ${pc.cyan(formatLocColumn(srcLoc))} ${pc.dim(fmtPct(srcLoc, stats.categories.other.loc))}`,\n );\n }\n }\n\n console.info();\n}\n\nexport async function runStats(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n\n createSpinner('counting files...');\n const stats = await collectStats(forkPath);\n spinnerSuccess('counted raw lines of code');\n\n printStats(stats, config.verbose);\n console.info();\n printCoverageSummary(forkPath, { refresh: config.coverage });\n}\n","/**\n * Coverage utilities for the Cella CLI stats service.\n *\n * Reads the cached `.coverage/coverage-summary.json` produced by the\n * `json-summary` Vitest reporter (see root vitest.config.ts) and renders a\n * compact overview. The stats service normally only reads\n * the artifact from the last default `pnpm test` run, warning when it is stale\n * or missing. Passing `--coverage` refreshes it first.\n */\n\nimport { spawnSync } from 'node:child_process';\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\nimport pc from './colors';\n\n/** A single metric block from a coverage-summary.json entry. */\ninterface CoverageMetric {\n total: number;\n covered: number;\n skipped: number;\n pct: number | 'Unknown';\n}\n\n/** One file (or the `total`) entry in coverage-summary.json. */\ninterface CoverageEntry {\n lines: CoverageMetric;\n statements: CoverageMetric;\n functions: CoverageMetric;\n branches: CoverageMetric;\n}\n\n/** Shape of Vitest's coverage-summary.json. Keys are absolute file paths plus `total`. */\ntype CoverageSummary = Record<string, CoverageEntry> & { total: CoverageEntry };\n\n/** Coverage data is considered stale after this many ms (7 days). */\nconst STALE_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** Path to the cached summary written by the `json-summary` reporter. */\nfunction summaryPath(forkPath: string): string {\n return join(forkPath, '.coverage', 'coverage-summary.json');\n}\n\n/** Color a percentage: green ≥ 80, yellow ≥ 50, red below. */\nfunction colorPct(pct: CoverageMetric['pct']): string {\n if (typeof pct !== 'number' || !Number.isFinite(pct)) return pc.dim('n/a');\n\n const label = `${pct.toFixed(2)}%`;\n if (pct >= 80) return pc.green(label);\n if (pct >= 50) return pc.yellow(label);\n return pc.red(label);\n}\n\n/** Human-friendly \"x days/hours ago\" from a timestamp. */\nfunction formatAge(ms: number): string {\n const days = Math.floor(ms / (24 * 60 * 60 * 1000));\n if (days >= 1) return `${days} day${days === 1 ? '' : 's'} ago`;\n const hours = Math.floor(ms / (60 * 60 * 1000));\n if (hours >= 1) return `${hours} hour${hours === 1 ? '' : 's'} ago`;\n const mins = Math.floor(ms / (60 * 1000));\n return `${mins} minute${mins === 1 ? '' : 's'} ago`;\n}\n\n/**\n * Re-run the full coverage suite via `pnpm test`. Output is streamed so the\n * user sees progress (Docker boot, test run, etc.). Returns true on success.\n */\nexport function refreshCoverage(forkPath: string): boolean {\n console.info(pc.dim('running `pnpm test` (this spins up Docker and runs the full suite)...'));\n const result = spawnSync('pnpm', ['test'], { cwd: forkPath, stdio: 'inherit' });\n return result.status === 0;\n}\n\n/**\n * Print a compact coverage overview from the cached summary file.\n *\n * @param forkPath - Repository root.\n * @param options.refresh - When true, run `pnpm test` first to regenerate\n * the cache before rendering.\n */\nexport function printCoverageSummary(forkPath: string, options: { refresh?: boolean } = {}): void {\n const file = summaryPath(forkPath);\n\n if (options.refresh) {\n const ok = refreshCoverage(forkPath);\n if (!ok) {\n console.info(pc.red('coverage run failed: showing last cached results (if any)'));\n }\n console.info();\n }\n\n if (!existsSync(file)) {\n console.info(pc.bold('coverage'));\n console.info(pc.yellow(' no coverage data found: run `pnpm test` to generate it'));\n console.info();\n return;\n }\n\n let summary: CoverageSummary;\n let mtimeMs: number;\n try {\n summary = JSON.parse(readFileSync(file, 'utf8')) as CoverageSummary;\n mtimeMs = statSync(file).mtimeMs;\n } catch {\n console.info(pc.bold('coverage'));\n console.info(pc.yellow(' could not read coverage-summary.json: run `pnpm test` to regenerate'));\n console.info();\n return;\n }\n\n const ageMs = Date.now() - mtimeMs;\n const stale = ageMs > STALE_THRESHOLD_MS;\n\n // Roll up per-package line coverage by the first path segment relative to root.\n const perPackage = new Map<string, { covered: number; total: number }>();\n for (const [key, entry] of Object.entries(summary)) {\n if (key === 'total') continue;\n const rel = relative(forkPath, key);\n if (rel.startsWith('..')) continue;\n const pkg = rel.split(sep)[0];\n const acc = perPackage.get(pkg) ?? { covered: 0, total: 0 };\n acc.covered += entry.lines.covered;\n acc.total += entry.lines.total;\n perPackage.set(pkg, acc);\n }\n\n // Header with freshness indicator.\n const ageLabel = formatAge(ageMs);\n console.info(pc.bold('coverage'), pc.dim(`(updated ${ageLabel})`));\n if (stale) {\n console.info(pc.yellow(' ⚠ data is older than 7 days: run `pnpm test` to refresh'));\n }\n\n if (!Object.keys(summary).some((key) => key !== 'total')) {\n console.info(pc.yellow(' no coverage data found: run `pnpm test` to regenerate'));\n console.info();\n return;\n }\n\n // Overall totals.\n const total = summary.total;\n console.info(\n ` ${pc.bold('overall')} ` +\n `lines ${colorPct(total.lines.pct)} ${pc.dim(`(${total.lines.covered}/${total.lines.total})`)} ` +\n `funcs ${colorPct(total.functions.pct)} ` +\n `branches ${colorPct(total.branches.pct)}`,\n );\n\n // Per-package line coverage, worst first.\n const rows = [...perPackage.entries()]\n .map(([pkg, v]) => ({ pkg, pct: v.total ? (100 * v.covered) / v.total : 0, ...v }))\n .sort((a, b) => a.pct - b.pct);\n\n const nameWidth = Math.max(...rows.map((r) => r.pkg.length), 0);\n for (const r of rows) {\n console.info(` ${r.pkg.padEnd(nameWidth)} ${colorPct(r.pct)} ${pc.dim(`(${r.covered}/${r.total})`)}`);\n }\n console.info();\n}\n","/**\n * Branch mode of the stats service (`cella stats --since <ref>`).\n *\n * Counts what the current branch changed since it left a ref, by kind of file, so a pull request\n * can say where its lines went: source, tests, generated output, docs.\n */\n\nimport pc from '../utils/colors';\nimport { createSpinner, DIVIDER, spinnerSuccess, writeStdout } from '../utils/display';\nimport { git } from '../utils/git';\nimport { classifyFile, getWorkspacePackages, matchPackage, sourceExtensions, type WorkspacePackage } from './stats';\n\n/** Kind of a changed file. `source` is code and styles that are none of the other kinds. */\nexport type ChangeKind = 'source' | 'test' | 'stories' | 'generated' | 'json' | 'docs' | 'other';\n\n/** What a changed source line holds. */\nexport type LineContent = 'code' | 'comments' | 'blank';\n\ninterface LineChange {\n added: number;\n removed: number;\n}\n\ninterface KindChange extends LineChange {\n files: number;\n}\n\nexport interface FileChange extends LineChange {\n path: string;\n kind: ChangeKind;\n}\n\n/** What a branch changed since it left a ref */\nexport interface BranchStats {\n /** The ref asked for, as typed */\n since: string;\n /** Short sha of the commit the branch left the ref at */\n mergeBase: string;\n /** Current branch name, or the short sha of a detached HEAD */\n head: string;\n total: KindChange;\n kinds: Record<ChangeKind, KindChange>;\n /** Changed source lines by what they hold; null when git could not produce the patch */\n sourceContent: Record<LineContent, LineChange> | null;\n /** Changed source lines per workspace package */\n sourceByPackage: Record<string, KindChange>;\n files: FileChange[];\n /** Files with uncommitted changes, which are not counted */\n uncommitted: number;\n}\n\nconst kindLabels: Record<ChangeKind, string> = {\n source: 'source',\n test: 'tests',\n stories: 'stories',\n generated: 'generated',\n json: 'json',\n docs: 'docs',\n other: 'other',\n};\n\nconst docExtensions = new Set(['md', 'mdx']);\n\n/** Lock files are written by the package manager, whatever their extension */\nconst lockFiles = new Set(['pnpm-lock.yaml', 'package-lock.json', 'yarn.lock', 'bun.lock', 'bun.lockb']);\n\n/** Code and style extensions whose lines are split into code, comments and blank */\nconst codeExtensions = [...sourceExtensions].filter((ext) => !ext.startsWith('json'));\n\n/**\n * Classify a changed file. Every file in a diff counts, so beyond the snapshot's categories this\n * knows docs and a rest group, and reads a lock file as generated.\n */\nexport function classifyChange(filePath: string): ChangeKind {\n const name = filePath.slice(filePath.lastIndexOf('/') + 1);\n if (lockFiles.has(name)) return 'generated';\n\n const category = classifyFile(filePath);\n if (category !== 'other') return category;\n\n const ext = name.includes('.') ? name.slice(name.lastIndexOf('.') + 1) : '';\n if (docExtensions.has(ext)) return 'docs';\n return sourceExtensions.has(ext) ? 'source' : 'other';\n}\n\n/**\n * Classify one source line. A diff shows changed lines only, so a comment is recognized by how the\n * line starts: `//`, `/*`, the `*` of a block comment's body or end, and JSX's `{/*`.\n */\nexport function classifyLine(text: string): LineContent {\n const line = text.trim();\n if (!line) return 'blank';\n if (line.startsWith('//') || line.startsWith('/*') || line.startsWith('*') || line.startsWith('{/*')) {\n return 'comments';\n }\n return 'code';\n}\n\n/** Parse `git diff --numstat -z --no-renames`: one `added<TAB>removed<TAB>path` record per file. */\nexport function parseNumstat(output: string): FileChange[] {\n const files: FileChange[] = [];\n for (const record of output.split('\\0')) {\n if (!record) continue;\n const [added, removed, ...rest] = record.split('\\t');\n const path = rest.join('\\t');\n if (!path) continue;\n // A binary file reports `-` for both counts\n files.push({\n path,\n kind: classifyChange(path),\n added: Number.parseInt(added, 10) || 0,\n removed: Number.parseInt(removed, 10) || 0,\n });\n }\n return files;\n}\n\n/**\n * Count the changed lines of a zero-context patch by what they hold, for the files `isCounted`\n * accepts. Hunk headers say how many lines follow, so a changed line that itself starts with\n * `+++` or `---` is never taken for a file header.\n */\nexport function countLineContent(\n patch: string,\n isCounted: (filePath: string) => boolean,\n): Record<LineContent, LineChange> {\n const content: Record<LineContent, LineChange> = {\n code: { added: 0, removed: 0 },\n comments: { added: 0, removed: 0 },\n blank: { added: 0, removed: 0 },\n };\n\n let counted = false;\n let remaining = 0;\n\n for (const line of patch.split('\\n')) {\n if (remaining > 0) {\n // \"\\" follows a line without being one\n if (line.startsWith('\\\\')) continue;\n remaining--;\n if (!counted) continue;\n const change = line.startsWith('+') ? 'added' : 'removed';\n content[classifyLine(line.slice(1))][change]++;\n continue;\n }\n\n // A path git had to quote matches no header below, so every file starts out uncounted\n if (line.startsWith('diff --git ')) {\n counted = false;\n continue;\n }\n\n if (line.startsWith('--- a/') || line.startsWith('+++ b/')) {\n counted = isCounted(line.slice(6));\n continue;\n }\n\n const hunk = /^@@ -\\d+(?:,(\\d+))? \\+\\d+(?:,(\\d+))? @@/.exec(line);\n if (hunk) remaining = Number(hunk[1] ?? 1) + Number(hunk[2] ?? 1);\n }\n\n return content;\n}\n\n/**\n * Collect what HEAD changed since it left `since`: committed work only, compared with the merge\n * base, which is what a pull request into that ref shows.\n */\nexport async function collectBranchStats(forkPath: string, since: string): Promise<BranchStats> {\n const sinceSha = await git(['rev-parse', '--verify', '--quiet', `${since}^{commit}`], forkPath, {\n ignoreErrors: true,\n });\n if (!sinceSha) throw new Error(`unknown ref '${since}'. pass a branch, tag or commit, such as origin/main`);\n\n const mergeBase = await git(['merge-base', sinceSha, 'HEAD'], forkPath, { ignoreErrors: true });\n if (!mergeBase) throw new Error(`the current branch shares no history with '${since}'`);\n\n const range = [mergeBase, 'HEAD'];\n const files = parseNumstat(await git(['diff', '--numstat', '-z', '--no-renames', ...range], forkPath));\n const kindOf = new Map(files.map((file) => [file.path, file.kind]));\n\n const emptyKind = (): KindChange => ({ files: 0, added: 0, removed: 0 });\n const kinds: Record<ChangeKind, KindChange> = {\n source: emptyKind(),\n test: emptyKind(),\n stories: emptyKind(),\n generated: emptyKind(),\n json: emptyKind(),\n docs: emptyKind(),\n other: emptyKind(),\n };\n const total = emptyKind();\n const packages: WorkspacePackage[] = await getWorkspacePackages(forkPath).catch(() => []);\n const byPackage = new Map<string, KindChange>();\n\n const add = (target: KindChange, file: FileChange) => {\n target.files++;\n target.added += file.added;\n target.removed += file.removed;\n };\n\n for (const file of files) {\n add(total, file);\n add(kinds[file.kind], file);\n if (file.kind !== 'source') continue;\n\n const pkg = matchPackage(file.path, packages);\n const entry = byPackage.get(pkg) ?? emptyKind();\n add(entry, file);\n byPackage.set(pkg, entry);\n }\n\n // The patch of code files only: generated JSON can run to megabytes and holds no comments.\n const patch = await git(\n ['diff', '-U0', '--no-renames', '--no-color', ...range, '--', ...codeExtensions.map((ext) => `*.${ext}`)],\n forkPath,\n { ignoreErrors: true },\n );\n const sourceContent =\n kinds.source.files > 0 && !patch ? null : countLineContent(patch, (path) => kindOf.get(path) === 'source');\n\n const sourceByPackage = Object.fromEntries(\n [...byPackage.entries()].sort((a, b) => net(b[1]) - net(a[1]) || a[0].localeCompare(b[0])),\n );\n\n const branch = await git(['rev-parse', '--abbrev-ref', 'HEAD'], forkPath);\n const status = await git(['status', '--porcelain'], forkPath, { ignoreErrors: true });\n\n return {\n since,\n mergeBase: mergeBase.slice(0, 7),\n head: branch === 'HEAD' ? await git(['rev-parse', '--short', 'HEAD'], forkPath) : branch,\n total,\n kinds,\n sourceContent,\n sourceByPackage,\n files: files.sort((a, b) => net(b) - net(a) || a.path.localeCompare(b.path)),\n uncommitted: status.split('\\n').filter(Boolean).length,\n };\n}\n\nfunction net(change: LineChange): number {\n return change.added - change.removed;\n}\n\n/** `+12`, `-3` or a bare `0`. */\nfunction signed(n: number): string {\n return n > 0 ? `+${n}` : String(n);\n}\n\n/** Kinds that changed, the one that grew most first. */\nfunction changedKinds(stats: BranchStats): [ChangeKind, KindChange][] {\n return (Object.entries(stats.kinds) as [ChangeKind, KindChange][])\n .filter(([, change]) => change.files > 0)\n .sort((a, b) => net(b[1]) - net(a[1]));\n}\n\n/** `code +70, comments +35, blank +15`: the net lines of each part that changed. */\nfunction formatNetList(parts: [string, LineChange][]): string {\n return parts\n .filter(([, change]) => change.added > 0 || change.removed > 0)\n .map(([label, change]) => `${label} ${signed(net(change))}`)\n .join(', ');\n}\n\n/**\n * Format the stats as markdown for a pull request description: a table with one row per kind of\n * file, then where the source lines went.\n */\nexport function formatMarkdown(stats: BranchStats): string {\n const row = (label: string, change: KindChange) =>\n `| ${label} | ${change.files} | ${signed(change.added)} | ${signed(-change.removed)} | ${signed(net(change))} |`;\n const capitalize = (text: string) => text.charAt(0).toUpperCase() + text.slice(1);\n\n const lines = [\n '| Kind | Files | Added | Removed | Net |',\n '| --- | ---: | ---: | ---: | ---: |',\n ...changedKinds(stats).map(([kind, change]) =>\n row(kind === 'json' ? 'JSON' : capitalize(kindLabels[kind]), change),\n ),\n `| **Total** | **${stats.total.files}** | **${signed(stats.total.added)}** | **${signed(-stats.total.removed)}** | **${signed(net(stats.total))}** |`,\n ];\n\n const notes: string[] = [];\n if (stats.sourceContent) {\n const content = formatNetList(Object.entries(stats.sourceContent));\n if (content) notes.push(`Source lines by content: ${content}.`);\n }\n const byPackage = formatNetList(Object.entries(stats.sourceByPackage));\n if (byPackage) notes.push(`Source lines by package: ${byPackage}.`);\n\n return notes.length > 0 ? [...lines, '', ...notes].join('\\n') : lines.join('\\n');\n}\n\n/** Print the stats as aligned terminal tables. */\nfunction printBranchStats(stats: BranchStats, verbose: boolean): void {\n const columns = (files: string, change: LineChange, label: string) =>\n ` ${files.padStart(5)} ${signed(change.added).padStart(8)} ${signed(-change.removed).padStart(8)} ${pc.cyan(signed(net(change)).padStart(8))} ${label}`;\n\n console.info();\n console.info(pc.dim(` ${'files'.padStart(5)} ${'added'.padStart(8)} ${'removed'.padStart(8)} ${'net'.padStart(8)}`));\n for (const [kind, change] of changedKinds(stats)) {\n console.info(columns(String(change.files), change, kindLabels[kind]));\n }\n console.info(columns(String(stats.total.files), stats.total, pc.bold('total')));\n\n if (stats.sourceContent && stats.kinds.source.files > 0) {\n console.info();\n console.info(pc.dim(' source lines by content'));\n for (const [content, change] of Object.entries(stats.sourceContent)) {\n console.info(columns('', change, content));\n }\n }\n\n const packages = Object.entries(stats.sourceByPackage);\n if (packages.length > 0) {\n console.info();\n console.info(pc.dim(' source lines by package'));\n for (const [name, change] of packages) {\n console.info(columns(String(change.files), change, name));\n }\n }\n\n if (verbose) {\n console.info();\n console.info(DIVIDER);\n console.info();\n for (const file of stats.files) {\n console.info(columns('', file, `${file.path} ${pc.dim(kindLabels[file.kind])}`));\n }\n }\n\n if (stats.uncommitted > 0) {\n console.info();\n console.info(\n pc.dim(` ${stats.uncommitted} uncommitted file${stats.uncommitted === 1 ? ' is' : 's are'} not counted`),\n );\n }\n\n console.info();\n}\n\n/**\n * Run the stats service in branch mode.\n */\nexport async function runBranchStats(\n forkPath: string,\n options: { since: string; markdown?: boolean; verbose?: boolean },\n): Promise<void> {\n createSpinner('counting changed lines...');\n const stats = await collectBranchStats(forkPath, options.since);\n spinnerSuccess(`Counted what ${stats.head} changed since ${stats.since} (${stats.mergeBase})`);\n\n if (stats.total.files === 0) {\n console.info(pc.dim(` nothing committed since ${stats.since}`));\n return;\n }\n\n if (options.markdown) {\n writeStdout(formatMarkdown(stats));\n if (stats.uncommitted > 0) console.info(pc.dim(`${stats.uncommitted} uncommitted file(s) are not counted`));\n return;\n }\n\n printBranchStats(stats, options.verbose ?? false);\n}\n"],"mappings":"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","names":["existsSync","statSync","join","resolve","process","process","process","process","process","existsSync","join","z","join","pad","existsSync","z","join","resolve","process","process","resolve","join","existsSync","join","existsSync","mkdir","dirname","join","resolve","join","existsSync","resolve","dirname","join","mkdir","existsSync","mkdir","readFile","writeFile","dirname","join","join","existsSync","readFile","mkdir","dirname","writeFile","existsSync","join","process","basename","writeFileSync","basename","join","process","process","join","basename","writeFileSync","existsSync","rm","join","existsSync","tmpdir","basename","join","resolve","process","resolve","join","tmpdir","basename","existsSync","process","Project","SyntaxKind","SyntaxKind","Project","upstreamChanged","upstreamOnly","existsSync","join","rm","execFileSync","mkdir","writeFile","dirname","join","join","execFileSync","mkdir","dirname","writeFile","basename","spawnSync","readFileSync","basename","join","relative","execFile","existsSync","readFileSync","writeFileSync","join","promisify","execFileAsync","promisify","execFile","join","existsSync","readFileSync","writeFileSync","str","readFileSync","join","spawnSync","basename","packageJsonPath","relative","select","dirname","join","resolve","dirname","resolve","join","unlinkSync","existsSync","dirname","resolve","dirname","resolve","existsSync","checkbox","select","fork","resolve","process","Separator","select","spawnSync","select","spawnSync","existsSync","readFileSync","writeFileSync","join","existsSync","readFileSync","join","readFileSync","join","existsSync","existsSync","readFileSync","writeFileSync","join","result","upstreamValue","forkValue","baseValue","kept","spawnSync","select","resolve","Separator","select","process","readFile","join","spawnSync","existsSync","readFileSync","statSync","join","relative","sep","join","spawnSync","existsSync","readFileSync","statSync","relative","sep","readFile","join","sep","resolve","existsSync","statSync","process","join"]}
1
+ {"version":3,"sources":["../src/cella-cli.ts","../src/cli.ts","../src/utils/colors.ts","../src/utils/env.ts","../src/utils/config.ts","../src/config/types.ts","../src/utils/errors.ts","../src/utils/managed-files.ts","../src/utils/module-territory.ts","../src/utils/display.ts","../package.json","../src/utils/overrides.ts","../src/utils/git.ts","../src/utils/manifest.ts","../src/utils/migration-notes.ts","../src/services/merge-engine.ts","../src/utils/versions.ts","../src/utils/cli-version.ts","../src/utils/upstream-overrides.ts","../src/services/analyze-core.ts","../src/services/migrate.ts","../src/services/analyze.ts","../src/services/audit.ts","../src/utils/audit-utils.ts","../src/utils/security-plan.ts","../src/utils/workspace-yaml.ts","../src/services/audit-security.ts","../src/services/contributions.ts","../src/utils/diff.ts","../src/services/contrib-core.ts","../src/services/fork-utils.ts","../src/services/forks.ts","../src/services/sync.ts","../src/utils/gh.ts","../src/services/packages.ts","../src/services/package-usage.ts","../src/services/stats.ts","../src/utils/coverage-utils.ts","../src/services/stats-since.ts"],"sourcesContent":["#!/usr/bin/env tsx\n/**\n * Cella CLI main entry point: resolves the fork path, loads the config,\n * parses the command line and routes to the selected service.\n */\n\nimport { existsSync, statSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport process from 'node:process';\nimport { parseCli } from './cli';\nimport type { CellaCliConfig, RuntimeConfig, SyncService } from './config/types';\nimport { runAnalyze } from './services/analyze';\nimport { runAudit } from './services/audit';\nimport { runContributions } from './services/contributions';\nimport { runForks } from './services/forks';\nimport { runMigrate } from './services/migrate';\nimport { runStats } from './services/stats';\nimport { runBranchStats } from './services/stats-since';\nimport { runSyncCommand } from './services/sync';\nimport pc from './utils/colors';\nimport { loadConfig } from './utils/config';\nimport { getEnv } from './utils/env';\nimport { errorMessage } from './utils/errors';\n\n/**\n * The fork path: the CELLA_FORK_PATH environment variable when set, else the current\n * working directory. A cwd inside cli/cella (pnpm --filter) resolves up to the fork root.\n */\nfunction getForkPath(): string {\n const envPath = getEnv('CELLA_FORK_PATH');\n if (envPath) {\n const resolved = resolve(envPath);\n if (!existsSync(resolved) || !statSync(resolved).isDirectory()) {\n throw new Error(`CELLA_FORK_PATH is not a valid directory: ${resolved}`);\n }\n return resolved;\n }\n\n let cwd = process.cwd();\n\n if (cwd.endsWith('/cli/cella') || cwd.endsWith('\\\\cli\\\\cella')) {\n cwd = resolve(cwd, '../..');\n }\n\n return cwd;\n}\n\n/**\n * Pre-flight check before running a service: verifies the path is a git repository.\n * The sync service cuts its own temporary branch from the trunk and owns its own\n * clean/resume state, so neither the current branch nor a dirty tree blocks a run.\n */\nfunction preflight(forkPath: string): void {\n if (!existsSync(join(forkPath, '.git'))) {\n throw new Error(`not a git repository: ${forkPath}`);\n }\n}\n\n/** What each service runs once the command line is parsed. */\nconst services: Record<SyncService, (config: RuntimeConfig) => Promise<unknown>> = {\n analyze: runAnalyze,\n sync: runSyncCommand,\n migrate: runMigrate,\n audit: runAudit,\n forks: runForks,\n contributions: runContributions,\n stats: async (config) => {\n if (config.md && !config.since) throw new Error('--md goes with --since <ref>');\n if (!config.since) return runStats(config);\n return runBranchStats(config, config.since);\n },\n};\n\nfunction isHelpOrVersionRequest(): boolean {\n return (\n process.argv.slice(2).some((arg) => arg === '--help' || arg === '-h' || arg === '--version' || arg === '-v') ||\n process.argv[2] === 'help'\n );\n}\n\nasync function main(): Promise<void> {\n try {\n const forkPath = getForkPath();\n\n if (isHelpOrVersionRequest()) {\n await parseCli({ settings: { upstreamUrl: '', upstreamBranch: 'main' } } as CellaCliConfig, forkPath);\n return;\n }\n\n const userConfig = await loadConfig(forkPath);\n\n const config = await parseCli(userConfig, forkPath);\n\n // Services that operate on other fork paths skip the local-repo preflight.\n if (!['audit', 'forks', 'contributions', 'stats'].includes(config.service)) {\n preflight(forkPath);\n }\n\n await services[config.service](config);\n\n console.info();\n } catch (error) {\n console.error();\n console.error(`${pc.red('✗')} ${errorMessage(error)}`);\n process.exit(1);\n }\n}\n\nmain();\n","/**\n * Command-line parsing: the service definitions, commander wiring, and the\n * interactive service menu, resolved into a RuntimeConfig.\n */\n\nimport process from 'node:process';\nimport { select } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport type { AnalyzeScope, CellaCliConfig, RuntimeConfig, SyncService } from './config/types';\nimport pc from './utils/colors';\nimport { isUpstreamRepo, resolveUpstream } from './utils/config';\nimport { MENU_DIVIDER, printHeader, setJsonMode, VERSION, warningMark } from './utils/display';\nimport { validateOverrides } from './utils/overrides';\n\ntype CliServiceSelection = {\n service?: SyncService;\n options: CliOptionState;\n};\n\ntype CliOptionState = Omit<RuntimeConfig, keyof CellaCliConfig | 'forkPath' | 'upstreamRef' | 'service'>;\n\ntype MenuContext = {\n hasForks: boolean;\n isUpstreamRepo: boolean;\n};\n\ntype ServiceOption = [flags: string, description: string];\n\ntype ServiceDefinition = {\n name: SyncService;\n description: string;\n options?: ServiceOption[];\n /** Arguments the service takes after its options, e.g. the ones `migrate --run` hands to the codemod. */\n operands?: ServiceOption;\n includeInMenu?: (context: MenuContext) => boolean;\n};\n\n/** A string option's value, or undefined when it was not passed. */\nconst str = (value: unknown): string | undefined => (typeof value === 'string' ? value : undefined);\n\n/** A boolean flag's value: true only when it was passed. */\nconst flag = (value: unknown): boolean => value === true;\n\nfunction readOptions(opts: Record<string, unknown>, operands: string[] = []): CliOptionState {\n const scope = str(opts.scope);\n if (scope && scope !== 'all' && scope !== 'risk' && scope !== 'protected') {\n throw new Error(`invalid --scope '${scope}'. expected one of: all, risk, protected`);\n }\n const normalizedScope = scope as AnalyzeScope | undefined;\n\n const run = str(opts.run);\n if (operands.length > 0 && !run) {\n throw new Error(`unexpected argument '${operands[0]}'. arguments after the options only go with --run <id>`);\n }\n\n return {\n verbose: flag(opts.verbose),\n list: flag(opts.list),\n json: flag(opts.json),\n scope: normalizedScope,\n fork: str(opts.fork),\n track: opts.track === 'release' || opts.track === 'branch' ? opts.track : undefined,\n ref: str(opts.ref) || undefined,\n keepConfig: flag(opts.keepConfig),\n unpinned: flag(opts.unpinned),\n since: str(opts.since) || undefined,\n md: flag(opts.md),\n all: flag(opts.all),\n show: str(opts.show),\n extract: str(opts.extract),\n run,\n runArgs: run ? operands : undefined,\n mark: Array.isArray(opts.mark) ? opts.mark.filter((id): id is string => typeof id === 'string') : undefined,\n };\n}\n\n// Option literals shared verbatim by more than one service.\nconst jsonOption: ServiceOption = ['--json', 'machine-readable output for tooling/agents'];\nconst trackOption: ServiceOption = ['--track <mode>', 'override upstream tracking for this run: release|branch'];\nconst refOption: ServiceOption = ['--ref <ref>', 'pin the upstream commit for this run: sha, release tag or branch'];\nconst unpinnedOption: ServiceOption = [\n '--unpinned',\n 'lift every pinned entry for this run (managed files stay pinned) and merge from the full upstream history',\n];\nconst forkOption: ServiceOption = ['--fork <name>', 'pre-select a fork by name (skips the fork selection prompt)'];\n\nconst serviceDefinitions: ServiceDefinition[] = [\n {\n name: 'analyze',\n description: 'dry run to see what would change on sync',\n options: [\n ['--list', 'non-interactive output for tooling (one file per line)'],\n jsonOption,\n ['--scope <scope>', 'analyze scope for --list/--json: all|risk|protected'],\n trackOption,\n refOption,\n unpinnedOption,\n ],\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'sync',\n description: 'merge upstream changes onto a fresh branch, sync package.json and open a squash-merge PR',\n options: [\n trackOption,\n refOption,\n ['--keep-config', 'merge with your sync config as it stands when upstream changed its own'],\n unpinnedOption,\n ],\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'migrate',\n description: 'list the upstream migration notes this app has not handled yet',\n options: [\n ['--all', 'list every upstream note, handled or not'],\n jsonOption,\n ['--show <id>', \"print one note's README\"],\n ['--extract <id>', \"write one note's folder under node_modules/.cache to run its codemod\"],\n ['--run <id>', \"run one note's codemod; files identical to upstream stay as they are\"],\n ['--mark <ids...>', 'record notes as handled'],\n ],\n operands: [\n '[codemodArgs...]',\n \"with --run, after `--`: arguments for the codemod (default: inventory and the note's roots)\",\n ],\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'audit',\n description: 'update outdated packages, then rebuild the security overrides from a fresh audit',\n options: [['--list', 'report only: no prompts, and nothing is written']],\n },\n {\n name: 'forks',\n description: 'run normal sync inside local fork repositories',\n options: [\n forkOption,\n ['--keep-config', \"merge with the fork's sync config as it stands when upstream changed its own\"],\n ],\n includeInMenu: (context) => context.hasForks,\n },\n {\n name: 'contributions',\n description: 'pull and adopt changes from local forks',\n options: [forkOption, jsonOption],\n includeInMenu: (context) => context.hasForks,\n },\n {\n name: 'stats',\n description: 'count files by category and workspace package',\n options: [\n ['-V, --verbose', 'show detailed output during operations'],\n ['--since <ref>', 'count what the current branch changed since it left <ref>, by kind of file'],\n ['--md', 'with --since: print the table as markdown for a pull request description'],\n ],\n },\n];\n\nfunction getMenuContext(userConfig: CellaCliConfig, forkPath: string): MenuContext {\n return {\n hasForks: (userConfig.forks?.length ?? 0) > 0,\n isUpstreamRepo: isUpstreamRepo(forkPath),\n };\n}\n\nfunction buildServiceChoices(context: MenuContext) {\n // Pad service labels to align descriptions (longest label is 'contributions').\n const label = (name: string) => name.padEnd(14);\n const baseChoices = serviceDefinitions\n .filter((service) => service.includeInMenu?.(context) ?? true)\n .map((service) => ({\n value: service.name,\n name: `${label(service.name)}${pc.dim(service.description)}`,\n }));\n\n return [\n ...baseChoices,\n { type: 'separator' as const, separator: MENU_DIVIDER },\n { value: 'exit' as const, name: pc.red(`${label('exit')}${pc.dim('quit without doing anything')}`) },\n ];\n}\n\nfunction addServiceCommand(\n program: Command,\n definition: ServiceDefinition,\n setSelection: (selection: CliServiceSelection) => void,\n) {\n const command = program.command(definition.name).description(definition.description);\n\n for (const option of definition.options ?? []) command.option(...option);\n if (definition.operands) command.argument(...definition.operands);\n\n // Commander hands declared arguments to the action before the options\n command.action((...args: unknown[]) => {\n const operands = definition.operands ? (args[0] as string[]) : [];\n const opts = (definition.operands ? args[1] : args[0]) as Record<string, unknown>;\n setSelection({\n service: definition.name,\n options: readOptions(opts, operands),\n });\n });\n}\n\nfunction buildProgram(setSelection: (selection: CliServiceSelection) => void): Command {\n const program = new Command('cella')\n .version(VERSION, '-v, --version', 'output the current version')\n .usage('[service] [options]')\n .helpOption('-h, --help', 'display help for a command')\n .showHelpAfterError()\n .addHelpText(\n 'after',\n [\n '',\n 'Examples:',\n ' $ cella analyze',\n ' $ cella analyze --json --scope risk',\n ' $ cella sync --track branch',\n ' $ cella sync --ref 4f7d87c',\n ' $ cella migrate --run 20261001T2116-tailwind-class-conventions -- rewrite frontend/src',\n ' $ cella migrate --mark 20261002T0614-config-switch',\n ' $ cella audit --list',\n ' $ cella stats --since origin/main --md',\n ' $ cella contributions --fork raak --json',\n ].join('\\n'),\n );\n\n for (const definition of serviceDefinitions) {\n addServiceCommand(program, definition, setSelection);\n }\n\n return program;\n}\n\nfunction parseCommandLine(argv: string[]): CliServiceSelection {\n if (argv.length <= 2) {\n return { options: readOptions({}) };\n }\n\n let selection: CliServiceSelection = { options: readOptions({}) };\n const program = buildProgram((nextSelection) => {\n selection = nextSelection;\n });\n\n program.parse(argv);\n return selection;\n}\n\nasync function promptForService(userConfig: CellaCliConfig, forkPath: string): Promise<SyncService> {\n const selected = await select<SyncService | 'exit'>({\n message: 'choose a service:',\n choices: buildServiceChoices(getMenuContext(userConfig, forkPath)),\n loop: false,\n });\n\n if (selected === 'exit') {\n console.info(pc.dim('exiting...'));\n console.info();\n process.exit(0);\n }\n\n console.info();\n return selected;\n}\n\nfunction buildRuntimeConfig(\n userConfig: CellaCliConfig,\n forkPath: string,\n selection: CliServiceSelection,\n upstreamRef: string,\n): RuntimeConfig {\n return { ...userConfig, forkPath, upstreamRef, service: selection.service ?? 'analyze', ...selection.options };\n}\n\nexport async function parseCli(userConfig: CellaCliConfig, forkPath: string): Promise<RuntimeConfig> {\n const selection = parseCommandLine(process.argv);\n\n // In machine-output modes (--json, --list, --md), reserve stdout for the payload/rows/table\n // and route all human output (header, warnings, spinner) to stderr. Audit's --list only skips\n // its interactive prompts; its report is the human output and stays on stdout.\n const machineList = selection.options.list && selection.service !== 'audit';\n if (selection.options.json || selection.options.md || machineList) setJsonMode(true);\n\n printHeader();\n\n // The upstream branch tip as last fetched: ignored entries are validated against it, and it is the\n // upstreamRef until the merge engine resolves the release tag when tracking releases.\n const { branchRef } = resolveUpstream(userConfig.settings);\n const warnings = await validateOverrides(userConfig, forkPath, branchRef);\n for (const warning of warnings) console.info(`${warningMark} ${warning}`);\n if (warnings.length > 0) console.info();\n\n if (!selection.service) {\n selection.service = await promptForService(userConfig, forkPath);\n }\n\n return buildRuntimeConfig(userConfig, forkPath, selection, branchRef);\n}\n","import process from 'node:process';\nimport { styleText } from 'node:util';\nimport { hasEnv } from './env';\n\ntype ColorStyle = 'blue' | 'bold' | 'cyan' | 'dim' | 'gray' | 'green' | 'magenta' | 'red' | 'white' | 'yellow';\n\nfunction colorsEnabled(): boolean {\n if (hasEnv('NO_COLOR')) return false;\n if (hasEnv('FORCE_COLOR')) return true;\n return !!process.stdout.isTTY;\n}\n\nfunction applyStyle(style: ColorStyle, text: string): string {\n if (!colorsEnabled()) return text;\n return styleText(style, text, { validateStream: false });\n}\n\nconst pc = {\n blue: (text: string) => applyStyle('blue', text),\n bold: (text: string) => applyStyle('bold', text),\n cyan: (text: string) => applyStyle('cyan', text),\n dim: (text: string) => applyStyle('dim', text),\n gray: (text: string) => applyStyle('gray', text),\n green: (text: string) => applyStyle('green', text),\n magenta: (text: string) => applyStyle('magenta', text),\n red: (text: string) => applyStyle('red', text),\n white: (text: string) => applyStyle('white', text),\n yellow: (text: string) => applyStyle('yellow', text),\n};\n\nexport default pc;\n","import process from 'node:process';\n\n/**\n * Centralized environment access for CLI/runtime integration points.\n */\nexport function getEnv(name: string): string | undefined {\n // biome-ignore lint/style/noProcessEnv: This module centralizes intentional CLI environment access.\n return process.env[name];\n}\n\n/** Whether the variable is set at all, even to an empty string. */\nexport function hasEnv(name: string): boolean {\n // biome-ignore lint/style/noProcessEnv: This module centralizes intentional CLI environment access.\n return name in process.env;\n}\n\n/** A mutable copy of the full environment, for passing to child processes. */\nexport function getEnvSnapshot(): NodeJS.ProcessEnv {\n // biome-ignore lint/style/noProcessEnv: This module centralizes intentional CLI environment access.\n return { ...process.env };\n}\n","/**\n * Config loading utilities for sync CLI.\n *\n * Shared between main entry point and forks service.\n */\n\nimport { existsSync, readFileSync, realpathSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { z } from 'zod';\nimport { type CellaCliConfig, cellaConfigSchema, type PackageJsonSyncKey, type SyncSettings } from '../config/types';\nimport { errorMessage } from './errors';\nimport { CONFIG_FILE } from './managed-files';\nimport { resolveAppModuleFolders } from './module-territory';\n\n/** Default git remote name used to point at the upstream repository. */\nexport const DEFAULT_UPSTREAM_REMOTE = 'cella-upstream';\n\n/** Default branch used when a config omits `upstreamBranch` or `releaseBase`; also cella's fork-compare base. */\nexport const DEFAULT_BRANCH = 'main';\n\n/**\n * Prefix for the temporary integration branches that `cella sync` cuts per run\n * (e.g. `cella/sync/20260702-1430`).\n *\n * The three-segment shape (`cella/sync/<stamp>`) means it can never collide with a real branch\n * named `cella` or `cella/sync`.\n */\nexport const DEFAULT_SYNC_PREFIX = 'cella/sync';\n\n/** The package.json keys that sync when a config omits `packageJsonSync`. */\nexport const DEFAULT_PACKAGE_JSON_SYNC: PackageJsonSyncKey[] = ['dependencies', 'devDependencies'];\n\n/** Whether the repo at `repoPath` is upstream cella itself (its root package.json is named 'cella'). */\nexport function isUpstreamRepo(repoPath: string): boolean {\n return JSON.parse(readFileSync(join(repoPath, 'package.json'), 'utf8')).name === 'cella';\n}\n\n/**\n * Whether `branch` is one of the temporary integration branches `cella sync` cuts, i.e. it\n * lives under the internal `cella/sync/` namespace.\n */\nexport function isTemporarySyncBranch(branch: string): boolean {\n return branch.startsWith(`${DEFAULT_SYNC_PREFIX}/`);\n}\n\n/**\n * Resolve the trunk branch `cella sync` cuts the temporary branch from and PRs into.\n */\nexport function resolveReleaseBase(settings: SyncSettings): string {\n return settings.releaseBase ?? DEFAULT_BRANCH;\n}\n\n/**\n * Build a unique temporary integration branch name for a sync cycle, e.g.\n * `cella/sync/20260702-1430`. Cutting a fresh branch per cycle keeps each PR\n * scoped to that sync's upstream delta.\n */\nexport function buildTemporarySyncBranch(): string {\n const now = new Date();\n const pad = (n: number) => String(n).padStart(2, '0');\n const stamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}`;\n return `${DEFAULT_SYNC_PREFIX}/${stamp}`;\n}\n\n/**\n * Resolve the upstream tracking plan from sync settings.\n *\n * Single source of truth shared by the CLI entry point and the merge engine.\n * The concrete ref for release tracking (latest tag) can only be resolved after\n * fetching, so this returns a plan; the merge engine turns it into a ref.\n *\n * - `track`: 'release' (default) syncs to the latest release tag; 'branch' follows the tip.\n * - `branchRef`: `<DEFAULT_UPSTREAM_REMOTE>/<branch>`, the branch-track ref and static fallback.\n */\nexport function resolveUpstream(settings: SyncSettings): {\n track: 'release' | 'branch';\n branchRef: string;\n} {\n const track = settings.upstreamTrack ?? 'release';\n const branch = settings.upstreamBranch ?? DEFAULT_BRANCH;\n const branchRef = `${DEFAULT_UPSTREAM_REMOTE}/${branch}`;\n return { track, branchRef };\n}\n\n/**\n * Load cella/cella.config.ts from a fork/repo path.\n */\nexport async function loadConfig(forkPath: string): Promise<CellaCliConfig> {\n const configPath = join(forkPath, CONFIG_FILE);\n\n if (!existsSync(configPath)) {\n throw new Error(`config file not found: ${configPath}`);\n }\n\n // Resolve symlinks and validate path stays within fork directory\n const realConfigPath = realpathSync(configPath);\n const realForkPath = realpathSync(resolve(forkPath));\n if (!realConfigPath.startsWith(`${realForkPath}/`)) {\n throw new Error('config path resolves outside fork directory');\n }\n\n let configModule: { default?: unknown };\n try {\n configModule = await import(realConfigPath);\n } catch (error) {\n // Syntax/runtime errors while evaluating the config must fail closed: a config that\n // cannot be loaded means sync protections (ignored/pinned) are unknown.\n throw new Error(`failed to load ${configPath}: ${errorMessage(error)}`);\n }\n\n // Strict schema validation.\n const result = cellaConfigSchema.safeParse(configModule.default);\n if (!result.success) {\n throw new Error(`invalid ${configPath}:\\n${z.prettifyError(result.error)}`);\n }\n const config: CellaCliConfig = result.data;\n\n // Auto-derive fork-owned module folders (modules declaring `owner: 'app'`) and merge\n // them into ignored. This keeps app modules as fork territory: upstream never\n // adds/modifies/deletes them during sync, and the contributions service never offers\n // them back upstream. Derived entries always exist (they come from real files), so\n // config validation never warns about them.\n const appModuleFolders = resolveAppModuleFolders(realForkPath);\n if (appModuleFolders.length > 0) {\n const existing = config.overrides?.ignored ?? [];\n config.overrides = {\n ...config.overrides,\n ignored: [...new Set([...existing, ...appModuleFolders])],\n };\n }\n\n return config;\n}\n","/**\n * Configuration types: the public cella/cella.config.ts surface, its runtime\n * schema, and the internal types the services share.\n */\n\nimport { z } from 'zod';\n\n// Public API for cella/cella.config.ts.\n\nconst PACKAGE_JSON_SYNC_KEYS = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n 'scripts',\n 'engines',\n 'packageManager',\n 'overrides',\n 'exports',\n 'pnpm',\n] as const;\n\n/** Valid package.json keys that can be synced */\nexport type PackageJsonSyncKey = (typeof PACKAGE_JSON_SYNC_KEYS)[number];\n\n/**\n * Sync settings: all configurable options for the sync CLI.\n * Hover over each property for documentation.\n */\nexport interface SyncSettings {\n /** Upstream repository URL (e.g., 'git@github.com:cellajs/cella.git') */\n upstreamUrl: string;\n\n /**\n * Upstream branch, used for `upstreamTrack: 'branch'` and for GitHub file links.\n * Defaults to 'main'.\n */\n upstreamBranch?: string;\n\n /**\n * How to track upstream cella. Defaults to 'release'.\n * - 'release' (default): sync to a published cella release tag (`0.18.1`, with or without `v`). Stable and\n * reviewable: each bump maps to a changelog. Uses the latest release.\n * - 'branch': follow the bleeding-edge tip of `upstreamBranch`. For cella\n * maintainers and forks doing active development on top of unreleased changes.\n */\n upstreamTrack?: 'release' | 'branch';\n\n /**\n * Trunk branch that `pnpm cella sync` cuts the temporary branch from and that you open the\n * squash-merge PR into. Defaults to 'main'. Cutting fresh from trunk each cycle keeps every\n * PR limited to that cycle's upstream delta (no accumulation) and `main` linear.\n */\n releaseBase?: string;\n\n /** Which package.json keys to sync (default: ['dependencies', 'devDependencies']). `type` always syncs. */\n packageJsonSync?: PackageJsonSyncKey[];\n\n /** Automatic package.json sync after the sync service completes (default: true). Set to false to turn it off. */\n syncWithPackages?: boolean;\n\n /**\n * How to link files in CLI output.\n * - 'commit' (default): Link to the commit that changed the file on GitHub.\n * - 'file': Link to the file in the repo at the upstream branch on GitHub.\n */\n fileLinkMode?: 'commit' | 'file';\n}\n\n/**\n * Configuration for a downstream fork repository that cella interacts with.\n *\n * Cella is the upstream/source-of-truth. For each fork it can:\n * - pull contributions FROM the fork's `pullBranch` (contributions service)\n * - run the normal temporary-branch sync flow inside the fork (forks service)\n */\nexport interface ForkConfig {\n /** Display name for the fork (also used as the contrib/<name> branch slug) */\n name: string;\n /** Local path to the fork repository (relative to this config or absolute) */\n localPath: string;\n /**\n * Git remote URL of the fork (e.g. 'git@github.com:org/fork.git').\n * When set, the contributions service fetches the fork's `pullBranch` from this\n * remote (the authoritative committed ref), so the comparison does not depend on\n * the local checkout being up to date. The local clone is still used to read the\n * fork's owned-folder territory when available.\n */\n remoteUrl?: string;\n /** Fork branch that cella pulls contributions from (contributions service) */\n pullBranch: string;\n}\n\n/** User-configurable sync options for cella/cella.config.ts. */\nexport interface CellaCliConfig {\n /** Core sync settings */\n settings: SyncSettings;\n\n /**\n * File overrides for controlling sync behavior per folder/file.\n */\n overrides?: {\n /**\n * Paths the fork fully owns: never synced (existing or new).\n * Exact paths or directory prefixes, not globs: 'bench' matches 'bench/' and\n * everything under it, 'README.md' matches that exact file.\n * Local territory: upstream cannot add, modify, or delete anything under these.\n */\n ignored?: string[];\n\n /**\n * Paths pinned to the fork: the fork copy wins whole-file.\n * Exact paths or directory prefixes, not globs: 'bench' matches 'bench/' and\n * everything under it, 'README.md' matches that exact file.\n * Upstream changes to a pinned file are dropped, not merged: analyze lists them under\n * \"protected but behind upstream\" to adopt by hand.\n * If fork deleted a pinned file, deletion is respected.\n */\n pinned?: string[];\n };\n\n /**\n * Downstream fork repositories that cella interacts with (for upstream template repos).\n * When configured, the 'forks' and 'contributions' services appear in the CLI menu.\n */\n forks?: ForkConfig[];\n}\n\n/**\n * Helper function for defining cella/cella.config.ts with type checking.\n */\nexport function defineConfig(config: CellaCliConfig): CellaCliConfig {\n return config;\n}\n\n/**\n * Strict runtime schema mirroring {@link CellaCliConfig}.\n *\n * The TS interfaces above stay the source of truth (and keep their hover docs for\n * config authors). This schema is what's enforced at load time: `.strict()` rejects\n * unknown keys, so a typo like `ignoredFolders` for `ignored` fails closed; a silent\n * fallback would drop sync protection (tsx does not typecheck the config).\n *\n * The `satisfies z.ZodType<CellaCliConfig>` assertion keeps schema and interface in\n * lockstep: if either drifts (a renamed/removed/mis-typed field), TypeScript errors here.\n */\nexport const cellaConfigSchema = z\n .object({\n settings: z\n .object({\n upstreamUrl: z.string().min(1),\n upstreamBranch: z.string().min(1).optional(),\n upstreamTrack: z.enum(['release', 'branch']).optional(),\n releaseBase: z.string().min(1).optional(),\n packageJsonSync: z.array(z.enum(PACKAGE_JSON_SYNC_KEYS)).optional(),\n syncWithPackages: z.boolean().optional(),\n fileLinkMode: z.enum(['commit', 'file']).optional(),\n })\n .strict(),\n overrides: z\n .object({\n ignored: z.array(z.string()).optional(),\n pinned: z.array(z.string()).optional(),\n })\n .strict()\n .optional(),\n forks: z\n .array(\n z\n .object({\n name: z.string().min(1),\n localPath: z.string().min(1),\n remoteUrl: z.string().optional(),\n pullBranch: z.string().min(1),\n })\n .strict(),\n )\n .optional(),\n })\n .strict() satisfies z.ZodType<CellaCliConfig>;\n\n// Internal types for the services.\n\n/** Sync services available in the CLI */\nexport type SyncService = 'analyze' | 'sync' | 'migrate' | 'audit' | 'forks' | 'contributions' | 'stats';\n\n/** Analyze output scope for interactive and machine-readable flows */\nexport type AnalyzeScope = 'all' | 'risk' | 'protected';\n\n/** Runtime configuration with all resolved values */\nexport interface RuntimeConfig extends CellaCliConfig {\n /** Resolved fork repository path */\n forkPath: string;\n\n /** Full upstream remote ref (e.g., 'cella-upstream/development') */\n upstreamRef: string;\n\n /** Selected sync service */\n service: SyncService;\n\n /** Non-interactive list output (for LLM/agent usage) */\n list: boolean;\n\n /** Machine-readable JSON output (for tooling/agent usage) */\n json: boolean;\n\n /** Scope of files returned in analyze list/json output */\n scope?: AnalyzeScope;\n\n /** Show verbose output */\n verbose: boolean;\n\n /** Pre-selected fork name (skips fork selection prompt) */\n fork?: string;\n\n /**\n * Override upstream tracking for this run (analyze/sync), ignoring `settings.upstreamTrack`.\n * 'branch' follows the upstream branch tip (bleeding edge); 'release' uses a release tag.\n */\n track?: 'release' | 'branch';\n\n /**\n * Pin the upstream ref for this run (analyze/sync), overriding `track`: a commit sha, a release\n * tag or an upstream branch name. Must be on the upstream branch or in an upstream release.\n */\n ref?: string;\n\n /**\n * Merge with the fork's sync config as it stands (sync service). Without it, a new merge stops\n * before anything changes when upstream changed its own `overrides` or `packageJsonSync` in ways\n * the fork config does not follow.\n */\n keepConfig?: boolean;\n\n /**\n * Lift every pinned entry for this run (analyze, sync): managed files stay pinned, and the merge\n * uses the full upstream history, so upstream changes that earlier syncs dropped come back too.\n */\n unpinned?: boolean;\n\n /** Count what the current branch changed since it left this ref, by kind of file (stats service) */\n since?: string;\n\n /** Print the `since` table as markdown for a pull request description (stats service) */\n md?: boolean;\n\n /** List every upstream migration note, not only the open ones (migrate service) */\n all?: boolean;\n\n /** Print one migration note's README (migrate service) */\n show?: string;\n\n /** Write one migration note's folder where its codemod can run (migrate service) */\n extract?: string;\n\n /** Run one migration note's codemod, keeping files identical to upstream as they are (migrate service) */\n run?: string;\n\n /** Arguments after `--`, passed to the codemod as given (migrate service, with `run`) */\n runArgs?: string[];\n\n /** Migration note ids to record as handled (migrate service) */\n mark?: string[];\n}\n\n/** File status after analysis */\nexport type FileStatus =\n | 'identical' // No changes needed\n | 'ahead' // Fork is ahead, protected (pinned/ignored)\n | 'local' // Local file (never existed upstream)\n | 'drifted' // Fork is ahead, NOT protected (at risk)\n | 'behind' // Upstream has changes to sync\n | 'diverged' // Both changed, will merge\n | 'pinned' // Fork wins on conflict\n | 'ignored' // Excluded from sync entirely\n | 'deleted' // Fork deleted, will stay deleted\n | 'renamed'; // Upstream renamed file\n\n/** Statuses the sync applies changes for: a staged sync holds at least one file with one of these. */\nexport const SYNC_APPLIED_STATUSES: readonly FileStatus[] = ['behind', 'diverged', 'renamed', 'ignored', 'pinned'];\n\n/** Commit metadata for a single log entry */\nexport interface CommitRangeEntry {\n hash: string;\n message: string;\n date: string;\n}\n\n/** Analyzed file with status and metadata */\nexport interface AnalyzedFile {\n path: string;\n status: FileStatus;\n /** True if file is in ignored list */\n isIgnored: boolean;\n /** True if file is in pinned list */\n isPinned: boolean;\n /** True if file exists in fork */\n existsInFork: boolean;\n /** True if file exists in upstream */\n existsInUpstream: boolean;\n /** Relative date when file was last changed (since merge-base) */\n changedAt?: string;\n /** Unix epoch seconds of the last change, for sorting */\n changedTs?: number;\n /** Short commit hash of the last change */\n changedCommit?: string;\n /** For diverged files: relative date of upstream change */\n upstreamChangedAt?: string;\n /** For diverged files: Unix epoch seconds of the upstream change, for sorting */\n upstreamChangedTs?: number;\n /** For diverged files: short commit hash of the upstream change */\n upstreamCommit?: string;\n /** For renamed files: the original path before rename */\n renamedFrom?: string;\n /**\n * Protected (pinned/ignored) files only: both sides changed since the merge-base. The fork\n * side wins whole-file, so upstream's changes to this path are dropped by the sync.\n */\n upstreamChanged?: boolean;\n /** For `upstreamChanged` files: lines upstream changed since the merge-base (undefined for binary) */\n upstreamChangedLines?: number;\n /**\n * Ignored files only: upstream changed, added or deleted the file since the merge-base and the\n * fork did not touch it. Ignored paths never sync, so without this flag the change stays unseen\n * (new config keys, version bumps). Managed files and generated output (`isGeneratedFile`) are\n * never flagged.\n */\n upstreamOnly?: boolean;\n /**\n * Pinned `ahead` files only: lines present upstream but absent from the fork (undefined for\n * binary). Independent of the sync point, so it also shows upstream content dropped by an\n * earlier sync, or removed on purpose; only a diff can tell.\n */\n upstreamLinesAbsent?: number;\n}\n\n/** Summary counts by status */\nexport interface AnalysisSummary {\n /** Changed package/config files that are handled separately from normal sync categories */\n managed: number;\n identical: number;\n ahead: number;\n local: number;\n drifted: number;\n behind: number;\n diverged: number;\n pinned: number;\n ignored: number;\n deleted: number;\n renamed: number;\n}\n\n/** Merge result from merge-engine */\nexport interface MergeResult {\n success: boolean;\n /** Upstream branch name for file links */\n upstreamBranch?: string;\n /** Resolved concrete upstream ref that was merged (branch ref or release tag ref) */\n upstreamRef?: string;\n /** Upstream release tag synced (when tracking releases) */\n upstreamTag?: string;\n files: AnalyzedFile[];\n summary: AnalysisSummary;\n conflicts: string[];\n /** Upstream GitHub URL base for commit links */\n upstreamGitHubUrl?: string;\n /** Upstream commit info */\n upstreamCommit?: CommitRangeEntry;\n /** Files that were auto-merged by git (diverged without remaining conflicts) */\n autoMergedFiles?: string[];\n /**\n * Protected (pinned/ignored) files resolved to the fork side although upstream also changed\n * them: upstream's hunks were dropped, not merged. Review each against upstream.\n */\n protectedConflicts?: string[];\n /** `protectedConflicts` grouped by the `pinned` or `ignored` entry they fall under, for one diff hint per entry. */\n protectedUpstreamChanges?: ProtectedUpstreamGroup[];\n /** Pasteable `<merge-base>..<upstream>` range of short SHAs, for `git diff` hints. */\n upstreamDiffRange?: string;\n /** How upstream's own sync config changed since the merge-base, where the fork config does not follow. */\n upstreamOverrides?: UpstreamOverridesReport;\n /** Files flagged `upstreamOnly`, grouped by the `ignored` entry they fall under (config order). */\n ignoredUpstreamChanges?: IgnoredUpstreamGroup[];\n /**\n * Upstream migration notes: how many the incoming ref holds, which ones upstream added since the\n * sync point, and how many stay open in the fork once those are added.\n */\n migrationNotes?: { total: number; arrived: string[]; open: number };\n}\n\n/** Entries of one sync config list (`pinned`, `ignored` or `packageJsonSync`) that the fork config does not mirror. */\nexport interface OverrideListChanges {\n /** Entries upstream added since the merge-base that the fork list lacks. */\n added: string[];\n /** Entries upstream removed since the merge-base that the fork list still carries. */\n removed: string[];\n}\n\n/**\n * Upstream sync config changes the fork should review. The sync config is managed (never merged),\n * so new upstream `pinned`/`ignored` entries and `packageJsonSync` keys only reach the fork by\n * hand. `unreadable` means upstream's config was missing or unparsable at one side (`base` =\n * merge-base, `incoming` = upstream ref), so nothing was compared.\n */\nexport type UpstreamOverridesReport =\n | {\n kind: 'changes';\n pinned: OverrideListChanges;\n ignored: OverrideListChanges;\n packageJsonSync: OverrideListChanges;\n }\n | { kind: 'unreadable'; side: 'base' | 'incoming' };\n\n/** Protected paths upstream also changed, under one `pinned` or `ignored` entry. */\nexport interface ProtectedUpstreamGroup {\n /** The `pinned` or `ignored` entry the paths fall under; the path itself when no entry covers it (a managed file). */\n entry: string;\n /** Paths under the entry, sorted. */\n paths: string[];\n}\n\n/** Upstream-only changes under one `ignored` entry. */\nexport interface IgnoredUpstreamGroup {\n /** The `ignored` entry (configured or derived from an app-owned module) the files fall under. */\n entry: string;\n /** Changed paths under the entry, sorted. */\n paths: string[];\n /** Paths the fork lacks (new upstream files). */\n added: number;\n /** Paths upstream deleted (the fork keeps them). */\n deleted: number;\n}\n","/**\n * Error helpers for sync CLI.\n */\n\n/** The message of an unknown thrown value: an Error's message, anything else via String(). */\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","/**\n * Files that cella manages outside the normal file sync categories.\n */\n\n/** Sync config path, relative to the fork repo root. Fork-owned, never synced from upstream. */\nexport const CONFIG_FILE = 'cella/cella.config.ts';\n\n/** Whether a path is a package.json file. */\nexport function isPackageJson(filePath: string): boolean {\n return filePath === 'package.json' || filePath.endsWith('/package.json');\n}\n\n/**\n * Check if a file path is generated output a fork regenerates itself: a `gen` path segment\n * (`sdk/gen/...`) or a `.gen.` file name (`routeTree.gen.ts`, `compose.gen.yml`). Upstream's\n * copy is never adopted, so upstream changes to it are not worth reporting.\n */\nexport function isGeneratedFile(filePath: string): boolean {\n const segments = filePath.split('/');\n return segments.includes('gen') || (segments.at(-1) ?? '').includes('.gen.');\n}\n\n/** Whether cella manages a path outside the normal sync categories: package.json files, the lockfile, the sync config. */\nexport function isManagedFile(filePath: string): boolean {\n return isPackageJson(filePath) || filePath === 'pnpm-lock.yaml' || filePath === CONFIG_FILE;\n}\n","/**\n * Static analysis of module ownership. A module with `owner: 'app'` in its `registerModule`,\n * `defineBackendModule` or `defineFrontendModule` call is fork territory: its source folder, plus\n * a matching frontend static asset folder, never syncs and is never offered back upstream.\n * Parsing is syntax-only (ts-morph, no type-checker).\n */\n\nimport { existsSync } from 'node:fs';\nimport { basename, join, relative, sep } from 'node:path';\nimport { Project, SyntaxKind } from 'ts-morph';\n\n/** Glob patterns (relative to repo root) for module definition files. */\nconst MODULE_FILE_GLOBS = [\n 'backend/src/modules/*/*-module.ts',\n 'frontend/src/modules/*/*-module.ts',\n 'frontend/src/modules/*/*-module.tsx',\n];\n\n/** Call names that register a module and carry its `owner` in the first argument. */\nconst MODULE_REGISTER_CALLS = new Set(['registerModule', 'defineBackendModule', 'defineFrontendModule']);\nconst FRONTEND_STATIC_ROOT = 'frontend/public/static';\n\n/** Read the string value of an object literal's `owner` property, if present. */\nfunction readOwner(call: import('ts-morph').CallExpression): string | undefined {\n const arg = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);\n const initializer = arg?.getProperty('owner')?.asKind(SyntaxKind.PropertyAssignment)?.getInitializer();\n return initializer?.asKind(SyntaxKind.StringLiteral)?.getLiteralValue();\n}\n\n/**\n * Scan a repository for module territory owned by the app (`owner: 'app'`).\n *\n * @param repoPath - Absolute path to the repository root to scan.\n * @returns Repo-relative folder paths (POSIX separators), deduplicated.\n */\nexport function resolveAppModuleFolders(repoPath: string): string[] {\n const project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipFileDependencyResolution: true,\n skipLoadingLibFiles: true,\n });\n\n const sourceFiles = project.addSourceFilesAtPaths(MODULE_FILE_GLOBS.map((glob) => `${repoPath}/${glob}`));\n\n const folders = new Set<string>();\n const moduleNames = new Set<string>();\n\n for (const sourceFile of sourceFiles) {\n const ownsApp = sourceFile\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .some((call) => MODULE_REGISTER_CALLS.has(call.getExpression().getText()) && readOwner(call) === 'app');\n\n if (!ownsApp) continue;\n\n const folder = relative(repoPath, sourceFile.getDirectoryPath()).split(sep).join('/');\n folders.add(folder);\n moduleNames.add(basename(folder));\n }\n\n for (const moduleName of moduleNames) {\n const staticFolder = `${FRONTEND_STATIC_ROOT}/${moduleName}`;\n if (existsSync(join(repoPath, staticFolder))) {\n folders.add(staticFolder);\n }\n }\n\n return [...folders];\n}\n","/**\n * Display utilities: console output formatting, spinners, hyperlinks, and the\n * report blocks analyze and sync print.\n */\n\nimport { resolve } from 'node:path';\nimport process from 'node:process';\nimport packageJson from '../../package.json' with { type: 'json' };\nimport type { AnalysisSummary, AnalyzedFile, CommitRangeEntry, FileStatus, MergeResult } from '../config/types';\nimport pc from './colors';\nimport { getEnv } from './env';\nimport { CONFIG_FILE, isManagedFile } from './managed-files';\n\n/** Version from package.json */\nexport const VERSION = packageJson.version;\n\n/** Options for generating links in CLI output */\nexport interface LinkOptions {\n /** Base GitHub URL for upstream (e.g., 'https://github.com/cellajs/cella') */\n upstreamGitHubUrl?: string;\n /** Upstream branch name for file links */\n upstreamBranch?: string;\n /** File link mode: 'commit' links to commit, 'file' links to file in repo */\n fileLinkMode?: 'commit' | 'file';\n /** Fork repository path for resolving file paths */\n forkPath?: string;\n}\n\n/** Line divider */\nexport const DIVIDER = '─'.repeat(60);\n\n/** Divider used above the exit entry of interactive menus */\nexport const MENU_DIVIDER = '─'.repeat(40);\n\n/** Most recent upstream commits shown per commit list (fetch detail, PR body) */\nexport const COMMIT_LIST_MAX = 50;\n\n/** Warning mark for non-fatal warnings */\nexport const warningMark = pc.yellow('⚠');\n\n/** Check mark for successful status lines */\nexport const checkMark = pc.green('✓');\n\n/** A progress line: `text` is read on every frame, `stop()` clears the line. */\ntype Spinner = { text: string; stop(): void };\n\n/** Active spinner reference */\nlet activeSpinner: Spinner | null = null;\n\n/**\n * When true, stdout is reserved for machine-readable payloads (e.g. `--json`),\n * so all human-facing output (header, warnings, steps, spinner) is routed to stderr.\n */\nlet jsonMode = false;\n\n/**\n * Enable JSON mode: keep stdout clean for the JSON payload by sending every\n * human-facing line (console.info/console.warn, header, spinner) to stderr.\n * This makes `cella --json ... | jq` pipe cleanly.\n */\nexport function setJsonMode(enabled: boolean): void {\n jsonMode = enabled;\n if (!enabled) return;\n const toStderr = (...args: unknown[]) => {\n process.stderr.write(`${args.map((a) => (typeof a === 'string' ? a : String(a))).join(' ')}\\n`);\n };\n console.info = toStderr;\n console.warn = toStderr;\n}\n\n/** Write a machine-readable payload to stdout (bypasses the stderr routing of JSON mode). */\nexport function writeStdout(text: string): void {\n process.stdout.write(text.endsWith('\\n') ? text : `${text}\\n`);\n}\n\nexport function printHeader(): void {\n const left = '⧈ cella cli';\n const right = 'cellajs.com';\n // Padding counts the visible characters only, not the ANSI codes\n const padding = Math.max(1, 60 - `${left} v${VERSION}`.length - right.length);\n console.info();\n console.info(`${pc.cyan(left)}${pc.dim(` · v${VERSION}`)}${pc.cyan(`${' '.repeat(padding)}${right}`)}`);\n console.info(DIVIDER);\n console.info();\n}\n\n/** Start a progress spinner; suppressed in test environments and JSON mode. */\nexport function createSpinner(text: string): Spinner {\n const enabled = !jsonMode && !getEnv('VITEST') && getEnv('NODE_ENV') !== 'test' && !!process.stdout.isTTY;\n const frames = ['-', '\\\\', '|', '/'];\n let frame = 0;\n let timer: ReturnType<typeof setInterval> | undefined;\n const spinner: Spinner = {\n text,\n stop() {\n clearInterval(timer);\n if (enabled) process.stdout.write('\\r\\x1b[2K');\n },\n };\n const render = () => process.stdout.write(`\\r${pc.cyan(frames[frame++ % frames.length])} ${spinner.text}`);\n if (enabled) {\n render();\n timer = setInterval(render, 80);\n }\n activeSpinner = spinner;\n return spinner;\n}\n\n/** Stop the spinner and print `message` as a completed step; `detail` adds a dim line and a blank line. */\nexport function spinnerSuccess(message?: string, detail?: string): void {\n stopSpinner();\n if (!message) return;\n console.info(`${checkMark} ${message}`);\n if (detail) {\n console.info(` ${pc.dim(detail)}`);\n console.info();\n }\n}\n\nexport function spinnerFail(message: string): void {\n stopSpinner();\n console.info(`${pc.red('✗')} ${message}`);\n}\n\nexport function spinnerText(text: string): void {\n if (activeSpinner) {\n activeSpinner.text = text;\n }\n}\n\nfunction stopSpinner(): void {\n if (activeSpinner) {\n activeSpinner.stop();\n activeSpinner = null;\n }\n}\n\n/**\n * Create a clickable hyperlink for terminals that support OSC 8.\n * Falls back to just the label if no URL provided.\n */\nexport function hyperlink(label: string, url?: string): string {\n if (!url) return label;\n // Strip control characters from URL to prevent terminal escape injection (CWE-116)\n // biome-ignore lint/suspicious/noControlCharactersInRegex: stripping control chars is the security purpose here.\n const safeUrl = url.replace(/[\\x00-\\x1f\\x7f]/g, '');\n // OSC 8 hyperlink format: \\x1b]8;;URL\\x07LABEL\\x1b]8;;\\x07\n return `\\x1b]8;;${safeUrl}\\x07${label}\\x1b]8;;\\x07`;\n}\n\n/** The fetched-upstream detail block, with clickable short commit hashes. */\nexport function formatFetchedUpstreamDetail(\n commitCount: number,\n commits: CommitRangeEntry[],\n upstreamGitHubUrl?: string,\n maxShownCommits = COMMIT_LIST_MAX,\n): string {\n const lines = [`${plural(commitCount, 'new commit')} since last merge`];\n\n const shown = commits.slice(0, maxShownCommits);\n for (const commit of shown) {\n const shortHash = commit.hash.slice(0, 7);\n const commitUrl = upstreamGitHubUrl ? `${upstreamGitHubUrl}/commit/${commit.hash}` : undefined;\n const hashLabel = hyperlink(shortHash, commitUrl);\n lines.push(` ${hashLabel} \"${commit.message}\" (${commit.date})`);\n }\n\n if (commitCount > shown.length) {\n lines.push(` ... and ${commitCount - shown.length} more`);\n }\n\n return lines.join('\\n');\n}\n\nfunction printSectionHeader(title: string): void {\n console.info();\n console.info(title);\n console.info(DIVIDER);\n console.info();\n}\n\n/**\n * The dim ` ≠ <date> <link>` tail of a file line, per fileLinkMode: the file at the upstream branch,\n * or the commit (a plain short hash without a GitHub URL). Empty without a date.\n */\nfunction formatFileDateInfo(\n filePath: string,\n commit: string | undefined,\n date: string | undefined,\n options: LinkOptions,\n): string {\n if (!date) return '';\n const { upstreamGitHubUrl: url, upstreamBranch, fileLinkMode = 'commit' } = options;\n let link = commit?.slice(0, 9) ?? '';\n if (url && fileLinkMode === 'file' && upstreamBranch) {\n link = hyperlink(filePath.split('/').pop() || filePath, `${url}/blob/${upstreamBranch}/${filePath}`);\n } else if (url) {\n link = commit ? hyperlink(link, `${url}/commit/${commit}`) : '';\n }\n return pc.dim(` ≠ ${date} ${link}`);\n}\n\nexport function formatMergeInProgressDetail(\n conflictCount: number,\n autoMergedFiles: string[],\n linkOptions: LinkOptions,\n maxFiles = 100,\n): string {\n const lines = [`${conflictCount} conflicts to resolve in IDE`];\n\n if (autoMergedFiles.length === 0) {\n return lines.join('\\n');\n }\n\n lines.push('');\n lines.push(` auto-merged files (${autoMergedFiles.length}):`);\n\n // Each file opens in VS Code from the fork workspace when the fork path is known\n const { forkPath } = linkOptions;\n const shown = autoMergedFiles.slice(0, maxFiles);\n for (const filePath of shown) {\n lines.push(` - ${forkPath ? hyperlink(filePath, `vscode://file${resolve(forkPath, filePath)}`) : filePath}`);\n }\n\n if (autoMergedFiles.length > shown.length) {\n lines.push(` ... + ${autoMergedFiles.length - shown.length} more`);\n }\n\n return lines.join('\\n');\n}\n\n/** Display configuration for a file status */\ninterface StatusConfig {\n icon: string;\n label: string;\n color: (text: string) => string;\n description?: string;\n}\n\ntype SummaryStatus = FileStatus | 'managed';\n\n/** Unified status display config: icon, label, color, and description for each status. */\nconst statusConfig: Record<FileStatus, StatusConfig> = {\n behind: { icon: pc.cyan('↓'), label: 'behind', color: pc.cyan, description: 'upstream changed, will sync' },\n diverged: { icon: pc.magenta('⇅'), label: 'diverged', color: pc.magenta, description: 'both changed, will merge' },\n drifted: { icon: pc.yellow('!'), label: 'drifted', color: pc.yellow, description: 'fork changed (at risk)' },\n ahead: { icon: pc.blue('↑'), label: 'ahead', color: pc.blue, description: 'fork changed (protected)' },\n local: { icon: pc.green('+'), label: 'local', color: pc.green, description: 'local file in cella folders' },\n pinned: { icon: pc.green('⨀'), label: 'pinned', color: pc.green, description: 'both changed, fork wins' },\n ignored: { icon: pc.gray('⨂'), label: 'ignored', color: pc.gray },\n identical: { icon: pc.gray('✓'), label: 'identical', color: pc.gray, description: 'no changes' },\n deleted: { icon: pc.red('✗'), label: 'deleted', color: pc.red },\n renamed: { icon: pc.blue('→'), label: 'renamed', color: pc.blue },\n};\n\nconst summaryStatusConfig: Record<SummaryStatus, StatusConfig> = {\n ...statusConfig,\n managed: {\n icon: pc.cyan('◇'),\n label: 'managed',\n color: pc.cyan,\n description: 'package.jsons & cella/cella.config.ts handled separately',\n },\n ignored: { ...statusConfig.ignored, description: 'protected by ignored config' },\n};\n\nfunction printSummary(summary: AnalysisSummary, title = 'summary'): void {\n printSectionHeader(pc.cyan(title));\n\n const maxCount = Math.max(...Object.values(summary));\n const countWidth = String(maxCount).length + 1;\n\n // Grouped layout with blank lines between groups\n const groups: SummaryStatus[][] = [\n ['managed', 'ignored'],\n ['identical'],\n ['ahead', 'local', 'drifted'],\n ['diverged', 'pinned'],\n ['behind'],\n ];\n for (const group of groups) {\n if (group !== groups[0]) console.info();\n for (const status of group) {\n const { icon, label, color, description } = summaryStatusConfig[status];\n const countStr = color(String(summary[status]).padStart(countWidth));\n console.info(` ${icon} ${countStr} ${label.padEnd(15)}${description ? pc.dim(description) : ''}`);\n }\n }\n}\n\n/** Options shared by the file-list section printers. */\ninterface FileSectionOptions {\n /** Override section header title */\n title?: string;\n /** Footer hint text (dimmed), one line per entry */\n hint?: string | string[];\n /** Which commit/date fields to use: 'fork' or 'upstream' */\n dateSource?: 'fork' | 'upstream';\n /** Per-file detail appended after the date/link info */\n suffix?: (file: AnalyzedFile) => string;\n}\n\n/**\n * Print a list of files as a section: header, one line per file (capped), optional hint.\n * `icon` may vary per file (e.g. pinned vs ignored) and `suffix` appends per-file detail.\n */\nfunction printFileSection(\n files: AnalyzedFile[],\n title: string,\n linkOptions: LinkOptions,\n options: FileSectionOptions & { icon: string | ((file: AnalyzedFile) => string) },\n): void {\n if (files.length === 0) return;\n\n printSectionHeader(`${title} ${pc.dim(`· ${files.length} files`)}`);\n\n const useUpstream = options.dateSource === 'upstream';\n const maxLines = 100;\n const shown = files.length > maxLines ? files.slice(0, maxLines) : files;\n\n for (const file of shown) {\n const icon = typeof options.icon === 'string' ? options.icon : options.icon(file);\n const commit = useUpstream ? file.upstreamCommit : file.changedCommit;\n const date = useUpstream ? file.upstreamChangedAt : file.changedAt;\n const dateInfo = formatFileDateInfo(file.path, commit, date, linkOptions);\n console.info(` ${icon} ${file.path}${dateInfo}${options.suffix?.(file) ?? ''}`);\n }\n\n if (files.length > maxLines) {\n console.info(pc.dim(` ... + ${files.length - maxLines} more`));\n }\n\n if (options.hint) {\n console.info();\n for (const line of Array.isArray(options.hint) ? options.hint : [options.hint]) {\n console.info(pc.dim(` ${line}`));\n }\n }\n}\n\n/**\n * Print a group of files with a specific status, including section header and footer.\n */\nfunction printFileGroup(\n files: AnalyzedFile[],\n status: FileStatus,\n linkOptions: LinkOptions,\n options?: FileSectionOptions,\n): void {\n const filtered = files.filter((f) => f.status === status && !isManagedFile(f.path));\n const config = statusConfig[status];\n const title = options?.title ?? `${config.icon} ${config.label}`;\n printFileSection(filtered, title, linkOptions, { ...options, icon: config.icon });\n}\n\n/**\n * Protected (pinned/ignored) files that upstream also changed since the last sync. The fork\n * side wins whole-file on these, so upstream's hunks are dropped: the regression class where\n * a pinned stylesheet misses new upstream utilities that synced components rely on.\n */\nexport function findProtectedBehind(files: AnalyzedFile[]): AnalyzedFile[] {\n return files.filter((file) => file.upstreamChanged && !isManagedFile(file.path));\n}\n\n/** Shared hint for protected-but-behind output (analyze section and sync summary). */\nconst PROTECTED_BEHIND_HINT =\n 'pinned/ignored files where upstream also changed since the last sync; the fork side wins on conflict, ' +\n 'so diff each against upstream and adopt what you need.';\n\n/** Icon by protection kind (⨂ ignored, ⨀ pinned) for protected-but-behind lines. */\nfunction protectionIcon(file: AnalyzedFile): string {\n return file.isIgnored ? statusConfig.ignored.icon : statusConfig.pinned.icon;\n}\n\n/** Per-file detail: how many lines upstream changed (dropped by the fork-wins resolution). */\nfunction formatUpstreamChangedLines(file: AnalyzedFile): string {\n if (file.upstreamChangedLines === undefined) return '';\n return pc.yellow(` · ${plural(file.upstreamChangedLines, 'line')} changed upstream`);\n}\n\n/** What a protected-but-behind list needs for its `git diff` hints. */\ntype ProtectedDiffSource = Pick<MergeResult, 'upstreamDiffRange' | 'protectedUpstreamChanges'>;\n\n/**\n * Pasteable `git diff` lines for a protected-but-behind list: one per `pinned` or `ignored` entry\n * that holds a listed path, under a line that introduces them. The range runs from the last sync\n * point to upstream, so each shows only what upstream changed; a diff of the fork against upstream\n * would show the fork's own changes too. Empty without a range or a matching entry.\n */\nfunction protectedDiffHints(source: ProtectedDiffSource | undefined, paths: string[]): string[] {\n const range = source?.upstreamDiffRange;\n if (!range) return [];\n const listed = new Set(paths);\n const groups = (source?.protectedUpstreamChanges ?? []).filter((group) => group.paths.some((p) => listed.has(p)));\n if (groups.length === 0) return [];\n return [\n 'what upstream changed since the last sync, per pinned/ignored entry:',\n ...groups.map((group) => ` git diff ${range} -- ${shellPath(group.entry)}`),\n ];\n}\n\n/** Per-file detail for pinned `ahead` files: upstream lines the fork lacks (only when > 0). */\nfunction formatUpstreamLinesAbsent(file: AnalyzedFile): string {\n const n = file.upstreamLinesAbsent ?? 0;\n return n > 0 ? pc.yellow(` · ${plural(n, 'upstream line')} absent`) : '';\n}\n\n/**\n * Print all analyze-mode file group sections in review order:\n * behind, ahead (protected), protected-but-behind, drifted, and diverged.\n *\n * Protected-but-behind covers every `pinned`-status file (both changed, fork wins) plus\n * ignored files upstream also changed, so there is no separate `pinned` group. With `diffSource`\n * (the merge result) it ends with one `git diff` line per pinned/ignored entry.\n */\nexport function printAnalysisFileGroups(\n files: AnalyzedFile[],\n linkOptions: LinkOptions,\n diffSource?: ProtectedDiffSource,\n): void {\n const protectedBehind = findProtectedBehind(files);\n printFileGroup(files, 'behind', linkOptions, {\n title: pc.cyan('↓ behind on upstream'),\n });\n printFileGroup(files, 'ahead', linkOptions, {\n title: `${pc.blue('↑ protected in fork')}`,\n suffix: formatUpstreamLinesAbsent,\n hint: [\n 'these files have fork changes but are protected (pinned); upstream did not change them since the last sync.',\n 'pinned files keep the fork copy whole; a count here is upstream content the fork never received, ' +\n 'deliberately or not: `analyze --unpinned` shows what a merge would bring in.',\n ],\n });\n printFileSection(protectedBehind, `${warningMark} ${pc.yellow('protected but behind upstream')}`, linkOptions, {\n icon: protectionIcon,\n suffix: formatUpstreamChangedLines,\n dateSource: 'upstream',\n hint: [\n PROTECTED_BEHIND_HINT,\n ...protectedDiffHints(\n diffSource,\n protectedBehind.map((file) => file.path),\n ),\n ],\n });\n printFileGroup(files, 'drifted', linkOptions, {\n title: `${warningMark} ${pc.yellow('drifted from upstream')}`,\n hint: 'these files have fork changes but are not pinned or ignored.',\n });\n printFileGroup(files, 'diverged', linkOptions, {\n title: `${pc.magenta('⇅ diverged')}`,\n hint: 'both fork and upstream changed.',\n dateSource: 'upstream',\n });\n}\n\nexport function printSyncComplete(result: MergeResult, options: { stagedBranch?: string } = {}): void {\n const updated = result.files.filter((file) => file.status === 'behind' || file.status === 'diverged').length;\n const diverged = result.files.filter((file) => file.status === 'diverged').length;\n const merged = result.autoMergedFiles?.length ?? Math.max(0, diverged - result.conflicts.length);\n const conflicts = result.conflicts.length;\n\n console.info();\n if (options.stagedBranch) {\n console.info(`${checkMark} sync merge staged on '${options.stagedBranch}'`);\n console.info(\n pc.dim(` ${updated} files updated, ${merged} auto-merged, ${conflicts} conflicts. committing next...`),\n );\n } else {\n console.info(`${checkMark} sync complete`);\n console.info(pc.dim(` ${updated} files updated, ${merged} auto-merged, ${conflicts} conflicts`));\n }\n\n printProtectedConflicts(result);\n console.info();\n}\n\n/**\n * List protected files the sync resolved to the fork side although upstream changed them\n * (`MergeResult.protectedConflicts`). Printed right when the drop happens so it is not\n * discovered weeks later as a styling or behavior regression. Silent when empty.\n */\nfunction printProtectedConflicts(result: MergeResult): void {\n const paths = result.protectedConflicts ?? [];\n if (paths.length === 0) return;\n\n const byPath = new Map(result.files.map((file) => [file.path, file]));\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(\n `${plural(paths.length, 'protected file kept', 'protected files kept')} the fork version, dropping upstream changes:`,\n )}`,\n );\n for (const path of paths) {\n const file = byPath.get(path);\n const icon = file ? protectionIcon(file) : statusConfig.pinned.icon;\n console.info(` ${icon} ${path}${file ? formatUpstreamChangedLines(file) : ''}`);\n }\n for (const line of [PROTECTED_BEHIND_HINT, ...protectedDiffHints(result, paths)]) console.info(pc.dim(` ${line}`));\n}\n\n/** `1 file`, `2 files`: a count with its noun. */\nexport function plural(count: number, singular: string, pluralForm = `${singular}s`): string {\n return `${count} ${count === 1 ? singular : pluralForm}`;\n}\n\n/** Quote a path for a pasteable shell command when it holds characters the shell would interpret. */\nfunction shellPath(path: string): string {\n return /^[\\w./@+-]+$/.test(path) ? path : `'${path.replace(/'/g, `'\\\\''`)}'`;\n}\n\n/**\n * Ignored paths upstream changed since the last sync while the fork left them untouched\n * (`MergeResult.ignoredUpstreamChanges`). Ignored paths never sync, so this is where new config\n * keys or version bumps under e.g. `shared/config` surface. One line per `ignored` entry with a\n * file count, plus a pasteable `git diff` of upstream's side. Silent when empty.\n */\nexport function printIgnoredUpstreamChanges(result: MergeResult): void {\n const groups = result.ignoredUpstreamChanges ?? [];\n if (groups.length === 0) return;\n\n const total = groups.reduce((count, group) => count + group.paths.length, 0);\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(`ignored paths changed upstream · ${plural(total, 'file')} under ${plural(groups.length, 'entry', 'entries')}`)}`,\n );\n for (const group of groups) {\n const counts = [plural(group.paths.length, 'file')];\n if (group.added > 0) counts.push(`${group.added} new`);\n if (group.deleted > 0) counts.push(`${group.deleted} deleted`);\n console.info(` ${statusConfig.ignored.icon} ${group.entry} ${pc.dim(`· ${counts.join(', ')}`)}`);\n if (result.upstreamDiffRange) {\n console.info(pc.dim(` git diff ${result.upstreamDiffRange} -- ${shellPath(group.entry)}`));\n }\n }\n console.info(pc.dim(' the fork left these untouched and ignored paths never sync: diff and adopt what you need.'));\n}\n\n/**\n * Upstream sync config entries the fork config does not follow (`MergeResult.upstreamOverrides`):\n * `overrides` entries and `packageJsonSync` keys upstream added that the fork lacks, and ones\n * upstream dropped that the fork still has. The sync config is managed and never merges, so these\n * only reach the fork by hand. Silent when there is nothing to report; one dim line when upstream's\n * config was unreadable.\n */\nexport function printUpstreamOverrideChanges(result: Pick<MergeResult, 'upstreamOverrides'>): void {\n const report = result.upstreamOverrides;\n if (!report) return;\n\n console.info();\n if (report.kind === 'unreadable') {\n const side = report.side === 'base' ? 'the last sync point' : 'the incoming ref';\n console.info(\n pc.dim(`upstream sync config not compared: upstream ${CONFIG_FILE} is missing or unreadable at ${side}`),\n );\n return;\n }\n\n const lines: string[] = [];\n for (const list of ['pinned', 'ignored', 'packageJsonSync'] as const) {\n for (const entry of report[list].added) lines.push(` ${pc.green('+')} ${list}: ${entry}`);\n for (const entry of report[list].removed) {\n lines.push(` ${pc.red('−')} ${list}: ${entry}${pc.dim(' · dropped upstream, still in your config')}`);\n }\n }\n console.info(\n `${warningMark} ${pc.yellow(`upstream changed its sync config · ${plural(lines.length, 'entry', 'entries')} to review`)}`,\n );\n for (const line of lines) console.info(line);\n console.info(pc.dim(` ${CONFIG_FILE} never syncs: add or drop these by hand where they fit your app.`));\n}\n\n/**\n * A pinned file whose fork content is byte-identical to the previous upstream (status\n * `behind`) never actually diverged: the pin is silently freezing it at the old upstream\n * version and dropping upstream's new changes. Because the fork copy equals the old\n * upstream, this produces no merge conflict and no type error, so it slips through unseen\n * (e.g. a pinned nav-config losing new upstream entries). These are the pins worth a look.\n * Managed files (package.json, the lockfile, the sync config) are always pinned but stay out:\n * the package sync reconciles their keys, so the pin masks nothing there.\n */\nexport function findMaskingPins(files: AnalyzedFile[]): AnalyzedFile[] {\n return files.filter(\n (file) =>\n file.isPinned &&\n !isManagedFile(file.path) &&\n file.status === 'behind' &&\n file.existsInFork &&\n file.existsInUpstream,\n );\n}\n\n/**\n * Warn when pins are masking upstream changes (see `findMaskingPins`). Silent by design\n * when there is nothing to report, so it is safe to call unconditionally after a summary.\n */\nfunction printMaskingPinWarning(files: AnalyzedFile[]): void {\n const masking = findMaskingPins(files);\n if (masking.length === 0) return;\n\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(\n `${plural(masking.length, 'pinned file matches', 'pinned files match')} the previous upstream but changed upstream:`,\n )}`,\n );\n console.info(pc.yellow(' the pin keeps the old fork copy and silently drops those upstream changes:'));\n for (const file of masking) {\n console.info(pc.dim(` ⨀ ${file.path}`));\n }\n console.info(\n pc.yellow(' if the fork never customized these, unpin them in cella/cella.config.ts to take upstream.'),\n );\n console.info();\n}\n\n/**\n * Print the post-engine report block shared by analyze and sync: the summary, then the upstream\n * changes the sync never brings in (ignored paths and upstream's own sync config), and pins that\n * silently freeze a file at the old upstream (no conflict, no type error).\n */\nexport function printEngineReports(result: MergeResult, title: string): void {\n printSummary(result.summary, title);\n printIgnoredUpstreamChanges(result);\n printUpstreamOverrideChanges(result);\n printMaskingPinWarning(result.files);\n}\n","{\n \"name\": \"@cellajs/cli\",\n \"version\": \"0.4.0\",\n \"private\": false,\n \"license\": \"MIT\",\n \"description\": \"CLI for managing your monorepo and syncing with upstream Cella.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/cellajs/cella-cli\"\n },\n \"homepage\": \"https://cellajs.com\",\n \"author\": \"CellaJS <info@cellajs.com>\",\n \"engines\": {\n \"node\": \"26.x\"\n },\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"exports\": {\n \".\": \"./dist/index.js\",\n \"./config\": {\n \"types\": \"./dist/config.d.ts\",\n \"import\": \"./dist/config.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\",\n \"index.js\",\n \"README.md\"\n ],\n \"bin\": {\n \"cella\": \"index.js\"\n },\n \"imports\": {\n \"#/*\": \"./src/*\"\n },\n \"scripts\": {\n \"start\": \"tsx index.ts\",\n \"clean\": \"rimraf ./dist\",\n \"build\": \"tsup\",\n \"test-build\": \"pnpm run build && node index.js --help\",\n \"prepublishOnly\": \"pnpm run test:release\",\n \"check\": \"pnpm ts && pnpm biome check --write .\",\n \"ts\": \"tsgo --pretty\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"test\": \"vitest run\",\n \"test:release\": \"pnpm run build && vitest run --config vitest.release.config.ts\",\n \"test:watch\": \"vitest\",\n \"prepare\": \"lefthook install\"\n },\n \"dependencies\": {\n \"@inquirer/core\": \"^12.0.3\",\n \"@inquirer/prompts\": \"^8.7.2\",\n \"@pierre/diffs\": \"^1.5.1\",\n \"commander\": \"^15.0.0\",\n \"ts-morph\": \"^28.0.0\",\n \"yaml\": \"^2.9.1\",\n \"zod\": \"^4.6.5\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.5.15\",\n \"@commitlint/cli\": \"^21.2.3\",\n \"@commitlint/config-conventional\": \"^21.2.3\",\n \"@evilmartians/lefthook\": \"^2.1.15\",\n \"@types/node\": \"26.6.3\",\n \"@typescript/native-preview\": \"7.0.0-dev.20260707.2\",\n \"rimraf\": \"^6.1.3\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.23.15\",\n \"typescript\": \"6.0.3\",\n \"vitest\": \"^5.0.3\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"keywords\": [\n \"cella\",\n \"cellajs\",\n \"cli\",\n \"sync\",\n \"template\"\n ],\n \"packageManager\": \"pnpm@11.8.0\",\n \"commitlint\": {\n \"extends\": [\n \"@commitlint/config-conventional\"\n ],\n \"rules\": {\n \"type-enum\": [\n 2,\n \"always\",\n [\n \"feat\",\n \"fix\",\n \"perf\",\n \"refactor\",\n \"revert\",\n \"docs\",\n \"chore\",\n \"build\",\n \"ci\",\n \"style\",\n \"test\"\n ]\n ],\n \"header-max-length\": [\n 2,\n \"always\",\n 120\n ],\n \"body-max-line-length\": [\n 0,\n \"always\",\n 200\n ],\n \"footer-max-line-length\": [\n 0,\n \"always\",\n 200\n ]\n }\n }\n}\n","/**\n * Override matching and validation: files matched against the ignored/pinned\n * paths, and config warnings for entries that cannot work.\n */\n\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { AnalyzedFile, CellaCliConfig, IgnoredUpstreamGroup, ProtectedUpstreamGroup } from '../config/types';\nimport { fileExistsAtRef, listChangedSinceRef, revParse } from './git';\nimport { isGeneratedFile, isManagedFile } from './managed-files';\nimport { isUpstreamOnly } from './migration-notes';\n\n/** Normalize an override entry: trimmed, no leading `./`, no trailing slash. */\nexport function normalizeEntry(entry: string): string {\n return entry.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n}\n\n/**\n * Whether a file path is owned by any of the given folders: entries are directory prefixes (not\n * globs) that match the path itself or anything nested under it.\n */\nexport function isUnderAnyFolder(filePath: string, folders: string[]): boolean {\n return folders.some((folder) => {\n const entry = normalizeEntry(folder);\n return filePath === entry || filePath.startsWith(`${entry}/`);\n });\n}\n\n/**\n * Whether a file is inside an ignored path, or an upstream-only one (migration notes),\n * which every fork ignores without listing it.\n */\nexport function isIgnored(filePath: string, config: CellaCliConfig): boolean {\n return isUpstreamOnly(filePath) || isUnderAnyFolder(filePath, config.overrides?.ignored || []);\n}\n\n/**\n * Whether a file is in the pinned list.\n * Managed files always count as pinned (handled separately by cella).\n */\nexport function isPinned(filePath: string, config: CellaCliConfig): boolean {\n if (isManagedFile(filePath)) return true;\n return isUnderAnyFolder(filePath, config.overrides?.pinned || []);\n}\n\n/** Normalized, deduplicated entries in config order, and a lookup for the most specific one holding a path. */\nfunction entryMatcher(list: string[]): [string[], (path: string) => string | undefined] {\n const entries = [...new Set(list.map(normalizeEntry).filter(Boolean))];\n const mostSpecificFirst = [...entries].sort((a, b) => b.length - a.length);\n return [entries, (path) => mostSpecificFirst.find((entry) => isUnderAnyFolder(path, [entry]))];\n}\n\n/**\n * Group `upstreamOnly` files by the most specific `ignored` entry they fall under, for one diff\n * hint per entry. Groups follow the order of `ignored`; managed files and generated output are\n * left out.\n */\nexport function groupIgnoredUpstreamChanges(files: AnalyzedFile[], ignored: string[]): IgnoredUpstreamGroup[] {\n const [entries, findEntry] = entryMatcher(ignored);\n const groups = new Map<string, IgnoredUpstreamGroup>();\n\n for (const file of files) {\n if (!file.upstreamOnly || isManagedFile(file.path) || isGeneratedFile(file.path)) continue;\n const entry = findEntry(file.path);\n if (!entry) continue;\n\n const group = groups.get(entry) ?? { entry, paths: [], added: 0, deleted: 0 };\n group.paths.push(file.path);\n if (!file.existsInFork) group.added++;\n if (!file.existsInUpstream) group.deleted++;\n groups.set(entry, group);\n }\n\n for (const group of groups.values()) group.paths.sort();\n return entries.flatMap((entry) => groups.get(entry) ?? []);\n}\n\n/**\n * Group protected paths upstream also changed by the most specific `pinned` or `ignored` entry\n * they fall under, for one diff hint per entry. A path no entry covers (a managed file) stands for\n * itself; groups follow the order the paths come in.\n */\nexport function groupProtectedUpstreamChanges(paths: string[], config: CellaCliConfig): ProtectedUpstreamGroup[] {\n const [, findEntry] = entryMatcher([...(config.overrides?.pinned ?? []), ...(config.overrides?.ignored ?? [])]);\n const groups = new Map<string, ProtectedUpstreamGroup>();\n\n for (const path of paths) {\n const entry = findEntry(path) ?? path;\n const group = groups.get(entry) ?? { entry, paths: [] };\n group.paths.push(path);\n groups.set(entry, group);\n }\n\n for (const group of groups.values()) group.paths.sort();\n return [...groups.values()];\n}\n\n/**\n * Warnings for override entries that cannot work: globs, pins missing from the fork, and ignored\n * entries neither the fork nor upstream has (a fork may ignore a path to keep it from arriving).\n * Also pins that do nothing: inside an ignored path (app modules included), gone from upstream\n * (the path is the app's own), or identical to upstream (it only drops upstream's next change).\n * Upstream is read at `upstreamRef` as last fetched; while it does not resolve, every ignored\n * entry missing from the fork warns and the upstream checks on pins are skipped.\n */\nexport async function validateOverrides(\n config: CellaCliConfig,\n forkPath: string,\n upstreamRef?: string,\n): Promise<string[]> {\n const warnings: string[] = [];\n const ignored = config.overrides?.ignored ?? [];\n const upstream = upstreamRef && (await revParse(forkPath, upstreamRef)) ? upstreamRef : undefined;\n const pinsUpstreamHas: string[] = [];\n\n for (const entry of config.overrides?.pinned ?? []) {\n const path = normalizeEntry(entry);\n const ignoredEntry = ignored.find((folder) => isUnderAnyFolder(path, [folder]));\n if (/[*?]/.test(entry)) warnings.push(`pin uses glob (not supported, use a path or folder): ${entry}`);\n else if (!existsSync(join(forkPath, path))) warnings.push(`pin not found: ${entry}`);\n else if (ignoredEntry) warnings.push(`pin does nothing, '${normalizeEntry(ignoredEntry)}' is ignored: ${entry}`);\n else if (!upstream) continue;\n else if (await fileExistsAtRef(forkPath, upstream, path)) pinsUpstreamHas.push(entry);\n else warnings.push(`pin does nothing, upstream no longer has it: ${entry}`);\n }\n\n if (upstream && pinsUpstreamHas.length > 0) {\n const differs = await listChangedSinceRef(forkPath, upstream, pinsUpstreamHas.map(normalizeEntry));\n for (const entry of pinsUpstreamHas) {\n if (differs.some((changed) => isUnderAnyFolder(changed, [entry]))) continue;\n warnings.push(`pin is identical to upstream, it only drops upstream's next change: ${entry}`);\n }\n }\n\n for (const entry of config.overrides?.ignored ?? []) {\n const path = normalizeEntry(entry);\n if (/[*?]/.test(entry)) {\n warnings.push(`ignored entry uses glob (not supported, use a path or folder): ${entry}`);\n } else if (!existsSync(join(forkPath, path))) {\n if (upstreamRef && (await fileExistsAtRef(forkPath, upstreamRef, path))) continue;\n warnings.push(`ignored entry not found: ${entry}`);\n }\n }\n\n return warnings;\n}\n","/**\n * Git command helpers: typed wrappers around common git operations, plus the\n * sync-point tracking and merge-base recovery machinery.\n */\n\nimport { execFile } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readdir, rmdir, unlink } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\nimport { promisify } from 'node:util';\nimport type { CommitRangeEntry } from '../config/types';\nimport { getEnvSnapshot } from './env';\nimport { MANIFEST_FILE, parseSyncManifest, readManifestBase, type SyncManifest } from './manifest';\n\nconst execFileAsync = promisify(execFile);\n\n/** Maximum stdout buffer for subprocess output (50MB). */\nexport const MAX_BUFFER = 50 * 1024 * 1024;\n\n/**\n * Replace the userinfo part of URLs in text (embedded tokens or passwords) with `***`.\n * Keeps secrets in git remote URLs out of error messages (CWE-532).\n */\nfunction redactUrlSecrets(text: string): string {\n return text.replace(/https?:\\/\\/[^@\\s]+@/g, (match) => {\n const protocol = match.startsWith('https') ? 'https' : 'http';\n return `${protocol}://***@`;\n });\n}\n\n/** Options for git command execution */\ninterface GitCommandOptions {\n /** Skip editor prompts (for merge commits, etc.) */\n skipEditor?: boolean;\n /** Ignore command errors: a failed command returns an empty string. */\n ignoreErrors?: boolean;\n /** Additional environment variables for the git command */\n env?: Record<string, string>;\n}\n\n/** Executes a git command and returns trimmed stdout. */\nexport async function git(args: string[], cwd: string, options: GitCommandOptions = {}): Promise<string> {\n const env = {\n ...getEnvSnapshot(),\n ...(options.skipEditor ? { GIT_EDITOR: 'true' } : {}),\n ...options.env,\n };\n\n try {\n const { stdout } = await execFileAsync('git', args, { cwd, env, maxBuffer: MAX_BUFFER });\n return stdout.trim();\n } catch (error) {\n if (options.ignoreErrors) return '';\n if (error instanceof Error) {\n error.message = redactUrlSecrets(error.message);\n }\n throw error;\n }\n}\n\n/** The object `ref` resolves to (`rev-parse -q --verify`), or null when it does not resolve. */\nexport async function revParse(cwd: string, ref: string): Promise<string | null> {\n return (await git(['rev-parse', '-q', '--verify', ref], cwd, { ignoreErrors: true })) || null;\n}\n\nexport async function getCurrentBranch(cwd: string): Promise<string> {\n return git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd);\n}\n\nexport async function switchBranch(cwd: string, branch: string): Promise<void> {\n await git(['switch', branch], cwd);\n}\n\n/**\n * Detach HEAD at a commit or ref (`git switch --detach`), holding no branch.\n */\nexport async function switchDetached(cwd: string, ref: string): Promise<void> {\n await git(['switch', '--detach', ref], cwd);\n}\n\n/**\n * Create and check out a new branch from a specific start point (branch/ref).\n *\n * `--no-track` keeps a remote-tracking start point (`origin/main`) from becoming the new\n * branch's upstream, where a bare `git push` could then land on the trunk.\n */\nexport async function createBranchFrom(cwd: string, branch: string, startPoint: string): Promise<void> {\n await git(['switch', '-c', branch, '--no-track', startPoint], cwd);\n}\n\n/** Whether a local branch exists. */\nexport async function branchExists(cwd: string, branch: string): Promise<boolean> {\n return (await revParse(cwd, `refs/heads/${branch}`)) !== null;\n}\n\n/**\n * The worktree that has `branch` checked out, or null when none has.\n *\n * Git refuses to switch to a branch another worktree has checked out (and to move its ref), so\n * callers that would switch to a shared branch such as the trunk check here first.\n */\nexport async function getBranchWorktree(cwd: string, branch: string): Promise<string | null> {\n const output = await git(['worktree', 'list', '--porcelain'], cwd, { ignoreErrors: true });\n let worktree: string | null = null;\n for (const line of output.split('\\n')) {\n if (line.startsWith('worktree ')) worktree = line.slice('worktree '.length);\n else if (line === `branch refs/heads/${branch}`) return worktree;\n }\n return null;\n}\n\n/**\n * Fast-forward a branch no worktree has checked out to `ref`, without checking it out.\n *\n * Fetching from the repository itself (`git fetch . <ref>:<branch>`) moves the branch ref only,\n * and git refuses when that is not a fast-forward or a worktree has the branch checked out.\n */\nexport async function fastForwardBranch(cwd: string, branch: string, ref: string): Promise<void> {\n await git(['fetch', '--quiet', '.', `${ref}:refs/heads/${branch}`], cwd);\n}\n\n/** Delete a local branch (force). No-op if it doesn't exist. */\nexport async function deleteBranch(cwd: string, branch: string): Promise<void> {\n await git(['branch', '-D', branch], cwd, { ignoreErrors: true });\n}\n\n/**\n * Fast-forward the current branch from its upstream tracking branch.\n * Best-effort: ignores errors (e.g. no origin, offline, or nothing to pull).\n */\nexport async function pullFastForward(cwd: string): Promise<void> {\n await git(['pull', '--ff-only'], cwd, { ignoreErrors: true, skipEditor: true });\n}\n\n/** How the current branch compares to its upstream tracking branch. */\ninterface UpstreamStatus {\n /** Upstream tracking ref (e.g. `origin/main`), or null when none is configured. */\n upstream: string | null;\n /** Commits the local branch has that its upstream doesn't. */\n ahead: number;\n /** Commits the upstream has that the local branch doesn't. */\n behind: number;\n}\n\n/**\n * A branch's upstream tracking ref (e.g. `origin/main`), or null when none is configured.\n * `branch` defaults to the current one.\n */\nexport async function getBranchUpstream(cwd: string, branch = ''): Promise<string | null> {\n const upstream = await git(['rev-parse', '--abbrev-ref', '--symbolic-full-name', `${branch}@{upstream}`], cwd, {\n ignoreErrors: true,\n });\n return upstream || null;\n}\n\n/**\n * Fetch a branch's upstream, then report how far ahead/behind the branch is.\n *\n * `branch` defaults to the current one. A named branch is compared by ref, without checking it\n * out, so this also works for a branch another worktree has checked out.\n *\n * The fetch is best-effort so an offline/no-remote run still returns whatever is already local.\n * Returns `upstream: null` when the branch has no tracking branch configured (local-only repo).\n */\nexport async function getUpstreamStatus(cwd: string, branch?: string): Promise<UpstreamStatus> {\n const local = branch ? `refs/heads/${branch}` : 'HEAD';\n const upstream = await getBranchUpstream(cwd, branch);\n if (!upstream) return { upstream: null, ahead: 0, behind: 0 };\n\n // Refresh the remote-tracking ref so the comparison reflects the remote's latest state.\n const remote = upstream.split('/')[0];\n await git(['fetch', remote], cwd, { ignoreErrors: true, skipEditor: true });\n\n const counts = await git(['rev-list', '--left-right', '--count', `${local}...${upstream}`], cwd, {\n ignoreErrors: true,\n });\n const [ahead, behind] = counts.split(/\\s+/).map((n) => Number.parseInt(n, 10) || 0);\n return { upstream, ahead: ahead ?? 0, behind: behind ?? 0 };\n}\n\n/**\n * Push a branch to a remote, setting upstream tracking.\n *\n * `forceWithLease` allows a rewritten branch (see `flattenBranch`) to replace the version\n * already on the remote, while still refusing to overwrite remote commits we haven't seen.\n */\nexport async function pushBranch(\n cwd: string,\n remote: string,\n branch: string,\n options: { forceWithLease?: boolean } = {},\n): Promise<void> {\n await git(['push', '-u', ...(options.forceWithLease ? ['--force-with-lease'] : []), remote, branch], cwd);\n}\n\n/**\n * List merge commits made on the current branch itself: commits with two parents on the\n * first-parent chain from HEAD down to where the branch forked off `baseRef` (newest first).\n *\n * `--first-parent` keeps the walk on the branch's own commits, so merge commits that merely\n * exist inside a merged-in history (e.g. upstream's internal merges) don't count.\n */\nexport async function listBranchMergeCommits(cwd: string, baseRef: string): Promise<string[]> {\n const out = await git(['rev-list', '--merges', '--first-parent', `${baseRef}..HEAD`], cwd, { ignoreErrors: true });\n return out ? out.split('\\n').filter(Boolean) : [];\n}\n\n/**\n * Rewrite the current branch as one commit with `message`, parented on the point where the\n * branch forked off `baseRef`. The tree (content) is kept exactly as-is; only the commit\n * graph changes, so the branch's diff against the base is untouched.\n *\n * Undoes a two-parent merge commit that was already made; {@link commitSquash} says why one is unwanted.\n */\nexport async function flattenBranch(cwd: string, baseRef: string, message: string): Promise<void> {\n const parent = await getMergeBase(cwd, baseRef, 'HEAD');\n const tree = await git(['rev-parse', 'HEAD^{tree}'], cwd);\n const commit = await git(['commit-tree', tree, '-p', parent, '-m', message], cwd);\n await git(['reset', '--hard', commit], cwd);\n}\n\n/**\n * Commit the staged changes as a single-parent commit, discarding any in-progress merge state.\n *\n * A normal commit with `MERGE_HEAD` present records a two-parent merge commit. Because the fork\n * doesn't share pushed ancestry with upstream (the local `git replace` graft that makes merges\n * incremental is never pushed), such a merge commit makes the PR list the upstream branch's\n * entire history. Removing the merge state first collapses the staged delta into one clean\n * commit, so the PR shows a single commit with the incremental diff.\n */\nexport async function commitSquash(cwd: string, message: string): Promise<void> {\n for (const file of ['MERGE_HEAD', 'MERGE_MSG', 'MERGE_MODE']) {\n const path = await gitPath(cwd, file);\n if (existsSync(path)) await unlink(path);\n }\n await git(['commit', '-m', message], cwd, { skipEditor: true });\n}\n\n/**\n * Absolute path of a file in the current worktree's git dir. In a linked worktree `.git` is a\n * pointer file and the git dir lives under the main checkout's `.git/worktrees/<name>`.\n */\nasync function gitPath(cwd: string, file: string): Promise<string> {\n return resolve(cwd, await git(['rev-parse', '--git-path', file], cwd));\n}\n\n/**\n * Stage every change in the working tree (`git add -A`), including untracked and deleted files.\n */\nexport async function stageAll(cwd: string): Promise<void> {\n await git(['add', '-A'], cwd);\n}\n\n/**\n * Whether a merge is currently in progress (MERGE_HEAD present), in a linked worktree too.\n */\nexport async function mergeInProgress(cwd: string): Promise<boolean> {\n return (await revParse(cwd, 'MERGE_HEAD')) !== null;\n}\n\nexport async function getShortSha(cwd: string, ref: string): Promise<string> {\n return git(['rev-parse', '--short', ref], cwd);\n}\n\nexport async function getWorkingTreeChangeCount(cwd: string): Promise<number> {\n const status = await git(['status', '--porcelain'], cwd);\n if (!status) return 0;\n return status.split('\\n').filter(Boolean).length;\n}\n\n/** Add the remote, or point an existing one at `url` (`remote add` fails when it exists). */\nexport async function ensureRemote(cwd: string, remoteName: string, url: string): Promise<void> {\n await git(['remote', 'add', remoteName, url], cwd, { ignoreErrors: true });\n await git(['remote', 'set-url', remoteName, url], cwd);\n}\n\nexport async function fetchRemote(cwd: string, remoteName: string): Promise<void> {\n await git(['fetch', remoteName], cwd);\n}\n\n/**\n * Fetch upstream tags into a remote-scoped namespace (`refs/<remoteName>/tags/*`),\n * never the local `refs/tags/*`. This keeps cella's release tags from\n * colliding with the fork's own release tags (forks run their own release-please).\n * `--no-tags` prevents git from also writing them into `refs/tags/*`.\n */\nexport async function fetchUpstreamTags(cwd: string, remoteName: string): Promise<void> {\n await git(['fetch', remoteName, '--no-tags', `+refs/tags/*:refs/${remoteName}/tags/*`], cwd);\n}\n\n/**\n * A template release tag is a version, with or without the `v` prefix (`0.18.1`, `v0.5.0`).\n * Component tags (`create-cella-0.2.3`) and other namespaces (`archive/pre-release`) start with a name.\n */\nconst releaseTagPattern = /^v?\\d[\\w.+-]*$/;\n\n/**\n * Resolve the latest upstream release tag (the highest version tag) from the\n * remote-scoped tag namespace. Returns the short tag name and its full ref, or null\n * when no release exists.\n */\nexport async function resolveLatestReleaseTag(\n cwd: string,\n remoteName: string,\n): Promise<{ tag: string; ref: string } | null> {\n const prefix = `refs/${remoteName}/tags/`;\n const output = await git(['for-each-ref', '--sort=-version:refname', '--format=%(refname)', prefix], cwd, {\n ignoreErrors: true,\n });\n if (!output) return null;\n for (const line of output.split('\\n')) {\n const ref = line.trim();\n if (!ref) continue;\n const tag = ref.slice(prefix.length);\n if (releaseTagPattern.test(tag)) return { tag, ref };\n }\n return null;\n}\n\n/**\n * Resolve a ref named for upstream (`--ref`) to a commit: a branch on the upstream remote, then a\n * tag from the remote-scoped tag namespace, then the ref as given (a sha). Upstream names come\n * first, so `main` means upstream's main and `1.0.0` upstream's release, never the fork's own.\n * Revision suffixes work too (`main~2`). Returns the commit sha, plus the release tag when the\n * ref is a release tag name itself (`1.2.3`, not `1.2.3~1`); null when nothing resolves.\n */\nexport async function resolveUpstreamCommit(\n cwd: string,\n remoteName: string,\n ref: string,\n): Promise<{ sha: string; release?: { tag: string; ref: string } } | null> {\n if (ref.startsWith('-')) return null;\n const tagRef = `refs/${remoteName}/tags/${ref}`;\n for (const candidate of [`refs/remotes/${remoteName}/${ref}`, tagRef, ref]) {\n const sha = await revParse(cwd, `${candidate}^{commit}`);\n if (!sha) continue;\n const release = candidate === tagRef && releaseTagPattern.test(ref) ? { tag: ref, ref: tagRef } : undefined;\n return { sha, release };\n }\n return null;\n}\n\n/**\n * Whether upstream published `sha`: reachable from the upstream branch (`branchRef`, e.g.\n * `cella-upstream/main`) or from an upstream release tag (remote-scoped namespace).\n */\nexport async function isPublishedUpstream(\n cwd: string,\n remoteName: string,\n branchRef: string,\n sha: string,\n): Promise<boolean> {\n const containing = await git(\n [\n 'for-each-ref',\n '--count=1',\n '--format=%(refname)',\n '--contains',\n sha,\n `refs/remotes/${branchRef}`,\n `refs/${remoteName}/tags/[0-9]*`,\n `refs/${remoteName}/tags/v[0-9]*`,\n ],\n cwd,\n { ignoreErrors: true },\n );\n return containing !== '';\n}\n\nexport async function getCommitInfo(cwd: string, ref: string): Promise<CommitRangeEntry> {\n const format = '%H%n%s%n%ar'; // hash, subject, relative date\n const output = await git(['log', '-1', `--format=${format}`, ref], cwd);\n const [hash, message, date] = output.split('\\n');\n return { hash, message, date };\n}\n\n/** The number of commits in `toRef` that are not in `fromRef`. */\nexport async function countCommitsBetween(cwd: string, fromRef: string, toRef: string): Promise<number> {\n const output = await git(['rev-list', '--count', `${fromRef}..${toRef}`], cwd);\n return Number.parseInt(output.trim(), 10) || 0;\n}\n\n/**\n * List commits in a ref range, oldest-first to match GitHub compare ordering. With `limit`, only the\n * newest `limit` commits (git applies `-n` before `--reverse`).\n */\nexport async function listCommitsBetween(\n cwd: string,\n fromRef: string,\n toRef: string,\n limit?: number,\n): Promise<CommitRangeEntry[]> {\n const args = ['log', '--format=%H%x1f%s%x1f%ar', '--reverse', `${fromRef}..${toRef}`];\n if (limit) args.push(`-n${limit}`);\n\n const output = await git(args, cwd, { ignoreErrors: true });\n if (!output) return [];\n\n const commits: CommitRangeEntry[] = [];\n for (const line of output.split('\\n')) {\n if (!line) continue;\n const [hash, message, date] = line.split('\\x1f');\n if (!hash || !message || !date) continue;\n commits.push({ hash, message, date });\n }\n return commits;\n}\n\nexport interface FileChangeInfo {\n date: string;\n hash: string;\n /** Unix epoch seconds of the change, for sorting */\n timestamp: number;\n}\n\n/**\n * Relative date and commit hash of the last change for every file in a range,\n * as filePath -> { date, hash, timestamp }; one `git log` call for the whole range.\n */\nexport async function getFileChangeInfo(\n cwd: string,\n fromRef: string,\n toRef: string,\n): Promise<Map<string, FileChangeInfo>> {\n const info = new Map<string, FileChangeInfo>();\n const output = await git(['log', '--name-only', '--format=%h %ct %ar', `${fromRef}..${toRef}`], cwd, {\n ignoreErrors: true,\n });\n if (!output) return info;\n\n let currentHash = '';\n let currentDate = '';\n let currentTimestamp = 0;\n for (const line of output.split('\\n')) {\n if (!line) continue;\n const match = line.match(/^([a-f0-9]{7,})\\s+(\\d+)\\s+(.+)$/);\n if (match) {\n currentHash = match[1];\n currentTimestamp = Number(match[2]);\n currentDate = match[3];\n } else if (currentHash && currentDate && !info.has(line)) {\n // git log lists newest first, so the first entry per path is its last change.\n info.set(line, { date: currentDate, hash: currentHash, timestamp: currentTimestamp });\n }\n }\n return info;\n}\n\n/** Whether the working tree is clean (no uncommitted changes). */\nexport async function isClean(cwd: string): Promise<boolean> {\n return (await getWorkingTreeChangeCount(cwd)) === 0;\n}\n\n/**\n * Perform a merge in the current directory, leaving it staged (--no-commit --no-edit).\n * Always uses --no-ff to prevent fast-forward, ensuring HEAD stays in place\n * and MERGE_HEAD is created for proper merge state tracking.\n */\nexport async function merge(cwd: string, ref: string): Promise<{ success: boolean; conflicts: string[] }> {\n try {\n await git(['merge', '--no-ff', '--no-commit', '--no-edit', ref], cwd, { skipEditor: true });\n return { success: true, conflicts: [] };\n } catch (error) {\n const conflicts = await getConflictedFiles(cwd);\n if (conflicts.length > 0) {\n return { success: false, conflicts };\n }\n throw error;\n }\n}\n\nexport async function getConflictedFiles(cwd: string): Promise<string[]> {\n const output = await git(['diff', '--name-only', '--diff-filter=U'], cwd, { ignoreErrors: true });\n if (!output) return [];\n return output.split('\\n').filter(Boolean);\n}\n\nexport async function mergeAbort(cwd: string): Promise<void> {\n await git(['merge', '--abort'], cwd, { ignoreErrors: true });\n}\n\nexport async function fileExistsAtRef(cwd: string, ref: string, filePath: string): Promise<boolean> {\n const result = await git(['ls-tree', '--name-only', ref, '--', filePath], cwd, { ignoreErrors: true });\n return result !== '';\n}\n\n/**\n * Check out paths from a ref into index and worktree. During a merge this also settles unmerged\n * (conflicted) paths on `ref`'s version, which `git restore --source` refuses to do.\n */\nexport async function checkoutFromRef(cwd: string, ref: string, paths: string[]): Promise<void> {\n await git(['checkout', ref, '--', ...paths], cwd);\n}\n\n/**\n * Restore a path from a ref into the working tree only, leaving the index untouched,\n * so adopted changes remain unstaged for review.\n */\nexport async function restoreWorktreeFromRef(cwd: string, ref: string, filePath: string): Promise<void> {\n await git(['restore', `--source=${ref}`, '--worktree', '--', filePath], cwd);\n}\n\n/**\n * Restore paths from a ref into the working tree only, in batches, leaving the index untouched.\n * Paths are taken literally, so a file name with glob characters (`[id].tsx`) restores that file.\n */\nexport async function batchRestoreWorktreeFromRef(cwd: string, ref: string, filePaths: string[]): Promise<void> {\n const batchSize = 200;\n for (let i = 0; i < filePaths.length; i += batchSize) {\n const batch = filePaths.slice(i, i + batchSize);\n await git(['--literal-pathspecs', 'restore', `--source=${ref}`, '--worktree', '--', ...batch], cwd);\n }\n}\n\n/**\n * Paths at `ref` whose working tree copy is byte-identical to it. Renames are not detected, so a\n * file the working tree moved away counts as changed at its old path.\n */\nexport async function listIdenticalToRef(cwd: string, ref: string): Promise<Set<string>> {\n const nulSeparated = (out: string) => out.split('\\0').filter(Boolean);\n const [tracked, changed] = await Promise.all([\n git(['ls-tree', '-r', '--name-only', '-z', ref], cwd),\n git(['diff', '--name-only', '--no-renames', '-z', ref, '--'], cwd),\n ]);\n const differs = new Set(nulSeparated(changed));\n return new Set(nulSeparated(tracked).filter((path) => !differs.has(path)));\n}\n\n/** Tracked paths under `paths` whose working tree copy differs from `ref` (renames not detected). */\nexport async function listChangedSinceRef(cwd: string, ref: string, paths: string[]): Promise<string[]> {\n const out = await git(['--literal-pathspecs', 'diff', '--name-only', '--no-renames', '-z', ref, '--', ...paths], cwd);\n return out.split('\\0').filter(Boolean);\n}\n\nexport async function getMergeBase(cwd: string, ref1: string, ref2: string): Promise<string> {\n return git(['merge-base', ref1, ref2], cwd);\n}\n\n/** File change status codes from git diff-tree */\ntype FileChangeStatus = 'A' | 'D' | 'M' | 'T' | 'R';\n\n/** File change info from git diff-tree */\ninterface FileChange {\n status: FileChangeStatus;\n baseHash: string | null;\n targetHash: string | null;\n /** For renames: the original path (before rename) */\n oldPath?: string;\n}\n\n/**\n * Files changed between two refs (`git diff-tree -r -M90%`), as filePath -> FileChange.\n * Status codes: A=added, D=deleted, M=modified, T=type-changed, R=renamed (90% similarity\n * threshold). A rename is keyed by its NEW path, with `oldPath` stored in the value.\n */\nexport async function getFileChanges(\n cwd: string,\n baseRef: string,\n targetRef: string,\n): Promise<Map<string, FileChange>> {\n const output = await git(['diff-tree', '-r', '-M90%', '--no-commit-id', baseRef, targetRef], cwd, {\n ignoreErrors: true,\n });\n const changes = new Map<string, FileChange>();\n\n // diff-tree prints the all-zero hash for a missing side (added/deleted files).\n const hashOrNull = (hash: string) => (hash === '0'.repeat(40) ? null : hash);\n\n for (const line of output.split('\\n')) {\n // `:oldmode newmode oldhash newhash status\\tpath`; a rename is `Rxx\\toldpath\\tnewpath`.\n const m = line.match(/^:\\d+ \\d+ ([a-f0-9]+) ([a-f0-9]+) ([ADMRT])\\d*\\t([^\\t]+)(?:\\t(.+))?$/);\n if (!m) continue;\n const status = m[3] as FileChangeStatus;\n changes.set(m[5] ?? m[4], {\n status,\n baseHash: hashOrNull(m[1]),\n targetHash: hashOrNull(m[2]),\n ...(status === 'R' ? { oldPath: m[4] } : {}),\n });\n }\n return changes;\n}\n\n/** Lines added/removed for one path (`null` for binary files, where git reports `-`). */\ninterface DiffStat {\n additions: number | null;\n deletions: number | null;\n}\n\n/**\n * Lines added/removed per file between two refs (`git diff --numstat`), optionally limited\n * to `paths`. Renames are not detected (`--no-renames`) so every entry is keyed by its plain\n * path, never git's `old => new` notation.\n */\nexport async function getDiffStat(\n cwd: string,\n fromRef: string,\n toRef: string,\n paths: string[] = [],\n): Promise<Map<string, DiffStat>> {\n const args = ['diff', '--numstat', '--no-renames', fromRef, toRef];\n if (paths.length > 0) args.push('--', ...paths);\n const out = await git(args, cwd, { ignoreErrors: true });\n\n const stat = new Map<string, DiffStat>();\n for (const line of out.split('\\n')) {\n if (!line.trim()) continue;\n const [a, d, ...rest] = line.split('\\t');\n const path = rest.join('\\t');\n if (!path) continue;\n stat.set(path, {\n additions: a === '-' ? null : Number(a),\n deletions: d === '-' ? null : Number(d),\n });\n }\n return stat;\n}\n\n/** All file hashes at a ref (one `ls-tree -r` call), as filePath -> hash. */\nexport async function getFileHashesAtRef(cwd: string, ref: string): Promise<Map<string, string>> {\n const output = await git(['ls-tree', '-r', ref], cwd);\n const hashes = new Map<string, string>();\n\n if (!output) return hashes;\n\n for (const line of output.split('\\n')) {\n if (!line) continue;\n // Parse: <mode> <type> <hash>\\t<path>\n const match = line.match(/^\\d+ \\w+ ([a-f0-9]+)\\t(.+)$/);\n if (match) {\n const [, hash, filePath] = match;\n hashes.set(filePath, hash);\n }\n }\n\n return hashes;\n}\n\n/**\n * Tracked delete (`git rm -f`), recording a deletion in the merge result. With `cached`, the paths\n * leave the index only and the working tree is untouched. Best-effort: never throws.\n */\nexport async function gitRm(cwd: string, paths: string[], options: { cached?: boolean } = {}): Promise<void> {\n await git(['rm', ...(options.cached ? ['--cached'] : []), '-f', '--', ...paths], cwd, { ignoreErrors: true });\n}\n\n/** Files staged as new additions vs HEAD (diff-filter=A): absent at HEAD, brought in by a merge. */\nexport async function getStagedNewFiles(cwd: string): Promise<string[]> {\n const output = await git(['diff', '--cached', '--name-only', '--diff-filter=A'], cwd, { ignoreErrors: true });\n return output ? output.split('\\n').filter(Boolean) : [];\n}\n\n/** Move a file (`git mv -f`), creating parent directories as needed. */\nexport async function gitMv(cwd: string, oldPath: string, newPath: string): Promise<void> {\n const newDir = dirname(join(cwd, newPath));\n await mkdir(newDir, { recursive: true });\n\n await git(['mv', '-f', oldPath, newPath], cwd);\n}\n\nexport async function fileExistsInWorktree(cwd: string, filePath: string): Promise<boolean> {\n return existsSync(join(cwd, filePath));\n}\n\n/**\n * Remove a file from the worktree filesystem if it exists.\n * Used to clean up files that git rm may not have removed (e.g., after squash merge).\n */\nexport async function removeFileFromWorktree(cwd: string, filePath: string): Promise<void> {\n const fullPath = join(cwd, filePath);\n try {\n await unlink(fullPath);\n await cleanupEmptyParentDirs(cwd, dirname(filePath));\n } catch {\n // File missing or not removable: ignore\n }\n}\n\n/**\n * Fully remove a file: tracked delete from the index (git rm) plus filesystem removal\n * for cases git rm leaves behind (e.g. during a merge), including empty parent dirs.\n */\nexport async function removeFileFully(cwd: string, filePath: string): Promise<void> {\n await gitRm(cwd, [filePath]);\n await removeFileFromWorktree(cwd, filePath);\n}\n\n/**\n * Recursively remove empty parent directories up to (but not including) the root.\n * Stops when encountering a non-empty directory or the root.\n */\nasync function cleanupEmptyParentDirs(cwd: string, relativePath: string): Promise<void> {\n if (!relativePath || relativePath === '.') return;\n\n const fullPath = join(cwd, relativePath);\n try {\n const entries = await readdir(fullPath);\n if (entries.length === 0) {\n await rmdir(fullPath);\n await cleanupEmptyParentDirs(cwd, dirname(relativePath));\n }\n } catch {\n // Directory missing, not empty, or not removable: stop\n }\n}\n\n// Sync ref tracking and merge-base recovery.\n\n/**\n * Store the upstream commit hash after a successful sync.\n * Used to recover correct merge-base when squash strategy creates single-parent commits.\n *\n * Also records the fork HEAD at store time as `refs/cella/last-sync-head`. The last-sync\n * ref is written while the merge is still staged (before the user commits), so it cannot be\n * trusted on its own: if the user runs `git merge --abort`, HEAD never advances and the ref\n * is left pointing at an upstream commit that was never actually integrated. Recording HEAD\n * lets `getEffectiveMergeBase` detect that an aborted/uncommitted merge produced a stale ref.\n */\nexport async function storeLastSyncRef(cwd: string, upstreamHash: string): Promise<void> {\n await git(['update-ref', 'refs/cella/last-sync', upstreamHash], cwd);\n const head = await revParse(cwd, 'HEAD');\n if (head) await git(['update-ref', 'refs/cella/last-sync-head', head], cwd);\n}\n\n/** Stage a single path (git add). Best-effort: never throws. */\nexport async function stagePath(cwd: string, path: string): Promise<void> {\n await git(['add', '--', path], cwd, { ignoreErrors: true });\n}\n\n/** The stored last-sync upstream ref, or null when no sync has been recorded. */\nexport async function getStoredSyncRef(cwd: string): Promise<string | null> {\n return revParse(cwd, 'refs/cella/last-sync');\n}\n\n/**\n * Read the sync manifest committed at a specific ref.\n *\n * This intentionally reads from git, not the working tree: a staged/aborted sync can leave the\n * worktree manifest ahead of the committed trunk, and that must not validate a sync point.\n */\nexport async function readManifestAtRef(cwd: string, ref: string): Promise<SyncManifest | null> {\n const raw = await git(['show', `${ref}:${MANIFEST_FILE}`], cwd, { ignoreErrors: true });\n if (!raw) return null;\n return parseSyncManifest(raw);\n}\n\n/** The upstream base commit SHA from the manifest committed at `ref`, or null. */\nexport async function readManifestBaseAtRef(cwd: string, ref: string): Promise<string | null> {\n const manifest = await readManifestAtRef(cwd, ref);\n return manifest ? manifest.upstream.commit.toLowerCase() : null;\n}\n\n/**\n * Read the `version` field of the root `package.json` committed at a ref.\n * Returns null when the file is absent or unparsable.\n */\nexport async function readPackageVersionAtRef(cwd: string, ref: string): Promise<string | null> {\n const raw = await git(['show', `${ref}:package.json`], cwd, { ignoreErrors: true });\n if (!raw) return null;\n\n try {\n const version = (JSON.parse(raw) as { version?: unknown }).version;\n return typeof version === 'string' && version ? version : null;\n } catch {\n return null;\n }\n}\n\n/** Whether a commit object is present in the local object store. */\nasync function commitObjectExists(cwd: string, sha: string): Promise<boolean> {\n return (await revParse(cwd, `${sha}^{commit}`)) !== null;\n}\n\n/** The root (parentless) commit of a ref's history, such as a create-cella scaffold's \"Initial commit\", or null. */\nasync function getRootCommit(cwd: string, ref: string): Promise<string | null> {\n const out = await git(['rev-list', '--max-parents=0', ref], cwd, { ignoreErrors: true });\n const roots = out.split('\\n').filter(Boolean);\n return roots.length > 0 ? roots[roots.length - 1] : null;\n}\n\n/**\n * Read the scaffold provenance trailer from the fork's root commit message.\n *\n * create-cella stamps `Cella-Base: <sha>` on the initial commit, recording the exact\n * upstream commit the scaffold snapshot was taken from. Riding in commit history, it\n * travels with push/clone (a local ref does not) and needs no file in the worktree.\n */\nasync function readRootTrailerBase(cwd: string, headRef: string): Promise<string | null> {\n const root = await getRootCommit(cwd, headRef);\n if (!root) return null;\n const message = await git(['show', '-s', '--format=%B', root], cwd, { ignoreErrors: true });\n const match = message.match(/^cella-base:\\s*([0-9a-f]{40})$/im);\n return match ? match[1].toLowerCase() : null;\n}\n\n/**\n * Whether the repository is a shallow clone (created with `git clone --depth`, or otherwise\n * carrying a `.git/shallow` graft). Shallow history is truncated below the graft point, so the\n * real common ancestor with upstream is absent: `git merge-base` finds nothing even when one\n * exists in the full history, and the 3-way file analysis walks an incomplete commit graph.\n */\nasync function isShallowRepository(cwd: string): Promise<boolean> {\n const out = await git(['rev-parse', '--is-shallow-repository'], cwd, { ignoreErrors: true });\n return out === 'true';\n}\n\n/**\n * Restore full history on a shallow clone by fetching from its own origin, so merge-base and the\n * 3-way analysis see the real commit graph.\n *\n * Throws an actionable error when the history cannot be restored (e.g. no reachable origin),\n * because sync cannot run correctly against truncated history.\n */\nasync function unshallowRepository(cwd: string): Promise<void> {\n try {\n await git(['fetch', '--unshallow'], cwd, { skipEditor: true });\n } catch (error) {\n const detail = error instanceof Error ? `\\n\\n${error.message}` : '';\n throw new Error(\n 'this is a shallow clone and its full history could not be restored automatically.\\n' +\n 'Sync needs the complete history to find the common ancestor with upstream. Restore it with:\\n\\n' +\n ' git fetch --unshallow\\n\\n' +\n `then re-run sync.${detail}`,\n );\n }\n}\n\n/**\n * Ensure a native git merge-base exists between the fork and upstream.\n *\n * A create-cella scaffold has unrelated history with upstream, so `git merge-base` finds nothing\n * and every sync fails at the very first step. This bootstraps ancestry non-destructively:\n * 0. If the repo is a shallow clone, restore its full history first: the real ancestor is\n * truncated away, so no graft can recover it; deepening the history brings it back.\n * 1. If a native merge-base already exists, do nothing (the common case).\n * 2. Otherwise resolve the logical base commit: sources are tried in order and the first\n * one whose commit actually exists after the upstream fetch wins: the sync-point\n * record (`refs/cella/last-sync` ref, then committed/worktree `cella/cella.manifest.json`),\n * then the scaffold origin (the root commit's `Cella-Base:` trailer).\n * 3. Graft the fork's root commit onto that base with `git replace --graft`, so every native\n * git operation (merge-base and the 3-way merge itself) sees correct ancestry, and record\n * the base as `refs/cella/last-sync`. The replace ref is local-only and never pushed, so\n * the fork's own published history stays clean.\n *\n * Throws an actionable error when no valid base can be determined.\n */\nexport async function ensureSyncBase(cwd: string, headRef: string, upstreamRef: string): Promise<void> {\n if (await isShallowRepository(cwd)) {\n await unshallowRepository(cwd);\n }\n\n const nativeBase = await git(['merge-base', headRef, upstreamRef], cwd, { ignoreErrors: true });\n if (nativeBase) return;\n\n const sources: Array<() => Promise<string | null>> = [\n () => getStoredSyncRef(cwd),\n () => readManifestBaseAtRef(cwd, headRef),\n () => readManifestBase(cwd),\n () => readRootTrailerBase(cwd, headRef),\n ];\n\n let baseSha: string | null = null;\n for (const source of sources) {\n const sha = await source();\n if (sha && (await commitObjectExists(cwd, sha))) {\n baseSha = sha;\n break;\n }\n }\n if (!baseSha) {\n throw new Error(\n `no common ancestor between the fork and '${upstreamRef}', and no sync base could be determined.\\n\\n` +\n 'This fork has unrelated history with upstream (typical for a create-cella scaffold, or after\\n' +\n 'upstream squashed its history) and no recorded base commit exists after fetching\\n' +\n 'upstream. Seed it manually with the upstream commit the fork was created from, then re-run sync:\\n\\n' +\n ' git update-ref refs/cella/last-sync <upstream-sha>\\n',\n );\n }\n\n const root = await getRootCommit(cwd, headRef);\n if (!root) throw new Error(\"could not determine the fork's root commit to bootstrap sync ancestry\");\n\n await git(['replace', '-f', '--graft', root, baseSha], cwd);\n await git(['update-ref', 'refs/cella/last-sync', baseSha], cwd);\n}\n\n/** Whether `ancestor` is an ancestor of `descendant`. */\nexport async function isAncestor(cwd: string, ancestor: string, descendant: string): Promise<boolean> {\n try {\n await git(['merge-base', '--is-ancestor', ancestor, descendant], cwd);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Legacy sync point for forks that last synced before the manifest was committed: the local\n * last-sync ref, discarded while HEAD still sits at the recorded sync HEAD (an aborted merge,\n * see {@link storeLastSyncRef}).\n */\nasync function getLegacySyncRef(cwd: string, headRef: string): Promise<string | null> {\n const storedRef = await getStoredSyncRef(cwd);\n if (!storedRef) return null;\n\n const storedHead = await revParse(cwd, 'refs/cella/last-sync-head');\n if (storedHead) {\n const currentHead = await revParse(cwd, headRef);\n if (currentHead && currentHead === storedHead) return null;\n }\n\n return storedRef;\n}\n\n/**\n * The effective merge-base, preferring the recorded sync point when it's more recent.\n * This handles stale merge-base caused by previous squash syncs (single-parent commits\n * don't update git's merge-base graph).\n *\n * The manifest committed at `headRef` is the authoritative record: it lands iff the sync commit lands\n * and travels with the repo. The local last-sync ref is the fallback for forks whose last sync predates it.\n *\n * @returns The effective base commit, whether git's base was stale, and the recorded sync point\n */\nexport async function getEffectiveMergeBase(\n cwd: string,\n headRef: string,\n upstreamRef: string,\n): Promise<{ base: string; isStale: boolean; storedRef: string | null }> {\n const gitBase = await getMergeBase(cwd, headRef, upstreamRef);\n\n const recorded = (await readManifestBaseAtRef(cwd, headRef)) ?? (await getLegacySyncRef(cwd, headRef));\n if (!recorded) {\n return { base: gitBase, isStale: false, storedRef: null };\n }\n\n // Only prefer the recorded sync point when it is actually newer than git's own answer.\n const recordedIsNewer = await isAncestor(cwd, gitBase, recorded);\n if (recordedIsNewer && recorded !== gitBase) {\n return { base: recorded, isStale: true, storedRef: recorded };\n }\n\n return { base: gitBase, isStale: false, storedRef: recorded };\n}\n\n/**\n * Run `fn` with a temporary local graft that makes `baseSha` an ancestor of `headRef`, so\n * native git operations (merge-base resolution and the 3-way merge itself) see the recorded\n * sync point, not a stale historical ancestor.\n *\n * Squash syncs advance the recorded sync point (manifest + `refs/cella/last-sync`) without\n * advancing git's commit graph, so a plain `git merge` replays every upstream change since the\n * last true merge ancestor: hunks the fork already integrated (or deliberately resolved away)\n * re-apply as clean auto-merges or re-conflict on every sync. The graft adds `baseSha` as an\n * extra parent of the `headRef` commit via `git replace --graft`; replace refs are local-only\n * and the ref is deleted right after `fn`, so nothing ever leaks into pushed history.\n *\n * Runs `fn` without grafting when the graft is unnecessary or unsafe:\n * - `baseSha` is already an ancestor of `headRef` (git's own merge-base is not stale), or\n * - a replacement object already exists for the `headRef` commit (never clobber, e.g. the\n * scaffold root graft from {@link ensureSyncBase} when the root commit is HEAD).\n */\nexport async function withTemporarySyncBaseGraft<T>(\n cwd: string,\n headRef: string,\n baseSha: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const headSha = await revParse(cwd, headRef);\n if (!headSha || !(await commitObjectExists(cwd, baseSha))) return fn();\n\n // Native ancestry already covers the base: nothing to graft.\n if (await isAncestor(cwd, baseSha, headSha)) return fn();\n\n // Never clobber an existing replacement object for this commit.\n const existingReplacement = await git(['replace', '-l', headSha], cwd, { ignoreErrors: true });\n if (existingReplacement) return fn();\n\n const parentsRaw = await git(['log', '-1', '--format=%P', headSha], cwd, { ignoreErrors: true });\n const parents = parentsRaw ? parentsRaw.split(/\\s+/) : [];\n\n await git(['replace', '-f', '--graft', headSha, ...parents, baseSha], cwd);\n try {\n return await fn();\n } finally {\n await git(['replace', '-d', headSha], cwd, { ignoreErrors: true });\n }\n}\n","/**\n * Cella sync manifest: the committed record of the last upstream sync point. `upstream.commit`\n * seeds the merge-base on a clone without `refs/cella/last-sync` (fresh clone, CI), and the rest\n * shows in each sync PR which upstream point the app moved to. The sync engine stages it with\n * every applied sync.\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\n/** Committed manifest path, relative to the fork repo root. */\nexport const MANIFEST_FILE = 'cella/cella.manifest.json';\n\n/** The last upstream sync point recorded in {@link MANIFEST_FILE}. */\nexport interface SyncManifest {\n upstream: {\n /** GitHub slug of the upstream repo, e.g. 'cellajs/cella'. */\n repo?: string;\n /** Tracking mode at sync time. */\n track?: 'release' | 'branch';\n /** Integrated upstream commit SHA: the merge-base bootstrap seed. */\n commit: string;\n /** Release tag when tracking releases, else null. */\n release?: string | null;\n /** Human-readable link to the commit or release on GitHub. */\n url?: string;\n /** UTC timestamp of the sync (ISO 8601). */\n syncedAt?: string;\n };\n}\n\n/** Parse and validate raw manifest JSON. Returns null when malformed or missing a 40-hex upstream commit. */\nexport function parseSyncManifest(raw: string): SyncManifest | null {\n try {\n const parsed = JSON.parse(raw) as SyncManifest;\n const commit = parsed?.upstream?.commit;\n if (typeof commit !== 'string' || !/^[0-9a-f]{40}$/i.test(commit)) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\n/** Read and validate the manifest. Returns null when absent or malformed. */\nexport async function readSyncManifest(cwd: string): Promise<SyncManifest | null> {\n try {\n return parseSyncManifest(await readFile(join(cwd, MANIFEST_FILE), 'utf8'));\n } catch {\n return null;\n }\n}\n\n/**\n * Return the recorded upstream base commit SHA, or null.\n * Bootstrap seed for {@link ensureSyncBase} when no local `refs/cella/last-sync` exists.\n */\nexport async function readManifestBase(cwd: string): Promise<string | null> {\n const manifest = await readSyncManifest(cwd);\n return manifest ? manifest.upstream.commit.toLowerCase() : null;\n}\n\n/** Write the manifest as pretty JSON with a trailing newline. */\nexport async function writeSyncManifest(cwd: string, manifest: SyncManifest): Promise<void> {\n const manifestPath = join(cwd, MANIFEST_FILE);\n // Ensure the cella/ folder exists (a fresh fork may not have it yet on first sync).\n await mkdir(dirname(manifestPath), { recursive: true });\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\n}\n","/**\n * Upstream migration notes, read from git.\n *\n * Upstream ships one note per sync-breaking change in `cella/migrations/<id>/`: a README.md that\n * opens with flat frontmatter, then the title and a summary paragraph, plus at most one codemod\n * (the one non-test `.ts` file). The folder is upstream-only: the sync never brings it into the\n * fork and removes a copy it finds. Notes are read from upstream commits the sync already fetched.\n *\n * The fork records only the notes it has not handled yet, in `cella/cella.migrations.json` as\n * `{ \"pending\": [...] }`. The sync adds the notes that arrive with it; `cella migrate --mark`\n * removes them. A missing file means nothing is pending, so a new app needs no seed. Notes are\n * information, never a gate: nothing blocks on a pending note.\n */\n\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { git } from './git';\n\n/** Upstream folder holding one subfolder per note. Upstream-only: never synced into a fork. */\nexport const NOTES_DIR = 'cella/migrations';\n\n/** The fork's record of notes still to handle. */\nexport const PENDING_FILE = 'cella/cella.migrations.json';\n\n/** A note folder name: `<YYYYMMDDThhmm>-<slug>`, UTC minute precision, so ids sort chronologically. */\nconst NOTE_ID = /^\\d{8}T\\d{4}-[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/** One note, as read at an upstream ref. */\nexport interface MigrationNote {\n id: string;\n /** The README's `# ` heading; the id when the README has none. */\n title: string;\n /** The paragraph under the title. */\n summary: string;\n /** Changes upstream in a way app-specific code must follow. */\n syncBreaking: boolean;\n /** Bumped `clientCacheVersion` or shipped a lens module. */\n clientCacheBump: boolean;\n /** Default scan roots for the codemod. */\n roots: string[];\n /** File name of the codemod inside the note folder, or null for a manual note. */\n codemod: string | null;\n}\n\n/** Whether a file in a note folder is a codemod script: a `.ts` file that is not a test. */\nfunction isCodemodFile(name: string): boolean {\n return name.endsWith('.ts') && !name.endsWith('.test.ts');\n}\n\n/** Whether a path is upstream-only: the sync never brings it in and removes a fork copy. */\nexport function isUpstreamOnly(filePath: string): boolean {\n return filePath === NOTES_DIR || filePath.startsWith(`${NOTES_DIR}/`);\n}\n\n/** The lines after the frontmatter, without HTML comment lines (a comment opens at the start of a line). */\nfunction bodyLines(lines: string[]): string[] {\n let inComment = false;\n return lines.filter((line) => {\n if (!inComment && !line.trimStart().startsWith('<!--')) return true;\n inComment = !line.includes('-->');\n return false;\n });\n}\n\n/** Parse a note README. Unreadable frontmatter values fall back to false/empty. */\nexport function parseNote(id: string, source: string, fileNames: string[]): MigrationNote {\n const lines = source.replace(/\\r\\n/g, '\\n').split('\\n');\n const close = lines[0] === '---' ? lines.indexOf('---', 1) : -1;\n const meta = new Map<string, string>();\n for (const line of lines.slice(1, Math.max(close, 1))) {\n const match = /^(\\w+):\\s*(.*)$/.exec(line);\n if (match) meta.set(match[1], match[2].trim());\n }\n\n const body = bodyLines(lines.slice(close + 1)).join('\\n');\n const blocks = body\n .split(/\\n\\s*\\n/)\n .map((block) => block.trim())\n .filter(Boolean);\n const title = /^# (.+)$/.exec(blocks[0] ?? '')?.[1].trim();\n const summary = title && blocks[1] && !/^(#|>|[-*|]|```)/.test(blocks[1]) ? blocks[1].replace(/\\s*\\n\\s*/g, ' ') : '';\n\n return {\n id,\n title: title || id,\n summary,\n syncBreaking: meta.get('syncBreaking') === 'true',\n clientCacheBump: meta.get('clientCacheBump') === 'true',\n roots: (meta.get('roots') ?? '')\n .split(',')\n .map((root) => root.trim())\n .filter(Boolean),\n codemod: fileNames.find(isCodemodFile) ?? null,\n };\n}\n\n/** Ids of every note at `ref`, oldest first; empty when the ref has no notes folder. */\nexport async function listNoteIds(cwd: string, ref: string): Promise<string[]> {\n const out = await git(['ls-tree', '--name-only', `${ref}:${NOTES_DIR}`], cwd, { ignoreErrors: true });\n return out\n .split('\\n')\n .filter((name) => NOTE_ID.test(name))\n .sort();\n}\n\n/** One note at `ref`, or null when its README is not there. */\nexport async function readNote(cwd: string, ref: string, id: string): Promise<MigrationNote | null> {\n const source = await git(['show', `${ref}:${NOTES_DIR}/${id}/README.md`], cwd, { ignoreErrors: true });\n if (!source) return null;\n const files = await git(['ls-tree', '--name-only', `${ref}:${NOTES_DIR}/${id}`], cwd, { ignoreErrors: true });\n return parseNote(id, source, files.split('\\n').filter(Boolean));\n}\n\n/** Notes upstream added between two commits: present at `to`, absent at `from`. */\nexport async function arrivedNoteIds(cwd: string, from: string, to: string): Promise<string[]> {\n const [before, after] = await Promise.all([listNoteIds(cwd, from), listNoteIds(cwd, to)]);\n const known = new Set(before);\n return after.filter((id) => !known.has(id));\n}\n\n/** The fork's pending note ids. A missing file is an empty list. */\nexport async function readPending(cwd: string): Promise<string[]> {\n const path = join(cwd, PENDING_FILE);\n if (!existsSync(path)) return [];\n const parsed = JSON.parse(await readFile(path, 'utf8')) as { pending?: unknown };\n return Array.isArray(parsed.pending) ? parsed.pending.filter((id): id is string => typeof id === 'string') : [];\n}\n\n/** Write the pending ids, sorted and de-duplicated; an empty list deletes the file. */\nexport async function writePending(cwd: string, ids: string[]): Promise<void> {\n const path = join(cwd, PENDING_FILE);\n const pending = [...new Set(ids)].sort();\n if (pending.length === 0) {\n await rm(path, { force: true });\n return;\n }\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify({ pending }, null, 2)}\\n`, 'utf8');\n}\n\n/** GitHub permalink to a note's README at a commit, when upstream is on GitHub. */\nexport function noteUrl(upstreamGitHubUrl: string | undefined, commit: string, id: string): string | undefined {\n return upstreamGitHubUrl ? `${upstreamGitHubUrl}/blob/${commit}/${NOTES_DIR}/${id}/README.md` : undefined;\n}\n\n/**\n * The one info line sync, analyze and migrate print, e.g.\n * `migration notes: 94 of 97 handled · 3 arrived with this sync · 3 open: pnpm cella migrate`.\n */\nexport function formatNotesLine(\n total: number,\n open: number,\n arrived?: number,\n options: { dryRun?: boolean } = {},\n): string {\n const parts = [open === 0 ? `all ${total} handled` : `${Math.max(0, total - open)} of ${total} handled`];\n if (arrived) parts.push(`${arrived} ${options.dryRun ? 'arrive' : 'arrived'} with this sync`);\n if (open > 0) parts.push(`${open} open: pnpm cella migrate`);\n return `migration notes: ${parts.join(' · ')}`;\n}\n","/**\n * Merge engine, shared by analyze and sync. Analyze classifies every file from git refs and never\n * touches the fork. Sync merges in the fork itself (`git merge --no-commit`), resolves pinned and\n * ignored files to the fork side and leaves the merge staged, conflicts keeping their markers for\n * IDE 3-way resolution.\n */\n\nimport { existsSync } from 'node:fs';\nimport { rm } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n type AnalysisSummary,\n type AnalyzedFile,\n type CommitRangeEntry,\n type MergeResult,\n type RuntimeConfig,\n SYNC_APPLIED_STATUSES,\n type UpstreamOverridesReport,\n} from '../config/types';\nimport { cliVersionMismatch, readUpstreamCliRange } from '../utils/cli-version';\nimport { DEFAULT_UPSTREAM_REMOTE, resolveUpstream } from '../utils/config';\nimport {\n COMMIT_LIST_MAX,\n createSpinner,\n formatFetchedUpstreamDetail,\n formatMergeInProgressDetail,\n spinnerSuccess,\n spinnerText,\n VERSION,\n} from '../utils/display';\nimport {\n checkoutFromRef,\n countCommitsBetween,\n ensureRemote,\n ensureSyncBase,\n fetchRemote,\n fetchUpstreamTags,\n fileExistsAtRef,\n fileExistsInWorktree,\n getCommitInfo,\n getConflictedFiles,\n getCurrentBranch,\n getEffectiveMergeBase,\n getMergeBase,\n getShortSha,\n getStagedNewFiles,\n getUpstreamStatus,\n getWorkingTreeChangeCount,\n git,\n gitMv,\n gitRm,\n isAncestor,\n isPublishedUpstream,\n listCommitsBetween,\n merge,\n mergeAbort,\n removeFileFromWorktree,\n removeFileFully,\n resolveLatestReleaseTag,\n resolveUpstreamCommit,\n stagePath,\n storeLastSyncRef,\n withTemporarySyncBaseGraft,\n} from '../utils/git';\nimport { CONFIG_FILE, isManagedFile } from '../utils/managed-files';\nimport { MANIFEST_FILE, type SyncManifest, writeSyncManifest } from '../utils/manifest';\nimport {\n arrivedNoteIds,\n listNoteIds,\n NOTES_DIR,\n PENDING_FILE,\n readPending,\n writePending,\n} from '../utils/migration-notes';\nimport { groupIgnoredUpstreamChanges, groupProtectedUpstreamChanges, isIgnored, isPinned } from '../utils/overrides';\nimport { compareUpstreamOverrides } from '../utils/upstream-overrides';\nimport { type AnalyzePredicates, analyzeRefs, enrichChangeInfo } from './analyze-core';\n\ntype ProgressCallback = (message: string, detail?: string) => void;\n\ntype StepCallback = (label: string, detail?: string) => void;\n\n/**\n * Thrown when the upstream commit is behind the fork's last sync point: the fork already has it,\n * and merging it would stage a revert. `cella sync` ends as a no-op on it, unless the run pinned\n * the ref itself (`--ref`).\n */\nexport class BehindSyncPointError extends Error {}\n\n/**\n * Thrown before a new merge starts when upstream changed its sync config in ways the fork config\n * does not follow. Carries the report so the caller can print it.\n */\nexport class UpstreamConfigChangedError extends Error {\n readonly report: UpstreamOverridesReport;\n\n constructor(report: UpstreamOverridesReport) {\n super(\n [\n 'upstream changed its sync config and yours does not follow it: stopped before the merge, nothing changed.',\n ` add or drop the entries that fit your app in ${CONFIG_FILE}, commit, then rerun.`,\n ' to merge with your config as it stands, rerun with --keep-config.',\n ].join('\\n'),\n );\n this.report = report;\n }\n}\n\n/** Convert a git remote URL (SSH `git@github.com:org/repo.git` or HTTPS) to a GitHub base URL. */\nexport function getGitHubBaseUrl(remoteUrl: string): string | null {\n const match = remoteUrl.match(/github\\.com[:/]([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n return match ? `https://github.com/${match[1]}/${match[2]}` : null;\n}\n\n/** Protected whole-file resolution: the fork side wins outright (ignored or pinned). */\nfunction isProtectedFile(file: AnalyzedFile): boolean {\n return file.isIgnored || file.isPinned;\n}\n\n/** Build analyzer predicates for the sync direction (local = fork, incoming = upstream). */\nfunction syncPredicates(config: RuntimeConfig): AnalyzePredicates {\n return {\n isIgnored: (path) => isIgnored(path, config),\n isPinned: (path) => (config.unpinned ? isManagedFile(path) : isPinned(path, config)),\n };\n}\n\n/**\n * Apply the merge directly in the fork. Files are classified from git refs before the merge starts,\n * so pinned and ignored files go back to the fork side in one batch right after it, and the merge\n * is left staged for IDE 3-way conflict resolution.\n */\nasync function applyDirectMerge(\n forkPath: string,\n upstreamRef: string,\n mergeBaseRef: string,\n config: RuntimeConfig,\n onProgress?: ProgressCallback,\n): Promise<{\n remainingConflicts: string[];\n analyzedFiles: AnalyzedFile[];\n autoMergedFiles: string[];\n protectedConflicts: string[];\n}> {\n onProgress?.('analyzing files...');\n const analyzedFiles = await analyzeRefs(\n forkPath,\n 'HEAD',\n upstreamRef,\n mergeBaseRef,\n syncPredicates(config),\n onProgress,\n );\n\n // Protected files go back to the fork side right after the merge: restored where the fork has\n // them, removed where it does not, so a fork deletion stands.\n const batchRestorePaths: string[] = [];\n const batchRemovePaths: string[] = [];\n for (const file of analyzedFiles) {\n if (file.status === 'identical' || file.status === 'ahead') continue;\n if (file.isIgnored || (file.isPinned && !file.renamedFrom)) {\n (file.existsInFork ? batchRestorePaths : batchRemovePaths).push(file.path);\n }\n }\n\n // The temporary graft makes the merge 3-way against the recorded sync point, not git's own\n // (squash-stale) merge-base; without it, upstream hunks earlier syncs integrated re-apply or\n // re-conflict on every run.\n onProgress?.('starting merge in fork...');\n await withTemporarySyncBaseGraft(forkPath, 'HEAD', mergeBaseRef, () => merge(forkPath, upstreamRef));\n\n if (batchRestorePaths.length > 0) {\n onProgress?.(`batch restoring ${batchRestorePaths.length} pinned/ignored files...`);\n await checkoutFromRef(forkPath, 'HEAD', batchRestorePaths);\n }\n if (batchRemovePaths.length > 0) {\n onProgress?.(`batch removing ${batchRemovePaths.length} ignored files...`);\n await gitRm(forkPath, batchRemovePaths);\n for (const filePath of batchRemovePaths) {\n await removeFileFromWorktree(forkPath, filePath);\n }\n }\n\n // The remaining files, one by one; protected ones went with the batch above.\n for (const file of analyzedFiles) {\n const { path: filePath, status, existsInFork } = file;\n if (status === 'identical' || status === 'ahead' || isProtectedFile(file)) continue;\n\n if (status === 'diverged') {\n // git's merge result stands for diverged files.\n onProgress?.(`→ ${filePath}: using git merge result (diverged)`);\n continue;\n }\n\n if (status === 'behind') {\n if (!existsInFork) {\n onProgress?.(`→ ${filePath}: adding from upstream (new file)`);\n await checkoutFromRef(forkPath, upstreamRef, [filePath]);\n } else if (!file.existsInUpstream) {\n // Upstream deleted the file: removed from the fork, including leftovers after a squash merge.\n onProgress?.(`→ ${filePath}: removing (deleted in upstream)`);\n await removeFileFully(forkPath, filePath);\n } else {\n // Both exist and only upstream changed: upstream's version is taken explicitly,\n // which resolves false conflicts from a stale merge-base (previous squash syncs).\n onProgress?.(`→ ${filePath}: accepting upstream (behind)`);\n await checkoutFromRef(forkPath, upstreamRef, [filePath]);\n }\n continue;\n }\n\n if (status === 'deleted') {\n await removeFileFully(forkPath, filePath);\n continue;\n }\n\n if (status === 'renamed' && file.renamedFrom) {\n // Upstream renames apply as git mv to preserve history.\n const oldPath = file.renamedFrom;\n const oldPathExists = await fileExistsInWorktree(forkPath, oldPath);\n const newPathExists = await fileExistsInWorktree(forkPath, filePath);\n\n if (oldPathExists && !newPathExists) {\n onProgress?.(`→ ${oldPath} → ${filePath}: moving (renamed in upstream)`);\n try {\n await gitMv(forkPath, oldPath, filePath);\n } catch {\n // git mv can fail mid-merge: fall back to remove plus checkout.\n await removeFileFully(forkPath, oldPath);\n await checkoutFromRef(forkPath, upstreamRef, [filePath]);\n }\n } else if (oldPathExists && newPathExists) {\n // Both exist (merge already staged the new file, but the old one is still in the worktree).\n onProgress?.(`→ ${oldPath} → ${filePath}: completing rename (removing old)`);\n await removeFileFully(forkPath, oldPath);\n await checkoutFromRef(forkPath, upstreamRef, [filePath]);\n } else {\n // Rename already applied (or neither path exists): the new path gets upstream's content.\n onProgress?.(`→ ${filePath}: updating from upstream (renamed)`);\n await checkoutFromRef(forkPath, upstreamRef, [filePath]);\n }\n }\n }\n\n // Protected files whose upstream changes the fork-wins resolution dropped, for the sync summary\n // (a Set keeps insertion order, so the report order stays).\n const protectedConflicts = new Set(analyzedFiles.filter((file) => file.upstreamChanged).map((file) => file.path));\n\n // Remaining git conflicts: only ignored/pinned resolve to the fork; the rest keep their markers.\n for (const filePath of await getConflictedFiles(forkPath)) {\n if (!isIgnored(filePath, config) && !syncPredicates(config).isPinned(filePath)) continue;\n\n if (await fileExistsAtRef(forkPath, 'HEAD', filePath)) {\n onProgress?.(`→ ${filePath}: keeping fork (protected conflict)`);\n await checkoutFromRef(forkPath, 'HEAD', [filePath]);\n protectedConflicts.add(filePath);\n } else {\n onProgress?.(`→ ${filePath}: removing (protected conflict, not in fork)`);\n await removeFileFully(forkPath, filePath);\n }\n }\n\n const remainingConflicts = await getConflictedFiles(forkPath);\n const remainingConflictSet = new Set(remainingConflicts);\n const autoMergedFiles = analyzedFiles\n .filter((file) => file.status === 'diverged' && !remainingConflictSet.has(file.path))\n .map((file) => file.path);\n\n // Safety net: during a merge, the batched `git rm` can silently fail on newly added files, leaving\n // ignored files staged as added in the index and deleted from the working tree (AD).\n const stagedNewFiles = await getStagedNewFiles(forkPath);\n const staleIgnoredFiles = stagedNewFiles.filter((f) => isIgnored(f, config));\n if (staleIgnoredFiles.length > 0) {\n onProgress?.(`cleaning up ${staleIgnoredFiles.length} ignored files still in index...`);\n await gitRm(forkPath, staleIgnoredFiles, { cached: true });\n for (const filePath of staleIgnoredFiles) {\n await removeFileFromWorktree(forkPath, filePath);\n }\n }\n\n return { remainingConflicts, analyzedFiles, autoMergedFiles, protectedConflicts: [...protectedConflicts] };\n}\n\nfunction calculateSummary(files: AnalyzedFile[]): AnalysisSummary {\n const summary: AnalysisSummary = {\n managed: 0,\n identical: 0,\n ahead: 0,\n local: 0,\n drifted: 0,\n behind: 0,\n diverged: 0,\n pinned: 0,\n ignored: 0,\n deleted: 0,\n renamed: 0,\n };\n\n for (const file of files) {\n if (file.status !== 'identical' && isManagedFile(file.path)) {\n summary.managed++;\n continue;\n }\n\n summary[file.status]++;\n }\n\n return summary;\n}\n\n/** Upstream context resolved once per run and shared by both engine modes. */\ninterface UpstreamContext {\n /** Concrete upstream ref merged from (branch tip, release-tag ref or a --ref commit sha) */\n upstreamRef: string;\n /** Release tag when tracking releases */\n releaseTag?: string;\n /** Effective merge-base used for the 3-way analysis, which is also the last sync point */\n mergeBase: string;\n /** Base of the merge itself: the sync point, or the natural merge-base under --unpinned */\n mergeRef: string;\n /** Upstream GitHub URL base for commit links */\n upstreamGitHubUrl?: string;\n /** Upstream HEAD commit info */\n upstreamCommit: CommitRangeEntry;\n}\n\nfunction formatLocalCheckoutDetail(\n forkPath: string,\n branch: string,\n headSha: string,\n changeCount: number,\n upstream: { upstream: string | null; ahead: number; behind: number },\n): string {\n const tracking = upstream.upstream\n ? `, tracking ${upstream.upstream} (${upstream.ahead} ahead, ${upstream.behind} behind)`\n : ', no tracking branch';\n const workingTree =\n changeCount === 0\n ? ' working tree clean'\n : ` ${changeCount} uncommitted change${changeCount === 1 ? '' : 's'} in working tree, not included in analysis`;\n\n return [`${forkPath}`, ` ${branch} @ ${headSha}${tracking}`, workingTree].join('\\n');\n}\n\n/**\n * Resolve a `--ref` to the upstream commit this run syncs to, after the fetch: an upstream branch\n * name, a release tag or a sha (see `resolveUpstreamCommit`). Refuses a ref that does not resolve,\n * or one upstream never published on its branch or in a release (a fork commit, an upstream\n * feature branch). A release tag syncs as that release; anything else as its commit sha, recorded\n * like branch tracking.\n */\nasync function resolvePinnedRef(\n forkPath: string,\n config: RuntimeConfig,\n remoteName: string,\n branchRef: string,\n ref: string,\n): Promise<{ ref: string; releaseTag?: string }> {\n const resolved = await resolveUpstreamCommit(forkPath, remoteName, ref);\n if (!resolved) {\n throw new Error(\n `--ref '${ref}' does not resolve to a commit. Pass a commit sha, a release tag or a branch on ` +\n `${config.settings.upstreamUrl}.`,\n );\n }\n if (!(await isPublishedUpstream(forkPath, remoteName, branchRef, resolved.sha))) {\n throw new Error(\n `--ref '${ref}' (${resolved.sha.slice(0, 7)}) is not on ${branchRef} or in an upstream release. ` +\n 'Sync only to commits upstream has published there.',\n );\n }\n return resolved.release ? { ref: resolved.release.ref, releaseTag: resolved.release.tag } : { ref: resolved.sha };\n}\n\n/**\n * Resolve everything both modes need from upstream: remote setup, the concrete\n * ref to merge (branch tip, latest release tag or a pinned --ref), sync ancestry bootstrap,\n * effective merge-base, and commit info for progress output.\n */\nasync function prepareUpstream(\n config: RuntimeConfig,\n onProgress?: ProgressCallback,\n onStep?: StepCallback,\n): Promise<UpstreamContext> {\n const { forkPath } = config;\n\n onProgress?.('checking local checkout...');\n const [branch, headSha, changeCount, upstreamStatus] = await Promise.all([\n getCurrentBranch(forkPath),\n getShortSha(forkPath, 'HEAD'),\n getWorkingTreeChangeCount(forkPath),\n getUpstreamStatus(forkPath),\n ]);\n onStep?.('local checkout', formatLocalCheckoutDetail(forkPath, branch, headSha, changeCount, upstreamStatus));\n\n onProgress?.('setting up upstream remote...');\n const { track: configTrack, branchRef } = resolveUpstream(config.settings);\n const remoteName = DEFAULT_UPSTREAM_REMOTE;\n // A per-run --track flag (config.track) overrides the configured tracking mode.\n const track = config.track ?? configTrack;\n await ensureRemote(forkPath, remoteName, config.settings.upstreamUrl);\n\n onProgress?.(`fetching upstream (${remoteName})...`);\n await fetchRemote(forkPath, remoteName);\n\n // Resolve the concrete ref to merge from. A per-run --ref pins it (and wins over --track);\n // otherwise release tracking (default) syncs to the latest published release tag and\n // branch tracking follows the upstream branch tip.\n let upstreamRef = branchRef;\n let releaseTag: string | undefined;\n if (config.ref) {\n await fetchUpstreamTags(forkPath, remoteName);\n const pinned = await resolvePinnedRef(forkPath, config, remoteName, branchRef, config.ref);\n upstreamRef = pinned.ref;\n releaseTag = pinned.releaseTag;\n } else if (track === 'release') {\n await fetchUpstreamTags(forkPath, remoteName);\n const latest = await resolveLatestReleaseTag(forkPath, remoteName);\n if (!latest) {\n throw new Error(\n `no upstream release tags found on '${remoteName}'. Set upstreamTrack: 'branch' to follow ${branchRef}, ` +\n `or check that ${config.settings.upstreamUrl} publishes release tags.`,\n );\n }\n upstreamRef = latest.ref;\n releaseTag = latest.tag;\n }\n const upstreamLabel = releaseTag ?? (config.ref ? `--ref ${config.ref}` : upstreamRef);\n\n // Expose the resolved ref to downstream steps (packages/analyze read config.upstreamRef\n // after the engine runs). The static fallback set at CLI parse time is the branch tip.\n config.upstreamRef = upstreamRef;\n onStep?.('remote configured', `${upstreamLabel} → ${config.settings.upstreamUrl}`);\n\n // Stop before anything merges when upstream was built with a newer CLI than this one.\n const cliRange = await readUpstreamCliRange(forkPath, upstreamRef);\n const cliMismatch = cliRange ? cliVersionMismatch(VERSION, cliRange) : null;\n if (cliMismatch) throw new Error(cliMismatch);\n\n // Bootstrap sync ancestry for forks with unrelated history (create-cella scaffold or an\n // upstream history squash). No-op once a native merge-base exists. Runs after fetch so the\n // base commit object is present, and after upstreamRef is finalized so release tags resolve.\n onProgress?.('checking sync base...');\n await ensureSyncBase(forkPath, 'HEAD', upstreamRef);\n\n const upstreamGitHubUrl = getGitHubBaseUrl(config.settings.upstreamUrl) ?? undefined;\n\n // Effective merge base (handles a stale base from previous squash syncs).\n const mergeBase = (await getEffectiveMergeBase(forkPath, 'HEAD', upstreamRef)).base;\n const mergeRef = config.unpinned ? await getMergeBase(forkPath, 'HEAD', upstreamRef) : mergeBase;\n\n const upstreamCommit = await getCommitInfo(forkPath, upstreamRef);\n\n // An upstream commit behind the sync point (an earlier run went further with --ref or --track\n // branch) would stage a revert of everything after it as if upstream had undone it: stop.\n if (upstreamCommit.hash !== mergeBase && (await isAncestor(forkPath, upstreamCommit.hash, mergeBase))) {\n const [upstreamShort, syncShort] = await Promise.all([\n getShortSha(forkPath, upstreamCommit.hash),\n getShortSha(forkPath, mergeBase),\n ]);\n const hint = config.ref\n ? 'Pick a newer --ref.'\n : releaseTag\n ? `Nothing to sync until a release past ${syncShort}; to follow the tip instead, run with --track branch.`\n : `Nothing to sync until '${branchRef}' moves past ${syncShort}.`;\n throw new BehindSyncPointError(\n `upstream ${upstreamLabel} (${upstreamShort}) is behind the last sync point ${syncShort}: the fork already ` +\n `has it, and syncing it would revert the upstream changes after it.\\n${hint}`,\n );\n }\n const commitCount = await countCommitsBetween(forkPath, mergeBase, upstreamRef);\n const upstreamCommits =\n commitCount > 0 ? await listCommitsBetween(forkPath, mergeBase, upstreamRef, COMMIT_LIST_MAX) : [];\n\n onStep?.('fetched upstream', formatFetchedUpstreamDetail(commitCount, upstreamCommits, upstreamGitHubUrl));\n\n return { upstreamRef, releaseTag, mergeBase, mergeRef, upstreamGitHubUrl, upstreamCommit };\n}\n\n/**\n * Stop a new merge when upstream changed its sync config since the sync point in ways the fork\n * config does not follow. The merge runs on the fork's config, so a path upstream newly ignores or\n * pins would arrive as an ordinary synced file (upstream renamed an ignored folder, the fork's list\n * still names the old one). `--keep-config` skips the gate; an unreadable upstream config or a\n * failed comparison never stops the run.\n */\nasync function assertSyncConfigFollowed(config: RuntimeConfig, ctx: UpstreamContext): Promise<void> {\n if (config.keepConfig) return;\n const report = await compareUpstreamOverrides(config.forkPath, ctx.mergeBase, ctx.upstreamRef, config).catch(\n () => undefined,\n );\n if (report?.kind === 'changes') throw new UpstreamConfigChangedError(report);\n}\n\n/** MergeResult fields shared by both engine modes. */\nfunction resultMeta(config: RuntimeConfig, ctx: UpstreamContext) {\n return {\n upstreamBranch: config.settings.upstreamBranch ?? 'main',\n upstreamRef: ctx.upstreamRef,\n upstreamTag: ctx.releaseTag,\n upstreamGitHubUrl: ctx.upstreamGitHubUrl,\n upstreamCommit: ctx.upstreamCommit,\n };\n}\n\n/**\n * Upstream changes the fork never receives, shared by both engine modes: the upstream config's\n * `overrides` entries and `packageJsonSync` keys the fork config does not follow (the config itself\n * never syncs), ignored files only upstream changed, and the protected files upstream also changed\n * (`protectedConflicts`) grouped by entry. Report only, read from refs (the merge state is\n * irrelevant); a failure here yields no report and never fails the run.\n */\nasync function upstreamOnlyReports(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n files: AnalyzedFile[],\n protectedConflicts: string[],\n): Promise<\n Pick<MergeResult, 'upstreamDiffRange' | 'upstreamOverrides' | 'ignoredUpstreamChanges' | 'protectedUpstreamChanges'>\n> {\n const { forkPath } = config;\n try {\n const [baseSha, upstreamSha, upstreamOverrides] = await Promise.all([\n getShortSha(forkPath, ctx.mergeBase),\n // the commit, not an annotated release tag object\n getShortSha(forkPath, ctx.upstreamCommit.hash),\n compareUpstreamOverrides(forkPath, ctx.mergeBase, ctx.upstreamRef, config),\n ]);\n return {\n upstreamDiffRange: `${baseSha}..${upstreamSha}`,\n upstreamOverrides,\n ignoredUpstreamChanges: groupIgnoredUpstreamChanges(files, config.overrides?.ignored ?? []),\n protectedUpstreamChanges: groupProtectedUpstreamChanges(protectedConflicts, config),\n };\n } catch {\n return {};\n }\n}\n\n/** Upstream migration notes for this sync range, plus the fork's pending list once the arrivals are added. */\ninterface NotesInRange {\n total: number;\n arrived: string[];\n pending: string[];\n}\n\n/**\n * Read the migration notes for this sync range: upstream's notes at the incoming ref and the ones\n * added since the recorded sync point. Runs before the sync point moves. A failure yields no notes\n * and never fails the run.\n */\nasync function readNotesInRange(config: RuntimeConfig, ctx: UpstreamContext): Promise<NotesInRange | undefined> {\n const { forkPath } = config;\n try {\n const [total, arrived, pending] = await Promise.all([\n listNoteIds(forkPath, ctx.upstreamRef),\n arrivedNoteIds(forkPath, ctx.mergeBase, ctx.upstreamRef),\n readPending(forkPath),\n ]);\n return { total: total.length, arrived, pending: [...new Set([...pending, ...arrived])] };\n } catch {\n return undefined;\n }\n}\n\n/** The {@link MergeResult} view of {@link NotesInRange}. */\nfunction notesResult(notes: NotesInRange | undefined): Pick<MergeResult, 'migrationNotes'> {\n return notes ? { migrationNotes: { total: notes.total, arrived: notes.arrived, open: notes.pending.length } } : {};\n}\n\n/**\n * Remove the fork's copy of the upstream-only notes folder (forks that synced it before it became\n * upstream-only, and new apps whose scaffold cloned it). Staged with the sync.\n */\nasync function removeUpstreamOnlyCopy(forkPath: string, onStep?: StepCallback): Promise<void> {\n if (!existsSync(join(forkPath, NOTES_DIR))) return;\n await git(['rm', '-r', '-q', '--ignore-unmatch', '--', NOTES_DIR], forkPath);\n await rm(join(forkPath, NOTES_DIR), { recursive: true, force: true });\n onStep?.('migration notes', `removed ${NOTES_DIR}/: notes stay upstream, list them with pnpm cella migrate`);\n}\n\n/**\n * SYNC MODE: merge, analyze, and resolve directly in the fork, then record the\n * sync point (local ref + committed manifest) and leave the merge staged.\n */\nasync function runSyncMerge(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n onProgress?: ProgressCallback,\n onStep?: StepCallback,\n): Promise<MergeResult> {\n const { forkPath } = config;\n const { upstreamRef, releaseTag, mergeRef, upstreamGitHubUrl, upstreamCommit } = ctx;\n\n // Last gate before anything merges (the CLI version gate runs in prepareUpstream)\n await assertSyncConfigFollowed(config, ctx);\n\n const notes = await readNotesInRange(config, ctx);\n\n const { remainingConflicts, analyzedFiles, autoMergedFiles, protectedConflicts } = await applyDirectMerge(\n forkPath,\n upstreamRef,\n mergeRef,\n config,\n onProgress,\n );\n\n const summary = calculateSummary(analyzedFiles);\n const synced = analyzedFiles.filter((file) => ['behind', 'diverged', 'renamed'].includes(file.status)).length;\n\n const totalResolved = analyzedFiles.filter((file) => SYNC_APPLIED_STATUSES.includes(file.status)).length;\n\n // Record the sync point in lockstep: the local `refs/cella/last-sync` ref plus the manifest,\n // staged so it rides in the sync commit.\n const syncManifest: SyncManifest = {\n upstream: {\n repo: upstreamGitHubUrl ? upstreamGitHubUrl.replace('https://github.com/', '') : undefined,\n track: releaseTag ? 'release' : 'branch',\n commit: upstreamCommit.hash,\n release: releaseTag ?? null,\n url: upstreamGitHubUrl\n ? releaseTag\n ? `${upstreamGitHubUrl}/releases/tag/${releaseTag}`\n : `${upstreamGitHubUrl}/commit/${upstreamCommit.hash}`\n : undefined,\n syncedAt: new Date().toISOString(),\n },\n };\n const recordSyncPoint = async () => {\n await storeLastSyncRef(forkPath, upstreamCommit.hash);\n await writeSyncManifest(forkPath, syncManifest);\n await stagePath(forkPath, MANIFEST_FILE);\n // Notes that arrived join the fork's pending list; an empty list deletes the file.\n if (notes) {\n await writePending(forkPath, notes.pending);\n await stagePath(forkPath, PENDING_FILE);\n }\n await removeUpstreamOnlyCopy(forkPath, onStep);\n };\n\n // MERGE_HEAD stays in both staged cases: the IDE shows a 3-way merge, `git merge --abort` works,\n // and the finishing rerun tells a staged sync from a dirty tree, then commits it single-parent.\n if (remainingConflicts.length > 0) {\n await recordSyncPoint();\n onStep?.(\n 'merge in progress',\n formatMergeInProgressDetail(remainingConflicts.length, autoMergedFiles, { forkPath }, 100),\n );\n } else if (totalResolved > 0) {\n const label = synced > 0 ? `${synced} files from upstream` : 'upstream changes';\n await recordSyncPoint();\n onStep?.('synced', `${label} (staged, commit to finish)`);\n } else {\n // Nothing changed: clean up the merge state.\n await mergeAbort(forkPath);\n onStep?.('up to date', 'no upstream changes to sync');\n }\n\n return {\n success: remainingConflicts.length === 0,\n files: analyzedFiles,\n summary,\n conflicts: remainingConflicts,\n autoMergedFiles,\n protectedConflicts,\n ...resultMeta(config, ctx),\n ...(await upstreamOnlyReports(config, ctx, analyzedFiles, protectedConflicts)),\n ...notesResult(notes),\n };\n}\n\n/** ANALYZE MODE: classify every file from git refs; the fork is never touched. */\nasync function runAnalyzePreview(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n onProgress?: ProgressCallback,\n onStep?: StepCallback,\n): Promise<MergeResult> {\n const { forkPath } = config;\n const notes = await readNotesInRange(config, ctx);\n\n onProgress?.('analyzing files...');\n const analyzedFiles = await analyzeRefs(\n forkPath,\n 'HEAD',\n ctx.upstreamRef,\n ctx.mergeRef,\n syncPredicates(config),\n onProgress,\n );\n await enrichChangeInfo(forkPath, analyzedFiles, ctx.mergeBase, 'HEAD', ctx.upstreamRef);\n const protectedConflicts = analyzedFiles.filter((f) => f.upstreamChanged).map((f) => f.path);\n const reports = await upstreamOnlyReports(config, ctx, analyzedFiles, protectedConflicts);\n onStep?.('analysis complete', `${analyzedFiles.length} files analyzed, dry run, no changes applied`);\n\n return {\n success: true,\n files: analyzedFiles,\n summary: calculateSummary(analyzedFiles),\n // For analyze mode, count diverged files as potential conflicts\n conflicts: analyzedFiles.filter((f) => f.status === 'diverged').map((f) => f.path),\n protectedConflicts,\n ...resultMeta(config, ctx),\n ...reports,\n ...notesResult(notes),\n };\n}\n\n/**\n * Merge engine entry point for analyze and sync: prepare upstream once, then run the requested\n * mode. Progress updates the spinner text; each completed step prints with its detail and starts a\n * fresh spinner.\n */\nexport async function runEngineWithSpinner(config: RuntimeConfig, apply: boolean): Promise<MergeResult> {\n const onProgress: ProgressCallback = (message) => spinnerText(message);\n const onStep: StepCallback = (label, detail) => {\n spinnerSuccess(label, detail);\n createSpinner('...');\n };\n const ctx = await prepareUpstream(config, onProgress, onStep);\n return apply ? runSyncMerge(config, ctx, onProgress, onStep) : runAnalyzePreview(config, ctx, onProgress, onStep);\n}\n","/**\n * Version parsing shared by package.json merging and the CLI version check.\n */\n\ninterface ComparableVersion {\n major: number;\n minor: number;\n patch: number;\n}\n\n/**\n * The version a plain version or simple range names (`1.2.3`, `^1.2`, `>=1.2.3`), or null for\n * anything else.\n */\nexport function parseComparableVersion(version: string): ComparableVersion | null {\n const trimmed = version.trim();\n const match = trimmed.match(\n /^(?:\\^|~|>=|<=|>|<|=)?\\s*v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/,\n );\n\n if (!match) return null;\n\n return {\n major: Number(match[1]),\n minor: Number(match[2] ?? 0),\n patch: Number(match[3] ?? 0),\n };\n}\n\n/** Standard comparator: negative when `left` is lower, zero when equal, positive when higher. */\nexport function compareVersions(left: ComparableVersion, right: ComparableVersion): number {\n if (left.major !== right.major) return left.major - right.major;\n if (left.minor !== right.minor) return left.minor - right.minor;\n return left.patch - right.patch;\n}\n\n/** Whether a version carries a prerelease tag (`2.0.0-beta.1`). */\nexport function isPrerelease(version: string): boolean {\n return /^v?\\d+(?:\\.\\d+){0,2}-/.test(version.trim());\n}\n\n/**\n * Order of two version strings; a prerelease sorts below its release. Unparsable input sorts\n * lowest, so it never wins a \"highest version\" pick.\n */\nexport function compareVersionStrings(left: string, right: string): number {\n const a = parseComparableVersion(left);\n const b = parseComparableVersion(right);\n if (!a || !b) return Number(!!a) - Number(!!b);\n return compareVersions(a, b) || Number(isPrerelease(right)) - Number(isPrerelease(left));\n}\n\n/**\n * Whether `version` falls inside a comparator range as security advisories write them:\n * space-separated comparators (`>=4.0.0 <4.3.2`, `<=3.0.3`), alternatives joined by `||`.\n * A range with no readable comparator matches nothing.\n */\nexport function satisfiesComparators(version: string, range: string): boolean {\n return range.split('||').some((alternative) => {\n const comparators = [...alternative.matchAll(/(>=|<=|>|<|=)?\\s*v?(\\d+(?:\\.\\d+){0,2}(?:-[0-9A-Za-z.-]+)?)/g)];\n if (comparators.length === 0) return false;\n return comparators.every(([, operator = '=', bound]) => {\n const order = compareVersionStrings(version, bound);\n if (operator === '>=') return order >= 0;\n if (operator === '<=') return order <= 0;\n if (operator === '>') return order > 0;\n if (operator === '<') return order < 0;\n return order === 0;\n });\n });\n}\n\n/**\n * Whether moving `from` to `to` leaves the range a caret allows: another major, or below 1.0\n * another minor (below 0.1 any other version).\n */\nexport function isBreakingJump(from: string, to: string): boolean {\n const a = parseComparableVersion(from);\n const b = parseComparableVersion(to);\n if (!a || !b) return true;\n if (a.major !== b.major) return true;\n if (a.major > 0) return false;\n if (a.minor !== b.minor) return true;\n return a.minor === 0 && a.patch !== b.patch;\n}\n","/**\n * The CLI version upstream asks for.\n *\n * A sync bumps the fork's `@cellajs/cli` along with its other packages, so each sync runs on the\n * CLI from before it. A fix to analyze or sync would reach a fork one sync late, and that run\n * would silently miss what the fix reports. Upstream's root package.json names the CLI it was\n * built with; a run on an older CLI stops before it touches the fork.\n */\n\nimport { git } from './git';\nimport { compareVersions, parseComparableVersion } from './versions';\n\nconst CLI_PACKAGE = '@cellajs/cli';\n\n/** The `@cellajs/cli` range in upstream's root package.json at `ref`, or null when it names none. */\nexport async function readUpstreamCliRange(repoPath: string, ref: string): Promise<string | null> {\n const source = await git(['show', `${ref}:package.json`], repoPath, { ignoreErrors: true });\n if (!source) return null;\n try {\n const pkg = JSON.parse(source) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n return pkg.devDependencies?.[CLI_PACKAGE] ?? pkg.dependencies?.[CLI_PACKAGE] ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * The error message when `running` is older than the lowest version `range` admits, else null.\n * A range with no lower bound (`<1.0.0`, `workspace:*`, `link:…`, `a || b`) never blocks.\n */\nexport function cliVersionMismatch(running: string, range: string): string | null {\n if (/^\\s*(<|>(?!=))/.test(range)) return null;\n const required = parseComparableVersion(range);\n const current = parseComparableVersion(running);\n if (!required || !current || compareVersions(current, required) >= 0) return null;\n return [\n `upstream needs ${CLI_PACKAGE} ${range}, this is ${running}: an older CLI misses fixes to the sync itself.`,\n ` update it, commit, then rerun: pnpm add -D -w '${CLI_PACKAGE}@${range}'`,\n ].join('\\n');\n}\n","/**\n * Upstream override changes: the sync never merges the fork's config, so this reads upstream's\n * `overrides` lists and `packageJsonSync` keys at the merge-base and the incoming ref (ts-morph,\n * syntax only) and reports the entries the fork config does not follow. Report only.\n */\n\nimport { Node, type ObjectLiteralExpression, Project, type SourceFile, SyntaxKind } from 'ts-morph';\nimport type { CellaCliConfig, OverrideListChanges, UpstreamOverridesReport } from '../config/types';\nimport { DEFAULT_PACKAGE_JSON_SYNC } from './config';\nimport { git } from './git';\nimport { CONFIG_FILE } from './managed-files';\nimport { isUnderAnyFolder, normalizeEntry } from './overrides';\n\n/** The lists the comparison reads from a sync config, as plain string entries. */\ninterface OverrideLists {\n pinned: string[];\n ignored: string[];\n /** `settings.packageJsonSync`, the default when the config names none; null when it cannot be read statically. */\n packageJsonSync: string[] | null;\n}\n\nconst LIST_KEYS = ['pinned', 'ignored'] as const;\n\n/** Resolve wrappers (`(x)`, `x as T`, `x satisfies T`) and same-file identifiers to the underlying expression. */\nfunction resolveExpression(node: Node | undefined, sourceFile: SourceFile, depth = 0): Node | undefined {\n if (!node || depth > 8) return node;\n if (Node.isParenthesizedExpression(node) || Node.isAsExpression(node) || Node.isSatisfiesExpression(node)) {\n return resolveExpression(node.getExpression(), sourceFile, depth + 1);\n }\n if (Node.isIdentifier(node)) {\n return resolveExpression(\n sourceFile.getVariableDeclaration(node.getText())?.getInitializer(),\n sourceFile,\n depth + 1,\n );\n }\n return node;\n}\n\n/** The config object: the `defineConfig({...})` argument, else a plain `export default {...}`. */\nfunction findConfigObject(sourceFile: SourceFile): ObjectLiteralExpression | undefined {\n for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n if (call.getExpression().getText() !== 'defineConfig') continue;\n const arg = resolveExpression(call.getArguments()[0], sourceFile);\n if (Node.isObjectLiteralExpression(arg)) return arg;\n }\n const exported = sourceFile.getExportAssignment((assignment) => !assignment.isExportEquals());\n const value = resolveExpression(exported?.getExpression(), sourceFile);\n return Node.isObjectLiteralExpression(value) ? value : undefined;\n}\n\n/**\n * Resolved value of a named property in an object literal: `undefined` when absent (spreads and\n * methods are not followed), `null` when present without a readable value.\n */\nfunction readProperty(object: ObjectLiteralExpression, name: string, sourceFile: SourceFile): Node | null | undefined {\n for (const property of object.getProperties()) {\n if (Node.isPropertyAssignment(property)) {\n if (property.getName().replace(/^['\"`]|['\"`]$/g, '') !== name) continue;\n return resolveExpression(property.getInitializer(), sourceFile) ?? null;\n }\n if (Node.isShorthandPropertyAssignment(property) && property.getName() === name) {\n return resolveExpression(property.getNameNode(), sourceFile) ?? null;\n }\n }\n return undefined;\n}\n\n/** String entries of an array literal; null when `node` is not one. Other elements (spreads, variables) are skipped. */\nfunction readStringEntries(node: Node): string[] | null {\n if (!Node.isArrayLiteralExpression(node)) return null;\n const entries: string[] = [];\n for (const element of node.getElements()) {\n if (Node.isStringLiteral(element) || Node.isNoSubstitutionTemplateLiteral(element)) {\n entries.push(element.getLiteralValue());\n }\n }\n return entries;\n}\n\n/**\n * `settings.packageJsonSync` of a config object: the default keys when `settings` or the list is\n * absent, null when either is present without a statically readable value.\n */\nfunction readPackageJsonSync(config: ObjectLiteralExpression, sourceFile: SourceFile): string[] | null {\n const settings = readProperty(config, 'settings', sourceFile);\n if (settings === undefined) return [...DEFAULT_PACKAGE_JSON_SYNC];\n if (!settings || !Node.isObjectLiteralExpression(settings)) return null;\n const keys = readProperty(settings, 'packageJsonSync', sourceFile);\n if (keys === undefined) return [...DEFAULT_PACKAGE_JSON_SYNC];\n return keys ? readStringEntries(keys) : null;\n}\n\n/**\n * Extract `overrides.pinned`, `overrides.ignored` and `settings.packageJsonSync` from config source\n * without evaluating it; only string literals count. Null when the config object or a present\n * `overrides`/list cannot be read statically; an unreadable `packageJsonSync` alone reads as null.\n */\nexport function parseOverrideLists(source: string): OverrideLists | null {\n try {\n const project = new Project({ useInMemoryFileSystem: true, skipLoadingLibFiles: true });\n const sourceFile = project.createSourceFile('cella.config.ts', source);\n const config = findConfigObject(sourceFile);\n if (!config) return null;\n\n const lists: OverrideLists = {\n pinned: [],\n ignored: [],\n packageJsonSync: readPackageJsonSync(config, sourceFile),\n };\n const overrides = readProperty(config, 'overrides', sourceFile);\n if (overrides === undefined) return lists;\n if (!overrides || !Node.isObjectLiteralExpression(overrides)) return null;\n\n for (const key of LIST_KEYS) {\n const list = readProperty(overrides, key, sourceFile);\n if (list === undefined) continue;\n const entries = list ? readStringEntries(list) : null;\n if (!entries) return null;\n lists[key] = entries;\n }\n return lists;\n } catch {\n return null;\n }\n}\n\n/**\n * Compare upstream's lists at the merge-base and at the incoming ref against the fork's lists.\n *\n * - added: new upstream entries the fork list lacks (an exact entry or a parent folder covers it).\n * - removed: entries upstream dropped that the fork list still carries verbatim.\n *\n * `packageJsonSync` keys compare by name, and not at all when a side could not be read. Entries\n * upstream had all along are never reported, whether or not the fork has them.\n */\nexport function diffOverrideLists(\n base: OverrideLists,\n incoming: OverrideLists,\n fork: OverrideLists,\n): Record<(typeof LIST_KEYS)[number] | 'packageJsonSync', OverrideListChanges> {\n const diff = (key: (typeof LIST_KEYS)[number]): OverrideListChanges => {\n const baseSet = new Set(base[key].map(normalizeEntry).filter(Boolean));\n const incomingSet = new Set(incoming[key].map(normalizeEntry).filter(Boolean));\n const forkEntries = fork[key].map(normalizeEntry).filter(Boolean);\n return {\n added: [...incomingSet].filter((entry) => !baseSet.has(entry) && !isUnderAnyFolder(entry, forkEntries)),\n removed: [...baseSet].filter((entry) => !incomingSet.has(entry) && forkEntries.includes(entry)),\n };\n };\n const diffKeys = (): OverrideListChanges => {\n const [baseKeys, incomingKeys, forkKeys] = [base.packageJsonSync, incoming.packageJsonSync, fork.packageJsonSync];\n if (!baseKeys || !incomingKeys || !forkKeys) return { added: [], removed: [] };\n return {\n added: [...new Set(incomingKeys)].filter((key) => !baseKeys.includes(key) && !forkKeys.includes(key)),\n removed: [...new Set(baseKeys)].filter((key) => !incomingKeys.includes(key) && forkKeys.includes(key)),\n };\n };\n return { pinned: diff('pinned'), ignored: diff('ignored'), packageJsonSync: diffKeys() };\n}\n\n/**\n * Report how upstream's `overrides` and `packageJsonSync` changed between the merge-base and the\n * incoming ref, limited to entries the fork config does not follow (see {@link diffOverrideLists}).\n * Undefined when there is nothing to report; `unreadable` when the config is missing or unparsable\n * at one side only.\n */\nexport async function compareUpstreamOverrides(\n repoPath: string,\n mergeBaseRef: string,\n incomingRef: string,\n forkConfig: CellaCliConfig,\n): Promise<UpstreamOverridesReport | undefined> {\n // Empty when upstream has no config at that ref.\n const [baseSource, incomingSource] = await Promise.all(\n [mergeBaseRef, incomingRef].map((ref) => git(['show', `${ref}:${CONFIG_FILE}`], repoPath, { ignoreErrors: true })),\n );\n if (baseSource === incomingSource) return undefined;\n\n const base = baseSource ? parseOverrideLists(baseSource) : null;\n if (!base) return { kind: 'unreadable', side: 'base' };\n const incoming = incomingSource ? parseOverrideLists(incomingSource) : null;\n if (!incoming) return { kind: 'unreadable', side: 'incoming' };\n\n const fork: OverrideLists = {\n pinned: forkConfig.overrides?.pinned ?? [],\n ignored: forkConfig.overrides?.ignored ?? [],\n packageJsonSync: forkConfig.settings.packageJsonSync ?? DEFAULT_PACKAGE_JSON_SYNC,\n };\n const changes = diffOverrideLists(base, incoming, fork);\n const count = Object.values(changes).reduce((n, list) => n + list.added.length + list.removed.length, 0);\n return count > 0 ? { kind: 'changes', ...changes } : undefined;\n}\n","/**\n * Direction-agnostic ref analyzer: compares a \"local\" ref against an \"incoming\" ref from a shared\n * merge-base and classifies every changed file, with git plumbing on refs only, never the working\n * tree. Sync runs it with local = fork HEAD and incoming = upstream, contributions with local =\n * cella branch and incoming = fork branch; `existsInFork`/`existsInUpstream` map to local/incoming.\n */\n\nimport type { AnalyzedFile, FileStatus } from '../config/types';\nimport { type FileChangeInfo, getDiffStat, getFileChangeInfo, getFileChanges, getFileHashesAtRef } from '../utils/git';\nimport { isGeneratedFile, isManagedFile } from '../utils/managed-files';\n\n/** Predicates that steer classification (direction-specific). */\nexport interface AnalyzePredicates {\n /** True if the file is inside owned/ignored territory (never synced). */\n isIgnored: (path: string) => boolean;\n /** True if the file is pinned (local wins on conflict). */\n isPinned: (path: string) => boolean;\n}\n\n/** Whether an ignored path can carry `upstreamOnly`: not managed and not generated output. */\nfunction isReportableIgnored(filePath: string): boolean {\n return !isManagedFile(filePath) && !isGeneratedFile(filePath);\n}\n\ntype ProgressCallback = (message: string) => void;\n\n/** Analyze files between a local and an incoming ref using a merge-base, in a repo that reaches all three. */\nexport async function analyzeRefs(\n repoPath: string,\n localRef: string,\n incomingRef: string,\n mergeBaseRef: string,\n predicates: AnalyzePredicates,\n onProgress?: ProgressCallback,\n): Promise<AnalyzedFile[]> {\n onProgress?.('collecting file hashes (batch)...');\n\n const [forkHashes, upstreamHashes, baseHashes] = await Promise.all([\n getFileHashesAtRef(repoPath, localRef),\n getFileHashesAtRef(repoPath, incomingRef),\n getFileHashesAtRef(repoPath, mergeBaseRef),\n ]);\n\n // Changes between base and each tip; rename detection runs at -M90%.\n const upstreamChanges = await getFileChanges(repoPath, mergeBaseRef, incomingRef);\n const forkChanges = await getFileChanges(repoPath, mergeBaseRef, localRef);\n\n // oldPath -> newPath for renames in incoming.\n const upstreamRenames = new Map<string, string>();\n for (const [newPath, change] of upstreamChanges) {\n if (change.status === 'R' && change.oldPath) {\n upstreamRenames.set(change.oldPath, newPath);\n }\n }\n\n const allFiles = new Set([...forkHashes.keys(), ...upstreamHashes.keys(), ...upstreamRenames.keys()]);\n\n const changedFiles = new Set([...upstreamChanges.keys(), ...forkChanges.keys(), ...upstreamRenames.keys()]);\n\n // Content hashes present anywhere in incoming, for O(1) rename-source lookups below.\n const upstreamHashSet = new Set(upstreamHashes.values());\n\n onProgress?.(\n `analyzing ${changedFiles.size} changed files (${allFiles.size - changedFiles.size} identical skipped)...`,\n );\n\n const analyzedFiles: AnalyzedFile[] = [];\n const handledOldPaths = new Set<string>();\n // Protected files flagged `upstreamChanged` via a rename: their numstat at the new path\n // would count the whole file as added, so they get no line count.\n const renamedProtected = new Set<string>();\n let processed = 0;\n\n for (const filePath of allFiles) {\n if (handledOldPaths.has(filePath)) continue;\n\n const inFork = forkHashes.has(filePath);\n const inUpstream = upstreamHashes.has(filePath);\n\n const fileIsIgnored = predicates.isIgnored(filePath);\n const fileIsPinned = predicates.isPinned(filePath);\n\n const upstreamChange = upstreamChanges.get(filePath);\n const isUpstreamRename = upstreamChange?.status === 'R' && upstreamChange.oldPath;\n\n const renamedToPath = upstreamRenames.get(filePath);\n\n const push = (status: FileStatus, extra: Partial<AnalyzedFile> = {}) =>\n analyzedFiles.push({\n path: filePath,\n status,\n isIgnored: fileIsIgnored,\n isPinned: fileIsPinned,\n existsInFork: inFork,\n existsInUpstream: inUpstream,\n ...extra,\n });\n\n if (!changedFiles.has(filePath) && inFork && inUpstream) {\n push('identical');\n continue;\n }\n\n processed++;\n if (processed % 100 === 0) {\n onProgress?.(`analyzing ${processed}/${changedFiles.size} changed files...`);\n }\n\n const forkHash = forkHashes.get(filePath) ?? null;\n const upstreamHash = upstreamHashes.get(filePath) ?? null;\n const baseHash = baseHashes.get(filePath) ?? null;\n\n let status: FileStatus;\n let renamedFrom: string | undefined;\n\n if (isUpstreamRename && upstreamChange.oldPath) {\n const oldPath = upstreamChange.oldPath;\n const oldPathInFork = forkHashes.has(oldPath);\n const forkOldHash = forkHashes.get(oldPath) ?? null;\n const baseOldHash = baseHashes.get(oldPath) ?? null;\n\n handledOldPaths.add(oldPath);\n\n const forkModifiedOld = forkOldHash !== baseOldHash;\n\n // A renamed directory (e.g. config/ → shared/) can leave the local pinned\n // list referencing the old path, so both paths count for pinned/ignored.\n const oldPathPinned = predicates.isPinned(oldPath);\n\n let upstreamChanged: boolean | undefined;\n if (fileIsPinned || oldPathPinned || predicates.isIgnored(oldPath)) {\n // Protected: local's version is kept at the new path.\n status = 'pinned';\n // Local edited the old file and incoming changed its content beyond the rename.\n if (forkModifiedOld && upstreamHash !== baseOldHash) {\n upstreamChanged = true;\n renamedProtected.add(filePath);\n }\n } else if (!oldPathInFork) {\n // Old path absent locally (deleted or moved): plain behind, git's merge handles it.\n status = 'behind';\n } else if (forkModifiedOld) {\n // Local modified the old file: diverged, git's merge surfaces the conflict.\n status = 'diverged';\n renamedFrom = oldPath;\n } else {\n // Unmodified old file locally: a clean rename to apply.\n status = 'renamed';\n renamedFrom = oldPath;\n }\n\n // Incoming moved a file into (or within) ignored territory and the local side never\n // touched the source: an upstream-only change at the new path.\n const upstreamOnly = fileIsIgnored && !forkModifiedOld && isReportableIgnored(filePath);\n\n push(status, { existsInUpstream: true, renamedFrom, upstreamChanged, upstreamOnly: upstreamOnly || undefined });\n continue;\n }\n\n // Old paths of incoming renames are handled at the new path.\n if (renamedToPath) {\n handledOldPaths.add(filePath);\n continue;\n }\n\n if (fileIsIgnored) {\n status = 'ignored';\n } else if (!inFork && inUpstream) {\n // Missing locally: a pinned path, or one at base that incoming left untouched, is a local\n // deletion that stays deleted (re-adding it would resurface it every sync). A path new in\n // incoming, or one incoming modified after the local side deleted it, comes from incoming.\n const locallyDeleted = baseHash !== null && upstreamHash === baseHash;\n status = fileIsPinned || locallyDeleted ? 'deleted' : 'behind';\n } else if (inFork && !inUpstream) {\n if (baseHash !== null) {\n // In base, deleted by incoming: sync the deletion unless pinned.\n status = fileIsPinned ? 'ahead' : 'behind';\n } else {\n // Local file (never existed in merge-base). If its exact content exists at a\n // different path in incoming, it is likely the source of a rename we couldn't\n // detect due to a squash merge-base: treated as behind so the rename applies.\n // (This file is absent from incoming, so any hash match is at another path.)\n status = forkHash && upstreamHashSet.has(forkHash) ? 'behind' : 'local';\n }\n } else if (forkHash === upstreamHash) {\n status = 'identical';\n } else {\n const forkChanged = forkHash !== baseHash;\n const upstreamChanged = upstreamHash !== baseHash;\n\n if (forkChanged && upstreamChanged) {\n status = fileIsPinned ? 'pinned' : 'diverged';\n } else if (forkChanged && !upstreamChanged) {\n status = fileIsPinned ? 'ahead' : 'drifted';\n } else {\n status = 'behind';\n }\n }\n\n // Protected file where BOTH sides changed since the merge-base (a local edit or deletion,\n // and incoming content that differs from base). Local wins whole-file, so incoming's\n // hunks are dropped; the flag lets analyze/sync surface the loss. A protected file\n // that only changed locally is plain `ahead`; one that only changed incoming (`behind`\n // with the local copy still equal to base) is reported separately as a masking pin.\n const upstreamChanged =\n (fileIsPinned || fileIsIgnored) && inUpstream && upstreamHash !== baseHash && forkHash !== baseHash;\n\n // Ignored file only incoming changed, added or deleted since the merge-base (the local copy,\n // or its absence, still equals base). Nothing local is dropped, but ignored paths never sync,\n // so the change would stay unseen. The pinned counterpart is the masking pin (`behind`).\n const upstreamOnly =\n fileIsIgnored && isReportableIgnored(filePath) && upstreamHash !== baseHash && forkHash === baseHash;\n\n push(status, { upstreamChanged: upstreamChanged || undefined, upstreamOnly: upstreamOnly || undefined });\n }\n\n // Size the dropped incoming changes: one numstat call limited to the flagged paths.\n const flagged = analyzedFiles.filter((file) => file.upstreamChanged && !renamedProtected.has(file.path));\n if (flagged.length > 0) {\n const stat = await getDiffStat(\n repoPath,\n mergeBaseRef,\n incomingRef,\n flagged.map((file) => file.path),\n );\n for (const file of flagged) {\n const entry = stat.get(file.path);\n if (entry && entry.additions !== null && entry.deletions !== null) {\n file.upstreamChangedLines = entry.additions + entry.deletions;\n }\n }\n }\n\n // Retroactive signal for pinned `ahead` files (incoming untouched since the merge-base, so\n // the check above cannot fire): count lines incoming has that local lacks, relative to\n // the tips, not the sync point. Pinned only; ignored territory is noise by design.\n const stale = analyzedFiles.filter(\n (file) =>\n file.status === 'ahead' &&\n file.isPinned &&\n !file.isIgnored &&\n file.existsInFork &&\n file.existsInUpstream &&\n forkHashes.get(file.path) !== upstreamHashes.get(file.path),\n );\n if (stale.length > 0) {\n // from = incoming, to = local: numstat deletions are incoming lines absent locally\n const stat = await getDiffStat(\n repoPath,\n incomingRef,\n localRef,\n stale.map((file) => file.path),\n );\n for (const file of stale) {\n const deletions = stat.get(file.path)?.deletions;\n if (deletions !== null && deletions !== undefined) file.upstreamLinesAbsent = deletions;\n }\n }\n\n return analyzedFiles;\n}\n\n/**\n * Enrich analyzed files in place with change dates and commit hashes: local-side dates for\n * ahead/drifted, incoming-side dates for behind, and both sides for diverged/pinned.\n */\nexport async function enrichChangeInfo(\n repoPath: string,\n files: AnalyzedFile[],\n mergeBaseRef: string,\n localRef: string,\n incomingRef: string,\n): Promise<void> {\n const forkInfo = await getFileChangeInfo(repoPath, mergeBaseRef, localRef);\n const upstreamInfo = await getFileChangeInfo(repoPath, mergeBaseRef, incomingRef);\n const setChanged = (file: AnalyzedFile, info: FileChangeInfo | undefined) => {\n if (!info) return;\n file.changedAt = info.date;\n file.changedTs = info.timestamp;\n file.changedCommit = info.hash;\n };\n\n for (const file of files) {\n if (file.status === 'identical') continue;\n\n if (file.status === 'ahead' || file.status === 'drifted') {\n setChanged(file, forkInfo.get(file.path));\n } else if (file.status === 'behind') {\n setChanged(file, upstreamInfo.get(file.path));\n } else if (file.status === 'diverged' || file.status === 'pinned' || file.upstreamChanged) {\n // Diverged/pinned (and protected files incoming also changed) carry both sides.\n setChanged(file, forkInfo.get(file.path));\n const info = upstreamInfo.get(file.path);\n if (info) {\n file.upstreamChangedAt = info.date;\n file.upstreamChangedTs = info.timestamp;\n file.upstreamCommit = info.hash;\n }\n }\n }\n}\n","/**\n * Migrate service: the upstream migration notes this fork has not handled yet.\n *\n * Notes live upstream only (see `utils/migration-notes`). They are read at the upstream commit the\n * fork last synced to, which the sync already fetched, so this works offline after a sync and\n * while a conflicted sync is still open. Each note also gets a GitHub permalink for readers\n * without the upstream remote. Nothing here blocks: the list is information to act on.\n *\n * `--run` runs a note's codemod from an extracted copy and puts back the files it changed that\n * were identical to upstream (see `runNote`).\n */\n\nimport { execFileSync, spawnSync } from 'node:child_process';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport type { MergeResult, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { DEFAULT_UPSTREAM_REMOTE } from '../utils/config';\nimport { checkMark, writeStdout } from '../utils/display';\nimport {\n batchRestoreWorktreeFromRef,\n ensureRemote,\n fetchRemote,\n getStoredSyncRef,\n git,\n listIdenticalToRef,\n MAX_BUFFER,\n readManifestBaseAtRef,\n revParse,\n} from '../utils/git';\nimport { readManifestBase } from '../utils/manifest';\nimport {\n formatNotesLine,\n listNoteIds,\n type MigrationNote,\n NOTES_DIR,\n noteUrl,\n readNote,\n readPending,\n writePending,\n} from '../utils/migration-notes';\nimport { getGitHubBaseUrl } from './merge-engine';\n\n/** Where `--extract` writes a note folder: inside the fork, so a codemod resolves the fork's packages. */\nconst EXTRACT_DIR = 'node_modules/.cache/cella/migrations';\n\n/** How many restored paths `--run` lists before it cuts the list short. */\nconst RESTORED_LIST_MAX = 20;\n\n/** Make sure an upstream commit is in this clone, fetching upstream once when it is not. */\nasync function ensureUpstreamCommit(config: RuntimeConfig, sha: string): Promise<void> {\n const { forkPath } = config;\n const present = async () => !!(await revParse(forkPath, `${sha}^{commit}`));\n if (await present()) return;\n await ensureRemote(forkPath, DEFAULT_UPSTREAM_REMOTE, config.settings.upstreamUrl);\n await fetchRemote(forkPath, DEFAULT_UPSTREAM_REMOTE);\n if (!(await present()))\n throw new Error(`upstream commit ${sha.slice(0, 7)} is not reachable from '${DEFAULT_UPSTREAM_REMOTE}'`);\n}\n\n/** The upstream commit the fork last synced to, fetched if this clone lacks it; null before any sync. */\nasync function resolveNotesRef(config: RuntimeConfig): Promise<string | null> {\n const { forkPath } = config;\n const ref = (await getStoredSyncRef(forkPath)) ?? (await readManifestBaseAtRef(forkPath, 'HEAD'));\n if (!ref) return null;\n await ensureUpstreamCommit(config, ref);\n return ref;\n}\n\n/** Open and total note counts at the fork's sync point, for the info line; null before any sync. */\nasync function readNotesStatus(config: RuntimeConfig): Promise<{ total: number; open: number } | null> {\n try {\n const ref = await resolveNotesRef(config);\n if (!ref) return null;\n const [ids, pending] = await Promise.all([listNoteIds(config.forkPath, ref), readPending(config.forkPath)]);\n return ids.length > 0 || pending.length > 0 ? { total: ids.length, open: pending.length } : null;\n } catch {\n return null;\n }\n}\n\n/** Print the dim info line at the end of a sync or analyze run. Never fails the run. */\nexport async function printMigrationNotesLine(config: RuntimeConfig, result?: MergeResult): Promise<void> {\n const notes = result?.migrationNotes;\n if (notes) {\n if (notes.total === 0) return;\n console.info();\n console.info(\n pc.dim(formatNotesLine(notes.total, notes.open, notes.arrived.length, { dryRun: config.service === 'analyze' })),\n );\n return;\n }\n const status = await readNotesStatus(config);\n if (!status) return;\n console.info();\n console.info(pc.dim(formatNotesLine(status.total, status.open)));\n}\n\n/** Print one note in the human list. */\nfunction printNote(index: number, note: MigrationNote, url: string | undefined): void {\n const tags = [\n note.codemod ? 'codemod' : 'manual',\n note.syncBreaking ? 'sync-breaking' : null,\n note.clientCacheBump ? 'cache-bump' : null,\n ]\n .filter(Boolean)\n .join(', ');\n console.info(`${index}. ${note.title} ${pc.dim(`[${tags}]`)}`);\n console.info(pc.dim(` id: ${note.id}`));\n if (note.summary) console.info(` ${note.summary}`);\n console.info(pc.dim(` read: pnpm cella migrate --show ${note.id}`));\n if (url) console.info(pc.dim(` ${url}`));\n if (note.codemod) console.info(pc.dim(` codemod: pnpm cella migrate --run ${note.id}`));\n console.info();\n}\n\n/**\n * Write a note's folder under {@link EXTRACT_DIR}, byte for byte. Returns the note, the folder\n * (relative to the fork) and its files.\n */\nasync function writeNoteFolder(\n config: RuntimeConfig,\n ref: string,\n id: string,\n): Promise<{ note: MigrationNote; target: string; files: string[] }> {\n const { forkPath } = config;\n const note = await readNote(forkPath, ref, id);\n if (!note) throw new Error(`no migration note '${id}' at upstream ${ref.slice(0, 7)}`);\n\n const files = (await git(['ls-tree', '-r', '--name-only', `${ref}:${NOTES_DIR}/${id}`], forkPath))\n .split('\\n')\n .filter(Boolean);\n const target = join(EXTRACT_DIR, id);\n for (const file of files) {\n // Byte for byte: the git helper trims its output.\n const content = execFileSync('git', ['show', `${ref}:${NOTES_DIR}/${id}/${file}`], {\n cwd: forkPath,\n maxBuffer: MAX_BUFFER,\n });\n const path = join(forkPath, target, file);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content);\n }\n return { note, target, files };\n}\n\n/** `--extract <id>`: write the note folder under {@link EXTRACT_DIR} and print how to run its codemod. */\nasync function extractNote(config: RuntimeConfig, ref: string, id: string): Promise<void> {\n const { note, target, files } = await writeNoteFolder(config, ref, id);\n\n console.info(`${checkMark} extracted ${files.length} file(s) to ${target}/`);\n console.info(pc.dim(` the README's ${NOTES_DIR}/${id}/ paths are this folder.`));\n if (note.codemod) {\n console.info(pc.dim(` pnpm exec tsx ${target}/${note.codemod} inventory ${note.roots.join(' ')}`));\n console.info(pc.dim(` or, keeping files identical to upstream as they are: pnpm cella migrate --run ${id}`));\n }\n}\n\n/**\n * `--run <id>`: run the note's codemod with `tsx` from the fork root, then give each file that was\n * identical to the manifest's upstream commit before the run, and changed by it, its upstream content back.\n */\nasync function runNote(config: RuntimeConfig, ref: string, id: string): Promise<void> {\n const { forkPath } = config;\n const { note, target } = await writeNoteFolder(config, ref, id);\n if (!note.codemod) {\n throw new Error(\n `migration note '${id}' ships no codemod script: its steps are manual, read them with \\`pnpm cella migrate --show ${id}\\`.`,\n );\n }\n const script = join(target, note.codemod);\n const args = config.runArgs?.length ? config.runArgs : ['inventory', ...note.roots];\n\n const upstreamCommit = (await readManifestBase(forkPath)) ?? ref;\n await ensureUpstreamCommit(config, upstreamCommit);\n const identical = await listIdenticalToRef(forkPath, upstreamCommit);\n\n console.info(pc.dim(`running pnpm exec tsx ${script} ${args.join(' ')}`));\n console.info();\n const child = spawnSync('pnpm', ['exec', 'tsx', script, ...args], { cwd: forkPath, stdio: 'inherit' });\n if (child.error) throw new Error(`could not run the codemod: ${child.error.message}`);\n\n // Also after a failed run: a codemod that stopped halfway may have rewritten files already.\n const stillIdentical = await listIdenticalToRef(forkPath, upstreamCommit);\n const restored = [...identical].filter((path) => !stillIdentical.has(path)).sort();\n await batchRestoreWorktreeFromRef(forkPath, upstreamCommit, restored);\n\n const upstreamShort = upstreamCommit.slice(0, 9);\n console.info();\n if (restored.length > 0) {\n console.info(`${checkMark} restored ${restored.length} file(s) to upstream ${upstreamShort}`);\n console.info(pc.dim(' the codemod changed them, and they were identical to upstream before the run:'));\n for (const path of restored.slice(0, RESTORED_LIST_MAX)) console.info(pc.dim(` ${path}`));\n if (restored.length > RESTORED_LIST_MAX) {\n console.info(pc.dim(` ... + ${restored.length - RESTORED_LIST_MAX} more`));\n }\n } else {\n console.info(pc.dim(`no file identical to upstream ${upstreamShort} was changed by the codemod.`));\n }\n\n if (child.status !== 0) throw new Error(`the codemod exited with code ${child.status ?? 'unknown'}`);\n if (!config.runArgs?.length) {\n const apply = ['rewrite', ...note.roots].join(' ');\n console.info(pc.dim(`report only. to apply: pnpm cella migrate --run ${id} -- ${apply}`));\n }\n}\n\n/** `--mark <ids…>`: drop handled notes from the pending list. */\nasync function markNotes(config: RuntimeConfig, ref: string, pending: string[], ids: string[]): Promise<void> {\n const open = new Set(pending);\n const unknown = ids.filter((id) => !open.has(id));\n for (const id of ids) open.delete(id);\n await writePending(config.forkPath, [...open]);\n const marked = ids.length - unknown.length;\n if (marked > 0) console.info(`${checkMark} recorded ${marked} note(s) as handled`);\n if (unknown.length > 0) console.info(pc.dim(`not pending, left as is: ${unknown.join(', ')}`));\n console.info(pc.dim(formatNotesLine((await listNoteIds(config.forkPath, ref)).length, open.size)));\n}\n\n/** Run the migrate service. */\nexport async function runMigrate(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n const ref = await resolveNotesRef(config);\n if (!ref) {\n console.info(pc.dim('no sync point recorded yet: migration notes start with the first `pnpm cella sync`.'));\n return;\n }\n\n const pending = await readPending(forkPath);\n const githubUrl = getGitHubBaseUrl(config.settings.upstreamUrl) ?? undefined;\n const urlOf = (id: string) => noteUrl(githubUrl, ref, id);\n\n if (config.mark?.length) return markNotes(config, ref, pending, config.mark);\n if (config.run) return runNote(config, ref, config.run);\n if (config.extract) return extractNote(config, ref, config.extract);\n\n if (config.show) {\n const source = await git(['show', `${ref}:${NOTES_DIR}/${config.show}/README.md`], forkPath, {\n ignoreErrors: true,\n });\n if (!source) throw new Error(`no migration note '${config.show}' at upstream ${ref.slice(0, 7)}`);\n const url = urlOf(config.show);\n if (url) console.info(pc.dim(url));\n console.info(source);\n return;\n }\n\n const ids = config.all ? await listNoteIds(forkPath, ref) : pending;\n const notes = (await Promise.all(ids.map((id) => readNote(forkPath, ref, id)))).map(\n (note, i) =>\n note ?? {\n id: ids[i],\n title: `${ids[i]} (no longer upstream)`,\n summary: '',\n syncBreaking: false,\n clientCacheBump: false,\n roots: [],\n codemod: null,\n },\n );\n const total = (await listNoteIds(forkPath, ref)).length;\n\n if (config.json) {\n const open = new Set(pending);\n const out = {\n upstreamCommit: ref,\n total,\n open: pending.length,\n notes: notes.map((note) => ({\n ...note,\n kind: note.codemod ? 'codemod' : 'manual',\n open: open.has(note.id),\n url: urlOf(note.id) ?? null,\n })),\n };\n writeStdout(JSON.stringify(out, null, 2));\n return;\n }\n\n console.info(pc.dim(formatNotesLine(total, pending.length)));\n if (notes.length === 0) return;\n console.info();\n for (const [i, note] of notes.entries()) printNote(i + 1, note, urlOf(note.id));\n if (pending.length > 0) {\n console.info(pc.dim(\"work each note's README, check with `pnpm check`, then record it:\"));\n console.info(pc.dim(` pnpm cella migrate --mark ${pending.join(' ')}`));\n }\n}\n","/**\n * Analyze service: a dry run of sync that shows what would change without applying.\n */\n\nimport type { MergeResult, RuntimeConfig } from '../config/types';\nimport {\n createSpinner,\n type LinkOptions,\n printAnalysisFileGroups,\n printEngineReports,\n spinnerSuccess,\n writeStdout,\n} from '../utils/display';\nimport { CONFIG_FILE } from '../utils/managed-files';\nimport { runEngineWithSpinner } from './merge-engine';\nimport { printMigrationNotesLine } from './migrate';\n\nconst scopeStatuses: Record<'all' | 'risk' | 'protected', Set<string>> = {\n all: new Set(['ahead', 'drifted', 'diverged']),\n risk: new Set(['drifted', 'diverged']),\n protected: new Set(['ahead']),\n};\n\n/**\n * Scope filter. Protected files upstream also changed (`upstreamChanged`, status `pinned` or\n * `ignored`) ride along in `all` and `protected`: they are the pins most worth reviewing. So do\n * ignored files only upstream changed (`upstreamOnly`), and the sync config when upstream's\n * overrides changed in ways the fork config does not follow.\n */\nfunction filterByScope(result: MergeResult, scope: 'all' | 'risk' | 'protected'): MergeResult['files'] {\n const statuses = scopeStatuses[scope];\n if (scope === 'risk') return result.files.filter((f) => statuses.has(f.status));\n const overridesChanged = result.upstreamOverrides?.kind === 'changes';\n return result.files.filter(\n (f) =>\n statuses.has(f.status) ||\n f.upstreamChanged === true ||\n f.upstreamOnly === true ||\n (overridesChanged && f.path === CONFIG_FILE),\n );\n}\n\nexport async function runAnalyze(config: RuntimeConfig): Promise<MergeResult> {\n createSpinner('starting analysis...');\n\n const result = await runEngineWithSpinner(config, false);\n\n spinnerSuccess();\n\n const scopedFiles = filterByScope(result, config.scope ?? 'all');\n\n if (config.json) {\n const overrides = result.upstreamOverrides?.kind === 'changes' ? result.upstreamOverrides : undefined;\n const out = scopedFiles.map((f) => ({\n path: f.path,\n status: f.status,\n changedAt: f.changedAt ?? null,\n changedCommit: f.changedCommit ?? null,\n upstreamChangedAt: f.upstreamChangedAt ?? null,\n upstreamCommit: f.upstreamCommit ?? null,\n upstreamChanged: f.upstreamChanged ?? false,\n upstreamChangedLines: f.upstreamChangedLines ?? null,\n upstreamLinesAbsent: f.upstreamLinesAbsent ?? null,\n upstreamOnly: f.upstreamOnly ?? false,\n // Only on the sync config: upstream override entries and packageJsonSync keys the fork config does not follow\n upstreamOverrides:\n overrides && f.path === CONFIG_FILE\n ? { pinned: overrides.pinned, ignored: overrides.ignored, packageJsonSync: overrides.packageJsonSync }\n : null,\n }));\n writeStdout(JSON.stringify(out, null, 2));\n return result;\n }\n\n if (config.list) {\n for (const file of scopedFiles) {\n writeStdout(file.path);\n }\n return result;\n }\n\n const linkOptions: LinkOptions = {\n upstreamGitHubUrl: result.upstreamGitHubUrl,\n upstreamBranch: result.upstreamBranch,\n fileLinkMode: config.settings.fileLinkMode,\n forkPath: config.forkPath,\n };\n\n // File lists first (analyze shows them for review); the summary and shared reports close the output.\n printAnalysisFileGroups(result.files, linkOptions, result);\n\n printEngineReports(result, 'analysis summary');\n\n await printMigrationNotesLine(config, result);\n\n console.info();\n\n return result;\n}\n","/**\n * Audit service for the Cella CLI.\n *\n * Two layers, in this order: update the outdated packages a developer picks, then run the security\n * pass on what is left (see audit-security.ts).\n */\n\nimport { spawnSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { basename, join, relative } from 'node:path';\nimport { checkbox, confirm, Separator } from '@inquirer/prompts';\nimport type { RuntimeConfig } from '../config/types';\nimport {\n type EnhancedPackageInfo,\n formatDependents,\n getReleasesUrl,\n getRepoUrl,\n getVulnIcon,\n isMajorVersionChange,\n middleTruncate,\n type OutdatedPackage,\n runPnpmAudit,\n runPnpmJson,\n} from '../utils/audit-utils';\nimport pc from '../utils/colors';\nimport { createSpinner, hyperlink, spinnerFail, spinnerSuccess, warningMark } from '../utils/display';\nimport { advisoriesFromAudit, SEVERITIES } from '../utils/security-plan';\nimport { readTopLevel } from '../utils/workspace-yaml';\nimport { runSecurityPass } from './audit-security';\n\n/** How the update layer ended: the security pass follows unless it failed or was cancelled. */\ntype UpdateOutcome = 'updated' | 'skipped' | 'cancelled' | 'failed';\n\n/** A dependent workspace's package.json: its dependency maps, for pin detection. */\ntype DependentPkgJson = Partial<Record<'dependencies' | 'devDependencies', Record<string, string>>>;\n\n/** Reader for dependents' package.jsons that loads each one once, caching by location. */\nfunction createDependentPkgReader(): (location: string) => DependentPkgJson | null {\n const cache = new Map<string, DependentPkgJson | null>();\n return (location) => {\n let cached = cache.get(location);\n if (cached === undefined) {\n try {\n cached = JSON.parse(readFileSync(join(location, 'package.json'), 'utf8'));\n } catch {\n cached = null;\n }\n cache.set(location, cached ?? null);\n }\n return cached ?? null;\n };\n}\n\nexport async function runAudit(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n\n const spinner = createSpinner('checking for outdated packages...');\n try {\n // --long adds each package's latest manifest, which holds its repository URL.\n const [outdated, auditResult] = await Promise.all([\n runPnpmJson(['-r', 'outdated', '--json', '--long'], forkPath),\n runPnpmAudit(forkPath),\n ]);\n if (!outdated) {\n spinnerFail('pnpm outdated gave no answer: run pnpm -r outdated to see why');\n console.info(`${warningMark} security pass skipped: it runs after the update check`);\n return;\n }\n const outdatedPackages = outdated as Record<string, OutdatedPackage>;\n const packageNames = Object.keys(outdatedPackages);\n\n if (packageNames.length === 0) {\n spinnerSuccess('all packages are up to date');\n console.info();\n await runSecurityPass(forkPath, { apply: !config.list });\n return;\n }\n\n const advisories = auditResult ? advisoriesFromAudit(auditResult) : [];\n const severityOf = (name: string) =>\n SEVERITIES.find((severity) => advisories.some((a) => a.module === name && a.severity === severity)) ?? null;\n const readDependentPkg = createDependentPkgReader();\n\n const enhancedPackages: EnhancedPackageInfo[] = packageNames.map((name) => {\n const pkg = outdatedPackages[name];\n const repoUrl = getRepoUrl(pkg.latestManifest?.repository?.url);\n\n // Workspaces that pin this package to an exact version.\n const pinnedIn: string[] = [];\n for (const d of pkg.dependentPackages) {\n const spec = readDependentPkg(d.location)?.[pkg.dependencyType]?.[name] || '';\n if (spec && !spec.startsWith('^') && !spec.startsWith('~') && !spec.startsWith('>')) {\n pinnedIn.push(d.name);\n }\n }\n\n return {\n name,\n current: pkg.current,\n latest: pkg.latest,\n dependentPackages: pkg.dependentPackages,\n isDev: pkg.dependencyType === 'devDependencies',\n isMajorUpdate: isMajorVersionChange(pkg.current, pkg.latest),\n pinnedIn,\n repoUrl,\n releasesUrl: getReleasesUrl(repoUrl),\n severity: severityOf(name),\n };\n });\n\n enhancedPackages.sort((a, b) => {\n const depCompare = dependentsText(a).localeCompare(dependentsText(b));\n if (depCompare !== 0) return depCompare;\n return a.name.localeCompare(b.name);\n });\n\n spinner.stop();\n\n printOutdatedResults(enhancedPackages, forkPath);\n console.info();\n\n // --list is the non-interactive mode: report only, no prompts and no writes.\n const outcome = config.list ? 'skipped' : await promptForUpdates(enhancedPackages, forkPath);\n if (outcome === 'cancelled') return;\n if (outcome === 'failed') {\n console.info(`${warningMark} security pass skipped: it needs a workspace that installs`);\n return;\n }\n await runSecurityPass(forkPath, { apply: !config.list });\n } finally {\n spinner.stop();\n }\n}\n\n/** The \"in\" column: the workspaces that depend on the package, as \"first +N\" when there are several. */\nconst dependentsText = (pkg: EnhancedPackageInfo): string => formatDependents(pkg.dependentPackages.map((d) => d.name));\n\nfunction printOutdatedResults(enhancedPackages: EnhancedPackageInfo[], forkPath: string): void {\n const DEV_TAG = ' (dev)';\n const MAX_NAME_LEN = 35;\n const MAX_DEPENDENTS_LEN = 15;\n const maxNameLen = Math.min(\n MAX_NAME_LEN,\n Math.max(7, ...enhancedPackages.map((p) => p.name.length + (p.isDev ? DEV_TAG.length : 0))),\n );\n const maxCurrentLen = Math.max(7, ...enhancedPackages.map((p) => p.current.length));\n const maxLatestLen = Math.max(6, ...enhancedPackages.map((p) => p.latest.length));\n const maxDependentsLen = Math.min(\n MAX_DEPENDENTS_LEN,\n Math.max(10, ...enhancedPackages.map((p) => dependentsText(p).length)),\n );\n\n // The vuln column is a single dot, so it gets no width budget.\n const header = [\n ' ',\n pc.bold('package'.padEnd(maxNameLen)),\n pc.bold('current'.padEnd(maxCurrentLen)),\n pc.bold('latest'.padEnd(maxLatestLen)),\n pc.bold('in'.padEnd(maxDependentsLen)),\n pc.bold('links'),\n ].join(' ');\n\n console.info(header);\n\n for (const pkg of enhancedPackages) {\n const vulnIndicator = pkg.severity ? getVulnIcon(pkg.severity) : ' ';\n\n const fullName = pkg.isDev ? `${pkg.name}${DEV_TAG}` : pkg.name;\n const displayName = middleTruncate(fullName, maxNameLen);\n const name = pc.white(displayName.padEnd(maxNameLen));\n\n const current = pc.red(pkg.current.padEnd(maxCurrentLen));\n const latestText = pkg.latest.padEnd(maxLatestLen);\n const latest = pkg.isMajorUpdate ? pc.bold(pc.green(latestText)) : pc.green(latestText);\n\n const dependents = pc.dim(middleTruncate(dependentsText(pkg), maxDependentsLen).padEnd(maxDependentsLen));\n\n const links: string[] = [];\n if (pkg.releasesUrl) {\n links.push(hyperlink(pc.blue('rel'), pkg.releasesUrl));\n }\n if (pkg.repoUrl) {\n links.push(hyperlink(pc.cyan('repo'), pkg.repoUrl));\n }\n\n const linksStr = links.length > 0 ? links.join(' ') : pc.dim('n/a');\n\n console.info(`${vulnIndicator} ${name} ${current} ${latest} ${dependents} ${linksStr}`);\n }\n\n // Package.json links with counts by dependent name.\n console.info();\n const dependentMap = new Map<string, { location: string; count: number }>();\n for (const pkg of enhancedPackages) {\n for (const { name, location } of pkg.dependentPackages) {\n const dependentName = name || basename(location);\n const existing = dependentMap.get(dependentName);\n if (existing) {\n existing.count++;\n } else {\n dependentMap.set(dependentName, { location, count: 1 });\n }\n }\n }\n const sortedDependents = [...dependentMap.entries()].sort((a, b) => a[0].localeCompare(b[0]));\n const maxDependentNameLen = Math.max(0, ...sortedDependents.map(([name]) => name.length));\n for (const [dependentName, { location, count }] of sortedDependents) {\n const packageJsonPath = join(location, 'package.json');\n const relativePath = relative(forkPath, packageJsonPath);\n const paddedName = dependentName.padEnd(maxDependentNameLen);\n console.info(\n ` ${pc.dim('•')} ${paddedName} ${hyperlink(relativePath, `file://${packageJsonPath}`)} ${pc.dim(`${count}`)}`,\n );\n }\n}\n\n/** The grouped checkbox choices for the update prompt: pinned packages, then the regular ones. */\nfunction buildUpdateChoices(\n packages: EnhancedPackageInfo[],\n): Array<{ name: string; value: string; checked: boolean } | Separator> {\n const makeChoice = (pkg: EnhancedPackageInfo) => {\n const devTag = pkg.isDev ? pc.dim(' (dev)') : '';\n const version = `${pc.red(pkg.current)} → ${pc.green(pkg.latest)}`;\n const pinnedWarning =\n pkg.pinnedIn.length > 0 ? ` ${warningMark} ${pc.dim(`pinned in ${pkg.pinnedIn.join(', ')}`)}` : '';\n return {\n name: `${pkg.name}${devTag} ${version}${pinnedWarning}`,\n value: pkg.name,\n checked: false,\n };\n };\n\n const pinned = packages.filter((p) => p.pinnedIn.length > 0);\n const regular = packages.filter((p) => p.pinnedIn.length === 0);\n\n const choices: Array<{ name: string; value: string; checked: boolean } | Separator> = [];\n\n if (pinned.length > 0) {\n choices.push(new Separator(pc.yellow(`── pinned (${pinned.length}) ──`)));\n choices.push(...pinned.map(makeChoice));\n }\n if (regular.length > 0) {\n if (pinned.length > 0) choices.push(new Separator(pc.dim(`── packages (${regular.length}) ──`)));\n choices.push(...regular.map(makeChoice));\n }\n\n return choices;\n}\n\n/** Package-selection prompt; the chosen updates run through {@link executeUpdates}. */\nasync function promptForUpdates(packages: EnhancedPackageInfo[], forkPath: string): Promise<UpdateOutcome> {\n let wantsUpdate: boolean;\n try {\n wantsUpdate = await confirm({ message: 'update packages?', default: true });\n } catch {\n return 'cancelled';\n }\n console.info();\n if (!wantsUpdate) return 'skipped';\n\n const choices = buildUpdateChoices(packages);\n\n let selected: string[];\n try {\n selected = await checkbox({\n message: 'toggle packages to update',\n choices,\n required: true,\n pageSize: 20,\n loop: false,\n theme: {\n icon: {\n cursor: '❯ ',\n },\n style: {\n highlight: (text: string) => text,\n keysHelpTip: (keys: [string, string][]) => {\n const tips = keys.map(([key, action]: [string, string]) => `${pc.dim(key)} ${action}`);\n return tips.join(' ');\n },\n renderSelectedChoices: (selectedChoices: Array<{ value?: string }>) =>\n pc.dim(`${selectedChoices.length} package${selectedChoices.length !== 1 ? 's' : ''} selected`),\n },\n },\n });\n } catch {\n return 'cancelled';\n }\n\n return executeUpdates(packages, forkPath, selected);\n}\n\n/** The selected updates: major bumps confirmed first, then one recursive `pnpm up` (catalog consumers normalized first). */\nasync function executeUpdates(\n packages: EnhancedPackageInfo[],\n forkPath: string,\n selectedPackages: string[],\n): Promise<UpdateOutcome> {\n console.info();\n console.info(pc.green(`✓ updating ${selectedPackages.length} package${selectedPackages.length !== 1 ? 's' : ''}`));\n console.info();\n\n const selectedMajor = packages.filter((p) => selectedPackages.includes(p.name) && p.isMajorUpdate);\n if (selectedMajor.length > 0) {\n const majorNames = selectedMajor.map((p) => pc.bold(p.name)).join(', ');\n try {\n const proceed = await confirm({\n message: `${selectedMajor.length} major update${selectedMajor.length > 1 ? 's' : ''} selected (${majorNames}). proceed?`,\n default: true,\n });\n if (!proceed) {\n console.info(pc.dim(' update cancelled'));\n console.info();\n return 'skipped';\n }\n } catch {\n return 'cancelled';\n }\n }\n\n const catalogPackages = readCatalogPackageNames(forkPath);\n\n const workspacePackages = new Map<string, string[]>();\n for (const pkgName of selectedPackages) {\n const pkg = packages.find((p) => p.name === pkgName);\n if (!pkg) continue;\n\n for (const { name: dependent } of pkg.dependentPackages) {\n const group = workspacePackages.get(dependent);\n if (group) group.push(pkgName);\n else workspacePackages.set(dependent, [pkgName]);\n }\n }\n\n // Summarize impacted workspaces before running a single workspace-wide update.\n // Catalog consumers are normalized before the recursive update so a strict\n // catalogMode cannot fail it with ERR_PNPM_CATALOG_VERSION_MISMATCH.\n for (const [workspace, pkgs] of workspacePackages) {\n const pkgList = pkgs.join(', ');\n console.info(`${pc.cyan('↑')} ${pc.bold(workspace)}: ${pc.dim(pkgList)}`);\n }\n\n console.info();\n\n const selectedCatalogPackages = selectedPackages.filter((pkgName) => catalogPackages.has(pkgName));\n\n if (selectedCatalogPackages.length > 0) {\n console.info(pc.dim(`normalizing catalog consumers: ${selectedCatalogPackages.join(', ')}`));\n const normalizeResult = spawnSync('pnpm', ['-r', 'up', ...selectedCatalogPackages], {\n cwd: forkPath,\n stdio: 'inherit',\n });\n\n console.info();\n if (normalizeResult.status !== 0) {\n console.error(pc.red(`✗ catalog normalization failed (exit code ${normalizeResult.status})`));\n return 'failed';\n }\n }\n\n // Run one recursive update so pnpm can rewrite catalogs and direct consumers atomically.\n const result = spawnSync('pnpm', ['-r', 'up', '--latest', ...selectedPackages], { cwd: forkPath, stdio: 'inherit' });\n\n console.info();\n if (result.status !== 0) {\n console.error(pc.red(`✗ update failed (exit code ${result.status})`));\n return 'failed';\n }\n console.info(pc.green(`✓ ${selectedPackages.length} package${selectedPackages.length > 1 ? 's' : ''} updated`));\n console.info();\n return 'updated';\n}\n\nfunction readCatalogPackageNames(forkPath: string): Set<string> {\n const workspacePath = join(forkPath, 'pnpm-workspace.yaml');\n try {\n const content = readFileSync(workspacePath, 'utf8');\n return new Set(Object.keys(readTopLevel(content, 'catalog') ?? {}));\n } catch {\n return new Set();\n }\n}\n","/**\n * Audit utilities: running pnpm, repository links and table formatting for the audit service.\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport pc from './colors';\nimport { parseComparableVersion } from './versions';\n\nconst execFileAsync = promisify(execFile);\n\n/** One package in `pnpm -r outdated --json --long`. */\nexport interface OutdatedPackage {\n current: string;\n latest: string;\n dependencyType: 'dependencies' | 'devDependencies';\n dependentPackages: Array<{ name: string; location: string }>;\n latestManifest?: { repository?: { url?: string } };\n}\n\nexport interface EnhancedPackageInfo {\n name: string;\n current: string;\n latest: string;\n dependentPackages: OutdatedPackage['dependentPackages'];\n isDev: boolean;\n isMajorUpdate: boolean;\n /** Workspace names where this package is pinned to an exact version (no ^ or ~) */\n pinnedIn: string[];\n repoUrl: string | null;\n releasesUrl: string | null;\n /** The highest severity the audit reports for the package, or null when it reports none. */\n severity: VulnerabilitySeverity | null;\n}\n\n/** Vulnerability severity levels */\nexport type VulnerabilitySeverity = 'critical' | 'high' | 'moderate' | 'low' | 'info';\n\n/** Audit result from pnpm audit --json */\nexport interface AuditResult {\n advisories: Record<string, AuditAdvisory>;\n}\n\ninterface AuditAdvisory {\n id: number;\n module_name: string;\n severity: VulnerabilitySeverity;\n vulnerable_versions: string;\n url: string;\n github_advisory_id?: string;\n findings: Array<{ version: string; paths: string[] }>;\n}\n\n/** A repository URL from package metadata, normalized to a plain https:// form. */\nexport function getRepoUrl(repositoryUrl: string | undefined): string | null {\n if (!repositoryUrl) return null;\n\n let url = repositoryUrl;\n\n if (url.startsWith('git+')) {\n url = url.slice(4);\n }\n\n if (url.endsWith('.git')) {\n url = url.slice(0, -4);\n }\n\n if (url.startsWith('git://')) {\n url = url.replace('git://', 'https://');\n }\n\n return url;\n}\n\n/** Whether the URL points to a GitHub repository. */\nfunction isGitHubRepoUrl(repoUrl: string | null): repoUrl is string {\n if (!repoUrl) return false;\n try {\n const parsed = new URL(repoUrl);\n return parsed.hostname === 'github.com' || parsed.hostname === 'www.github.com';\n } catch {\n return false;\n }\n}\n\n/** The GitHub releases URL, or null for a non-GitHub repo. */\nexport function getReleasesUrl(repoUrl: string | null): string | null {\n if (!isGitHubRepoUrl(repoUrl)) return null;\n return `${repoUrl}/releases`;\n}\n\n/** Whether the update is a major version change. */\nexport function isMajorVersionChange(current: string, latest: string): boolean {\n const from = parseComparableVersion(current);\n const to = parseComparableVersion(latest);\n return !!from && !!to && to.major > from.major;\n}\n\n/** Runs a pnpm command to completion with its output captured; `ok` is false on a non-zero exit. */\nexport async function runPnpm(args: string[], cwd: string): Promise<{ ok: boolean; stdout: string; stderr: string }> {\n try {\n const { stdout, stderr } = await execFileAsync('pnpm', args, {\n encoding: 'utf8',\n maxBuffer: 10 * 1024 * 1024,\n cwd,\n });\n return { ok: true, stdout, stderr };\n } catch (error) {\n // When pnpm wrote nothing (it did not start), the error itself explains the failure.\n const { stdout = '', stderr = '' } = error as { stdout?: string; stderr?: string };\n return { ok: false, stdout, stderr: stdout || stderr ? stderr : String(error) };\n }\n}\n\n/**\n * Runs a pnpm command and parses its JSON stdout. pnpm exits non-zero when it finds outdated\n * packages or vulnerabilities (expected output, not an error), so the exit code is not checked.\n * pnpm prints warnings, such as a Node version outside `engines`, on stdout ahead of the JSON, so\n * only errors are logged. Returns null for empty or unparsable output; never throws.\n */\nexport async function runPnpmJson(args: string[], cwd: string): Promise<unknown> {\n try {\n return JSON.parse((await runPnpm([...args, '--loglevel=error'], cwd)).stdout);\n } catch {\n return null;\n }\n}\n\n/**\n * Parsed `pnpm audit --json`; null when the audit could not run. A clean audit is a result with\n * no advisories, so a caller can tell \"nothing found\" from \"no answer\".\n */\nexport async function runPnpmAudit(cwd: string): Promise<AuditResult | null> {\n const result = (await runPnpmJson(['audit', '--json'], cwd)) as Partial<AuditResult> | null;\n if (!result || typeof result.advisories !== 'object' || result.advisories === null) return null;\n return result as AuditResult;\n}\n\n/** Publish time per version of a package, as its registry lists them; null when it does not answer. */\nexport async function fetchPublishTimes(name: string, cwd: string): Promise<Record<string, string> | null> {\n const times = await runPnpmJson(['view', name, 'time', '--json'], cwd);\n return times && typeof times === 'object' ? (times as Record<string, string>) : null;\n}\n\n/** Severity dot per vulnerability level. */\nconst vulnIcons: Record<VulnerabilitySeverity, string> = {\n critical: pc.red('●'),\n high: pc.red('●'),\n moderate: pc.yellow('●'),\n low: pc.blue('●'),\n info: pc.gray('●'),\n};\n\nexport function getVulnIcon(severity: VulnerabilitySeverity): string {\n return vulnIcons[severity] ?? pc.gray('●');\n}\n\n/** Middle-truncation to maxLen, e.g. \"very-long-package-name\" -> \"very-lo…e-name\". */\nexport function middleTruncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n const ellipsis = '…';\n const charsToShow = maxLen - ellipsis.length;\n const frontChars = Math.ceil(charsToShow / 2);\n const backChars = Math.floor(charsToShow / 2);\n return str.slice(0, frontChars) + ellipsis + str.slice(-backChars);\n}\n\n/** Dependents as \"first +N\" when multiple. */\nexport function formatDependents(dependents: string[]): string {\n if (dependents.length === 0) return '';\n if (dependents.length === 1) return dependents[0];\n return `${dependents[0]} +${dependents.length - 1}`;\n}\n","/**\n * The plan behind the audit's security pass: which advisories an override can fix, which have a\n * fix that is too young to install, and which have none. Pure, so the service around it only\n * gathers the inputs and carries the plan out.\n */\n\nimport type { AuditResult, VulnerabilitySeverity } from './audit-utils';\nimport { compareVersionStrings, isBreakingJump, isPrerelease, satisfiesComparators } from './versions';\nimport type { AuditSettings } from './workspace-yaml';\n\n/** One advisory from `pnpm audit --json`, reduced to what the plan needs. */\nexport interface Advisory {\n ghsa: string;\n module: string;\n severity: VulnerabilitySeverity;\n /** Vulnerable versions as a comparator range, e.g. `>=4.0.0 <4.3.2`. */\n range: string;\n /** The vulnerable versions the lockfile holds. */\n installed: string[];\n /** The workspace dependencies that pull the package in. */\n via: string[];\n /** A workspace depends on the package directly, so its own manifest decides the version. */\n direct: boolean;\n}\n\n/** What can be done about an item. */\nexport type Remedy =\n /** A published, installable version outside every vulnerable range. */\n | { kind: 'override'; target: string; breaking: boolean }\n /** The fix exists but is younger than the release age. */\n | { kind: 'fresh'; target: string; breaking: boolean; hoursOld: number }\n /** Nothing published fixes it. */\n | { kind: 'none' };\n\n/** How an item relates to the settings from before this run. */\nexport type Standing =\n /** An override of the same line was in place: applied again without asking. */\n | 'carried'\n /** Its advisories were ignored and stay so. */\n | 'ignored'\n /** Not seen before: applied when safe, asked about otherwise. */\n | 'new';\n\n/** The advisories on one package that share a remedy. */\nexport interface SecurityItem {\n module: string;\n severity: VulnerabilitySeverity;\n ghsas: string[];\n /** The lowest vulnerable version installed. */\n installed: string;\n via: string[];\n direct: boolean;\n remedy: Remedy;\n standing: Standing;\n /** The override entries that apply the remedy; empty when there is none. */\n overrides: Record<string, string>;\n}\n\n/** Publish time per version of one package, as the registry's `time` field gives it. */\nexport type PublishTimes = Record<string, string>;\n\nexport interface PlanInput {\n advisories: Advisory[];\n /** Publish times per package name; a package the registry did not answer for is absent. */\n published: Record<string, PublishTimes>;\n /** The settings from before the run. */\n previous: AuditSettings;\n /** `minimumReleaseAge` in minutes. */\n releaseAgeMinutes: number;\n now: number;\n}\n\n/** Severity levels, most severe first. */\nexport const SEVERITIES: VulnerabilitySeverity[] = ['critical', 'high', 'moderate', 'low', 'info'];\n\n/**\n * Whether an override key is audit output. A key with a version selector and no parent\n * (`pkg@<1.2.3`) is what an audit fix writes: the audit owns it and rebuilds it every run. A key\n * without a selector (`pkg`) or scoped to a parent (`parent>pkg`) is a decision someone made.\n */\nexport function isAuditOverride(key: string): boolean {\n // pnpm reads `>` as the parent delimiter unless a space, `|` or `@` comes before it.\n if (/[^ |@]>/.test(key)) return false;\n return key.indexOf('@', 1) > 0;\n}\n\n/** The package an override key targets. */\nexport function overrideModule(key: string): string {\n const child = key.split(/(?<=[^ |@])>/).at(-1) ?? key;\n const at = child.indexOf('@', 1);\n return at > 0 ? child.slice(0, at) : child;\n}\n\n/** A `name@version` release-age exclude split in two, or null for a name-only entry or a pattern. */\nexport function parseVersionedExclude(entry: string): { name: string; version: string } | null {\n const at = entry.lastIndexOf('@');\n if (at <= 0) return null;\n const version = entry.slice(at + 1);\n return /^\\d+\\.\\d+\\.\\d+[0-9A-Za-z.+-]*$/.test(version) ? { name: entry.slice(0, at), version } : null;\n}\n\n/** The advisories in an audit result. Paths look like `workspace>direct-dep>…>package`. */\nexport function advisoriesFromAudit(audit: AuditResult): Advisory[] {\n return Object.values(audit.advisories).map((advisory) => {\n const paths = (advisory.findings ?? []).flatMap((finding) => finding.paths ?? []).map((path) => path.split('>'));\n return {\n ghsa: advisory.github_advisory_id ?? advisory.url ?? String(advisory.id),\n module: advisory.module_name,\n severity: advisory.severity,\n range: advisory.vulnerable_versions,\n installed: [...new Set((advisory.findings ?? []).map((finding) => finding.version))],\n via: [...new Set(paths.map((parts) => parts[parts.length > 2 ? 1 : 0]))],\n direct: paths.some((parts) => parts.length === 2),\n };\n });\n}\n\n/** Milliseconds since `name@version` was published; NaN when the registry lists no time for it. */\nconst publishedAgo = (name: string, version: string, input: Pick<PlanInput, 'published' | 'now'>): number =>\n input.now - Date.parse(input.published[name]?.[version] ?? '');\n\n/** Whether the release age lets `name@version` install: it is old enough, or an exclude names it. */\nfunction isInstallable(name: string, version: string, input: PlanInput): boolean {\n const excludes = input.previous.releaseAgeExcludes;\n if (excludes.includes(name) || excludes.includes(`${name}@${version}`)) return true;\n const age = publishedAgo(name, version, input);\n return Number.isNaN(age) || age >= input.releaseAgeMinutes * 60_000;\n}\n\n/** Whether an override target such as `^7.0.2` or `>=0.28.1` lets `version` in. */\nfunction admits(target: string, version: string): boolean {\n const base = target.replace(/^[\\^~>=<\\s]+/, '');\n if (compareVersionStrings(base, version) > 0) return false;\n return target.trim().startsWith('>') || !isBreakingJump(base, version);\n}\n\n/** The audit overrides a package had before the run. */\nconst previousOverrides = (module: string, previous: AuditSettings): Array<[key: string, target: string]> =>\n Object.entries(previous.overrides).filter(([key]) => isAuditOverride(key) && overrideModule(key) === module);\n\n/**\n * The audit overrides a package had before the run whose target a published version still meets.\n * An item that is left open keeps them: leaving it open must not undo a fix that was in place.\n */\nexport function standingOverrides(\n module: string,\n input: Pick<PlanInput, 'previous' | 'published'>,\n): Record<string, string> {\n const versions = Object.keys(input.published[module] ?? {});\n return Object.fromEntries(\n previousOverrides(module, input.previous).filter(([, target]) => versions.some((v) => admits(target, v))),\n );\n}\n\n/**\n * One item per package and remedy. What the advisory database claims as patched is not trusted,\n * because pnpm guesses it: the fix for an advisory is the lowest published release above what is\n * installed that leaves its range. A release outside every range of the package comes first, and\n * one the release age lets install comes before one it holds back.\n */\nexport function planSecurity(input: PlanInput): SecurityItem[] {\n const ignored = new Set(input.previous.ignoredGhsas);\n const byModule = Map.groupBy(input.advisories, (advisory) => advisory.module);\n const items: SecurityItem[] = [];\n\n for (const [module, advisories] of byModule) {\n const versions = Object.keys(input.published[module] ?? {}).filter((v) => /^\\d/.test(v));\n const stable = versions.filter((v) => !isPrerelease(v)).sort(compareVersionStrings);\n const escapesAll = (v: string) => !advisories.some((advisory) => satisfiesComparators(v, advisory.range));\n\n const fixOf = (advisory: Advisory): string | undefined => {\n const highest = [...advisory.installed].sort(compareVersionStrings).at(-1) ?? '0.0.0';\n const candidates = stable.filter(\n (v) => compareVersionStrings(v, highest) > 0 && !satisfiesComparators(v, advisory.range),\n );\n const installable = candidates.filter((v) => isInstallable(module, v, input));\n const pick = (among: string[]) => among.find(escapesAll) ?? among[0];\n return pick(installable) ?? pick(candidates);\n };\n\n for (const [fix, group] of Map.groupBy(advisories, fixOf)) {\n const installed = [...new Set(group.flatMap((advisory) => advisory.installed))].sort(compareVersionStrings);\n const ghsas = group.map((advisory) => advisory.ghsa);\n const allIgnored = ghsas.every((ghsa) => ignored.has(ghsa));\n const breaking = !!fix && installed.some((v) => isBreakingJump(v, fix));\n\n let remedy: Remedy = { kind: 'none' };\n let standing: Standing = allIgnored ? 'ignored' : 'new';\n let overrides: Record<string, string> = {};\n\n if (fix) {\n const hoursOld = Math.max(0, Math.floor(publishedAgo(module, fix, input) / 3_600_000));\n remedy = isInstallable(module, fix, input)\n ? { kind: 'override', target: fix, breaking }\n : { kind: 'fresh', target: fix, breaking, hoursOld };\n\n overrides = Object.fromEntries(\n [...new Set(group.map((advisory) => advisory.range))].map((range) => {\n const key = `${module}@${range}`;\n const kept = input.previous.overrides[key];\n // A target someone widened by hand (`>=1.2.3`) stays as written while it still admits the fix.\n return [key, kept && admits(kept, fix) ? kept : `^${fix}`];\n }),\n );\n\n if (remedy.kind === 'override') {\n if (previousOverrides(module, input.previous).some(([, target]) => admits(target, fix))) standing = 'carried';\n // An ignored advisory whose fix arrived moves to an override, unless that takes a breaking jump.\n else if (allIgnored && !breaking) standing = 'new';\n }\n }\n\n items.push({\n module,\n severity: SEVERITIES.find((severity) => group.some((advisory) => advisory.severity === severity)) ?? 'info',\n ghsas,\n installed: installed[0] ?? '',\n via: [...new Set(group.flatMap((advisory) => advisory.via))],\n direct: group.some((advisory) => advisory.direct),\n remedy,\n standing,\n overrides,\n });\n }\n }\n\n return items.sort(\n (a, b) => SEVERITIES.indexOf(a.severity) - SEVERITIES.indexOf(b.severity) || a.module.localeCompare(b.module),\n );\n}\n\n/**\n * The release-age excludes worth keeping: name-only entries, and versioned ones whose version is\n * still younger than the release age. An aged version installs without its exclude, and one the\n * registry does not list points at nothing.\n */\nexport function liveExcludes(input: Omit<PlanInput, 'advisories'>): string[] {\n return input.previous.releaseAgeExcludes.filter((entry) => {\n const versioned = parseVersionedExclude(entry);\n // Kept as well when the registry gave no answer for the package: silence is not proof of age.\n if (!versioned || !input.published[versioned.name]) return true;\n return publishedAgo(versioned.name, versioned.version, input) < input.releaseAgeMinutes * 60_000;\n });\n}\n","/**\n * Reads and edits the settings in `pnpm-workspace.yaml` that the audit service manages. Edits go\n * through a parsed document, so comments, quoting and every other setting stay as they are.\n */\n\nimport { type Document, isMap, isScalar, isSeq, parseDocument, type YAMLMap } from 'yaml';\n\n/** The audit-related settings of a `pnpm-workspace.yaml`. */\nexport interface AuditSettings {\n /** `overrides`: selector key to target range. */\n overrides: Record<string, string>;\n /** `minimumReleaseAgeExclude` entries: a package name, optionally with `@version`. */\n releaseAgeExcludes: string[];\n /** `auditConfig.ignoreGhsas`: advisory ids that `pnpm audit` leaves out. */\n ignoredGhsas: string[];\n}\n\nconst record = (value: unknown): Record<string, unknown> =>\n value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n\nconst stringRecord = (value: unknown): Record<string, string> =>\n Object.fromEntries(Object.entries(record(value)).map(([key, entry]) => [key, String(entry)]));\n\nconst stringList = (value: unknown): string[] => (Array.isArray(value) ? value.map(String) : []);\n\n/**\n * The audit settings in the file content; a missing or malformed block reads as empty. Throws on\n * content that is not valid YAML, which could not be written back either.\n */\nexport function readAuditSettings(content: string): AuditSettings {\n const doc = parseDocument(content);\n if (doc.errors.length > 0) throw new Error(doc.errors[0].message);\n const settings = record(doc.toJS());\n return {\n overrides: stringRecord(settings.overrides),\n releaseAgeExcludes: stringList(settings.minimumReleaseAgeExclude),\n ignoredGhsas: stringList(record(settings.auditConfig).ignoreGhsas),\n };\n}\n\n/** A top-level setting of the file as plain data, e.g. the `catalog` map; undefined when it is missing. */\nexport function readTopLevel(content: string, key: string): unknown {\n return record(parseDocument(content).toJS())[key];\n}\n\n/** Files that `patchedDependencies` points at, relative to the workspace root. */\nexport function readPatchFiles(content: string): string[] {\n return Object.values(stringRecord(record(parseDocument(content).toJS()).patchedDependencies));\n}\n\nconst keyOf = (pair: { key: unknown }): string => String(isScalar(pair.key) ? pair.key.value : pair.key);\n\nconst itemText = (item: unknown): string => String(isScalar(item) ? item.value : item);\n\n/** Runs `change` on a map; a map whose keys were sorted is sorted again afterwards, as pnpm keeps them. */\nfunction keepingOrder(map: YAMLMap, change: () => void): void {\n const keys = map.items.map(keyOf);\n const wasSorted = keys.every((key, i) => i === 0 || keys[i - 1].localeCompare(key) <= 0);\n change();\n if (wasSorted) map.items.sort((a, b) => keyOf(a).localeCompare(keyOf(b)));\n}\n\n/** The map at `path`, created (with its parents) when missing. */\nfunction mapAt(doc: Document, path: string[]): YAMLMap {\n if (path.length === 0) {\n if (!isMap(doc.contents)) doc.contents = doc.createNode({}) as YAMLMap;\n return doc.contents as YAMLMap;\n }\n const parent = mapAt(doc, path.slice(0, -1));\n const key = path[path.length - 1];\n const existing = parent.get(key, true);\n if (isMap(existing)) {\n // An empty `{}` would keep its entries on one line.\n if (existing.items.length === 0) existing.flow = false;\n return existing;\n }\n const created = doc.createNode({}) as YAMLMap;\n keepingOrder(parent, () => parent.set(key, created));\n return created;\n}\n\n/** Make the map at `path` hold exactly `entries`: untouched pairs keep their node, position and comments. */\nfunction syncMap(doc: Document, path: string[], entries: Record<string, string>): void {\n if (!isMap(doc.getIn(path)) && Object.keys(entries).length === 0) return;\n\n const map = mapAt(doc, path);\n keepingOrder(map, () => {\n for (const key of map.items.map(keyOf)) if (!(key in entries)) map.delete(key);\n for (const [key, value] of Object.entries(entries)) map.set(key, value);\n });\n if (map.items.length === 0) doc.deleteIn(path);\n}\n\n/** Make the list at `path` hold exactly `entries`: kept items stay in place, new ones go last. */\nfunction syncList(doc: Document, path: string[], entries: string[]): void {\n const current = doc.getIn(path);\n if (!isSeq(current)) {\n if (entries.length === 0) return;\n const parent = mapAt(doc, path.slice(0, -1));\n keepingOrder(parent, () => parent.set(path[path.length - 1], doc.createNode(entries)));\n return;\n }\n\n current.items = current.items.filter((item) => entries.includes(itemText(item)));\n const present = new Set(current.items.map(itemText));\n for (const entry of entries) if (!present.has(entry)) current.add(doc.createNode(entry));\n if (current.items.length === 0) doc.deleteIn(path);\n else current.flow = false;\n}\n\n/**\n * The file content with the audit settings replaced by `next`. A block that ends up empty is\n * removed, and so is an `auditConfig` left without keys.\n */\nexport function writeAuditSettings(content: string, next: AuditSettings): string {\n const doc = parseDocument(content);\n syncMap(doc, ['overrides'], next.overrides);\n syncList(doc, ['minimumReleaseAgeExclude'], next.releaseAgeExcludes);\n syncList(doc, ['auditConfig', 'ignoreGhsas'], next.ignoredGhsas);\n\n const auditConfig = doc.getIn(['auditConfig']);\n if (isMap(auditConfig) && auditConfig.items.length === 0) doc.deleteIn(['auditConfig']);\n\n return doc.toString({ lineWidth: 0, singleQuote: true });\n}\n","/**\n * The security pass of the audit service. Audit overrides are derived data: every run drops them,\n * resolves the workspace without them in a staging copy, and puts back only what a current\n * advisory still needs. The workspace itself changes once, at the end, when the staged result\n * differs from what is there.\n */\n\nimport { spawnSync } from 'node:child_process';\nimport { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { dirname, join, relative } from 'node:path';\nimport { confirm, select } from '@inquirer/prompts';\nimport {\n fetchPublishTimes,\n formatDependents,\n getVulnIcon,\n middleTruncate,\n runPnpm,\n runPnpmAudit,\n runPnpmJson,\n} from '../utils/audit-utils';\nimport pc from '../utils/colors';\nimport { checkMark, createSpinner, DIVIDER, spinnerText, warningMark } from '../utils/display';\nimport {\n type Advisory,\n advisoriesFromAudit,\n isAuditOverride,\n liveExcludes,\n overrideModule,\n type PublishTimes,\n parseVersionedExclude,\n planSecurity,\n type SecurityItem,\n standingOverrides,\n} from '../utils/security-plan';\nimport { type AuditSettings, readAuditSettings, readPatchFiles, writeAuditSettings } from '../utils/workspace-yaml';\n\nconst WORKSPACE_FILE = 'pnpm-workspace.yaml';\nconst LOCK_FILE = 'pnpm-lock.yaml';\n\n/** Root files, next to the manifests, that decide how pnpm resolves. */\nconst RESOLUTION_FILES = ['package.json', LOCK_FILE, '.npmrc', '.pnpmfile.cjs'];\n\n/** What happens to an item: an override is written, its advisories are ignored, or it stays reported. */\ntype Action = 'override' | 'ignore' | 'open';\n\ninterface Decision {\n item: SecurityItem;\n action: Action;\n /** A release-age exclude that lets a fix younger than the release age install. */\n exclude?: string;\n}\n\nconst readOr = (path: string, fallback = ''): string => (existsSync(path) ? readFileSync(path, 'utf8') : fallback);\n\nconst count = (n: number, noun: string, plural = `${noun}s`): string => `${n} ${n === 1 ? noun : plural}`;\n\nconst isBreaking = (item: SecurityItem): boolean => item.remedy.kind !== 'none' && item.remedy.breaking;\n\n/**\n * Whether a developer decides about the item: it is new, and its fix is missing, too young, a\n * breaking jump, or for a package a workspace depends on directly (its manifest sets that version).\n */\nconst needsDecision = (item: SecurityItem): boolean =>\n item.standing === 'new' && (item.remedy.kind !== 'override' || item.remedy.breaking || item.direct);\n\nconst sameEntries = (a: Record<string, string>, b: Record<string, string>): boolean =>\n Object.keys(a).length === Object.keys(b).length && Object.entries(a).every(([key, value]) => b[key] === value);\n\n/**\n * A copy of everything pnpm reads to resolve the workspace: manifests, lockfile, pnpm config and\n * patch files. Resolving there leaves the workspace and its node_modules alone.\n */\nasync function createStaging(forkPath: string, workspaceYaml: string): Promise<string> {\n const staging = mkdtempSync(join(tmpdir(), 'cella-audit-'));\n const projects = ((await runPnpmJson(['ls', '-r', '--depth', '-1', '--json'], forkPath)) ?? []) as Array<{\n path: string;\n }>;\n const files = [\n ...RESOLUTION_FILES,\n ...readPatchFiles(workspaceYaml),\n ...projects.map((project) => join(relative(forkPath, project.path), 'package.json')),\n ];\n for (const file of new Set(files)) {\n if (file.startsWith('..') || !existsSync(join(forkPath, file))) continue;\n mkdirSync(dirname(join(staging, file)), { recursive: true });\n cpSync(join(forkPath, file), join(staging, file));\n }\n return staging;\n}\n\n/** Resolve the staging copy under `settings`; returns the lockfile, or pnpm's output on failure. */\nasync function resolveStaging(\n staging: string,\n workspaceYaml: string,\n settings: AuditSettings,\n): Promise<{ lock: string } | { error: string }> {\n writeFileSync(join(staging, WORKSPACE_FILE), writeAuditSettings(workspaceYaml, settings));\n const result = await runPnpm(['install', '--lockfile-only', '--no-frozen-lockfile', '--ignore-scripts'], staging);\n return result.ok ? { lock: readOr(join(staging, LOCK_FILE)) } : { error: `${result.stdout}${result.stderr}`.trim() };\n}\n\n/** The versions of a package that a lockfile holds. */\nfunction lockedVersions(lock: string, name: string): string[] {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\/]/g, '\\\\$&');\n const versions = [...lock.matchAll(new RegExp(`^ {2}'?${escaped}@(\\\\d[^:'()\\\\s]*)`, 'gm'))].map((match) => match[1]);\n return [...new Set(versions)];\n}\n\n/** `installed → fix`, flagged when the fix is a breaking jump; the installed version alone without a fix. */\nfunction versionsText(item: SecurityItem): string {\n if (item.remedy.kind === 'none') return item.installed;\n return `${item.installed} → ${item.remedy.target}${isBreaking(item) ? ' ⚠' : ''}`;\n}\n\n/** One line of context for an item that is not simply fixed by its override. */\nfunction noteText(item: SecurityItem, releaseAgeHours: number): string {\n if (item.remedy.kind === 'none') return 'no fix published';\n if (item.remedy.kind === 'fresh')\n return `fix published ${item.remedy.hoursOld}h ago, inside the ${releaseAgeHours}h release age`;\n if (item.standing === 'ignored') return 'the fix is a breaking jump';\n return '';\n}\n\nfunction printGroup(title: string, items: SecurityItem[], releaseAgeHours: number): void {\n if (items.length === 0) return;\n const nameWidth = Math.min(30, Math.max(...items.map((item) => item.module.length)));\n const versionWidth = Math.max(...items.map((item) => versionsText(item).length));\n\n console.info(pc.bold(`${title} (${items.length})`));\n for (const item of items) {\n const name = pc.white(middleTruncate(item.module, nameWidth).padEnd(nameWidth));\n const source = `${formatDependents(item.via)}${item.direct ? ' (direct)' : ''}`;\n const tail = [source, noteText(item, releaseAgeHours)].filter(Boolean).join(' · ');\n console.info(\n `${getVulnIcon(item.severity)} ${name} ${item.severity.padEnd(8)} ${versionsText(item).padEnd(versionWidth)} ${pc.dim(tail)}`,\n );\n }\n console.info();\n}\n\nfunction printDropped(title: string, rows: Array<[name: string, reason: string]>): void {\n if (rows.length === 0) return;\n const nameWidth = Math.min(40, Math.max(...rows.map(([name]) => name.length)));\n console.info(pc.bold(`${title} (${rows.length})`));\n for (const [name, reason] of rows) {\n console.info(`${pc.green('○')} ${pc.white(middleTruncate(name, nameWidth).padEnd(nameWidth))} ${pc.dim(reason)}`);\n }\n console.info();\n}\n\n/** Why an audit override from before the run is not coming back. */\nfunction droppedReason(key: string, items: SecurityItem[], bareLock: string): string {\n const module = overrideModule(key);\n const item = items.find((candidate) => candidate.module === module);\n if (item) return item.remedy.kind === 'none' ? 'no published version fixes it' : 'replaced by another range';\n const versions = lockedVersions(bareLock, module);\n return versions.length > 0 ? `resolves to ${versions.join(', ')} on its own` : 'no longer installed';\n}\n\n/** Ask about the items that need a decision; everything else follows from its standing. */\nasync function decide(items: SecurityItem[], releaseAgeHours: number): Promise<Decision[]> {\n const decisions: Decision[] = [];\n\n for (const item of items) {\n const { remedy } = item;\n const jump = remedy.kind === 'none' ? '' : `${item.installed} → ${remedy.target}`;\n\n if (!needsDecision(item)) {\n decisions.push({ item, action: item.standing === 'ignored' ? 'ignore' : 'override' });\n } else if (remedy.kind === 'none') {\n const ignore = await confirm({\n message: `${item.module}: no fix is published. ignore ${item.ghsas.join(', ')} until one is?`,\n default: true,\n });\n decisions.push({ item, action: ignore ? 'ignore' : 'open' });\n } else if (remedy.kind === 'fresh') {\n const action = await select<Action>({\n message: `${item.module}: fix ${remedy.target} was published ${remedy.hoursOld}h ago, inside the ${releaseAgeHours}h release age`,\n choices: [\n { name: 'wait and re-run later', value: 'open' },\n { name: 'install now, with an exclude that a later audit removes', value: 'override' },\n ],\n });\n decisions.push({ item, action, exclude: action === 'override' ? `${item.module}@${remedy.target}` : undefined });\n } else {\n const message = item.direct\n ? `the fix is ${jump}, and ${item.via[0]} depends on it directly`\n : `the fix jumps ${jump}, past what ${formatDependents(item.via)} asks for`;\n const action = await select<Action>({\n message: `${item.module}: ${message}`,\n choices: [\n { name: item.direct ? 'leave open, update it in package.json' : 'leave open', value: 'open' },\n { name: 'apply the override', value: 'override' },\n { name: 'ignore the advisory', value: 'ignore' },\n ],\n });\n decisions.push({ item, action });\n }\n }\n\n return decisions;\n}\n\n/**\n * The settings that carry out the decisions, on top of `kept`: the overrides the audit does not\n * own, plus the ones a package had before when its item is left open.\n */\nfunction settingsFor(decisions: Decision[], kept: Record<string, string>, excludes: string[]): AuditSettings {\n const overriding = decisions.filter((decision) => decision.action === 'override');\n return {\n overrides: { ...kept, ...Object.assign({}, ...overriding.map((decision) => decision.item.overrides)) },\n releaseAgeExcludes: [...new Set([...excludes, ...overriding.flatMap((decision) => decision.exclude ?? [])])],\n ignoredGhsas: decisions\n .filter((decision) => decision.action === 'ignore')\n .flatMap((decision) => decision.item.ghsas),\n };\n}\n\n/** `before → after` with what moved, or the count alone when nothing did. */\nfunction changeLine(label: string, before: string[], after: string[]): string {\n const dropped = before.filter((entry) => !after.includes(entry)).length;\n const added = after.filter((entry) => !before.includes(entry)).length;\n const moved = [dropped ? `${dropped} dropped` : '', added ? `${added} added` : ''].filter(Boolean).join(', ');\n const counts = moved ? `${before.length} → ${after.length}` : String(after.length);\n return ` ${label.padEnd(9)} ${counts.padEnd(7)} ${pc.dim(moved || 'unchanged')}`;\n}\n\n/**\n * Run the security pass on the workspace at `forkPath`. With `apply` off it reports what it would\n * do and writes nothing.\n */\nexport async function runSecurityPass(forkPath: string, options: { apply: boolean }): Promise<void> {\n const workspaceYaml = readOr(join(forkPath, WORKSPACE_FILE));\n const workspaceLock = readOr(join(forkPath, LOCK_FILE));\n let previous: AuditSettings;\n try {\n previous = readAuditSettings(workspaceYaml);\n } catch (error) {\n console.error(\n `${pc.red('✗')} ${WORKSPACE_FILE} could not be read: ${error instanceof Error ? error.message : error}`,\n );\n return;\n }\n const auditKeys = Object.keys(previous.overrides).filter(isAuditOverride);\n const lasting = Object.fromEntries(Object.entries(previous.overrides).filter(([key]) => !isAuditOverride(key)));\n\n const spinner = createSpinner(\n auditKeys.length > 0\n ? `resolving without the ${count(auditKeys.length, 'audit override')}...`\n : 'resolving the workspace...',\n );\n const fail = (message: string, detail = ''): void => {\n spinner.stop();\n console.error(`${pc.red('✗')} ${message}`);\n if (detail) console.error(pc.dim(detail.split('\\n').slice(-12).join('\\n')));\n console.info(pc.dim(' the workspace is unchanged'));\n console.info();\n };\n\n const staging = await createStaging(forkPath, workspaceYaml);\n try {\n // Ignores come off as well, so an ignored advisory is seen again and can pick up a fix.\n const bare = await resolveStaging(staging, workspaceYaml, { ...previous, overrides: lasting, ignoredGhsas: [] });\n if ('error' in bare) return fail('could not resolve the workspace without its audit overrides', bare.error);\n\n spinnerText('checking for vulnerabilities...');\n const audit = await runPnpmAudit(staging);\n if (!audit) return fail('pnpm audit gave no answer, so nothing can be decided');\n const advisories = advisoriesFromAudit(audit);\n\n spinnerText(`checking ${count(advisories.length, 'advisory', 'advisories')} against the registry...`);\n const versionedExcludes = previous.releaseAgeExcludes.flatMap((entry) => parseVersionedExclude(entry)?.name ?? []);\n const names = [...new Set([...advisories.map((advisory) => advisory.module), ...versionedExcludes])];\n const times = await Promise.all(names.map((name) => fetchPublishTimes(name, forkPath)));\n const published: Record<string, PublishTimes> = Object.fromEntries(\n names.map((name, i) => [name, times[i]]).filter(([, answer]) => answer),\n );\n // A fix is only judged absent when the registry answered: silence must not turn into an ignore.\n const unanswered = advisories.map((advisory) => advisory.module).filter((name) => !published[name]);\n if (unanswered.length > 0) return fail(`the registry did not answer for ${[...new Set(unanswered)].join(', ')}`);\n\n const releaseAge = Number.parseInt((await runPnpm(['config', 'get', 'minimumReleaseAge'], forkPath)).stdout, 10);\n const releaseAgeMinutes = Number.isNaN(releaseAge) ? 0 : releaseAge;\n const releaseAgeHours = Math.round(releaseAgeMinutes / 60);\n const planInput = { advisories, published, previous, releaseAgeMinutes, now: Date.now() };\n const items = planSecurity(planInput);\n const excludes = liveExcludes(planInput);\n spinner.stop();\n\n const changes = printPlan({\n items,\n previous,\n auditKeys,\n lasting,\n advisories,\n bareLock: bare.lock,\n releaseAgeHours,\n });\n if (!options.apply) {\n if (changes) console.info(pc.dim('run without --list to apply'));\n console.info();\n return;\n }\n\n let decisions: Decision[];\n try {\n decisions = await decide(items, releaseAgeHours);\n } catch {\n console.info(pc.dim(' cancelled, the workspace is unchanged'));\n return;\n }\n\n const open = decisions.filter((decision) => decision.action === 'open').map((decision) => decision.item.module);\n const kept = Object.assign({}, lasting, ...open.map((module) => standingOverrides(module, planInput)));\n const next = settingsFor(decisions, kept, excludes);\n const nextYaml = writeAuditSettings(workspaceYaml, next);\n\n if (nextYaml === workspaceYaml) {\n const state = `${count(auditKeys.length, 'override')} · ${next.ignoredGhsas.length} ignored`;\n console.info(`${checkMark} security settings are current ${pc.dim(`· ${state}`)}`);\n printOpen(open);\n return;\n }\n\n const summarize = (): void => {\n console.info(pc.bold(WORKSPACE_FILE));\n console.info(changeLine('overrides', auditKeys, Object.keys(next.overrides).filter(isAuditOverride)));\n console.info(changeLine('excludes', previous.releaseAgeExcludes, next.releaseAgeExcludes));\n console.info(changeLine('ignored', previous.ignoredGhsas, next.ignoredGhsas));\n console.info();\n };\n\n // Ignores and aged excludes do not change what resolves: the file is all there is to write.\n if (sameEntries(next.overrides, previous.overrides)) {\n writeFileSync(join(forkPath, WORKSPACE_FILE), nextYaml);\n console.info(`${checkMark} ${WORKSPACE_FILE} updated ${pc.dim('· nothing to install')}`);\n printOpen(open);\n summarize();\n return;\n }\n\n const stagingSpinner = createSpinner('resolving with the new settings...');\n const staged = await resolveStaging(staging, workspaceYaml, next);\n stagingSpinner.stop();\n if ('error' in staged) return fail('could not resolve the workspace with the new settings', staged.error);\n\n writeFileSync(join(forkPath, WORKSPACE_FILE), nextYaml);\n writeFileSync(join(forkPath, LOCK_FILE), staged.lock);\n const install = spawnSync('pnpm', ['install'], { cwd: forkPath, stdio: 'inherit' });\n console.info();\n if (install.status !== 0) {\n writeFileSync(join(forkPath, WORKSPACE_FILE), workspaceYaml);\n writeFileSync(join(forkPath, LOCK_FILE), workspaceLock);\n console.error(`${pc.red('✗')} pnpm install failed (exit code ${install.status})`);\n console.info(pc.dim(` ${WORKSPACE_FILE} and ${LOCK_FILE} are back as they were; run pnpm install to match`));\n console.info();\n return;\n }\n\n // The workspace's own audit has the last word on what is still reported.\n const verified = await runPnpmAudit(forkPath);\n const reported = verified ? [...new Set(advisoriesFromAudit(verified).map((advisory) => advisory.module))] : open;\n console.info(`${checkMark} installed${reported.length === 0 ? ` ${pc.dim('·')} audit clean` : ''}`);\n printOpen(reported);\n\n summarize();\n } finally {\n spinner.stop();\n rmSync(staging, { recursive: true, force: true });\n }\n}\n\nfunction printOpen(modules: string[]): void {\n if (modules.length > 0) {\n console.info(`${warningMark} ${count(modules.length, 'package')} still reported: ${modules.join(', ')}`);\n }\n console.info();\n}\n\n/** The report of the staged audit: what stays, what is new, what goes. Returns whether a run would change anything. */\nfunction printPlan(plan: {\n items: SecurityItem[];\n previous: AuditSettings;\n auditKeys: string[];\n lasting: Record<string, string>;\n advisories: Advisory[];\n bareLock: string;\n releaseAgeHours: number;\n}): boolean {\n const { items, previous, releaseAgeHours } = plan;\n const kept = items.filter((item) => item.standing === 'carried');\n const undecided = items.filter(needsDecision);\n const added = items.filter((item) => item.standing === 'new' && !needsDecision(item));\n const ignored = items.filter((item) => item.standing === 'ignored');\n\n const plannedKeys = new Set(\n items.flatMap((item) => (item.standing === 'ignored' ? [] : Object.keys(item.overrides))),\n );\n // What happens to the overrides of a package that awaits a decision follows from the answer.\n const pending = new Set(undecided.map((item) => item.module));\n const droppedOverrides = plan.auditKeys\n .filter((key) => !plannedKeys.has(key) && !pending.has(overrideModule(key)))\n .map((key): [string, string] => [key, droppedReason(key, items, plan.bareLock)]);\n\n const reportedGhsas = new Set(plan.advisories.map((advisory) => advisory.ghsa));\n const fixedGhsas = new Set([...kept, ...added].flatMap((item) => item.ghsas));\n const droppedIgnores = previous.ignoredGhsas\n .filter((ghsa) => !reportedGhsas.has(ghsa) || fixedGhsas.has(ghsa))\n .map((ghsa): [string, string] => [ghsa, fixedGhsas.has(ghsa) ? 'a fix is published' : 'no longer applies']);\n\n console.info(pc.bold('security'));\n console.info(DIVIDER);\n if (items.length === 0 && droppedOverrides.length === 0 && droppedIgnores.length === 0) {\n console.info(`${checkMark} no vulnerabilities found`);\n console.info();\n return false;\n }\n\n printGroup('override kept', kept, releaseAgeHours);\n printGroup('fix available', added, releaseAgeHours);\n printGroup('needs a decision', undecided, releaseAgeHours);\n printGroup('ignored', ignored, releaseAgeHours);\n printDropped('override dropped', droppedOverrides);\n printDropped('ignore dropped', droppedIgnores);\n\n const lastingCount = Object.keys(plan.lasting).length;\n if (lastingCount > 0) {\n console.info(pc.dim(`${count(lastingCount, 'override')} without a version selector left as written`));\n }\n if (items.some(isBreaking)) {\n console.info(pc.dim('⚠ a breaking jump: another major, or another minor below 1.0'));\n }\n console.info();\n return added.length + undecided.length + droppedOverrides.length + droppedIgnores.length > 0;\n}\n","/**\n * Contributions service for sync CLI.\n *\n * Upstream-side (cella): based on the configured `forks`, lets the user pick a\n * single fork, pulls its `pullBranch` and builds a clean local `contrib/<fork>`\n * branch with only that fork's contributed files. Then shows an interactive TUI\n * to review and adopt individual files into the working tree.\n */\n\nimport {\n createPrompt,\n isDownKey,\n isEnterKey,\n isSpaceKey,\n isUpKey,\n useKeypress,\n usePagination,\n useState,\n} from '@inquirer/core';\nimport { select } from '@inquirer/prompts';\nimport type { RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { DEFAULT_BRANCH, isUpstreamRepo, loadConfig } from '../utils/config';\nimport { gitDiffFile, openDiffInBrowser } from '../utils/diff';\nimport {\n checkMark,\n createSpinner,\n DIVIDER,\n spinnerFail,\n spinnerSuccess,\n warningMark,\n writeStdout,\n} from '../utils/display';\nimport { errorMessage } from '../utils/errors';\nimport {\n checkoutFromRef,\n getCurrentBranch,\n getDiffStat,\n git,\n gitRm,\n removeFileFromWorktree,\n restoreWorktreeFromRef,\n} from '../utils/git';\nimport { buildContribBranch, type ContribFile, detectContributableFiles } from './contrib-core';\nimport { printNoForksHint, resolveForkBasePath, type ValidatedFork, validateForkPath } from './fork-utils';\n\ninterface ContribItem extends ContribFile {\n /** Lines added in the fork vs cella base (null for binary files) */\n additions: number | null;\n /** Lines removed in the fork vs cella base (null for binary files) */\n deletions: number | null;\n /** Whether file is selected for acceptance */\n checked: boolean;\n}\n\ninterface ContribPromptConfig {\n message: string;\n items: ContribItem[];\n /** Name of the fork being reviewed (used to label diffs cella/ vs <fork>/) */\n forkName: string;\n /** Base ref the contrib branch was built on (for diffing) */\n baseRef: string;\n /** The local `contrib/<fork>` branch holding the fork's files */\n branch: string;\n /** Repo path where contrib branches live */\n cwd: string;\n pageSize?: number;\n}\n\n/**\n * Interactive prompt for reviewing contributed files.\n * Returns items selected for acceptance.\n */\nconst contribPrompt = createPrompt<ContribItem[], ContribPromptConfig>((config, done) => {\n const { pageSize = 20, baseRef, branch, cwd, forkName } = config;\n\n const [items, setItems] = useState<ContribItem[]>(config.items);\n const [active, setActive] = useState(0);\n const [statusMsg, setStatusMsg] = useState('');\n const [promptStatus, setPromptStatus] = useState<'idle' | 'done'>('idle');\n\n useKeypress(async (key) => {\n const last = items.length - 1;\n\n if (items.length === 0) {\n if (isEnterKey(key) || key.name === 'q') {\n setPromptStatus('done');\n done([]);\n }\n return;\n }\n\n if (key.name === 'q') {\n setPromptStatus('done');\n done([]);\n return;\n }\n\n if (isEnterKey(key)) {\n const selected = items.filter((i) => i.checked);\n if (selected.length === 0) {\n setStatusMsg('select files with space first, or q to quit');\n return;\n }\n setPromptStatus('done');\n done(selected);\n return;\n }\n\n // Navigation\n if (key.ctrl && isUpKey(key)) {\n setActive(0);\n setStatusMsg('');\n return;\n }\n if (key.ctrl && isDownKey(key)) {\n setActive(last);\n setStatusMsg('');\n return;\n }\n if (isUpKey(key)) {\n setActive(active <= 0 ? 0 : active - 1);\n setStatusMsg('');\n return;\n }\n if (isDownKey(key)) {\n setActive(active >= last ? last : active + 1);\n setStatusMsg('');\n return;\n }\n\n if (isSpaceKey(key)) {\n setItems(items.map((item, i) => (i === active ? { ...item, checked: !item.checked } : item)));\n return;\n }\n\n // d = open diff in browser (non-blocking, the list stays up)\n if (key.name === 'd') {\n const { path } = items[active];\n try {\n const patch = gitDiffFile(cwd, `${baseRef}..${branch}`, path);\n if (patch.length === 0) return setStatusMsg(`no changes for ${path}`);\n await openDiffInBrowser(patch.toString(), { filePath: path, srcLabel: 'cella', dstLabel: forkName }, cwd);\n setStatusMsg(`opened ${path} in browser`);\n } catch (error) {\n setStatusMsg(`diff failed: ${errorMessage(error)}`);\n }\n return;\n }\n\n if (key.name === 'a') {\n const allChecked = items.every((item) => item.checked);\n setItems(items.map((item) => ({ ...item, checked: !allChecked })));\n setStatusMsg(allChecked ? 'deselected all' : 'selected all');\n return;\n }\n });\n\n // Render: done state\n if (promptStatus === 'done') {\n const checked = items.filter((i) => i.checked);\n if (checked.length > 0) {\n return `${checkMark} ${checked.length} files accepted`;\n }\n return `${checkMark} done`;\n }\n\n // Render: empty\n if (items.length === 0) {\n return `${checkMark} no contributions: press enter`;\n }\n\n // Render: paginated list\n const checkedCount = items.filter((i) => i.checked).length;\n\n const page = usePagination({\n items,\n active,\n renderItem({ item, isActive }) {\n const checkbox = item.checked ? pc.green('●') : pc.dim('○');\n const cursor = isActive ? pc.cyan('❯') : ' ';\n const newLabel = item.kind === 'created' ? pc.yellow(' · not in cella') : '';\n const delLabel = item.kind === 'deleted' ? pc.yellow(' [del]') : '';\n const statusTag = item.status === 'diverged' ? pc.yellow(' ⚠ diverged') : '';\n const dateLabel = item.changedAt ? pc.dim(` · ${item.changedAt}`) : '';\n const line = `${cursor} ${checkbox} ${item.path}${delLabel}${statusTag}${newLabel}${dateLabel}`;\n return isActive ? pc.cyan(line) : line;\n },\n pageSize,\n loop: false,\n });\n\n const countInfo =\n checkedCount > 0 ? `${items.length} files, ${pc.green(`${checkedCount} selected`)}` : `${items.length} files`;\n const header = `${pc.cyan('⬇')} ${config.message} ${pc.dim(`(${countInfo})`)}`;\n\n const keys: [string, string][] = [\n ['↑↓', 'navigate'],\n ['d', 'diff in browser'],\n ['a', '(de)select all'],\n ['space', 'select'],\n ['⏎', 'accept'],\n ['q', 'quit'],\n ];\n const helpLine = keys.map(([k, a]) => `${pc.bold(k)} ${pc.dim(a)}`).join(pc.dim(' · '));\n\n const statusLine = statusMsg ? ` ${pc.dim(statusMsg)}` : '';\n\n const lines = [header, page, statusLine, helpLine].filter(Boolean).join('\\n').trimEnd();\n return `${lines}\\x1B[?25l`;\n});\n\n/**\n * Resolve the fork to pull from: the explicit --fork by name, the single valid fork with --json,\n * or an interactive prompt. Throws when no fork can be selected; returns undefined only when the\n * prompt selects nothing.\n */\nasync function selectFork(config: RuntimeConfig, validated: ValidatedFork[]): Promise<ValidatedFork | undefined> {\n if (config.fork) {\n const match = validated.find((v) => v.fork.name === config.fork);\n if (!match?.valid) {\n throw new Error(`fork '${config.fork}' not found or invalid in config`);\n }\n return match;\n }\n\n if (config.json) {\n const validForks = validated.filter((v) => v.valid);\n if (validForks.length === 0) throw new Error('no valid forks configured');\n if (validForks.length > 1) throw new Error('multiple forks configured; pass --fork <name> to choose one');\n return validForks[0];\n }\n\n const choices = validated.map((v) => ({\n value: v.fork.name,\n name: v.valid\n ? `${v.fork.name} ${pc.dim(`[${v.fork.pullBranch}] ${v.fork.localPath}`)}`\n : `${v.fork.name} ${pc.dim(v.fork.localPath)}`,\n disabled: v.valid ? false : (v.error ?? 'invalid'),\n }));\n const picked = await select<string>({\n message: 'select fork to pull contributions from:',\n choices,\n loop: false,\n });\n const selected = validated.find((v) => v.fork.name === picked);\n if (!selected) console.info(pc.dim('no fork selected.'));\n return selected;\n}\n\n/** Short sha + relative date of the fork's committed pullBranch HEAD (for the comparison banner). */\nasync function forkRefMeta(cellaPath: string, forkRef: string): Promise<{ sha: string; date: string }> {\n const out = await git(['log', '-1', '--format=%h%x09%cr', forkRef], cellaPath, { ignoreErrors: true });\n const [sha = forkRef.slice(0, 7), date = 'unknown'] = out.split('\\t');\n return { sha, date };\n}\n\n/**\n * Run the contributions service.\n *\n * Based on the configured `forks`, lets the user select one fork, pulls its\n * `pullBranch`, builds a clean local `contrib/<fork>` branch, then presents\n * an interactive TUI to review and adopt individual files.\n */\nexport async function runContributions(config: RuntimeConfig): Promise<void> {\n const forks = config.forks ?? [];\n\n if (forks.length === 0) {\n printNoForksHint('add forks to pull contributions from:');\n return;\n }\n\n // Compare forks against cella's currently checked-out branch, not a fixed\n // configured branch, so contributions reflect the branch you're working on.\n const baseRef = await getCurrentBranch(config.forkPath);\n\n // Warn when not on cella's base branch. The comparison is a 3-way analysis against\n // merge-base(baseRef, fork), so a long-lived feature branch has an older merge-base\n // than 'main' and may surface extra 'diverged' files that would show clean from main.\n if (baseRef !== DEFAULT_BRANCH) {\n console.info(\n `${warningMark} ${pc.yellow(`not on base branch '${DEFAULT_BRANCH}'`)} ${pc.dim(`comparing forks against '${baseRef}'`)}`,\n );\n console.info(\n ` ${pc.dim(`older merge-base may show extra 'diverged' files; switch to '${DEFAULT_BRANCH}' for the cleanest result`)}`,\n );\n console.info('');\n }\n\n const forkBasePath = await resolveForkBasePath(config.forkPath);\n const validated = forks.map((fork) => validateForkPath(fork, forkBasePath));\n\n const selectedFork = await selectFork(config, validated);\n if (!selectedFork) return;\n\n const { fork, resolvedPath } = selectedFork;\n const forkName = fork.name;\n\n createSpinner('pulling fork contributions...');\n const allItems: ContribItem[] = [];\n let forkBanner: { pullBranch: string; sha: string; date: string } | null = null;\n let branch = '';\n\n try {\n // Prefer the fork's remote (authoritative committed ref) over the local clone.\n await git(['fetch', fork.remoteUrl ?? resolvedPath, fork.pullBranch], config.forkPath);\n const forkRef = await git(['rev-parse', 'FETCH_HEAD'], config.forkPath);\n const meta = await forkRefMeta(config.forkPath, forkRef);\n forkBanner = { pullBranch: fork.pullBranch, sha: meta.sha, date: meta.date };\n\n // Read the fork's own owned folders so its fork-specific modules aren't offered back\n let forkTerritory: string[] = [];\n try {\n const forkConfig = await loadConfig(resolvedPath);\n forkTerritory = forkConfig.overrides?.ignored ?? [];\n } catch {\n // Fork may not have a cella/cella.config.ts: no extra territory to exclude\n }\n\n const files = await detectContributableFiles(config.forkPath, baseRef, forkRef, config, forkTerritory);\n if (files.length > 0) {\n const built = await buildContribBranch(config.forkPath, baseRef, forkRef, files, forkName);\n if (built.appliedFiles.length > 0) {\n branch = built.branch;\n const stat = await getDiffStat(config.forkPath, baseRef, branch);\n for (const file of files) {\n const { additions = null, deletions = null } = stat.get(file.path) ?? {};\n allItems.push({ ...file, additions, deletions, checked: false });\n }\n }\n }\n } catch (error) {\n spinnerFail(`failed to pull ${forkName}`);\n console.info(pc.red(` ✗ ${errorMessage(error)}`));\n return;\n }\n\n if (allItems.length === 0) {\n spinnerSuccess('no contributions found');\n return;\n }\n\n // Sort by most recent fork change first (undated files last), path as tie-breaker,\n // so the top of the list shows where the fork last drifted (further) apart.\n allItems.sort((a, b) => (b.changedTs ?? 0) - (a.changedTs ?? 0) || a.path.localeCompare(b.path));\n\n spinnerSuccess(`${allItems.length} files from ${forkName}`);\n\n // Make the comparison basis explicit: the fork is compared at its committed pullBranch HEAD,\n // not its working tree, so uncommitted fork edits never appear here.\n if (forkBanner) {\n console.info(\n ` ${pc.dim(`${forkName}: comparing committed '${forkBanner.pullBranch}' @ ${forkBanner.sha} (${forkBanner.date}); uncommitted fork changes are not included`)}`,\n );\n }\n\n // Machine-readable JSON output for tooling/agent usage\n if (config.json) {\n const out = allItems.map((item) => ({\n fork: forkName,\n path: item.path,\n status: item.status,\n kind: item.kind === 'deleted' ? 'deleted' : 'modified',\n changedAt: item.changedAt ?? null,\n changedTs: item.changedTs ?? null,\n additions: item.additions,\n deletions: item.deletions,\n }));\n writeStdout(JSON.stringify(out, null, 2));\n return;\n }\n\n console.info();\n console.info(DIVIDER);\n\n const selected = await contribPrompt({\n message: `contributions from ${forkName}`,\n items: allItems,\n forkName,\n baseRef,\n branch,\n cwd: config.forkPath,\n pageSize: 20,\n });\n\n if (selected.length === 0) {\n console.info();\n return;\n }\n\n // Apply selected files into the working tree (unstaged in upstream cella, staged in a fork)\n createSpinner(`applying ${selected.length} files...`);\n const applyUnstaged = isUpstreamRepo(config.forkPath);\n\n let applied = 0;\n const errors: string[] = [];\n\n for (const item of selected) {\n try {\n // Reject paths with traversal components (CWE-22)\n if (item.path.includes('..') || item.path.startsWith('/')) {\n errors.push(`${item.path}: rejected (path traversal)`);\n continue;\n }\n if (item.kind === 'deleted') {\n if (applyUnstaged) {\n await removeFileFromWorktree(config.forkPath, item.path);\n } else {\n await gitRm(config.forkPath, [item.path]);\n }\n } else {\n if (applyUnstaged) {\n await restoreWorktreeFromRef(config.forkPath, branch, item.path);\n } else {\n await checkoutFromRef(config.forkPath, branch, [item.path]);\n }\n }\n applied++;\n } catch (error) {\n errors.push(`${item.path}: ${errorMessage(error)}`);\n }\n }\n\n if (errors.length > 0) {\n spinnerFail(`applied ${applied}/${selected.length} files (${errors.length} errors)`);\n for (const err of errors) {\n console.info(pc.red(` ✗ ${err}`));\n }\n } else {\n spinnerSuccess(`applied ${applied} files ${pc.dim(applyUnstaged ? '(unstaged)' : '(staged)')}`);\n }\n\n // No per-file summary: the applied files are visible in the IDE's source control view.\n console.info();\n console.info(\n pc.dim(\n applyUnstaged\n ? ' files are unstaged: review, stage what you want, and commit when ready'\n : ' files are staged: review and commit when ready',\n ),\n );\n console.info();\n}\n","/**\n * Diff helpers: a single-file `git diff`, and a diff rendered as a self-contained\n * HTML page that opens in the default browser. Used by the analyze and\n * contributions services.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { basename, join } from 'node:path';\nimport process from 'node:process';\nimport { MAX_BUFFER } from './git';\n\n/**\n * Run `git diff` for a single file over `range` (`a..b`, or one ref to diff against the working\n * tree). Returns the raw diff, empty when the file is identical.\n *\n * With `dstPrefix`, the sides are labeled `cella/<path>` vs `<dstPrefix>/<path>`,\n * not opaque a/ and b/: used for the `--diff` stdout mode where the labels carry\n * meaning. Without it, standard a/ b/ prefixes are kept, which the HTML\n * renderer's patch parser requires.\n */\nexport function gitDiffFile(\n cwd: string,\n range: string,\n filePath: string,\n options: { dstPrefix?: string } = {},\n): Buffer {\n const args = ['diff', '--no-color'];\n if (options.dstPrefix) args.push('--src-prefix=cella/', `--dst-prefix=${options.dstPrefix}/`);\n args.push(range, '--', filePath);\n\n try {\n return execFileSync('git', args, { cwd, maxBuffer: MAX_BUFFER });\n } catch (error) {\n const stderr = (error as { stderr?: Buffer }).stderr?.toString().trim();\n throw new Error(stderr || `failed to diff ${filePath}`);\n }\n}\n\n/** Labels shown in the header of a rendered diff page. */\ninterface DiffPageMeta {\n /** File path shown in the page header and title */\n filePath: string;\n /** Label for the upstream side (e.g. 'cella') */\n srcLabel: string;\n /** Label for the local side (e.g. the fork name) */\n dstLabel: string;\n /** Extra context shown after the labels (e.g. 'includes uncommitted changes') */\n note?: string;\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\n\n/**\n * Render a unified diff as a complete, self-contained HTML document.\n *\n * Highlighting and diff layout come from `@pierre/diffs` (Shiki-based), rendered\n * server-side to static HTML: no scripts, no external requests, adapts to the\n * viewer's light/dark preference. The patch must use standard a/ b/ prefixes\n * (call `gitDiffFile` without `dstPrefix`); side labels belong in `meta`.\n */\nexport async function renderDiffPage(patch: string, meta: DiffPageMeta): Promise<string> {\n // Lazy import: the CLI is a short-lived process and most invocations never\n // render a diff, so startup shouldn't pay Shiki's module-load cost.\n const { preloadPatchDiff } = await import('@pierre/diffs/ssr');\n\n const { prerenderedHTML } = await preloadPatchDiff({\n patch,\n options: {\n diffStyle: 'split',\n themeType: 'system',\n lineDiffType: 'word-alt',\n hunkSeparators: 'line-info',\n overflow: 'wrap',\n disableFileHeader: true,\n },\n });\n\n const title = `${escapeHtml(meta.filePath)} · ${escapeHtml(meta.srcLabel)} vs ${escapeHtml(meta.dstLabel)}`;\n const note = meta.note ? `<span class=\"note\">· ${escapeHtml(meta.note)}</span>` : '';\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${title}</title>\n<style>\n :root { color-scheme: light dark; }\n * { box-sizing: border-box; }\n body {\n margin: 0;\n font-family: ui-sans-serif, system-ui, -apple-system, sans-serif;\n background: light-dark(#fafafa, #111);\n color: light-dark(#111, #eee);\n }\n header {\n display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap;\n padding: 0.9rem 1.25rem;\n border-bottom: 1px solid light-dark(#e2e2e2, #2a2a2a);\n position: sticky; top: 0;\n background: inherit;\n }\n header .brand { font-weight: 600; color: light-dark(#0891b2, #22d3ee); }\n header code { font-family: ui-monospace, monospace; font-size: 0.9rem; }\n header .sides { margin-left: auto; font-size: 0.8rem; opacity: 0.7; }\n main { max-width: 1400px; margin: 1rem auto; padding: 0 1rem 2rem; }\n .diff-shell {\n border: 1px solid light-dark(#e2e2e2, #2a2a2a);\n border-radius: 8px; overflow: hidden;\n background: light-dark(#fff, #161616);\n }\n</style>\n</head>\n<body>\n<header>\n <span class=\"brand\">⧈ cella diff</span>\n <code>${escapeHtml(meta.filePath)}</code>\n <span class=\"sides\">${escapeHtml(meta.srcLabel)} ← → ${escapeHtml(meta.dstLabel)} ${note}</span>\n</header>\n<main>\n <!-- Declarative shadow DOM: the library's CSS targets :host, which only\n matches inside a shadow root (its browser component renders into one). -->\n <div class=\"diff-shell\">\n <template shadowrootmode=\"open\">\n${prerenderedHTML}\n </template>\n </div>\n</main>\n</body>\n</html>`;\n}\n\n/** Open a file or URL with `open` (macOS) or `xdg-open` (best-effort: a\n * missing or failing opener is not fatal; the page path is printed anyway). */\nfunction openWithDefaultApp(target: string): void {\n try {\n execFileSync(process.platform === 'darwin' ? 'open' : 'xdg-open', [target], { stdio: 'ignore' });\n } catch {\n // e.g. headless environment without a browser/opener\n }\n}\n\n/**\n * Render a diff page, write it to a stable temp path, and open it in the browser.\n *\n * The output path is keyed by repo name and file path and overwritten on each\n * view, so repeat views don't litter tmp and a browser refresh shows the latest\n * render.\n *\n * @returns Absolute path of the written HTML file.\n */\nexport async function openDiffInBrowser(patch: string, meta: DiffPageMeta, repoPath: string): Promise<string> {\n const html = await renderDiffPage(patch, meta);\n\n const dir = join(tmpdir(), `cella-diff-${basename(repoPath)}`);\n mkdirSync(dir, { recursive: true });\n const outPath = join(dir, `${meta.filePath.replace(/[^\\w.-]+/g, '-')}.html`);\n\n writeFileSync(outPath, html);\n openWithDefaultApp(outPath);\n return outPath;\n}\n","/**\n * Shared contribution engine.\n *\n * Cella (upstream) pulls a fork's branch and detects which files the fork\n * changed, created, or deleted relative to cella's base branch. It then builds\n * a clean local `contrib/<fork>` branch (the base branch plus only the fork's\n * file overlays) so the changes can be reviewed and adopted without a\n * working-tree checkout.\n *\n * The fork's blobs are read directly from the fetched ref (already in cella's\n * object store), never from the filesystem.\n */\n\nimport { rmSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport type { CellaCliConfig, FileStatus } from '../config/types';\nimport { git } from '../utils/git';\nimport { isIgnored, isPinned, isUnderAnyFolder } from '../utils/overrides';\nimport { analyzeRefs, enrichChangeInfo } from './analyze-core';\n\n/** A single contributable file with classification and metadata. */\nexport interface ContribFile {\n /** File path relative to repo root */\n path: string;\n /** How adopting this file changes cella */\n kind: 'modified' | 'created' | 'deleted';\n /** Analyzer status from cella's POV (behind = fork ahead, diverged = both changed) */\n status: FileStatus;\n /** Relative date of the fork's change (e.g. '3 days ago') */\n changedAt?: string;\n /** Unix epoch seconds of the fork's change, for sorting */\n changedTs?: number;\n}\n\nasync function listFilesAtRef(repoPath: string, ref: string): Promise<Set<string>> {\n const raw = await git(['ls-tree', '-r', '--name-only', ref], repoPath);\n return new Set(raw.split('\\n').filter(Boolean));\n}\n\n/**\n * Detect the files a fork contributes relative to cella's base branch.\n *\n * Uses a merge-base 3-way analysis (cella = local, fork = incoming) so the\n * result distinguishes fork-ahead changes from cella's own drift. Only files\n * where the fork is ahead (status `behind`) or both sides changed (`diverged`)\n * are contributable. `forkTerritory` (the fork's own `ignored` list) keeps fork-specific modules out.\n */\nexport async function detectContributableFiles(\n repoPath: string,\n baseRef: string,\n forkRef: string,\n config: CellaCliConfig,\n forkTerritory: string[] = [],\n): Promise<ContribFile[]> {\n // Common ancestor for 3-way comparison; fall back to baseRef if histories are unrelated\n const mergeBase = (await git(['merge-base', baseRef, forkRef], repoPath, { ignoreErrors: true })).trim() || baseRef;\n\n const predicates = {\n isIgnored: (path: string) => isIgnored(path, config) || isUnderAnyFolder(path, forkTerritory),\n isPinned: (path: string) => isPinned(path, config),\n };\n\n // local = cella (baseRef), incoming = fork (forkRef)\n const analyzed = await analyzeRefs(repoPath, baseRef, forkRef, mergeBase, predicates);\n await enrichChangeInfo(repoPath, analyzed, mergeBase, baseRef, forkRef);\n\n // Base directory set for the sibling heuristic on created files.\n // Seed with '.' because the repo root always exists in cella, so new fork\n // files at the root (e.g. a shared config) are offered, not silently skipped.\n const baseFiles = await listFilesAtRef(repoPath, baseRef);\n const baseDirs = new Set<string>(['.']);\n for (const f of baseFiles) {\n let dir = dirname(f);\n while (dir !== '.') {\n baseDirs.add(dir);\n dir = dirname(dir);\n }\n }\n\n const files: ContribFile[] = [];\n for (const file of analyzed) {\n // Only files where the fork is ahead of cella are contributable\n if (file.status !== 'behind' && file.status !== 'diverged') continue;\n if (file.isIgnored || file.isPinned) continue;\n\n const inCella = file.existsInFork; // local side\n const inFork = file.existsInUpstream; // incoming side\n\n let kind: ContribFile['kind'];\n if (inCella && !inFork) {\n kind = 'deleted';\n } else if (!inCella && inFork) {\n // New fork file: only offer it when its directory already exists in cella,\n // so fork-specific modules don't flood the list (territory handles the rest)\n if (!baseDirs.has(dirname(file.path))) continue;\n kind = 'created';\n } else {\n kind = 'modified';\n }\n\n // Fork-side change date: 'behind' stores it in changedAt, 'diverged' in upstreamChangedAt\n const changedAt = file.status === 'diverged' ? file.upstreamChangedAt : file.changedAt;\n const changedTs = file.status === 'diverged' ? file.upstreamChangedTs : file.changedTs;\n files.push({ path: file.path, kind, status: file.status, changedAt, changedTs });\n }\n\n return files;\n}\n\n/**\n * Read mode and blob hash for a file at a ref.\n * Returns null if the path is not a regular blob at the ref.\n */\nasync function readBlobInfo(\n repoPath: string,\n ref: string,\n filePath: string,\n): Promise<{ mode: string; hash: string } | null> {\n const line = await git(['ls-tree', ref, '--', filePath], repoPath, { ignoreErrors: true });\n if (!line) return null;\n // Format: \"<mode> <type> <hash>\\t<path>\"\n const match = line.match(/^(\\d{6}) (\\w+) ([0-9a-f]+)\\t/);\n if (!match) return null;\n const [, mode, type, hash] = match;\n if (type !== 'blob') return null;\n // Only allow regular (100644) and executable (100755) file modes; skip symlinks/gitlinks\n if (mode !== '100644' && mode !== '100755') return null;\n return { mode, hash };\n}\n\n/**\n * Build a clean local `contrib/<fork>` branch from a fork's contributed files.\n *\n * The branch is created on top of `baseRef` with only the fork's file overlays\n * applied via a temporary index; the working tree is never touched.\n *\n * @returns The branch name and number of files applied.\n */\nexport async function buildContribBranch(\n repoPath: string,\n baseRef: string,\n forkRef: string,\n files: ContribFile[],\n forkName: string,\n): Promise<{ branch: string; appliedFiles: string[] }> {\n const branch = `contrib/${forkName}`;\n // Resolve the actual git dir: in a linked worktree `.git` is a pointer file, and the\n // worktree's git dir lives under the main checkout's `.git/worktrees/<name>`.\n const gitDir = resolve(repoPath, await git(['rev-parse', '--git-dir'], repoPath));\n const tmpIndex = join(gitDir, `tmp-contrib-index-${forkName.replace(/[^\\w.-]/g, '_')}`);\n const indexEnv = { GIT_INDEX_FILE: tmpIndex };\n\n try {\n // Seed the temp index with cella's base tree\n await git(['read-tree', baseRef], repoPath, { env: indexEnv });\n\n const appliedFiles: string[] = [];\n\n // Overlay the fork's files (blobs already in the object store via fetch) and remove its deletions\n for (const { path, kind } of files) {\n if (kind === 'deleted') {\n await git(['update-index', '--remove', path], repoPath, { env: indexEnv, ignoreErrors: true });\n appliedFiles.push(`(deleted) ${path}`);\n continue;\n }\n const blob = await readBlobInfo(repoPath, forkRef, path);\n if (!blob) continue;\n const cacheinfo = `${blob.mode},${blob.hash},${path}`;\n await git(['update-index', '--add', '--replace', '--cacheinfo', cacheinfo], repoPath, { env: indexEnv });\n appliedFiles.push(path);\n }\n\n if (appliedFiles.length === 0) {\n return { branch, appliedFiles };\n }\n\n // Write tree and commit on top of base\n const treeHash = await git(['write-tree'], repoPath, { env: indexEnv });\n const parentHash = await git(['rev-parse', baseRef], repoPath);\n const commitBody = appliedFiles.map((f) => `- ${f}`).join('\\n');\n const commitMessage = `contrib(${forkName}): ${appliedFiles.length} files\\n\\n${commitBody}`;\n const commitHash = await git(['commit-tree', treeHash, '-p', parentHash, '-m', commitMessage], repoPath);\n\n // Create/update the local branch ref without checkout\n await git(['update-ref', `refs/heads/${branch}`, commitHash], repoPath);\n\n return { branch, appliedFiles };\n } finally {\n rmSync(tmpIndex, { force: true });\n }\n}\n","/**\n * Shared helpers for the fork-aware services (`forks` and `contributions`).\n */\n\nimport { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport type { ForkConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { git } from '../utils/git';\nimport { CONFIG_FILE } from '../utils/managed-files';\n\n/**\n * Base directory that relative fork `localPath` values resolve against: the main checkout (the\n * parent of the shared git common dir), also from a linked worktree. Falls back to `repoPath`\n * outside a repository.\n */\nexport async function resolveForkBasePath(repoPath: string): Promise<string> {\n const commonDir = await git(['rev-parse', '--git-common-dir'], repoPath, { ignoreErrors: true });\n return commonDir ? dirname(resolve(repoPath, commonDir)) : repoPath;\n}\n\n/** A fork config paired with its validation result. */\nexport interface ValidatedFork {\n fork: ForkConfig;\n resolvedPath: string;\n valid: boolean;\n error?: string;\n}\n\n/**\n * Validate a fork's local path resolves safely and points at a git repository.\n *\n * @param requireConfig when true, the fork must also contain a `cella/cella.config.ts`.\n */\nexport function validateForkPath(fork: ForkConfig, basePath: string, requireConfig = false): ValidatedFork {\n const resolvedPath = resolve(basePath, fork.localPath);\n\n // Validate resolved path doesn't escape the parent directory via traversal (CWE-22)\n if (!resolvedPath.startsWith(resolve(basePath, '..'))) {\n return { fork, resolvedPath, valid: false, error: 'path resolves outside parent directory' };\n }\n if (!existsSync(resolvedPath)) return { fork, resolvedPath, valid: false, error: 'path does not exist' };\n if (!existsSync(`${resolvedPath}/.git`)) return { fork, resolvedPath, valid: false, error: 'not a git repository' };\n if (requireConfig && !existsSync(`${resolvedPath}/${CONFIG_FILE}`)) {\n return { fork, resolvedPath, valid: false, error: `missing ${CONFIG_FILE}` };\n }\n\n return { fork, resolvedPath, valid: true };\n}\n\n/**\n * Print the \"no forks configured\" empty-state with a config example.\n *\n * @param action a short dim line describing what forks enable (e.g. 'add forks to your config:').\n */\nexport function printNoForksHint(action: string): void {\n console.info(pc.yellow('no forks configured in cella/cella.config.ts'));\n console.info(pc.dim(action));\n console.info(pc.dim(` forks: [{ name: 'my-app', localPath: '../my-app', pullBranch: 'development' }]`));\n}\n","/**\n * Forks service: runs the sync service inside configured local fork repositories\n * from the upstream template. Selecting a fork runs sync immediately (plus\n * packages when enabled), then returns to the selection menu.\n */\n\nimport { resolve } from 'node:path';\nimport process from 'node:process';\nimport { Separator, select } from '@inquirer/prompts';\nimport type { ForkConfig, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { loadConfig, resolveUpstream } from '../utils/config';\nimport { MENU_DIVIDER } from '../utils/display';\nimport { getCommitInfo, getCurrentBranch, getStoredSyncRef, getWorkingTreeChangeCount } from '../utils/git';\nimport { printNoForksHint, resolveForkBasePath, validateForkPath } from './fork-utils';\nimport { runSyncCommand } from './sync';\n\n/** Status info gathered from a fork repository */\ninterface ForkStatus {\n branch: string;\n dirty: number;\n lastSync: { date: string; message: string } | null;\n}\n\n/** Git status info for a fork: branch, dirty state, last sync. */\nasync function gatherForkStatus(forkPath: string): Promise<ForkStatus> {\n const [branch, dirty, syncRef] = await Promise.all([\n getCurrentBranch(forkPath).catch(() => 'unknown'),\n getWorkingTreeChangeCount(forkPath).catch(() => 0),\n getStoredSyncRef(forkPath),\n ]);\n\n let lastSync: { date: string; message: string } | null = null;\n if (syncRef) {\n const commitInfo = await getCommitInfo(forkPath, syncRef).catch(() => null);\n lastSync = { date: commitInfo?.date ?? 'unknown', message: commitInfo?.message ?? '' };\n }\n\n return { branch, dirty, lastSync };\n}\n\nfunction formatForkChoice(name: string, status: ForkStatus | null): string {\n if (!status) return name;\n\n // Sync: date and truncated commit message.\n let syncPart: string;\n if (status.lastSync) {\n const msg =\n status.lastSync.message.length > 36 ? `${status.lastSync.message.slice(0, 36)}…` : status.lastSync.message;\n syncPart = pc.dim(`${status.lastSync.date}`);\n if (msg) syncPart += pc.dim(` '${msg}'`);\n } else {\n syncPart = pc.dim('never synced');\n }\n\n const dirtyPart = status.dirty > 0 ? pc.yellow(`${status.dirty} uncommitted`) : '';\n\n const parts = [name, pc.dim(`[${status.branch}]`), syncPart];\n if (dirtyPart) parts.push(dirtyPart);\n\n return parts.join(pc.dim(' · '));\n}\n\n/** Fork choices with live status info, gathered in parallel. */\nasync function buildForkChoices(\n forks: ForkConfig[],\n basePath: string,\n): Promise<Array<{ value: string; name: string; disabled?: string }>> {\n const validated = forks.map((fork) => validateForkPath(fork, basePath, true));\n\n const statusEntries = await Promise.all(\n validated\n .filter((v) => v.valid)\n .map(async (v) => {\n const status = await gatherForkStatus(v.resolvedPath);\n return { path: v.fork.localPath, status };\n }),\n );\n const statusMap = new Map(statusEntries.map((e) => [e.path, e.status]));\n\n return validated.map((v) => {\n if (!v.valid) {\n return {\n value: v.fork.localPath,\n name: `${v.fork.name} ${pc.dim(v.fork.localPath)}`,\n disabled: v.error,\n };\n }\n return {\n value: v.fork.localPath,\n name: formatForkChoice(v.fork.name, statusMap.get(v.fork.localPath) ?? null),\n };\n });\n}\n\n/** Sync a single fork by running the same service flow the fork owner would run locally. */\nasync function syncFork(config: RuntimeConfig, fork: ForkConfig, forkPath: string): Promise<void> {\n console.info();\n console.info(pc.cyan(`syncing to ${fork.name}...`));\n console.info(pc.dim(`path: ${forkPath}`));\n console.info();\n\n const forkConfig = await loadConfig(forkPath);\n await runSyncCommand({\n ...forkConfig,\n forkPath,\n upstreamRef: resolveUpstream(forkConfig.settings).branchRef,\n service: 'sync',\n list: false,\n json: false,\n verbose: false,\n keepConfig: config.keepConfig,\n });\n}\n\nexport async function runForks(config: RuntimeConfig): Promise<void> {\n const forks = config.forks ?? [];\n\n if (forks.length === 0) {\n printNoForksHint('add forks to your config:');\n return;\n }\n\n // --fork is the non-interactive mode.\n if (config.fork) {\n const match = forks.find((f) => f.name === config.fork);\n if (!match) {\n throw new Error(`fork '${config.fork}' not found in config`);\n }\n const resolvedPath = resolve(await resolveForkBasePath(config.forkPath), match.localPath);\n await syncFork(config, match, resolvedPath);\n return;\n }\n\n // Choices are rebuilt each iteration so the menu reflects updated status.\n const forkBasePath = await resolveForkBasePath(config.forkPath);\n while (true) {\n const choices = await buildForkChoices(forks, forkBasePath);\n const forkChoices = [...choices, new Separator(MENU_DIVIDER), { value: '_exit', name: pc.dim('exit') }];\n\n const selectedPath = await select<string>({\n message: 'select fork to sync:',\n choices: forkChoices,\n loop: false,\n });\n\n if (selectedPath === '_exit') {\n process.exit(0);\n }\n\n const resolvedForkPath = resolve(forkBasePath, selectedPath);\n const selectedFork = forks.find((f) => f.localPath === selectedPath);\n if (!selectedFork) {\n console.error(pc.red(`fork '${selectedPath}' not found in config`));\n continue;\n }\n\n await syncFork(config, selectedFork, resolvedForkPath);\n\n console.info();\n }\n}\n","/**\n * Sync service for the cella CLI.\n *\n * Runs the merge engine directly in the fork (no worktree) so conflicts surface in the IDE, on\n * a fresh temporary branch cut from the trunk. The service is idempotent: if a run stops at\n * conflicts, resolve them and run `cella sync` again to finish the same merge.\n */\n\nimport { spawnSync } from 'node:child_process';\nimport { select } from '@inquirer/prompts';\nimport { type CommitRangeEntry, type MergeResult, type RuntimeConfig, SYNC_APPLIED_STATUSES } from '../config/types';\nimport pc from '../utils/colors';\nimport {\n buildTemporarySyncBranch,\n DEFAULT_SYNC_PREFIX,\n isTemporarySyncBranch,\n resolveReleaseBase,\n} from '../utils/config';\nimport {\n COMMIT_LIST_MAX,\n checkMark,\n createSpinner,\n printEngineReports,\n printSyncComplete,\n printUpstreamOverrideChanges,\n spinnerFail,\n spinnerSuccess,\n warningMark,\n} from '../utils/display';\nimport { errorMessage } from '../utils/errors';\nimport { closePr, type GhPullRequest, ghAvailable, listOpenSyncPrs, mergePrSquash } from '../utils/gh';\nimport {\n branchExists,\n commitSquash,\n countCommitsBetween,\n createBranchFrom,\n deleteBranch,\n fastForwardBranch,\n fetchRemote,\n flattenBranch,\n getBranchUpstream,\n getBranchWorktree,\n getCommitInfo,\n getConflictedFiles,\n getCurrentBranch,\n getMergeBase,\n getShortSha,\n getUpstreamStatus,\n isAncestor,\n isClean,\n listBranchMergeCommits,\n listCommitsBetween,\n mergeInProgress,\n pullFastForward,\n pushBranch,\n readManifestAtRef,\n readManifestBaseAtRef,\n readPackageVersionAtRef,\n stageAll,\n switchBranch,\n switchDetached,\n} from '../utils/git';\nimport { readSyncManifest } from '../utils/manifest';\nimport { listNoteIds, noteUrl, readNote, readPending } from '../utils/migration-notes';\nimport { BehindSyncPointError, runEngineWithSpinner, UpstreamConfigChangedError } from './merge-engine';\nimport { printMigrationNotesLine } from './migrate';\nimport { runPackages } from './packages';\n\n/** Context for the temporary branch a sync cycle runs on. */\ninterface TemporarySyncBranch {\n /** The freshly cut temporary branch, e.g. `cella/sync/20260702-1430`. */\n temporaryBranch: string;\n /** The trunk the branch was cut from and PRs land into (`releaseBase`, default `main`). */\n base: string;\n /** The branch the user was on before the cycle started, 'HEAD' when detached (for cleanup on no-op). */\n startBranch: string;\n /** The commit the user was on before the cycle started (to return to a detached start). */\n startCommit: string;\n}\n\n/**\n * Make sure the trunk is current with its remote and return the ref a sync cycle cuts its branch\n * from. Compares refs and never checks the trunk out, so this also works from a linked worktree\n * while another worktree has the trunk checked out. A trunk behind its remote is fast-forwarded\n * (or, checked out elsewhere, left alone and the remote-tracking ref used); a diverged trunk stops\n * the run, since a PR against an out-of-date base brings avoidable conflicts.\n */\nasync function resolveCycleStart(forkPath: string, base: string, currentBranch: string): Promise<string> {\n // No local trunk branch to compare: cut from origin's, which `git switch` would have created it from.\n if (!(await branchExists(forkPath, base))) {\n await fetchRemote(forkPath, 'origin').catch(() => {});\n console.info(pc.dim(`'${base}' has no local branch: cutting from 'origin/${base}'.`));\n return `origin/${base}`;\n }\n\n const { upstream, ahead, behind } = await getUpstreamStatus(forkPath, base);\n\n if (!upstream) {\n console.info(pc.dim(`'${base}' has no upstream: skipping the up-to-date check.`));\n return base;\n }\n\n if (ahead > 0 && behind > 0) {\n throw new Error(\n `'${base}' has diverged from '${upstream}' (${ahead} ahead, ${behind} behind).\\n` +\n `Reconcile '${base}' with '${upstream}' first (e.g. rebase or reset it), then re-run sync.`,\n );\n }\n\n if (behind > 0) {\n const worktree = currentBranch === base ? null : await getBranchWorktree(forkPath, base);\n if (worktree) {\n console.info(\n pc.dim(`'${base}' is ${behind} behind '${upstream}' but checked out at ${worktree}; leaving it as it is.`),\n );\n return upstream;\n }\n console.info(pc.dim(`fast-forwarding '${base}' to '${upstream}' (${behind} behind)...`));\n if (currentBranch === base) await pullFastForward(forkPath);\n else await fastForwardBranch(forkPath, base, upstream);\n return base;\n }\n\n if (ahead > 0) {\n console.info(pc.dim(`'${base}' is ${ahead} commit(s) ahead of '${upstream}' (unpushed); continuing.`));\n }\n return base;\n}\n\n/** Bring the trunk up to date and cut a fresh throwaway `cella/sync/<stamp>` branch from it. */\nasync function setupTemporarySyncBranch(config: RuntimeConfig): Promise<TemporarySyncBranch> {\n const { forkPath, settings } = config;\n const base = resolveReleaseBase(settings);\n const startBranch = await getCurrentBranch(forkPath);\n const startCommit = (await getCommitInfo(forkPath, 'HEAD')).hash;\n\n console.info(pc.dim(`updating '${base}'...`));\n const startPoint = await resolveCycleStart(forkPath, base, startBranch);\n\n const temporaryBranch = buildTemporarySyncBranch();\n\n console.info(pc.dim(`creating temporary sync branch '${temporaryBranch}' from '${startPoint}'...`));\n console.info();\n await createBranchFrom(forkPath, temporaryBranch, startPoint);\n\n return { temporaryBranch, base, startBranch, startCommit };\n}\n\n/**\n * The trunk ref a sync branch was cut from, to read its own commits against (`<ref>..HEAD`): the\n * trunk, or its remote-tracking ref when the trunk is behind it. `resolveCycleStart` cuts from\n * `origin` when another worktree holds a stale trunk, and that stale trunk would count origin's\n * newer commits as part of the sync branch.\n */\nasync function resolveCutBase(forkPath: string, base: string): Promise<string> {\n if (!(await branchExists(forkPath, base))) return `origin/${base}`;\n const upstream = await getBranchUpstream(forkPath, base);\n return upstream && (await isAncestor(forkPath, base, upstream)) ? upstream : base;\n}\n\n/**\n * Leave the sync branch for the trunk, after shipping it. When another worktree has the trunk\n * checked out, git refuses to switch to it: detach at the trunk instead, so this worktree holds\n * no branch and the sync branch can be deleted once its PR lands. Returns where it left HEAD.\n */\nasync function returnToBase(forkPath: string, base: string): Promise<string> {\n const worktree = await getBranchWorktree(forkPath, base);\n if (worktree) {\n console.info(pc.dim(`'${base}' is checked out at ${worktree}; detaching at '${base}' here instead...`));\n await switchDetached(forkPath, base);\n return `detached at '${base}'`;\n }\n\n console.info(pc.dim(`switching back to '${base}'...`));\n await switchBranch(forkPath, base);\n await pullFastForward(forkPath).catch(() => {});\n return `back on '${base}'`;\n}\n\n/** Run the merge engine against the current branch, leaving the merge staged in the fork. */\nexport async function runSync(\n config: RuntimeConfig,\n options?: {\n stagedBranch?: string;\n },\n): Promise<MergeResult> {\n createSpinner('starting sync...');\n\n let result: MergeResult;\n try {\n result = await runEngineWithSpinner(config, true);\n } catch (error) {\n // The engine threw, usually a stop before the merge: end the spinner, and when the sync config\n // gate stopped it, show what upstream changed.\n spinnerSuccess();\n if (error instanceof UpstreamConfigChangedError) {\n printUpstreamOverrideChanges({ upstreamOverrides: error.report });\n console.info();\n }\n throw error;\n }\n\n if (result.success) {\n spinnerSuccess();\n } else {\n spinnerFail('sync completed with conflicts');\n }\n\n // Print summary (no file lists for sync) plus the shared upstream-changes reports\n printEngineReports(result, 'merge summary');\n if (config.unpinned) {\n console.info(pc.yellow('⚠ --unpinned: every pinned entry was merged from upstream; keep only what you want.'));\n console.info();\n }\n\n const staged = result.files.some((file) => SYNC_APPLIED_STATUSES.includes(file.status));\n const stagedBranch =\n options?.stagedBranch && result.conflicts.length === 0 && staged ? options.stagedBranch : undefined;\n printSyncComplete(result, { stagedBranch });\n\n await printMigrationNotesLine(config, result);\n\n return result;\n}\n\n/** Conventional PR title prefix required by release-please. */\nconst SYNC_PR_TITLE = 'chore: sync upstream cella';\n\n/**\n * Build the sync commit subject, e.g. `chore: sync upstream cella v0.2.2 (4f7d87c)`.\n *\n * The upstream version comes from the manifest's release tag when tracking releases, else from\n * upstream's root package.json at the merged commit. Falls back to the bare title (+ short sha)\n * when a lookup fails, so committing never blocks on cosmetics.\n */\nasync function buildSyncCommitMessage(forkPath: string, upstreamRef: string): Promise<string> {\n const shortSha = await getShortSha(forkPath, upstreamRef).catch(() => '');\n if (!shortSha) return SYNC_PR_TITLE;\n\n const manifest = await readSyncManifest(forkPath);\n const version =\n manifest?.upstream.release ?? (await readPackageVersionAtRef(forkPath, upstreamRef).catch(() => null));\n return version ? `${SYNC_PR_TITLE} v${version.replace(/^v/, '')} (${shortSha})` : `${SYNC_PR_TITLE} ${shortSha}`;\n}\n\n/**\n * Qualify bare `#123` references in an upstream commit subject with the upstream repo slug.\n * Left bare, GitHub would auto-link them to the fork's own issue/PR #123 in the PR body.\n */\nfunction qualifyPrRefs(subject: string, repoSlug?: string): string {\n if (!repoSlug) return subject;\n return subject.replace(/(^|[^\\w/])#(\\d+)\\b/g, `$1${repoSlug}#$2`);\n}\n\n/** Inputs for {@link buildSyncPrBody}, recovered from the committed sync manifests. */\ninterface SyncPrBodyInput {\n /** GitHub slug of the upstream repo, e.g. 'cellajs/cella'. */\n repoSlug?: string;\n /** Upstream version or release tag at the sync point (leading `v` optional). */\n version?: string | null;\n /** Previous upstream sync point (full sha), when known. */\n fromSha?: string | null;\n /** Upstream commit this sync moved to (full sha). */\n toSha: string;\n /** Upstream commits in the range, oldest first (possibly truncated to the newest N). */\n commits: CommitRangeEntry[];\n /** Total commits in the range (may exceed `commits.length` when truncated). */\n totalCount: number;\n /** Upstream migration notes at the sync point: the total, and the ones the app has not handled yet. */\n notes?: { total: number; open: Array<{ id: string; title: string; url?: string }> };\n}\n\n/** Render the sync PR body: where the sync moved to, plus the upstream commits it brought in. */\nexport function buildSyncPrBody(input: SyncPrBodyInput): string {\n const { repoSlug, version, fromSha, toSha, commits, totalCount, notes } = input;\n const githubUrl = repoSlug ? `https://github.com/${repoSlug}` : undefined;\n const short = (sha: string) => sha.slice(0, 7);\n const commitRef = (sha: string) =>\n githubUrl ? `[\\`${short(sha)}\\`](${githubUrl}/commit/${sha})` : `\\`${short(sha)}\\``;\n\n const upstreamName = githubUrl ? `[${repoSlug}](${githubUrl})` : 'cella';\n const versionSuffix = version ? ` (v${version.replace(/^v/, '')})` : '';\n const lines = [`Syncs upstream ${upstreamName} to ${commitRef(toSha)}${versionSuffix}.`];\n\n if (totalCount > 0 && fromSha) {\n const compare = githubUrl ? ` ([compare](${githubUrl}/compare/${short(fromSha)}...${short(toSha)}))` : '';\n lines.push('', `**${totalCount} upstream commit${totalCount === 1 ? '' : 's'} since last sync**${compare}:`, '');\n if (totalCount > commits.length) lines.push(`- …${totalCount - commits.length} earlier commit(s) not shown`);\n for (const commit of commits) {\n lines.push(`- ${commitRef(commit.hash)} ${qualifyPrRefs(commit.message, repoSlug)}`);\n }\n }\n\n if (notes && notes.total > 0) {\n const { total, open } = notes;\n if (open.length === 0) lines.push('', `**Migration notes**: all ${total} handled.`);\n else {\n lines.push(\n '',\n `**Migration notes**: ${Math.max(0, total - open.length)} of ${total} handled, open (\\`pnpm cella migrate\\`):`,\n '',\n );\n for (const note of open)\n lines.push(`- ${note.url ? `[${note.title}](${note.url})` : note.title} (\\`${note.id}\\`)`);\n }\n }\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/**\n * Build the PR body for a finished sync branch: the upstream commits between the trunk's last\n * recorded sync point and the one this branch moves to, both read from committed manifests.\n * Undefined when the branch has no committed manifest (the caller falls back to `--fill`).\n */\nasync function buildSyncPrBodyForBranch(forkPath: string, base: string): Promise<string | undefined> {\n const manifest = await readManifestAtRef(forkPath, 'HEAD');\n if (!manifest) return undefined;\n\n const toSha = manifest.upstream.commit.toLowerCase();\n // The trunk's committed manifest is the previous sync point; merge-base covers forks whose\n // last sync predates the manifest. `refs/cella/last-sync` is no help here: the merge already\n // moved it to `toSha`.\n const fromSha =\n (await readManifestBaseAtRef(forkPath, base)) ?? (await getMergeBase(forkPath, base, toSha).catch(() => null));\n const version = manifest.upstream.release ?? (await readPackageVersionAtRef(forkPath, toSha).catch(() => null));\n\n const totalCount = fromSha ? await countCommitsBetween(forkPath, fromSha, toSha).catch(() => 0) : 0;\n const commits = fromSha && totalCount > 0 ? await listCommitsBetween(forkPath, fromSha, toSha, COMMIT_LIST_MAX) : [];\n\n const notes = await readPrBodyNotes(forkPath, toSha, manifest.upstream.repo).catch(() => undefined);\n return buildSyncPrBody({ repoSlug: manifest.upstream.repo, version, fromSha, toSha, commits, totalCount, notes });\n}\n\n/** Migration notes for the PR body: the total at the sync point and the app's open ones, with permalinks. */\nasync function readPrBodyNotes(forkPath: string, toSha: string, repoSlug?: string): Promise<SyncPrBodyInput['notes']> {\n const githubUrl = repoSlug ? `https://github.com/${repoSlug}` : undefined;\n const [ids, pending] = await Promise.all([listNoteIds(forkPath, toSha), readPending(forkPath)]);\n const open = await Promise.all(\n pending.map(async (id) => ({\n id,\n title: (await readNote(forkPath, toSha, id))?.title ?? id,\n url: noteUrl(githubUrl, toSha, id),\n })),\n );\n return { total: ids.length, open };\n}\n\n/** Print the GitHub CLI command for opening the finished sync PR. */\nfunction printPrCreateStep(branch: string, base: string, title = SYNC_PR_TITLE): void {\n console.info(pc.dim(` gh pr create --base ${base} --head ${branch} --title \"${title}\" --fill`));\n}\n\n/**\n * Safety net run before a sync branch goes public: rewrite a branch holding merge commits as one\n * commit with identical content. A manual `git commit` on the staged merge records a two-parent\n * merge commit, and since upstream's history is not on `origin`, the PR would list every upstream\n * commit ever made. Returns true if the branch was rewritten, so the caller force-pushes.\n */\nasync function flattenSyncBranch(forkPath: string, branch: string, base: string): Promise<boolean> {\n const mergeCommits = await listBranchMergeCommits(forkPath, base);\n if (mergeCommits.length === 0) return false;\n\n // The most recent merge's second parent is the upstream tip that was merged in.\n const message = await buildSyncCommitMessage(forkPath, `${mergeCommits[0]}^2`);\n\n console.info(\n pc.yellow(\n `'${branch}' contains ${mergeCommits.length} merge commit(s): the PR would list the entire upstream history.`,\n ),\n );\n console.info(pc.dim(`flattening '${branch}' to a single commit (same content)...`));\n await flattenBranch(forkPath, base, message);\n return true;\n}\n\n/**\n * Push the finished sync branch to `origin`, open a PR into the trunk, and switch back to the\n * trunk (see `returnToBase`). A failed push prints the manual steps and leaves you on the branch;\n * a missing or failed `gh` prints the `gh` command but still returns you to the trunk.\n */\nasync function shipSyncBranch(config: RuntimeConfig, branch: string): Promise<void> {\n const { forkPath, settings } = config;\n const base = resolveReleaseBase(settings);\n // The PR targets `base`; its commits and body are read against the trunk the branch was cut from.\n const cutBase = await resolveCutBase(forkPath, base);\n\n const flattened = await flattenSyncBranch(forkPath, branch, cutBase);\n let prUrl: string | undefined;\n let prOpened = false;\n\n // The PR title is the versioned sync commit subject, rebuilt from the manifest rather than read\n // from HEAD: drift-triage commits may sit on top of the sync commit (release-please only needs\n // the prefix).\n const upstreamCommit = (await readSyncManifest(forkPath))?.upstream.commit;\n const prTitle = upstreamCommit ? await buildSyncCommitMessage(forkPath, upstreamCommit) : SYNC_PR_TITLE;\n\n console.info(pc.dim(`pushing '${branch}' to origin...`));\n try {\n await pushBranch(forkPath, 'origin', branch, { forceWithLease: flattened });\n } catch (error) {\n console.info(pc.yellow(`push failed (${errorMessage(error).split('\\n')[0]}). finish manually:`));\n console.info(pc.dim(` git push -u origin ${branch}`));\n printPrCreateStep(branch, base, prTitle);\n return;\n }\n\n if (ghAvailable()) {\n console.info(pc.dim('opening a pull request...'));\n const prBody = await buildSyncPrBodyForBranch(forkPath, cutBase);\n const bodyArgs = prBody ? ['--body', prBody] : ['--fill'];\n const pr = spawnSync('gh', ['pr', 'create', '--base', base, '--head', branch, '--title', prTitle, ...bodyArgs], {\n cwd: forkPath,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n prUrl = `${pr.stdout ?? ''}\\n${pr.stderr ?? ''}`.match(/https?:\\/\\/\\S+/)?.[0];\n prOpened = pr.status === 0;\n if (!prOpened) {\n console.info(pc.yellow('could not open the PR automatically (it may already exist). open it with:'));\n if (prUrl) console.info(pc.dim(` ${prUrl}`));\n printPrCreateStep(branch, base, prTitle);\n }\n } else {\n console.info(pc.yellow('`gh` not found, open the PR manually:'));\n printPrCreateStep(branch, base, prTitle);\n }\n\n const position = await returnToBase(forkPath, base);\n\n console.info();\n if (prUrl) {\n console.info(`${checkMark} sync pull request ${prOpened ? 'opened' : 'ready'}`);\n console.info(pc.dim(` ${prUrl} · branch pushed, ${position}`));\n } else {\n console.info(`${checkMark} sync branch pushed`);\n console.info(pc.dim(` '${branch}' is on origin, ${position}`));\n }\n await printMigrationNotesLine(config);\n}\n\n/**\n * Run `pnpm install` then `pnpm check` before committing the merge, so the lockfile and generated\n * files the merge left stale land in the same commit. Returns false if a step fails (the merge is\n * left in progress to retry).\n */\nfunction finalizeWorkspace(forkPath: string): boolean {\n for (const args of [['install'], ['check']]) {\n console.info(pc.dim(`running pnpm ${args.join(' ')}...`));\n const result = spawnSync('pnpm', args, { cwd: forkPath, stdio: 'inherit' });\n if (result.status !== 0) return false;\n }\n return true;\n}\n\n/** Outcome of a sync cycle run on a fresh temporary branch. */\ntype SyncCycleOutcome =\n | { status: 'conflicts'; branch: TemporarySyncBranch }\n | { status: 'staged'; branch: TemporarySyncBranch }\n | { status: 'noop'; behind?: string };\n\n/**\n * Return to where the cycle started and drop the throwaway branch. Only for a branch that holds\n * nothing: an up-to-date run, or one that stopped before the merge.\n */\nasync function discardTemporarySyncBranch(forkPath: string, branch: TemporarySyncBranch): Promise<void> {\n if (branch.startBranch === 'HEAD') await switchDetached(forkPath, branch.startCommit);\n else await switchBranch(forkPath, branch.startBranch);\n await deleteBranch(forkPath, branch.temporaryBranch);\n}\n\n/**\n * After the merge step threw: drop the throwaway branch when the run stopped before the merge (a\n * gate, an unreachable upstream, a ref that does not resolve), so nothing changed and a rerun\n * starts a fresh cycle (an empty sync branch is never shipped). A branch that holds a merge or\n * changes stays as it is. Returns whether the branch was dropped.\n */\nasync function discardUnusedSyncBranch(forkPath: string, branch: TemporarySyncBranch): Promise<boolean> {\n const unused =\n (await getCurrentBranch(forkPath)) === branch.temporaryBranch &&\n !(await mergeInProgress(forkPath)) &&\n (await isClean(forkPath));\n if (!unused) return false;\n\n await discardTemporarySyncBranch(forkPath, branch);\n const start = branch.startBranch === 'HEAD' ? `at ${branch.startCommit.slice(0, 7)}` : `on '${branch.startBranch}'`;\n console.info(pc.dim(`removed the unused '${branch.temporaryBranch}', back ${start}.`));\n return true;\n}\n\n/**\n * Run one sync cycle on a fresh temporary branch: cut the branch, merge upstream (+ packages),\n * and report the resulting state. On `noop` (nothing new, or `behind`: only a point the last sync\n * already went past) the throwaway branch is gone and the start branch restored; a run that stops\n * before the merge throws, after dropping the branch the same way.\n */\nasync function runSyncCycle(config: RuntimeConfig): Promise<SyncCycleOutcome> {\n const { forkPath } = config;\n const branch = await setupTemporarySyncBranch(config);\n\n let result: MergeResult;\n try {\n result = await runSync(config, { stagedBranch: branch.temporaryBranch });\n } catch (error) {\n const discarded = await discardUnusedSyncBranch(forkPath, branch).catch(() => false);\n // Tracking a release or branch the last sync went past is nothing to sync, not a failure.\n // A pinned --ref behind the sync point stays an error: the run cannot do what it was asked.\n if (discarded && error instanceof BehindSyncPointError && !config.ref) {\n return { status: 'noop', behind: error.message };\n }\n throw error;\n }\n\n if (config.settings.syncWithPackages !== false) {\n // Run package sync even when the merge left conflicts: package.json files that are\n // themselves conflicted are skipped and reported; all others are still synced.\n await runPackages(config, { conflictedFiles: result.conflicts });\n }\n\n if (result.conflicts.length > 0) return { status: 'conflicts', branch };\n\n // Nothing staged: already up to date. Return to where the run started and drop the throwaway\n // branch (a fresh cycle never starts on a sync branch: those resume or ship instead).\n if (!(await mergeInProgress(forkPath))) {\n await discardTemporarySyncBranch(forkPath, branch);\n return { status: 'noop' };\n }\n\n return { status: 'staged', branch };\n}\n\n/**\n * Commit an in-progress merge on the temporary sync branch as one single-parent commit, then stop\n * there for drift triage; shipping is always its own rerun. Stops early while conflicts remain.\n */\nasync function commitSyncMerge(config: RuntimeConfig, branch: string): Promise<void> {\n const { forkPath } = config;\n const conflicts = await getConflictedFiles(forkPath);\n\n console.info();\n if (conflicts.length > 0) {\n console.info(pc.yellow(`${conflicts.length} file(s) still conflict on '${branch}':`));\n for (const file of conflicts) console.info(pc.dim(` ${file}`));\n console.info(pc.dim('resolve and stage them, then re-run `pnpm cella sync` to finish (it commits for you).'));\n return;\n }\n\n // Stage resolved conflicts and manual edits before tooling that may fail, so they are recorded.\n await stageAll(forkPath);\n\n if (!finalizeWorkspace(forkPath)) {\n console.info();\n console.info(\n pc.yellow('`pnpm install`/`pnpm check` failed. fix the issues, then re-run `pnpm cella sync` to finish.'),\n );\n return;\n }\n\n // The subject reads MERGE_HEAD, which commitSquash clears; re-stage what install/check touched.\n const message = await buildSyncCommitMessage(forkPath, 'MERGE_HEAD');\n await stageAll(forkPath);\n await commitSquash(forkPath, message);\n console.info();\n console.info(pc.green(`committed the sync on '${branch}' as '${message}'.`));\n console.info(pc.dim(`staying on '${branch}' without pushing.`));\n console.info(pc.dim(' run drift triage (`pnpm cella analyze`), commit any follow-ups, then:'));\n console.info(pc.dim(' pnpm cella sync (pushes the branch and opens the PR)'));\n await printMigrationNotesLine(config);\n}\n\n/**\n * Merge the open sync PR(s) so the trunk carries the recorded sync point before a new cycle cuts\n * from it. The newest PR is a content superset of any older ones (each cycle re-syncs from the\n * same stale trunk base), so the newest is squash-merged and the rest are closed. A merge GitHub\n * refuses (conflicts, failing required checks) stops the run.\n */\nasync function mergeOpenSyncPrs(config: RuntimeConfig, open: GhPullRequest[]): Promise<'continue' | 'cancel'> {\n const { forkPath, settings } = config;\n const base = resolveReleaseBase(settings);\n const [newest, ...superseded] = open;\n\n console.info();\n console.info(pc.dim(`squash-merging #${newest.number} into '${base}'...`));\n const merged = mergePrSquash(forkPath, newest.number, { deleteBranch: true });\n if (!merged.ok) {\n console.info();\n console.info(pc.yellow(`could not merge #${newest.number}: resolve it first, then re-run \\`pnpm cella sync\\`:`));\n if (merged.output) console.info(pc.dim(merged.output.replace(/^/gm, ' ')));\n console.info(pc.dim(` ${newest.url}`));\n return 'cancel';\n }\n console.info(`${checkMark} merged #${newest.number}`);\n // Drop the stale local branch that tracked the merged PR (the remote one went with --delete-branch).\n await deleteBranch(forkPath, newest.headRefName);\n\n for (const pr of superseded) {\n console.info(pc.dim(`closing #${pr.number}: its changes are included in #${newest.number}...`));\n closePr(forkPath, pr.number);\n await deleteBranch(forkPath, pr.headRefName);\n }\n\n return 'continue';\n}\n\n/**\n * Before cutting a fresh sync branch, offer to merge an earlier sync PR that is still open: the\n * sync point lives in the manifest on the sync branch, so a cycle cut from a trunk without it\n * re-includes that PR's whole delta. A silent `continue` without `gh`, an open PR or a TTY.\n */\nasync function guardAgainstOpenSyncPr(config: RuntimeConfig): Promise<'continue' | 'cancel'> {\n const { forkPath } = config;\n\n if (!ghAvailable() || !process.stdout.isTTY) return 'continue';\n\n const open = listOpenSyncPrs(forkPath, DEFAULT_SYNC_PREFIX);\n if (open.length === 0) return 'continue';\n\n const many = open.length > 1;\n console.info();\n console.info(\n `${warningMark} ${pc.yellow(`${many ? `${open.length} earlier sync PRs are` : 'an earlier sync PR is'} still open and unmerged:`)}`,\n );\n for (const pr of open) {\n console.info(pc.dim(` #${pr.number} ${pr.title}`));\n console.info(pc.dim(` ${pr.url}`));\n }\n console.info(pc.dim(` starting a new sync now produces a PR that re-includes ${many ? 'these' : 'those'} changes.`));\n console.info();\n\n const choice = await select<'merge' | 'continue' | 'cancel'>({\n message: 'how do you want to proceed?',\n choices: [\n {\n value: 'merge',\n name: `merge ${many ? 'them' : `#${open[0].number}`} first, then sync ${pc.dim('(recommended)')}`,\n },\n { value: 'continue', name: `continue anyway ${pc.dim('(new PR will re-include the unmerged changes)')}` },\n { value: 'cancel', name: pc.red('cancel') },\n ],\n loop: false,\n });\n\n if (choice === 'cancel') return 'cancel';\n if (choice === 'continue') return 'continue';\n return mergeOpenSyncPrs(config, open);\n}\n\n/**\n * Run the standalone `cella sync` command. Idempotent: each run advances the sync one stage (cut\n * and merge, commit, ship) and never commits and ships in the same run.\n */\nexport async function runSyncCommand(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n const currentBranch = await getCurrentBranch(forkPath);\n const onSyncBranch = isTemporarySyncBranch(currentBranch);\n\n // Resume path: finish the merge an earlier run left staged on this branch.\n if (onSyncBranch && (await mergeInProgress(forkPath))) {\n await commitSyncMerge(config, currentBranch);\n return;\n }\n\n // On a sync branch with the merge already committed: ship it. Edits not committed would be left\n // out of the pushed branch, so a dirty tree stops the run.\n if (onSyncBranch) {\n if (!(await isClean(forkPath))) {\n console.info();\n console.info(\n pc.yellow(\n `sync branch '${currentBranch}' has uncommitted changes.\\n` +\n 'commit them first (`git commit --amend --no-edit` or a new commit).',\n ),\n );\n return;\n }\n await shipSyncBranch(config, currentBranch);\n return;\n }\n\n // Fresh cycle, from a clean tree only.\n if (!(await isClean(forkPath))) {\n throw new Error('working directory has uncommitted changes. please commit or stash before syncing.');\n }\n if ((await guardAgainstOpenSyncPr(config)) === 'cancel') return;\n\n const outcome = await runSyncCycle(config);\n console.info();\n\n if (outcome.status === 'noop') {\n if (outcome.behind) {\n console.info(pc.green('nothing to sync: the last sync already went past this upstream point.'));\n for (const line of outcome.behind.split('\\n')) console.info(pc.dim(` ${line}`));\n } else {\n console.info(pc.green('already up to date with upstream, nothing to sync.'));\n }\n return;\n }\n\n const { temporaryBranch } = outcome.branch;\n if (outcome.status === 'conflicts') {\n console.info(`${warningMark} ${pc.yellow(`conflicts on '${temporaryBranch}'. Resolve and stage them, then:`)}`);\n console.info(pc.dim(' pnpm cella sync'));\n console.info(pc.dim(' rerun commits the sync and stops for drift triage; a further rerun ships (push + PR).'));\n console.info(pc.dim(' let the rerun commit: a manual `git commit` records a merge commit that bloats the PR.'));\n return;\n }\n\n await commitSyncMerge(config, temporaryBranch);\n}\n","/**\n * GitHub CLI (`gh`) helpers for the cella CLI.\n *\n * Thin wrappers around `gh` used by the sync service to list, merge, and close the sync pull\n * requests. Every wrapper degrades gracefully when `gh` is missing or a call fails, so a sync\n * run on a repo without `gh`/`origin` still works; it just skips the PR automation.\n */\n\nimport { spawnSync } from 'node:child_process';\n\n/** An open pull request, as returned by `gh pr list --json`. */\nexport interface GhPullRequest {\n number: number;\n title: string;\n headRefName: string;\n url: string;\n}\n\n/** Result of a `gh` invocation: whether it exited 0, plus its combined stdout+stderr. */\ninterface GhResult {\n ok: boolean;\n output: string;\n}\n\n/** Whether the GitHub CLI is available on PATH. */\nexport function ghAvailable(): boolean {\n return spawnSync('gh', ['--version'], { stdio: 'ignore' }).status === 0;\n}\n\n/** Run `gh` in `cwd`, capturing stdout+stderr. Never throws. */\nfunction runGh(cwd: string, args: string[]): GhResult {\n const result = spawnSync('gh', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });\n const output = `${result.stdout ?? ''}${result.stderr ?? ''}`.trim();\n return { ok: result.status === 0, output };\n}\n\n/**\n * List open sync PRs (head branch under `<prefix>/`, e.g. `cella/sync/`), newest first (highest PR number).\n * Returns an empty array when `gh` fails (no auth, no origin) so callers degrade to a no-op.\n */\nexport function listOpenSyncPrs(cwd: string, prefix: string): GhPullRequest[] {\n const { ok, output } = runGh(cwd, [\n 'pr',\n 'list',\n '--state',\n 'open',\n '--json',\n 'number,title,headRefName,url',\n '--limit',\n '50',\n ]);\n if (!ok || !output) return [];\n\n let parsed: GhPullRequest[];\n try {\n parsed = JSON.parse(output) as GhPullRequest[];\n } catch {\n return [];\n }\n\n return parsed.filter((pr) => pr.headRefName.startsWith(`${prefix}/`)).sort((a, b) => b.number - a.number);\n}\n\n/** Squash-merge a PR (by number, branch, or URL) now; fails when the PR is not mergeable. */\nexport function mergePrSquash(cwd: string, ref: string | number, options: { deleteBranch?: boolean } = {}): GhResult {\n return runGh(cwd, ['pr', 'merge', String(ref), '--squash', ...(options.deleteBranch ? ['--delete-branch'] : [])]);\n}\n\n/** Close a PR without merging (used to discard superseded sync PRs). */\nexport function closePr(cwd: string, ref: string | number): GhResult {\n return runGh(cwd, ['pr', 'close', String(ref)]);\n}\n","/**\n * Packages service: package.json keys synced between fork and upstream, three-way against the merge-base\n * package.json (upstream as of the previous sync):\n * - Add: entries that are new upstream are added\n * - Follow: an entry the fork never touched (still equal to its base value) follows upstream,\n * whether upstream rewrote a script, changed a range, or dropped the entry\n * - Keep: an entry the fork added or changed stays, except that a strictly higher upstream\n * version still bumps it; an entry the fork removed is not re-added\n * - Still used: a dependency or script upstream dropped stays while fork-authored code still\n * imports it, runs its CLI or runs the script (see package-usage.ts)\n * - Supports nested `pnpm` key (overrides, patchedDependencies, packageExtensions)\n * - `type` always syncs, whatever `packageJsonSync` lists (see mergeModuleType)\n * - A workspace package.json upstream added since the base arrives verbatim\n * Without a base (first sync, unrelated history) every upstream entry is added or bumped and\n * nothing is removed.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { PackageJsonSyncKey, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { DEFAULT_PACKAGE_JSON_SYNC } from '../utils/config';\nimport { createSpinner, plural, spinnerSuccess, spinnerText, warningMark } from '../utils/display';\nimport { errorMessage } from '../utils/errors';\nimport { getEffectiveMergeBase, git } from '../utils/git';\nimport { isIgnored } from '../utils/overrides';\nimport { compareVersions, parseComparableVersion } from '../utils/versions';\nimport { type ForkUsage, loadForkUsage } from './package-usage';\n\n/** A parsed package.json: only `pnpm` is typed, the synced keys are read through the index signature. */\ninterface PackageJson {\n pnpm?: {\n overrides?: Record<string, string>;\n patchedDependencies?: Record<string, string>;\n packageExtensions?: Record<string, Record<string, unknown>>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\n/**\n * Whether the upstream version is strictly higher than the fork's; never downgrades.\n * For non-parseable values (workspace:*, etc.), false (the fork's value stays).\n */\nfunction isHigherVersion(upstreamVersion: string, forkVersion: string): boolean {\n if (upstreamVersion === forkVersion) return false;\n\n const upCoerced = parseComparableVersion(upstreamVersion);\n const forkCoerced = parseComparableVersion(forkVersion);\n\n if (!upCoerced || !forkCoerced) return false;\n\n return compareVersions(upCoerced, forkCoerced) > 0;\n}\n\ninterface RecordMergeResult {\n merged: Record<string, string>;\n changed: boolean;\n added: string[];\n updated: string[];\n removed: string[];\n /** Entries upstream dropped that stay because the fork still uses them */\n kept: { name: string; usedAt: string }[];\n}\n\ninterface RecordMergeOptions {\n /** Let a strictly higher upstream version win over the fork's own value (false for scripts, patch paths) */\n bumpHigher?: boolean;\n /** Where the fork still uses an entry, so upstream dropping it does not remove it */\n findUse?: (name: string) => string | undefined;\n /** Order entries as upstream does instead of alphabetically (scripts, which are grouped by hand) */\n upstreamOrder?: boolean;\n}\n\n/** Keys whose entries are packages the code imports or whose CLIs it runs. */\nconst DEPENDENCY_KEYS: readonly PackageJsonSyncKey[] = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n];\n\n/**\n * Three-way merge for a Record<string, string> key (dependencies, scripts, overrides, ...).\n * `baseRecord` is the key at the merge-base: an entry whose fork value still equals its base\n * value was never touched by the fork and follows upstream, an update or a removal alike. An\n * entry the fork changed stays, unless `bumpHigher` and upstream carries a strictly higher\n * version. An entry the fork removed (in base, absent in fork) is not re-added, and one upstream\n * dropped stays while `findUse` finds it in use. Without a base every upstream entry is added or\n * bumped and nothing is removed.\n * Returns the merged record sorted alphabetically (or in upstream's order, see `orderLikeUpstream`),\n * plus the keys added, updated, removed and kept.\n */\nfunction mergeRecord(\n forkRecord: Record<string, string> | undefined,\n upstreamRecord: Record<string, string> | undefined,\n baseRecord: Record<string, string> | undefined,\n { bumpHigher = true, findUse, upstreamOrder = false }: RecordMergeOptions = {},\n): RecordMergeResult | undefined {\n if (!upstreamRecord) return undefined;\n\n const merged = { ...(forkRecord || {}) };\n const base = baseRecord || {};\n const added: string[] = [];\n const updated: string[] = [];\n const removed: string[] = [];\n const kept: RecordMergeResult['kept'] = [];\n\n for (const [name, upstreamValue] of Object.entries(upstreamRecord)) {\n const forkValue = merged[name];\n\n if (forkValue === undefined) {\n // In base but not in fork: the fork removed it on purpose\n if (name in base) continue;\n merged[name] = upstreamValue;\n added.push(name);\n } else if (forkValue === upstreamValue) {\n } else if (base[name] === forkValue) {\n // Untouched by the fork: follow upstream, a downgrade or a rewritten script included\n merged[name] = upstreamValue;\n updated.push(name);\n } else if (bumpHigher && isHigherVersion(upstreamValue, forkValue)) {\n // Both sides changed it: a strictly higher upstream version wins (with upstream's range prefix)\n merged[name] = upstreamValue;\n updated.push(name);\n }\n // Otherwise the fork's own value stays\n }\n\n // Entries upstream dropped: removed when the fork never touched them and does not use them\n for (const [name, forkValue] of Object.entries(merged)) {\n if (name in upstreamRecord) continue;\n if (base[name] === undefined || base[name] !== forkValue) continue;\n const usedAt = findUse?.(name);\n if (usedAt) {\n kept.push({ name, usedAt });\n continue;\n }\n delete merged[name];\n removed.push(name);\n }\n\n const keys = upstreamOrder\n ? orderLikeUpstream(Object.keys(merged), Object.keys(upstreamRecord))\n : Object.keys(merged).sort((a, b) => a.localeCompare(b));\n const ordered = Object.fromEntries(keys.map((name) => [name, merged[name]]));\n const changed = added.length + updated.length + removed.length > 0;\n return { merged: ordered, changed, added, updated, removed, kept };\n}\n\n/**\n * Order record keys as upstream does. A key only the fork has stays right after the key before it\n * in the fork's order, so the fork's own entries keep their place among the ones they belong with.\n */\nfunction orderLikeUpstream(forkKeys: string[], upstreamKeys: string[]): string[] {\n const upstream = new Set(upstreamKeys);\n const forkOnlyAfter = new Map<string | undefined, string[]>();\n let anchor: string | undefined;\n for (const key of forkKeys) {\n if (upstream.has(key)) anchor = key;\n else forkOnlyAfter.set(anchor, [...(forkOnlyAfter.get(anchor) ?? []), key]);\n }\n\n const present = new Set(forkKeys);\n const ordered = [...(forkOnlyAfter.get(undefined) ?? [])];\n for (const key of upstreamKeys) {\n if (present.has(key)) ordered.push(key);\n ordered.push(...(forkOnlyAfter.get(key) ?? []));\n }\n return ordered;\n}\n\n/** A subpath map (`{ \".\": …, \"./config\": … }`), not a string or a conditions object. */\nfunction isSubpathMap(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n return Object.keys(value).every((name) => name.startsWith('.'));\n}\n\n/**\n * Safe merge for the `exports` key: upstream subpaths the fork lacks are added, the\n * fork's own never touched. Only merges when both sides are subpath maps: a string or conditions object\n * can't take extra subpaths, and condition order is significant. Keeps the fork's key order.\n */\nfunction safeMergeExports(\n forkExports: unknown,\n upstreamExports: unknown,\n): { merged: Record<string, unknown>; changed: boolean; added: string[] } | undefined {\n if (!isSubpathMap(upstreamExports)) return undefined;\n if (forkExports !== undefined && !isSubpathMap(forkExports)) return undefined;\n\n const merged = { ...(forkExports || {}) };\n const added = Object.keys(upstreamExports).filter((name) => !(name in merged));\n for (const name of added) merged[name] = upstreamExports[name];\n\n return { merged, changed: added.length > 0, added };\n}\n\n/**\n * Merge for the `pnpm` key: `overrides` and `patchedDependencies` merge three-way like any\n * record; `packageExtensions` and other sub-keys are add-only.\n */\nfunction safeMergePnpm(\n forkPnpm: PackageJson['pnpm'],\n upstreamPnpm: PackageJson['pnpm'],\n basePnpm: PackageJson['pnpm'],\n): { merged: PackageJson['pnpm']; changed: boolean } | undefined {\n if (!upstreamPnpm) return undefined;\n\n const merged: NonNullable<PackageJson['pnpm']> = { ...(forkPnpm || {}) };\n let changed = false;\n\n // overrides add, follow and bump like dependencies; patch paths carry no version to compare\n for (const sub of ['overrides', 'patchedDependencies'] as const) {\n const result = mergeRecord(merged[sub], upstreamPnpm[sub], basePnpm?.[sub], { bumpHigher: sub === 'overrides' });\n if (result?.changed) {\n merged[sub] = result.merged;\n changed = true;\n }\n }\n\n // pnpm.packageExtensions: new packages and new sub-keys are added, never removed\n if (upstreamPnpm.packageExtensions) {\n const forkExts = (merged.packageExtensions || {}) as Record<string, Record<string, unknown>>;\n const upstreamExts = upstreamPnpm.packageExtensions as Record<string, Record<string, unknown>>;\n\n for (const [pkg, upstreamExt] of Object.entries(upstreamExts)) {\n if (!(pkg in forkExts)) {\n forkExts[pkg] = upstreamExt;\n changed = true;\n } else {\n for (const [subKey, subValue] of Object.entries(upstreamExt)) {\n if (!(subKey in forkExts[pkg])) {\n forkExts[pkg][subKey] = subValue;\n changed = true;\n }\n }\n }\n }\n\n merged.packageExtensions = forkExts;\n }\n\n // Other pnpm sub-keys are added when missing in the fork.\n for (const [key, value] of Object.entries(upstreamPnpm)) {\n if (['overrides', 'patchedDependencies', 'packageExtensions'].includes(key)) continue;\n if (!(key in merged)) {\n merged[key] = value;\n changed = true;\n }\n }\n\n return { merged, changed };\n}\n\n/**\n * Three-way merge for `type`, which decides how Node loads the package's `.js` files, so it syncs\n * whatever `packageJsonSync` lists. Follows upstream where the fork still has the merge-base value\n * (an update or a removal alike) and keeps a value the fork set itself; never version-bumped.\n * A fork without `type` gets upstream's even when the base had one: `type` never synced before,\n * so a missing one is a missed upstream change, not a removal (to opt out, set \"commonjs\").\n * Returns the fork's new value and the change, or null when the fork's value stays.\n */\nfunction mergeModuleType(\n forkType: unknown,\n upstreamType: unknown,\n baseType: unknown,\n): { value: string | undefined; change: 'added' | 'updated' | 'removed' } | null {\n const asString = (value: unknown) => (typeof value === 'string' ? value : undefined);\n const fork = asString(forkType);\n const upstream = asString(upstreamType);\n if (fork === upstream) return null;\n if (fork === undefined) return { value: upstream, change: 'added' };\n if (fork !== asString(baseType)) return null;\n return { value: upstream, change: upstream === undefined ? 'removed' : 'updated' };\n}\n\n/**\n * Set a top-level key in place. A key the file already has keeps its position; a new one goes\n * where cella's own package.json files keep it, after `name`, `version` and `private` (whichever\n * comes last), else first.\n */\nfunction setTopLevelKey(pkg: PackageJson, key: string, value: unknown): void {\n if (key in pkg) {\n pkg[key] = value;\n return;\n }\n const entries = Object.entries(pkg);\n const after = Math.max(...['name', 'version', 'private'].map((name) => entries.findIndex(([k]) => k === name)));\n entries.splice(after + 1, 0, [key, value]);\n for (const name of Object.keys(pkg)) delete pkg[name];\n Object.assign(pkg, Object.fromEntries(entries));\n}\n\n/** The fork's package.json at `filePath`, null when there is none; one that does not parse throws. */\nfunction readPackageJson(filePath: string): PackageJson | null {\n if (!existsSync(filePath)) return null;\n try {\n return JSON.parse(readFileSync(filePath, 'utf8'));\n } catch (error) {\n throw new Error(`cannot parse ${filePath}: ${errorMessage(error)}`);\n }\n}\n\n/** The package.json path of a workspace location ('' is the root). */\nfunction packageJsonPath(relativePath: string): string {\n return relativePath ? `${relativePath}/package.json` : 'package.json';\n}\n\n/** A package.json at a git ref, raw and parsed; null when the ref has no such file. */\nasync function readPackageJsonAtRef(\n forkPath: string,\n ref: string,\n relativePath: string,\n): Promise<{ raw: string; data: PackageJson } | null> {\n try {\n const raw = await git(['show', `${ref}:${packageJsonPath(relativePath)}`], forkPath);\n return { raw, data: JSON.parse(raw) };\n } catch {\n return null;\n }\n}\n\n/** Every package.json location upstream has; the fork side is judged per location. */\nasync function discoverPackageLocations(forkPath: string, upstreamRef: string): Promise<string[]> {\n const stdout = await git(['ls-tree', '-r', '--name-only', upstreamRef], forkPath, { ignoreErrors: true });\n return stdout\n .split('\\n')\n .filter((p) => p.endsWith('/package.json') || p === 'package.json')\n .map((p) => (p === 'package.json' ? '' : p.replace('/package.json', '')));\n}\n\n/**\n * The upstream commit the fork last synced (the recorded sync point, else git's merge-base);\n * null when neither resolves, which turns every key merge into add-only.\n */\nasync function resolveMergeBase(forkPath: string, upstreamRef: string): Promise<string | null> {\n try {\n return (await getEffectiveMergeBase(forkPath, 'HEAD', upstreamRef)).base || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Sync a single package.json file three-way (fork, upstream, merge-base).\n *\n * A location the fork lacks is a workspace upstream added since the base: its package.json\n * lands verbatim when the merge brought the directory (and the location is not ignored). A\n * package.json the base had and the fork removed stays removed.\n *\n * Returns the change lines, plus the entries upstream dropped that stay because `usage` found\n * the fork still using them.\n */\nasync function syncPackageJson(\n config: RuntimeConfig,\n baseRef: string | null,\n usage: ForkUsage | null,\n relativePath: string,\n keysToSync: PackageJsonSyncKey[],\n): Promise<{ updated: boolean; changes: string[]; kept: string[] }> {\n const { forkPath, upstreamRef } = config;\n const changes: string[] = [];\n const kept: string[] = [];\n const pkgRelPath = packageJsonPath(relativePath);\n const pkgPath = join(forkPath, pkgRelPath);\n\n const forkPkg = readPackageJson(pkgPath);\n const upstream = await readPackageJsonAtRef(forkPath, upstreamRef, relativePath);\n const basePkg = baseRef ? (await readPackageJsonAtRef(forkPath, baseRef, relativePath))?.data : undefined;\n\n if (!upstream) return { updated: false, changes, kept };\n\n if (!forkPkg) {\n const workspaceArrived = relativePath !== '' && existsSync(join(forkPath, relativePath));\n if (basePkg || !workspaceArrived || isIgnored(pkgRelPath, config)) return { updated: false, changes, kept };\n writeFileSync(pkgPath, upstream.raw.endsWith('\\n') ? upstream.raw : `${upstream.raw}\\n`, 'utf8');\n return { updated: true, changes: ['copied from upstream (new workspace)'], kept };\n }\n\n const upstreamPkg = upstream.data;\n let updated = false;\n\n const type = mergeModuleType(forkPkg.type, upstreamPkg.type, basePkg?.type);\n if (type) {\n if (type.value === undefined) delete forkPkg.type;\n else setTopLevelKey(forkPkg, 'type', type.value);\n updated = true;\n changes.push(`type: ${type.change}`);\n }\n\n for (const key of keysToSync) {\n if (key === 'pnpm') {\n const result = safeMergePnpm(forkPkg.pnpm, upstreamPkg.pnpm, basePkg?.pnpm);\n if (result?.changed) {\n forkPkg.pnpm = result.merged;\n updated = true;\n changes.push('pnpm: merged');\n }\n continue;\n }\n\n if (key === 'packageManager') {\n // A string, merged as a one-entry record: it adds, follows and bumps like a dependency\n const asRecord = (pkg?: PackageJson) => (pkg?.[key] ? { [key]: String(pkg[key]) } : undefined);\n const result = mergeRecord(asRecord(forkPkg), asRecord(upstreamPkg), asRecord(basePkg));\n if (result?.changed) {\n forkPkg[key] = result.merged[key];\n updated = true;\n changes.push(`${key}: ${result.added.length > 0 ? 'added' : 'updated'}`);\n }\n continue;\n }\n\n if (key === 'exports') {\n // Add-only, subpath maps only: the fork gains new upstream subpaths, keeps any it defines\n // itself, and a subpath it has repointed stays repointed.\n const result = safeMergeExports(forkPkg.exports, upstreamPkg.exports);\n if (result?.changed) {\n forkPkg.exports = result.merged;\n updated = true;\n changes.push(...result.added.map((name) => `exports.${name}: added`));\n }\n continue;\n }\n\n // All Record<string, string> keys merge three-way; scripts carry no version to compare.\n const forkValue = forkPkg[key] as Record<string, string> | undefined;\n const upstreamValue = upstreamPkg[key] as Record<string, string> | undefined;\n const baseValue = basePkg?.[key] as Record<string, string> | undefined;\n\n let findUse: RecordMergeOptions['findUse'];\n if (usage && key === 'scripts') findUse = (name) => usage.findScript(name);\n else if (usage && DEPENDENCY_KEYS.includes(key)) findUse = (name) => usage.findPackage(relativePath, name);\n const isScripts = key === 'scripts';\n const result = mergeRecord(forkValue, upstreamValue, baseValue, {\n bumpHigher: !isScripts,\n findUse,\n upstreamOrder: isScripts,\n });\n kept.push(...(result?.kept ?? []).map(({ name, usedAt }) => `${key}.${name}: used in ${usedAt}`));\n if (result?.changed) {\n forkPkg[key] = result.merged;\n updated = true;\n changes.push(\n ...result.added.map((name) => `${key}.${name}: added`),\n ...result.updated.map((name) => `${key}.${name}: updated`),\n ...result.removed.map((name) => `${key}.${name}: removed`),\n );\n }\n }\n\n if (updated) writeFileSync(pkgPath, `${JSON.stringify(forkPkg, null, 2)}\\n`, 'utf8');\n\n return { updated, changes, kept };\n}\n\n/**\n * Run the packages sync service.\n *\n * Discovers every package.json location upstream has, then merges the configured keys three-way\n * against the merge-base (see the file header for the rules).\n *\n * When `conflictedFiles` is provided (e.g. after a sync that left conflicts),\n * any package.json that is itself unmerged is skipped to avoid clobbering\n * conflict markers; all other package.json files are still synced.\n */\nexport async function runPackages(config: RuntimeConfig, options: { conflictedFiles?: string[] } = {}): Promise<void> {\n createSpinner('syncing package.json files...');\n\n const keysToSync = config.settings.packageJsonSync || DEFAULT_PACKAGE_JSON_SYNC;\n const conflictedSet = new Set(options.conflictedFiles ?? []);\n\n const baseRef = await resolveMergeBase(config.forkPath, config.upstreamRef);\n // Before any package.json is rewritten: the fork-authored scripts are judged on the fork's own copy\n const usage = baseRef ? await loadForkUsage(config.forkPath, config.upstreamRef, baseRef) : null;\n const locations = await discoverPackageLocations(config.forkPath, config.upstreamRef);\n const reports: { path: string; changes: string[]; kept: string[] }[] = [];\n const skipped: string[] = [];\n\n for (const location of locations) {\n const pkgRelPath = packageJsonPath(location);\n\n // Skip package.json files that are themselves conflicted from the merge:\n // writing to them would clobber the conflict markers the user must resolve.\n if (conflictedSet.has(pkgRelPath)) {\n skipped.push(pkgRelPath);\n continue;\n }\n\n spinnerText(`syncing ${location || 'root'}/package.json...`);\n\n const { updated, changes, kept } = await syncPackageJson(config, baseRef, usage, location, keysToSync);\n if (updated || kept.length > 0) reports.push({ path: pkgRelPath, changes, kept });\n }\n\n const changedCount = reports.filter(({ changes }) => changes.length > 0).length;\n spinnerSuccess('package sync complete', `${plural(changedCount, 'package.json was', 'package.jsons were')} changed`);\n\n for (const { path, changes } of reports) {\n if (changes.length === 0) continue;\n console.info(` ${path}`);\n for (const change of changes) console.info(` ${pc.dim(change)}`);\n }\n\n // Entries upstream dropped that the fork still uses: the user decides when they can go\n const kept = reports.flatMap(({ path, kept }) => kept.map((entry) => `${path} ${entry}`));\n const them = kept.length === 1 ? 'it' : 'them';\n printWarnList(`kept ${plural(kept.length, 'entry', 'entries')} upstream dropped, the fork still uses ${them}:`, kept);\n printWarnList(\n `skipped ${skipped.length} conflicted package.json file(s): resolve the conflicts, commit the merge, then rerun \\`pnpm cella sync\\`:`,\n skipped,\n );\n}\n\n/** A warning header with one `→ entry` line per entry; silent without entries. */\nfunction printWarnList(header: string, entries: string[]): void {\n if (entries.length === 0) return;\n console.info();\n console.info(`${warningMark} ${pc.yellow(header)}`);\n for (const entry of entries) console.info(` ${pc.dim('→')} ${entry}`);\n}\n","/**\n * Where the fork's own code still uses a package or a script.\n *\n * The package sync removes an entry upstream dropped when the fork never touched it in\n * package.json, but a fork can use an inherited entry without touching it: an import in a\n * fork-only module, a CLI in a fork script, a script name in a fork workflow. Only fork-authored\n * content is searched: files that differ from upstream after the file merge, and package.json\n * scripts the fork added or changed. Upstream no longer uses what it dropped, so a reference in\n * that content is the fork's own. A false match keeps the entry, which is the safe side: a stale\n * entry costs an install, a missing one breaks the fork.\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { git } from '../utils/git';\nimport { isManagedFile, isPackageJson } from '../utils/managed-files';\nimport { isUnderAnyFolder } from '../utils/overrides';\n\n/** Fork-authored content: a file, or one package.json script. */\ninterface ForkSource {\n /** Repo-relative path, which scopes a workspace's packages to its directory */\n path: string;\n /** Where the reference is, as reported to the user */\n label: string;\n /** The content, read on first use */\n text: () => string;\n}\n\n/** Answers where the fork still uses an entry upstream dropped; undefined when nowhere. */\nexport interface ForkUsage {\n /** A fork-authored place inside `location` that imports `name` or runs one of its CLIs */\n findPackage(location: string, name: string): string | undefined;\n /** A fork-authored place anywhere in the repo that runs script `name` through a package manager */\n findScript(name: string): string | undefined;\n}\n\n/** Larger files are generated or binary and are not searched. */\nconst MAX_FILE_BYTES = 1024 * 1024;\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** A file's text, or '' when it is missing, too large or binary. */\nfunction readSearchable(filePath: string): string {\n try {\n if (statSync(filePath).size > MAX_FILE_BYTES) return '';\n const text = readFileSync(filePath, 'utf8');\n return text.includes('\\0') ? '' : text;\n } catch {\n return '';\n }\n}\n\nfunction fileSource(forkPath: string, path: string): ForkSource {\n let text: string | undefined;\n return { path, label: path, text: () => (text ??= readSearchable(join(forkPath, path))) };\n}\n\nasync function readScriptsAtRef(forkPath: string, ref: string, path: string): Promise<Record<string, string>> {\n try {\n return JSON.parse(await git(['show', `${ref}:${path}`], forkPath)).scripts ?? {};\n } catch {\n return {};\n }\n}\n\n/** The scripts of a fork package.json that differ from both the merge-base and upstream. */\nasync function scriptSources(\n forkPath: string,\n upstreamRef: string,\n baseRef: string,\n path: string,\n): Promise<ForkSource[]> {\n let forkScripts: Record<string, string>;\n try {\n forkScripts = JSON.parse(readFileSync(join(forkPath, path), 'utf8')).scripts ?? {};\n } catch {\n return [];\n }\n const baseScripts = await readScriptsAtRef(forkPath, baseRef, path);\n const upstreamScripts = await readScriptsAtRef(forkPath, upstreamRef, path);\n\n return Object.entries(forkScripts)\n .filter(([name, value]) => value !== baseScripts[name] && value !== upstreamScripts[name])\n .map(([name, value]) => ({ path, label: `${path} (scripts.${name})`, text: () => value }));\n}\n\n/** The CLI names a package installs, from its installed package.json; its bare name when not installed. */\nfunction binNames(forkPath: string, location: string, name: string): string[] {\n const bareName = name.split('/').pop() as string;\n for (const dir of [join(forkPath, location), forkPath]) {\n const manifest = join(dir, 'node_modules', name, 'package.json');\n if (!existsSync(manifest)) continue;\n try {\n const { bin } = JSON.parse(readFileSync(manifest, 'utf8'));\n if (typeof bin === 'string') return [bareName];\n return bin && typeof bin === 'object' ? Object.keys(bin) : [];\n } catch {\n return [];\n }\n }\n return [bareName];\n}\n\n/**\n * How code refers to a package: a quoted specifier or subpath (imports, requires, config\n * strings), the package an `@types/*` entry types, and its CLI names as whole words.\n */\nfunction packagePatterns(forkPath: string, location: string, name: string): RegExp[] {\n const specifiers = [name];\n const typed = name.match(/^@types\\/(.+)$/);\n if (typed) specifiers.push(typed[1].includes('__') ? `@${typed[1].replace('__', '/')}` : typed[1]);\n\n const patterns = specifiers.map((specifier) => new RegExp(`(['\"\\`])${escapeRegExp(specifier)}(?:/[^'\"\\`\\\\s]*)?\\\\1`));\n for (const bin of binNames(forkPath, location, name)) {\n patterns.push(new RegExp(`(?:^|[\\\\s'\"\\`(;&|=])${escapeRegExp(bin)}(?=$|[\\\\s'\"\\`);&|])`, 'm'));\n }\n return patterns;\n}\n\n/** A package manager command that names the script as a whole word, e.g. `pnpm --filter backend geoip:download`. */\nfunction scriptPattern(name: string): RegExp {\n return new RegExp(`\\\\b(?:pnpm|npm|yarn|bun)\\\\s+(?:[^\\\\n;&|]*?\\\\s)?${escapeRegExp(name)}(?=$|[\\\\s'\"\\`);&|])`, 'm');\n}\n\n/**\n * Collect the fork-authored content: files in the working tree (the merge result) that differ\n * from upstream, minus managed files, plus the scripts the fork added or changed. Call before\n * any package.json is rewritten.\n */\nexport async function loadForkUsage(forkPath: string, upstreamRef: string, baseRef: string): Promise<ForkUsage> {\n const diff = await git(['diff', '--name-only', '-z', '--diff-filter=d', upstreamRef], forkPath);\n const sources: ForkSource[] = [];\n\n for (const path of diff.split('\\0').filter(Boolean)) {\n if (isPackageJson(path)) sources.push(...(await scriptSources(forkPath, upstreamRef, baseRef, path)));\n else if (!isManagedFile(path)) sources.push(fileSource(forkPath, path));\n }\n\n const findIn = (scoped: ForkSource[], patterns: RegExp[]) =>\n scoped.find((source) => patterns.some((pattern) => pattern.test(source.text())))?.label;\n\n return {\n findPackage: (location, name) =>\n findIn(\n location ? sources.filter((source) => isUnderAnyFolder(source.path, [location])) : sources,\n packagePatterns(forkPath, location, name),\n ),\n findScript: (name) => findIn(sources, [scriptPattern(name)]),\n };\n}\n","/**\n * Stats service for cella CLI.\n *\n * Counts files in the codebase using `git ls-files` (fast, respects .gitignore).\n * Categorizes by type and workspace package.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { printCoverageSummary } from '../utils/coverage-utils';\nimport { createSpinner, DIVIDER, spinnerSuccess } from '../utils/display';\nimport { git } from '../utils/git';\nimport { readTopLevel } from '../utils/workspace-yaml';\n\n/** Extensions Biome can check (source code, config, styles) */\nexport const sourceExtensions = new Set(['ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs', 'json', 'jsonc', 'css', 'html']);\n\n/** File category for classification */\ntype FileCategory = 'test' | 'stories' | 'generated' | 'json' | 'other';\n\n/** Per-package file and LOC counts, broken down by category */\ninterface PackageStats {\n total: number;\n loc: number;\n categories: Record<FileCategory, { files: number; loc: number }>;\n}\n\n/** Stats result for display or JSON output */\ninterface StatsResult {\n total: number;\n totalLoc: number;\n categories: Record<FileCategory, { files: number; loc: number }>;\n packages: Record<string, PackageStats>;\n}\n\n/** Workspace package definition from pnpm-workspace.yaml */\nexport interface WorkspacePackage {\n /** Display name (e.g., 'backend', 'cli/cella') */\n name: string;\n /** Path prefix to match (e.g., 'backend/', 'cli/cella/') */\n prefix: string;\n}\n\n/** Workspace package names and path prefixes from pnpm-workspace.yaml. */\nexport async function getWorkspacePackages(forkPath: string): Promise<WorkspacePackage[]> {\n const content = await readFile(join(forkPath, 'pnpm-workspace.yaml'), 'utf8');\n const patterns = readTopLevel(content, 'packages');\n\n return (Array.isArray(patterns) ? patterns.map(String) : []).map((pattern) => {\n // Wildcard patterns like 'cli/*' are resolved per file when matching.\n if (pattern.endsWith('/*')) {\n const base = pattern.slice(0, -2);\n return { name: `${base}/*`, prefix: `${base}/` };\n }\n return { name: pattern, prefix: `${pattern}/` };\n });\n}\n\nexport function classifyFile(filePath: string): FileCategory {\n if (\n filePath.includes('.test.') ||\n filePath.includes('.spec.') ||\n filePath.includes('/tests/') ||\n filePath.includes('/test/') ||\n filePath.startsWith('tests/') ||\n filePath.includes('/__tests__/')\n ) {\n return 'test';\n }\n\n if (filePath.includes('.stories.')) {\n return 'stories';\n }\n\n if (\n filePath.includes('.gen.') ||\n filePath.includes('.gen/') ||\n filePath.includes('/gen/') ||\n filePath.startsWith('drizzle/') ||\n filePath.includes('/drizzle/') ||\n filePath.endsWith('.d.ts') ||\n filePath.includes('.tsbuildinfo')\n ) {\n return 'generated';\n }\n\n if (filePath.endsWith('.json') || filePath.endsWith('.jsonc')) {\n return 'json';\n }\n\n return 'other';\n}\n\n/** The workspace package owning a file, with wildcard patterns resolved per file. */\nexport function matchPackage(filePath: string, packages: WorkspacePackage[]): string {\n for (const pkg of packages) {\n if (pkg.name.endsWith('/*')) {\n if (filePath.startsWith(pkg.prefix)) {\n // Extract the actual subpackage name (e.g., 'cli/cella' from 'cli/cella/src/foo.ts')\n const rest = filePath.slice(pkg.prefix.length);\n const subDir = rest.split('/')[0];\n if (subDir) {\n return `${pkg.prefix}${subDir}`;\n }\n }\n } else if (filePath.startsWith(pkg.prefix)) {\n return pkg.name;\n }\n }\n return '(root)';\n}\n\n/** Pathspec patterns for source extensions */\nconst sourcePathspecs = [...sourceExtensions].map((ext) => `*.${ext}`);\n\n/** File and LOC stats for the repository; one `git grep -c ''` call yields paths and line counts. */\nasync function collectStats(forkPath: string): Promise<StatsResult> {\n // Tracked source files with line counts (respects .gitignore, ~15ms).\n const output = await git(['grep', '-c', '', '--', ...sourcePathspecs], forkPath, { ignoreErrors: true });\n\n const packages = await getWorkspacePackages(forkPath);\n\n // Parse \"path:count\" lines\n const entries: { path: string; loc: number }[] = [];\n for (const line of output.split('\\n')) {\n if (!line) continue;\n const sep = line.lastIndexOf(':');\n if (sep === -1) continue;\n entries.push({ path: line.slice(0, sep), loc: Number.parseInt(line.slice(sep + 1), 10) });\n }\n\n const emptyCat = () => ({\n test: { files: 0, loc: 0 },\n stories: { files: 0, loc: 0 },\n generated: { files: 0, loc: 0 },\n json: { files: 0, loc: 0 },\n other: { files: 0, loc: 0 },\n });\n const categories = emptyCat();\n const pkgStats = new Map<string, PackageStats>();\n let totalLoc = 0;\n\n for (const { path, loc } of entries) {\n const category = classifyFile(path);\n categories[category].files++;\n categories[category].loc += loc;\n totalLoc += loc;\n\n const pkg = matchPackage(path, packages);\n let entry = pkgStats.get(pkg);\n if (!entry) {\n entry = { total: 0, loc: 0, categories: emptyCat() };\n pkgStats.set(pkg, entry);\n }\n entry.total++;\n entry.loc += loc;\n entry.categories[category].files++;\n entry.categories[category].loc += loc;\n }\n\n const sortedPackages = Object.fromEntries(\n [...pkgStats.entries()].sort((a, b) => b[1].categories.other.loc - a[1].categories.other.loc),\n );\n\n return { total: entries.length, totalLoc, categories, packages: sortedPackages };\n}\n\nfunction pad(n: number, width = 6): string {\n return String(n).padStart(width);\n}\n\nfunction formatLoc(n: number): string {\n if (n >= 1000) return `${(n / 1000).toFixed(1)}k`;\n return String(n);\n}\n\nfunction fmtPct(value: number, total: number): string {\n const pct = ((value / total) * 100).toFixed(1);\n return `${pct.padStart(5)}%`;\n}\n\nfunction printStats(stats: StatsResult, verbose: boolean): void {\n console.info();\n console.info(\n ` ${pc.bold('code files'.padEnd(13))} ${String(stats.total)} ${pc.dim(`(${[...sourceExtensions].join(' ')})`)}`,\n );\n console.info(` ${pc.bold('lines of code')} ${pc.cyan(formatLoc(stats.totalLoc))}`);\n console.info();\n\n const catEntries: [string, { files: number; loc: number }][] = [\n ['source & config', stats.categories.other],\n ['test', stats.categories.test],\n ['stories', stats.categories.stories],\n ['generated', stats.categories.generated],\n ['json', stats.categories.json],\n ];\n for (const [label, data] of catEntries) {\n console.info(\n ` ${pad(data.files)} ${pc.dim(fmtPct(data.files, stats.total))} ${label.padEnd(18)} ${pc.cyan(formatLoc(data.loc).padStart(8))} ${pc.dim(fmtPct(data.loc, stats.totalLoc))}`,\n );\n }\n\n console.info();\n console.info(DIVIDER);\n console.info();\n\n const header = verbose\n ? ` ${''.padEnd(6)} ${'package'.padEnd(18)} ${'loc'.padStart(8)} ${'test'.padStart(6)} ${'story'.padStart(6)} ${'gen'.padStart(6)} ${'json'.padStart(6)} ${'src'.padStart(6)}`\n : ' source & config by package';\n console.info(pc.dim(header));\n const { other } = stats.categories;\n for (const [name, { categories: c }] of Object.entries(stats.packages)) {\n if (c.other.files === 0) continue;\n // Verbose: file counts per category. Plain: shares of all source & config files and lines.\n const head = verbose\n ? pc.dim(pad(c.other.files))\n : `${pad(c.other.files)} ${pc.dim(fmtPct(c.other.files, other.files))}`;\n const tail = verbose\n ? ` ${[c.test, c.stories, c.generated, c.json, c.other].map((cat) => pc.dim(pad(cat.files))).join(' ')}`\n : ` ${pc.dim(fmtPct(c.other.loc, other.loc))}`;\n console.info(` ${head} ${name.padEnd(18)} ${pc.cyan(formatLoc(c.other.loc).padStart(8))}${tail}`);\n }\n\n console.info();\n}\n\nexport async function runStats(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n\n createSpinner('counting files...');\n const stats = await collectStats(forkPath);\n spinnerSuccess('counted raw lines of code');\n\n printStats(stats, config.verbose);\n console.info();\n printCoverageSummary(forkPath);\n}\n","/**\n * Coverage overview for the stats service, from the `.coverage/coverage-summary.json` that the\n * `json-summary` Vitest reporter writes on `pnpm test`.\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\nimport pc from './colors';\n\n/** A single metric block from a coverage-summary.json entry. */\ninterface CoverageMetric {\n total: number;\n covered: number;\n skipped: number;\n pct: number | 'Unknown';\n}\n\n/** One file (or the `total`) entry in coverage-summary.json. */\ninterface CoverageEntry {\n lines: CoverageMetric;\n statements: CoverageMetric;\n functions: CoverageMetric;\n branches: CoverageMetric;\n}\n\n/** Shape of Vitest's coverage-summary.json. Keys are absolute file paths plus `total`. */\ntype CoverageSummary = Record<string, CoverageEntry> & { total: CoverageEntry };\n\n/** Coverage data is considered stale after this many ms (7 days). */\nconst STALE_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** Color a percentage: green ≥ 80, yellow ≥ 50, red below. */\nfunction colorPct(pct: CoverageMetric['pct']): string {\n if (typeof pct !== 'number' || !Number.isFinite(pct)) return pc.dim('n/a');\n\n const label = `${pct.toFixed(2)}%`;\n if (pct >= 80) return pc.green(label);\n if (pct >= 50) return pc.yellow(label);\n return pc.red(label);\n}\n\n/** Human-friendly \"x days/hours ago\" from a timestamp. */\nfunction formatAge(ms: number): string {\n const days = Math.floor(ms / (24 * 60 * 60 * 1000));\n if (days >= 1) return `${days} day${days === 1 ? '' : 's'} ago`;\n const hours = Math.floor(ms / (60 * 60 * 1000));\n if (hours >= 1) return `${hours} hour${hours === 1 ? '' : 's'} ago`;\n const mins = Math.floor(ms / (60 * 1000));\n return `${mins} minute${mins === 1 ? '' : 's'} ago`;\n}\n\n/** Print a compact coverage overview from the cached summary file. */\nexport function printCoverageSummary(forkPath: string): void {\n const file = join(forkPath, '.coverage', 'coverage-summary.json');\n let summary: CoverageSummary | undefined;\n let mtimeMs = 0;\n let problem = 'no coverage data found';\n if (existsSync(file)) {\n try {\n mtimeMs = statSync(file).mtimeMs;\n summary = JSON.parse(readFileSync(file, 'utf8')) as CoverageSummary;\n } catch {\n problem = 'could not read coverage-summary.json';\n }\n }\n if (!summary || !Object.keys(summary).some((key) => key !== 'total')) {\n console.info(pc.bold('coverage'));\n console.info(pc.yellow(` ${problem}: run \\`pnpm test\\` to generate it`));\n console.info();\n return;\n }\n\n const ageMs = Date.now() - mtimeMs;\n const stale = ageMs > STALE_THRESHOLD_MS;\n\n // Roll up per-package line coverage by the first path segment relative to root.\n const perPackage = new Map<string, { covered: number; total: number }>();\n for (const [key, entry] of Object.entries(summary)) {\n if (key === 'total') continue;\n const rel = relative(forkPath, key);\n if (rel.startsWith('..')) continue;\n const pkg = rel.split(sep)[0];\n const acc = perPackage.get(pkg) ?? { covered: 0, total: 0 };\n acc.covered += entry.lines.covered;\n acc.total += entry.lines.total;\n perPackage.set(pkg, acc);\n }\n\n // Header with freshness indicator.\n const ageLabel = formatAge(ageMs);\n console.info(pc.bold('coverage'), pc.dim(`(updated ${ageLabel})`));\n if (stale) {\n console.info(pc.yellow(' ⚠ data is older than 7 days: run `pnpm test` to refresh'));\n }\n\n // Overall totals.\n const total = summary.total;\n console.info(\n ` ${pc.bold('overall')} ` +\n `lines ${colorPct(total.lines.pct)} ${pc.dim(`(${total.lines.covered}/${total.lines.total})`)} ` +\n `funcs ${colorPct(total.functions.pct)} ` +\n `branches ${colorPct(total.branches.pct)}`,\n );\n\n // Per-package line coverage, worst first.\n const rows = [...perPackage.entries()]\n .map(([pkg, v]) => ({ pkg, pct: v.total ? (100 * v.covered) / v.total : 0, ...v }))\n .sort((a, b) => a.pct - b.pct);\n\n const nameWidth = Math.max(...rows.map((r) => r.pkg.length), 0);\n for (const r of rows) {\n console.info(` ${r.pkg.padEnd(nameWidth)} ${colorPct(r.pct)} ${pc.dim(`(${r.covered}/${r.total})`)}`);\n }\n console.info();\n}\n","/**\n * Branch mode of the stats service (`cella stats --since <ref>`).\n *\n * Counts what the current branch changed since it left a ref, by kind of file, so a pull request\n * can say where its lines went: source, tests, generated output, docs.\n */\n\nimport type { RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { createSpinner, DIVIDER, spinnerSuccess, writeStdout } from '../utils/display';\nimport { git, revParse } from '../utils/git';\nimport { classifyFile, getWorkspacePackages, matchPackage, sourceExtensions, type WorkspacePackage } from './stats';\n\n/** Kind of a changed file. `source` is code and styles that are none of the other kinds. */\nexport type ChangeKind = 'source' | 'test' | 'stories' | 'generated' | 'json' | 'docs' | 'other';\n\n/** What a changed source line holds. */\nexport type LineContent = 'code' | 'comments' | 'blank';\n\ninterface LineChange {\n added: number;\n removed: number;\n}\n\ninterface KindChange extends LineChange {\n files: number;\n}\n\nexport interface FileChange extends LineChange {\n path: string;\n kind: ChangeKind;\n}\n\n/** What a branch changed since it left a ref */\nexport interface BranchStats {\n /** The ref asked for, as typed */\n since: string;\n /** Short sha of the commit the branch left the ref at */\n mergeBase: string;\n /** Current branch name, or the short sha of a detached HEAD */\n head: string;\n total: KindChange;\n kinds: Record<ChangeKind, KindChange>;\n /** Changed source lines by what they hold; null when git could not produce the patch */\n sourceContent: Record<LineContent, LineChange> | null;\n /** Changed source lines per workspace package */\n sourceByPackage: Record<string, KindChange>;\n files: FileChange[];\n /** Files with uncommitted changes, which are not counted */\n uncommitted: number;\n}\n\n/** A kind as the tables name it. */\nconst kindLabel = (kind: ChangeKind) => (kind === 'test' ? 'tests' : kind);\n\nconst docExtensions = new Set(['md', 'mdx']);\n\n/** Lock files are written by the package manager, whatever their extension */\nconst lockFiles = new Set(['pnpm-lock.yaml', 'package-lock.json', 'yarn.lock', 'bun.lock', 'bun.lockb']);\n\n/** Code and style extensions whose lines are split into code, comments and blank */\nconst codeExtensions = [...sourceExtensions].filter((ext) => !ext.startsWith('json'));\n\n/**\n * Classify a changed file. Every file in a diff counts, so beyond the snapshot's categories this\n * knows docs and a rest group, and reads a lock file as generated.\n */\nexport function classifyChange(filePath: string): ChangeKind {\n const name = filePath.slice(filePath.lastIndexOf('/') + 1);\n if (lockFiles.has(name)) return 'generated';\n\n const category = classifyFile(filePath);\n if (category !== 'other') return category;\n\n const ext = name.includes('.') ? name.slice(name.lastIndexOf('.') + 1) : '';\n if (docExtensions.has(ext)) return 'docs';\n return sourceExtensions.has(ext) ? 'source' : 'other';\n}\n\n/**\n * Classify one source line. A diff shows changed lines only, so a comment is recognized by how the\n * line starts: `//`, `/*`, the `*` of a block comment's body or end, and JSX's `{/*`.\n */\nexport function classifyLine(text: string): LineContent {\n const line = text.trim();\n if (!line) return 'blank';\n if (line.startsWith('//') || line.startsWith('/*') || line.startsWith('*') || line.startsWith('{/*')) {\n return 'comments';\n }\n return 'code';\n}\n\n/** Parse `git diff --numstat -z --no-renames`: one `added<TAB>removed<TAB>path` record per file. */\nexport function parseNumstat(output: string): FileChange[] {\n const files: FileChange[] = [];\n for (const record of output.split('\\0')) {\n if (!record) continue;\n const [added, removed, ...rest] = record.split('\\t');\n const path = rest.join('\\t');\n if (!path) continue;\n // A binary file reports `-` for both counts\n files.push({\n path,\n kind: classifyChange(path),\n added: Number.parseInt(added, 10) || 0,\n removed: Number.parseInt(removed, 10) || 0,\n });\n }\n return files;\n}\n\n/**\n * Count the changed lines of a zero-context patch by what they hold, for the files `isCounted`\n * accepts. Hunk headers say how many lines follow, so a changed line that itself starts with\n * `+++` or `---` is never taken for a file header.\n */\nexport function countLineContent(\n patch: string,\n isCounted: (filePath: string) => boolean,\n): Record<LineContent, LineChange> {\n const content: Record<LineContent, LineChange> = {\n code: { added: 0, removed: 0 },\n comments: { added: 0, removed: 0 },\n blank: { added: 0, removed: 0 },\n };\n\n let counted = false;\n let remaining = 0;\n\n for (const line of patch.split('\\n')) {\n if (remaining > 0) {\n // \"\\" follows a line without being one\n if (line.startsWith('\\\\')) continue;\n remaining--;\n if (!counted) continue;\n const change = line.startsWith('+') ? 'added' : 'removed';\n content[classifyLine(line.slice(1))][change]++;\n continue;\n }\n\n // A path git had to quote matches no header below, so every file starts out uncounted\n if (line.startsWith('diff --git ')) {\n counted = false;\n continue;\n }\n\n if (line.startsWith('--- a/') || line.startsWith('+++ b/')) {\n counted = isCounted(line.slice(6));\n continue;\n }\n\n const hunk = /^@@ -\\d+(?:,(\\d+))? \\+\\d+(?:,(\\d+))? @@/.exec(line);\n if (hunk) remaining = Number(hunk[1] ?? 1) + Number(hunk[2] ?? 1);\n }\n\n return content;\n}\n\n/**\n * Collect what HEAD changed since it left `since`: committed work only, compared with the merge\n * base, which is what a pull request into that ref shows.\n */\nexport async function collectBranchStats(forkPath: string, since: string): Promise<BranchStats> {\n const sinceSha = await revParse(forkPath, `${since}^{commit}`);\n if (!sinceSha) throw new Error(`unknown ref '${since}'. pass a branch, tag or commit, such as origin/main`);\n\n const mergeBase = await git(['merge-base', sinceSha, 'HEAD'], forkPath, { ignoreErrors: true });\n if (!mergeBase) throw new Error(`the current branch shares no history with '${since}'`);\n\n const range = [mergeBase, 'HEAD'];\n const files = parseNumstat(await git(['diff', '--numstat', '-z', '--no-renames', ...range], forkPath));\n const kindOf = new Map(files.map((file) => [file.path, file.kind]));\n\n const emptyKind = (): KindChange => ({ files: 0, added: 0, removed: 0 });\n const kinds: Record<ChangeKind, KindChange> = {\n source: emptyKind(),\n test: emptyKind(),\n stories: emptyKind(),\n generated: emptyKind(),\n json: emptyKind(),\n docs: emptyKind(),\n other: emptyKind(),\n };\n const total = emptyKind();\n const packages: WorkspacePackage[] = await getWorkspacePackages(forkPath).catch(() => []);\n const byPackage = new Map<string, KindChange>();\n\n const add = (target: KindChange, file: FileChange) => {\n target.files++;\n target.added += file.added;\n target.removed += file.removed;\n };\n\n for (const file of files) {\n add(total, file);\n add(kinds[file.kind], file);\n if (file.kind !== 'source') continue;\n\n const pkg = matchPackage(file.path, packages);\n const entry = byPackage.get(pkg) ?? emptyKind();\n add(entry, file);\n byPackage.set(pkg, entry);\n }\n\n // The patch of code files only: generated JSON can run to megabytes and holds no comments.\n const patch = await git(\n ['diff', '-U0', '--no-renames', '--no-color', ...range, '--', ...codeExtensions.map((ext) => `*.${ext}`)],\n forkPath,\n { ignoreErrors: true },\n );\n const sourceContent =\n kinds.source.files > 0 && !patch ? null : countLineContent(patch, (path) => kindOf.get(path) === 'source');\n\n const sourceByPackage = Object.fromEntries(\n [...byPackage.entries()].sort((a, b) => net(b[1]) - net(a[1]) || a[0].localeCompare(b[0])),\n );\n\n const branch = await git(['rev-parse', '--abbrev-ref', 'HEAD'], forkPath);\n const status = await git(['status', '--porcelain'], forkPath, { ignoreErrors: true });\n\n return {\n since,\n mergeBase: mergeBase.slice(0, 7),\n head: branch === 'HEAD' ? await git(['rev-parse', '--short', 'HEAD'], forkPath) : branch,\n total,\n kinds,\n sourceContent,\n sourceByPackage,\n files: files.sort((a, b) => net(b) - net(a) || a.path.localeCompare(b.path)),\n uncommitted: status.split('\\n').filter(Boolean).length,\n };\n}\n\nfunction net(change: LineChange): number {\n return change.added - change.removed;\n}\n\n/** `+12`, `-3` or a bare `0`. */\nfunction signed(n: number): string {\n return n > 0 ? `+${n}` : String(n);\n}\n\n/** Kinds that changed, the one that grew most first. */\nfunction changedKinds(stats: BranchStats): [ChangeKind, KindChange][] {\n return (Object.entries(stats.kinds) as [ChangeKind, KindChange][])\n .filter(([, change]) => change.files > 0)\n .sort((a, b) => net(b[1]) - net(a[1]));\n}\n\n/** `code +70, comments +35, blank +15`: the net lines of each part that changed. */\nfunction formatNetList(parts: [string, LineChange][]): string {\n return parts\n .filter(([, change]) => change.added > 0 || change.removed > 0)\n .map(([label, change]) => `${label} ${signed(net(change))}`)\n .join(', ');\n}\n\n/**\n * Format the stats as markdown for a pull request description: a table with one row per kind of\n * file, then where the source lines went.\n */\nexport function formatMarkdown(stats: BranchStats): string {\n const row = (label: string, change: KindChange) =>\n `| ${label} | ${change.files} | ${signed(change.added)} | ${signed(-change.removed)} | ${signed(net(change))} |`;\n const capitalize = (text: string) => text.charAt(0).toUpperCase() + text.slice(1);\n\n const lines = [\n '| Kind | Files | Added | Removed | Net |',\n '| --- | ---: | ---: | ---: | ---: |',\n ...changedKinds(stats).map(([kind, change]) => row(kind === 'json' ? 'JSON' : capitalize(kindLabel(kind)), change)),\n `| **Total** | **${stats.total.files}** | **${signed(stats.total.added)}** | **${signed(-stats.total.removed)}** | **${signed(net(stats.total))}** |`,\n ];\n\n const notes: string[] = [];\n if (stats.sourceContent) {\n const content = formatNetList(Object.entries(stats.sourceContent));\n if (content) notes.push(`Source lines by content: ${content}.`);\n }\n const byPackage = formatNetList(Object.entries(stats.sourceByPackage));\n if (byPackage) notes.push(`Source lines by package: ${byPackage}.`);\n\n return notes.length > 0 ? [...lines, '', ...notes].join('\\n') : lines.join('\\n');\n}\n\n/** Print the stats as aligned terminal tables. */\nfunction printBranchStats(stats: BranchStats, verbose: boolean): void {\n const columns = (files: string, change: LineChange, label: string) =>\n ` ${files.padStart(5)} ${signed(change.added).padStart(8)} ${signed(-change.removed).padStart(8)} ${pc.cyan(signed(net(change)).padStart(8))} ${label}`;\n\n console.info();\n console.info(pc.dim(` ${'files'.padStart(5)} ${'added'.padStart(8)} ${'removed'.padStart(8)} ${'net'.padStart(8)}`));\n for (const [kind, change] of changedKinds(stats)) {\n console.info(columns(String(change.files), change, kindLabel(kind)));\n }\n console.info(columns(String(stats.total.files), stats.total, pc.bold('total')));\n\n if (stats.sourceContent && stats.kinds.source.files > 0) {\n console.info();\n console.info(pc.dim(' source lines by content'));\n for (const [content, change] of Object.entries(stats.sourceContent)) {\n console.info(columns('', change, content));\n }\n }\n\n const packages = Object.entries(stats.sourceByPackage);\n if (packages.length > 0) {\n console.info();\n console.info(pc.dim(' source lines by package'));\n for (const [name, change] of packages) {\n console.info(columns(String(change.files), change, name));\n }\n }\n\n if (verbose) {\n console.info();\n console.info(DIVIDER);\n console.info();\n for (const file of stats.files) {\n console.info(columns('', file, `${file.path} ${pc.dim(kindLabel(file.kind))}`));\n }\n }\n\n if (stats.uncommitted > 0) {\n console.info();\n console.info(\n pc.dim(` ${stats.uncommitted} uncommitted file${stats.uncommitted === 1 ? ' is' : 's are'} not counted`),\n );\n }\n\n console.info();\n}\n\n/** Run the stats service in branch mode. */\nexport async function runBranchStats(config: RuntimeConfig, since: string): Promise<void> {\n createSpinner('counting changed lines...');\n const stats = await collectBranchStats(config.forkPath, since);\n spinnerSuccess(`Counted what ${stats.head} changed since ${stats.since} (${stats.mergeBase})`);\n\n if (stats.total.files === 0) {\n console.info(pc.dim(` nothing committed since ${stats.since}`));\n return;\n }\n\n if (config.md) {\n writeStdout(formatMarkdown(stats));\n if (stats.uncommitted > 0) console.info(pc.dim(`${stats.uncommitted} uncommitted file(s) are not counted`));\n return;\n }\n\n printBranchStats(stats, config.verbose);\n}\n"],"mappings":";;;AAMA,SAAS,cAAAA,cAAY,YAAAC,iBAAgB;AACrC,SAAS,QAAAC,QAAM,WAAAC,gBAAe;AAC9B,OAAOC,cAAa;;;ACHpB,OAAOC,cAAa;AACpB,SAAS,cAAc;AACvB,SAAS,eAAe;;;ACPxB,OAAOC,cAAa;AACpB,SAAS,iBAAiB;;;ACD1B,OAAOC,cAAa;AAKb,SAAS,OAAO,MAAkC;AAEvD,SAAOA,SAAQ,IAAI,IAAI;AACzB;AAGO,SAAS,OAAO,MAAuB;AAE5C,SAAO,QAAQA,SAAQ;AACzB;AAGO,SAAS,iBAAoC;AAElD,SAAO,EAAE,GAAGA,SAAQ,IAAI;AAC1B;;;ADdA,SAAS,gBAAyB;AAChC,MAAI,OAAO,UAAU,EAAG,QAAO;AAC/B,MAAI,OAAO,aAAa,EAAG,QAAO;AAClC,SAAO,CAAC,CAACC,SAAQ,OAAO;AAC1B;AAEA,SAAS,WAAW,OAAmB,MAAsB;AAC3D,MAAI,CAAC,cAAc,EAAG,QAAO;AAC7B,SAAO,UAAU,OAAO,MAAM,EAAE,gBAAgB,MAAM,CAAC;AACzD;AAEA,IAAM,KAAK;AAAA,EACT,MAAM,CAAC,SAAiB,WAAW,QAAQ,IAAI;AAAA,EAC/C,MAAM,CAAC,SAAiB,WAAW,QAAQ,IAAI;AAAA,EAC/C,MAAM,CAAC,SAAiB,WAAW,QAAQ,IAAI;AAAA,EAC/C,KAAK,CAAC,SAAiB,WAAW,OAAO,IAAI;AAAA,EAC7C,MAAM,CAAC,SAAiB,WAAW,QAAQ,IAAI;AAAA,EAC/C,OAAO,CAAC,SAAiB,WAAW,SAAS,IAAI;AAAA,EACjD,SAAS,CAAC,SAAiB,WAAW,WAAW,IAAI;AAAA,EACrD,KAAK,CAAC,SAAiB,WAAW,OAAO,IAAI;AAAA,EAC7C,OAAO,CAAC,SAAiB,WAAW,SAAS,IAAI;AAAA,EACjD,QAAQ,CAAC,SAAiB,WAAW,UAAU,IAAI;AACrD;AAEA,IAAO,iBAAQ;;;AExBf,SAAS,cAAAC,aAAY,cAAc,oBAAoB;AACvD,SAAS,QAAAC,OAAM,eAAe;AAC9B,SAAS,KAAAC,UAAS;;;ACHlB,SAAS,SAAS;AAIlB,IAAM,yBAAyB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA8HO,IAAM,oBAAoB,EAC9B,OAAO;AAAA,EACN,UAAU,EACP,OAAO;AAAA,IACN,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC7B,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IAC3C,eAAe,EAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,SAAS;AAAA,IACtD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IACxC,iBAAiB,EAAE,MAAM,EAAE,KAAK,sBAAsB,CAAC,EAAE,SAAS;AAAA,IAClE,kBAAkB,EAAE,QAAQ,EAAE,SAAS;AAAA,IACvC,cAAc,EAAE,KAAK,CAAC,UAAU,MAAM,CAAC,EAAE,SAAS;AAAA,EACpD,CAAC,EACA,OAAO;AAAA,EACV,WAAW,EACR,OAAO;AAAA,IACN,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,IACtC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACvC,CAAC,EACA,OAAO,EACP,SAAS;AAAA,EACZ,OAAO,EACJ;AAAA,IACC,EACG,OAAO;AAAA,MACN,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MACtB,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MAC3B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,MAC/B,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC9B,CAAC,EACA,OAAO;AAAA,EACZ,EACC,SAAS;AACd,CAAC,EACA,OAAO;AAoGH,IAAM,wBAA+C,CAAC,UAAU,YAAY,WAAW,WAAW,QAAQ;;;AClR1G,SAAS,aAAa,OAAwB;AACnD,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;;ACFO,IAAM,cAAc;AAGpB,SAAS,cAAc,UAA2B;AACvD,SAAO,aAAa,kBAAkB,SAAS,SAAS,eAAe;AACzE;AAOO,SAAS,gBAAgB,UAA2B;AACzD,QAAM,WAAW,SAAS,MAAM,GAAG;AACnC,SAAO,SAAS,SAAS,KAAK,MAAM,SAAS,GAAG,EAAE,KAAK,IAAI,SAAS,OAAO;AAC7E;AAGO,SAAS,cAAc,UAA2B;AACvD,SAAO,cAAc,QAAQ,KAAK,aAAa,oBAAoB,aAAa;AAClF;;;AClBA,SAAS,kBAAkB;AAC3B,SAAS,UAAU,MAAM,UAAU,WAAW;AAC9C,SAAS,SAAS,kBAAkB;AAGpC,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,wBAAwB,oBAAI,IAAI,CAAC,kBAAkB,uBAAuB,sBAAsB,CAAC;AACvG,IAAM,uBAAuB;AAG7B,SAAS,UAAU,MAA6D;AAC9E,QAAM,MAAM,KAAK,aAAa,EAAE,CAAC,GAAG,OAAO,WAAW,uBAAuB;AAC7E,QAAM,cAAc,KAAK,YAAY,OAAO,GAAG,OAAO,WAAW,kBAAkB,GAAG,eAAe;AACrG,SAAO,aAAa,OAAO,WAAW,aAAa,GAAG,gBAAgB;AACxE;AAQO,SAAS,wBAAwB,UAA4B;AAClE,QAAM,UAAU,IAAI,QAAQ;AAAA,IAC1B,6BAA6B;AAAA,IAC7B,8BAA8B;AAAA,IAC9B,qBAAqB;AAAA,EACvB,CAAC;AAED,QAAM,cAAc,QAAQ,sBAAsB,kBAAkB,IAAI,CAAC,SAAS,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;AAExG,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,cAAc,oBAAI,IAAY;AAEpC,aAAW,cAAc,aAAa;AACpC,UAAM,UAAU,WACb,qBAAqB,WAAW,cAAc,EAC9C,KAAK,CAAC,SAAS,sBAAsB,IAAI,KAAK,cAAc,EAAE,QAAQ,CAAC,KAAK,UAAU,IAAI,MAAM,KAAK;AAExG,QAAI,CAAC,QAAS;AAEd,UAAM,SAAS,SAAS,UAAU,WAAW,iBAAiB,CAAC,EAAE,MAAM,GAAG,EAAE,KAAK,GAAG;AACpF,YAAQ,IAAI,MAAM;AAClB,gBAAY,IAAI,SAAS,MAAM,CAAC;AAAA,EAClC;AAEA,aAAW,cAAc,aAAa;AACpC,UAAM,eAAe,GAAG,oBAAoB,IAAI,UAAU;AAC1D,QAAI,WAAW,KAAK,UAAU,YAAY,CAAC,GAAG;AAC5C,cAAQ,IAAI,YAAY;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,OAAO;AACpB;;;AJpDO,IAAM,0BAA0B;AAGhC,IAAM,iBAAiB;AASvB,IAAM,sBAAsB;AAG5B,IAAM,4BAAkD,CAAC,gBAAgB,iBAAiB;AAG1F,SAAS,eAAe,UAA2B;AACxD,SAAO,KAAK,MAAM,aAAaC,MAAK,UAAU,cAAc,GAAG,MAAM,CAAC,EAAE,SAAS;AACnF;AAMO,SAAS,sBAAsB,QAAyB;AAC7D,SAAO,OAAO,WAAW,GAAG,mBAAmB,GAAG;AACpD;AAKO,SAAS,mBAAmB,UAAgC;AACjE,SAAO,SAAS,eAAe;AACjC;AAOO,SAAS,2BAAmC;AACjD,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAMC,OAAM,CAAC,MAAc,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG;AACpD,QAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,GAAGA,KAAI,IAAI,SAAS,IAAI,CAAC,CAAC,GAAGA,KAAI,IAAI,QAAQ,CAAC,CAAC,IAAIA,KAAI,IAAI,SAAS,CAAC,CAAC,GAAGA,KAAI,IAAI,WAAW,CAAC,CAAC;AAChI,SAAO,GAAG,mBAAmB,IAAI,KAAK;AACxC;AAYO,SAAS,gBAAgB,UAG9B;AACA,QAAM,QAAQ,SAAS,iBAAiB;AACxC,QAAM,SAAS,SAAS,kBAAkB;AAC1C,QAAM,YAAY,GAAG,uBAAuB,IAAI,MAAM;AACtD,SAAO,EAAE,OAAO,UAAU;AAC5B;AAKA,eAAsB,WAAW,UAA2C;AAC1E,QAAM,aAAaD,MAAK,UAAU,WAAW;AAE7C,MAAI,CAACE,YAAW,UAAU,GAAG;AAC3B,UAAM,IAAI,MAAM,0BAA0B,UAAU,EAAE;AAAA,EACxD;AAGA,QAAM,iBAAiB,aAAa,UAAU;AAC9C,QAAM,eAAe,aAAa,QAAQ,QAAQ,CAAC;AACnD,MAAI,CAAC,eAAe,WAAW,GAAG,YAAY,GAAG,GAAG;AAClD,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAEA,MAAI;AACJ,MAAI;AACF,mBAAe,MAAM,OAAO;AAAA,EAC9B,SAAS,OAAO;AAGd,UAAM,IAAI,MAAM,kBAAkB,UAAU,KAAK,aAAa,KAAK,CAAC,EAAE;AAAA,EACxE;AAGA,QAAM,SAAS,kBAAkB,UAAU,aAAa,OAAO;AAC/D,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI,MAAM,WAAW,UAAU;AAAA,EAAMC,GAAE,cAAc,OAAO,KAAK,CAAC,EAAE;AAAA,EAC5E;AACA,QAAM,SAAyB,OAAO;AAOtC,QAAM,mBAAmB,wBAAwB,YAAY;AAC7D,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,WAAW,OAAO,WAAW,WAAW,CAAC;AAC/C,WAAO,YAAY;AAAA,MACjB,GAAG,OAAO;AAAA,MACV,SAAS,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,UAAU,GAAG,gBAAgB,CAAC,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO;AACT;;;AK/HA,SAAS,WAAAC,gBAAe;AACxB,OAAOC,cAAa;;;ACNpB;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,SAAW;AAAA,EACX,SAAW;AAAA,EACX,aAAe;AAAA,EACf,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,UAAY;AAAA,EACZ,QAAU;AAAA,EACV,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,SAAW;AAAA,IACT,KAAK;AAAA,IACL,YAAY;AAAA,MACV,OAAS;AAAA,MACT,QAAU;AAAA,IACZ;AAAA,IACA,kBAAkB;AAAA,EACpB;AAAA,EACA,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,KAAO;AAAA,IACL,OAAS;AAAA,EACX;AAAA,EACA,SAAW;AAAA,IACT,OAAO;AAAA,EACT;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,OAAS;AAAA,IACT,OAAS;AAAA,IACT,cAAc;AAAA,IACd,gBAAkB;AAAA,IAClB,OAAS;AAAA,IACT,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,MAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,SAAW;AAAA,EACb;AAAA,EACA,cAAgB;AAAA,IACd,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,WAAa;AAAA,IACb,YAAY;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,iBAAmB;AAAA,IACjB,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,mCAAmC;AAAA,IACnC,0BAA0B;AAAA,IAC1B,eAAe;AAAA,IACf,8BAA8B;AAAA,IAC9B,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,YAAc;AAAA,IACd,QAAU;AAAA,EACZ;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAkB;AAAA,EAClB,YAAc;AAAA,IACZ,SAAW;AAAA,MACT;AAAA,IACF;AAAA,IACA,OAAS;AAAA,MACP,aAAa;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,qBAAqB;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,wBAAwB;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,0BAA0B;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AD7GO,IAAM,UAAU,gBAAY;AAe5B,IAAM,UAAU,SAAI,OAAO,EAAE;AAG7B,IAAM,eAAe,SAAI,OAAO,EAAE;AAGlC,IAAM,kBAAkB;AAGxB,IAAM,cAAc,eAAG,OAAO,QAAG;AAGjC,IAAM,YAAY,eAAG,MAAM,QAAG;AAMrC,IAAI,gBAAgC;AAMpC,IAAI,WAAW;AAOR,SAAS,YAAY,SAAwB;AAClD,aAAW;AACX,MAAI,CAAC,QAAS;AACd,QAAM,WAAW,IAAI,SAAoB;AACvC,IAAAC,SAAQ,OAAO,MAAM,GAAG,KAAK,IAAI,CAAC,MAAO,OAAO,MAAM,WAAW,IAAI,OAAO,CAAC,CAAE,EAAE,KAAK,GAAG,CAAC;AAAA,CAAI;AAAA,EAChG;AACA,UAAQ,OAAO;AACf,UAAQ,OAAO;AACjB;AAGO,SAAS,YAAY,MAAoB;AAC9C,EAAAA,SAAQ,OAAO,MAAM,KAAK,SAAS,IAAI,IAAI,OAAO,GAAG,IAAI;AAAA,CAAI;AAC/D;AAEO,SAAS,cAAoB;AAClC,QAAM,OAAO;AACb,QAAM,QAAQ;AAEd,QAAM,UAAU,KAAK,IAAI,GAAG,KAAK,GAAG,IAAI,KAAK,OAAO,GAAG,SAAS,MAAM,MAAM;AAC5E,UAAQ,KAAK;AACb,UAAQ,KAAK,GAAG,eAAG,KAAK,IAAI,CAAC,GAAG,eAAG,IAAI,UAAO,OAAO,EAAE,CAAC,GAAG,eAAG,KAAK,GAAG,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;AACtG,UAAQ,KAAK,OAAO;AACpB,UAAQ,KAAK;AACf;AAGO,SAAS,cAAc,MAAuB;AACnD,QAAM,UAAU,CAAC,YAAY,CAAC,OAAO,QAAQ,KAAK,OAAO,UAAU,MAAM,UAAU,CAAC,CAACA,SAAQ,OAAO;AACpG,QAAM,SAAS,CAAC,KAAK,MAAM,KAAK,GAAG;AACnC,MAAI,QAAQ;AACZ,MAAI;AACJ,QAAM,UAAmB;AAAA,IACvB;AAAA,IACA,OAAO;AACL,oBAAc,KAAK;AACnB,UAAI,QAAS,CAAAA,SAAQ,OAAO,MAAM,WAAW;AAAA,IAC/C;AAAA,EACF;AACA,QAAM,SAAS,MAAMA,SAAQ,OAAO,MAAM,KAAK,eAAG,KAAK,OAAO,UAAU,OAAO,MAAM,CAAC,CAAC,IAAI,QAAQ,IAAI,EAAE;AACzG,MAAI,SAAS;AACX,WAAO;AACP,YAAQ,YAAY,QAAQ,EAAE;AAAA,EAChC;AACA,kBAAgB;AAChB,SAAO;AACT;AAGO,SAAS,eAAe,SAAkB,QAAuB;AACtE,cAAY;AACZ,MAAI,CAAC,QAAS;AACd,UAAQ,KAAK,GAAG,SAAS,IAAI,OAAO,EAAE;AACtC,MAAI,QAAQ;AACV,YAAQ,KAAK,KAAK,eAAG,IAAI,MAAM,CAAC,EAAE;AAClC,YAAQ,KAAK;AAAA,EACf;AACF;AAEO,SAAS,YAAY,SAAuB;AACjD,cAAY;AACZ,UAAQ,KAAK,GAAG,eAAG,IAAI,QAAG,CAAC,IAAI,OAAO,EAAE;AAC1C;AAEO,SAAS,YAAY,MAAoB;AAC9C,MAAI,eAAe;AACjB,kBAAc,OAAO;AAAA,EACvB;AACF;AAEA,SAAS,cAAoB;AAC3B,MAAI,eAAe;AACjB,kBAAc,KAAK;AACnB,oBAAgB;AAAA,EAClB;AACF;AAMO,SAAS,UAAU,OAAe,KAAsB;AAC7D,MAAI,CAAC,IAAK,QAAO;AAGjB,QAAM,UAAU,IAAI,QAAQ,oBAAoB,EAAE;AAElD,SAAO,WAAW,OAAO,OAAO,KAAK;AACvC;AAGO,SAAS,4BACd,aACA,SACA,mBACA,kBAAkB,iBACV;AACR,QAAM,QAAQ,CAAC,GAAG,OAAO,aAAa,YAAY,CAAC,mBAAmB;AAEtE,QAAM,QAAQ,QAAQ,MAAM,GAAG,eAAe;AAC9C,aAAW,UAAU,OAAO;AAC1B,UAAM,YAAY,OAAO,KAAK,MAAM,GAAG,CAAC;AACxC,UAAM,YAAY,oBAAoB,GAAG,iBAAiB,WAAW,OAAO,IAAI,KAAK;AACrF,UAAM,YAAY,UAAU,WAAW,SAAS;AAChD,UAAM,KAAK,KAAK,SAAS,KAAK,OAAO,OAAO,MAAM,OAAO,IAAI,GAAG;AAAA,EAClE;AAEA,MAAI,cAAc,MAAM,QAAQ;AAC9B,UAAM,KAAK,aAAa,cAAc,MAAM,MAAM,OAAO;AAAA,EAC3D;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,mBAAmB,OAAqB;AAC/C,UAAQ,KAAK;AACb,UAAQ,KAAK,KAAK;AAClB,UAAQ,KAAK,OAAO;AACpB,UAAQ,KAAK;AACf;AAMA,SAAS,mBACP,UACA,QACA,MACA,SACQ;AACR,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,EAAE,mBAAmB,KAAK,gBAAgB,eAAe,SAAS,IAAI;AAC5E,MAAI,OAAO,QAAQ,MAAM,GAAG,CAAC,KAAK;AAClC,MAAI,OAAO,iBAAiB,UAAU,gBAAgB;AACpD,WAAO,UAAU,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK,UAAU,GAAG,GAAG,SAAS,cAAc,IAAI,QAAQ,EAAE;AAAA,EACrG,WAAW,KAAK;AACd,WAAO,SAAS,UAAU,MAAM,GAAG,GAAG,WAAW,MAAM,EAAE,IAAI;AAAA,EAC/D;AACA,SAAO,eAAG,IAAI,WAAM,IAAI,IAAI,IAAI,EAAE;AACpC;AAEO,SAAS,4BACd,eACA,iBACA,aACA,WAAW,KACH;AACR,QAAM,QAAQ,CAAC,GAAG,aAAa,8BAA8B;AAE7D,MAAI,gBAAgB,WAAW,GAAG;AAChC,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,wBAAwB,gBAAgB,MAAM,IAAI;AAG7D,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,QAAQ,gBAAgB,MAAM,GAAG,QAAQ;AAC/C,aAAW,YAAY,OAAO;AAC5B,UAAM,KAAK,OAAO,WAAW,UAAU,UAAU,gBAAgBC,SAAQ,UAAU,QAAQ,CAAC,EAAE,IAAI,QAAQ,EAAE;AAAA,EAC9G;AAEA,MAAI,gBAAgB,SAAS,MAAM,QAAQ;AACzC,UAAM,KAAK,WAAW,gBAAgB,SAAS,MAAM,MAAM,OAAO;AAAA,EACpE;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAaA,IAAM,eAAiD;AAAA,EACrD,QAAQ,EAAE,MAAM,eAAG,KAAK,QAAG,GAAG,OAAO,UAAU,OAAO,eAAG,MAAM,aAAa,8BAA8B;AAAA,EAC1G,UAAU,EAAE,MAAM,eAAG,QAAQ,QAAG,GAAG,OAAO,YAAY,OAAO,eAAG,SAAS,aAAa,2BAA2B;AAAA,EACjH,SAAS,EAAE,MAAM,eAAG,OAAO,GAAG,GAAG,OAAO,WAAW,OAAO,eAAG,QAAQ,aAAa,yBAAyB;AAAA,EAC3G,OAAO,EAAE,MAAM,eAAG,KAAK,QAAG,GAAG,OAAO,SAAS,OAAO,eAAG,MAAM,aAAa,2BAA2B;AAAA,EACrG,OAAO,EAAE,MAAM,eAAG,MAAM,GAAG,GAAG,OAAO,SAAS,OAAO,eAAG,OAAO,aAAa,8BAA8B;AAAA,EAC1G,QAAQ,EAAE,MAAM,eAAG,MAAM,QAAG,GAAG,OAAO,UAAU,OAAO,eAAG,OAAO,aAAa,0BAA0B;AAAA,EACxG,SAAS,EAAE,MAAM,eAAG,KAAK,QAAG,GAAG,OAAO,WAAW,OAAO,eAAG,KAAK;AAAA,EAChE,WAAW,EAAE,MAAM,eAAG,KAAK,QAAG,GAAG,OAAO,aAAa,OAAO,eAAG,MAAM,aAAa,aAAa;AAAA,EAC/F,SAAS,EAAE,MAAM,eAAG,IAAI,QAAG,GAAG,OAAO,WAAW,OAAO,eAAG,IAAI;AAAA,EAC9D,SAAS,EAAE,MAAM,eAAG,KAAK,QAAG,GAAG,OAAO,WAAW,OAAO,eAAG,KAAK;AAClE;AAEA,IAAM,sBAA2D;AAAA,EAC/D,GAAG;AAAA,EACH,SAAS;AAAA,IACP,MAAM,eAAG,KAAK,QAAG;AAAA,IACjB,OAAO;AAAA,IACP,OAAO,eAAG;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA,SAAS,EAAE,GAAG,aAAa,SAAS,aAAa,8BAA8B;AACjF;AAEA,SAAS,aAAa,SAA0B,QAAQ,WAAiB;AACvE,qBAAmB,eAAG,KAAK,KAAK,CAAC;AAEjC,QAAM,WAAW,KAAK,IAAI,GAAG,OAAO,OAAO,OAAO,CAAC;AACnD,QAAM,aAAa,OAAO,QAAQ,EAAE,SAAS;AAG7C,QAAM,SAA4B;AAAA,IAChC,CAAC,WAAW,SAAS;AAAA,IACrB,CAAC,WAAW;AAAA,IACZ,CAAC,SAAS,SAAS,SAAS;AAAA,IAC5B,CAAC,YAAY,QAAQ;AAAA,IACrB,CAAC,QAAQ;AAAA,EACX;AACA,aAAW,SAAS,QAAQ;AAC1B,QAAI,UAAU,OAAO,CAAC,EAAG,SAAQ,KAAK;AACtC,eAAW,UAAU,OAAO;AAC1B,YAAM,EAAE,MAAM,OAAO,OAAO,YAAY,IAAI,oBAAoB,MAAM;AACtE,YAAM,WAAW,MAAM,OAAO,QAAQ,MAAM,CAAC,EAAE,SAAS,UAAU,CAAC;AACnE,cAAQ,KAAK,KAAK,IAAI,IAAI,QAAQ,KAAK,MAAM,OAAO,EAAE,CAAC,GAAG,cAAc,eAAG,IAAI,WAAW,IAAI,EAAE,EAAE;AAAA,IACpG;AAAA,EACF;AACF;AAkBA,SAAS,iBACP,OACA,OACA,aACA,SACM;AACN,MAAI,MAAM,WAAW,EAAG;AAExB,qBAAmB,GAAG,KAAK,IAAI,eAAG,IAAI,QAAK,MAAM,MAAM,QAAQ,CAAC,EAAE;AAElE,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,WAAW;AACjB,QAAM,QAAQ,MAAM,SAAS,WAAW,MAAM,MAAM,GAAG,QAAQ,IAAI;AAEnE,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO,QAAQ,KAAK,IAAI;AAChF,UAAM,SAAS,cAAc,KAAK,iBAAiB,KAAK;AACxD,UAAM,OAAO,cAAc,KAAK,oBAAoB,KAAK;AACzD,UAAM,WAAW,mBAAmB,KAAK,MAAM,QAAQ,MAAM,WAAW;AACxE,YAAQ,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,QAAQ,GAAG,QAAQ,SAAS,IAAI,KAAK,EAAE,EAAE;AAAA,EACjF;AAEA,MAAI,MAAM,SAAS,UAAU;AAC3B,YAAQ,KAAK,eAAG,IAAI,WAAW,MAAM,SAAS,QAAQ,OAAO,CAAC;AAAA,EAChE;AAEA,MAAI,QAAQ,MAAM;AAChB,YAAQ,KAAK;AACb,eAAW,QAAQ,MAAM,QAAQ,QAAQ,IAAI,IAAI,QAAQ,OAAO,CAAC,QAAQ,IAAI,GAAG;AAC9E,cAAQ,KAAK,eAAG,IAAI,KAAK,IAAI,EAAE,CAAC;AAAA,IAClC;AAAA,EACF;AACF;AAKA,SAAS,eACP,OACA,QACA,aACA,SACM;AACN,QAAM,WAAW,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC;AAClF,QAAM,SAAS,aAAa,MAAM;AAClC,QAAM,QAAQ,SAAS,SAAS,GAAG,OAAO,IAAI,IAAI,OAAO,KAAK;AAC9D,mBAAiB,UAAU,OAAO,aAAa,EAAE,GAAG,SAAS,MAAM,OAAO,KAAK,CAAC;AAClF;AAOO,SAAS,oBAAoB,OAAuC;AACzE,SAAO,MAAM,OAAO,CAAC,SAAS,KAAK,mBAAmB,CAAC,cAAc,KAAK,IAAI,CAAC;AACjF;AAGA,IAAM,wBACJ;AAIF,SAAS,eAAe,MAA4B;AAClD,SAAO,KAAK,YAAY,aAAa,QAAQ,OAAO,aAAa,OAAO;AAC1E;AAGA,SAAS,2BAA2B,MAA4B;AAC9D,MAAI,KAAK,yBAAyB,OAAW,QAAO;AACpD,SAAO,eAAG,OAAO,SAAM,OAAO,KAAK,sBAAsB,MAAM,CAAC,mBAAmB;AACrF;AAWA,SAAS,mBAAmB,QAAyC,OAA2B;AAC9F,QAAM,QAAQ,QAAQ;AACtB,MAAI,CAAC,MAAO,QAAO,CAAC;AACpB,QAAM,SAAS,IAAI,IAAI,KAAK;AAC5B,QAAM,UAAU,QAAQ,4BAA4B,CAAC,GAAG,OAAO,CAAC,UAAU,MAAM,MAAM,KAAK,CAAC,MAAM,OAAO,IAAI,CAAC,CAAC,CAAC;AAChH,MAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AACjC,SAAO;AAAA,IACL;AAAA,IACA,GAAG,OAAO,IAAI,CAAC,UAAU,cAAc,KAAK,OAAO,UAAU,MAAM,KAAK,CAAC,EAAE;AAAA,EAC7E;AACF;AAGA,SAAS,0BAA0B,MAA4B;AAC7D,QAAM,IAAI,KAAK,uBAAuB;AACtC,SAAO,IAAI,IAAI,eAAG,OAAO,SAAM,OAAO,GAAG,eAAe,CAAC,SAAS,IAAI;AACxE;AAUO,SAAS,wBACd,OACA,aACA,YACM;AACN,QAAM,kBAAkB,oBAAoB,KAAK;AACjD,iBAAe,OAAO,UAAU,aAAa;AAAA,IAC3C,OAAO,eAAG,KAAK,2BAAsB;AAAA,EACvC,CAAC;AACD,iBAAe,OAAO,SAAS,aAAa;AAAA,IAC1C,OAAO,GAAG,eAAG,KAAK,0BAAqB,CAAC;AAAA,IACxC,QAAQ;AAAA,IACR,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,IAEF;AAAA,EACF,CAAC;AACD,mBAAiB,iBAAiB,GAAG,WAAW,IAAI,eAAG,OAAO,+BAA+B,CAAC,IAAI,aAAa;AAAA,IAC7G,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,MAAM;AAAA,MACJ;AAAA,MACA,GAAG;AAAA,QACD;AAAA,QACA,gBAAgB,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,MACzC;AAAA,IACF;AAAA,EACF,CAAC;AACD,iBAAe,OAAO,WAAW,aAAa;AAAA,IAC5C,OAAO,GAAG,WAAW,IAAI,eAAG,OAAO,uBAAuB,CAAC;AAAA,IAC3D,MAAM;AAAA,EACR,CAAC;AACD,iBAAe,OAAO,YAAY,aAAa;AAAA,IAC7C,OAAO,GAAG,eAAG,QAAQ,iBAAY,CAAC;AAAA,IAClC,MAAM;AAAA,IACN,YAAY;AAAA,EACd,CAAC;AACH;AAEO,SAAS,kBAAkB,QAAqB,UAAqC,CAAC,GAAS;AACpG,QAAM,UAAU,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,WAAW,YAAY,KAAK,WAAW,UAAU,EAAE;AACtG,QAAM,WAAW,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,WAAW,UAAU,EAAE;AAC3E,QAAM,SAAS,OAAO,iBAAiB,UAAU,KAAK,IAAI,GAAG,WAAW,OAAO,UAAU,MAAM;AAC/F,QAAM,YAAY,OAAO,UAAU;AAEnC,UAAQ,KAAK;AACb,MAAI,QAAQ,cAAc;AACxB,YAAQ,KAAK,GAAG,SAAS,0BAA0B,QAAQ,YAAY,GAAG;AAC1E,YAAQ;AAAA,MACN,eAAG,IAAI,KAAK,OAAO,mBAAmB,MAAM,iBAAiB,SAAS,gCAAgC;AAAA,IACxG;AAAA,EACF,OAAO;AACL,YAAQ,KAAK,GAAG,SAAS,gBAAgB;AACzC,YAAQ,KAAK,eAAG,IAAI,KAAK,OAAO,mBAAmB,MAAM,iBAAiB,SAAS,YAAY,CAAC;AAAA,EAClG;AAEA,0BAAwB,MAAM;AAC9B,UAAQ,KAAK;AACf;AAOA,SAAS,wBAAwB,QAA2B;AAC1D,QAAM,QAAQ,OAAO,sBAAsB,CAAC;AAC5C,MAAI,MAAM,WAAW,EAAG;AAExB,QAAM,SAAS,IAAI,IAAI,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC;AACpE,UAAQ,KAAK;AACb,UAAQ;AAAA,IACN,GAAG,WAAW,IAAI,eAAG;AAAA,MACnB,GAAG,OAAO,MAAM,QAAQ,uBAAuB,sBAAsB,CAAC;AAAA,IACxE,CAAC;AAAA,EACH;AACA,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,OAAO,IAAI,IAAI;AAC5B,UAAM,OAAO,OAAO,eAAe,IAAI,IAAI,aAAa,OAAO;AAC/D,YAAQ,KAAK,KAAK,IAAI,IAAI,IAAI,GAAG,OAAO,2BAA2B,IAAI,IAAI,EAAE,EAAE;AAAA,EACjF;AACA,aAAW,QAAQ,CAAC,uBAAuB,GAAG,mBAAmB,QAAQ,KAAK,CAAC,EAAG,SAAQ,KAAK,eAAG,IAAI,KAAK,IAAI,EAAE,CAAC;AACpH;AAGO,SAAS,OAAOC,QAAe,UAAkB,aAAa,GAAG,QAAQ,KAAa;AAC3F,SAAO,GAAGA,MAAK,IAAIA,WAAU,IAAI,WAAW,UAAU;AACxD;AAGA,SAAS,UAAU,MAAsB;AACvC,SAAO,eAAe,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,MAAM,OAAO,CAAC;AAC3E;AAQO,SAAS,4BAA4B,QAA2B;AACrE,QAAM,SAAS,OAAO,0BAA0B,CAAC;AACjD,MAAI,OAAO,WAAW,EAAG;AAEzB,QAAM,QAAQ,OAAO,OAAO,CAACA,QAAO,UAAUA,SAAQ,MAAM,MAAM,QAAQ,CAAC;AAC3E,UAAQ,KAAK;AACb,UAAQ;AAAA,IACN,GAAG,WAAW,IAAI,eAAG,OAAO,uCAAoC,OAAO,OAAO,MAAM,CAAC,UAAU,OAAO,OAAO,QAAQ,SAAS,SAAS,CAAC,EAAE,CAAC;AAAA,EAC7I;AACA,aAAW,SAAS,QAAQ;AAC1B,UAAM,SAAS,CAAC,OAAO,MAAM,MAAM,QAAQ,MAAM,CAAC;AAClD,QAAI,MAAM,QAAQ,EAAG,QAAO,KAAK,GAAG,MAAM,KAAK,MAAM;AACrD,QAAI,MAAM,UAAU,EAAG,QAAO,KAAK,GAAG,MAAM,OAAO,UAAU;AAC7D,YAAQ,KAAK,KAAK,aAAa,QAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,eAAG,IAAI,QAAK,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC,EAAE;AAChG,QAAI,OAAO,mBAAmB;AAC5B,cAAQ,KAAK,eAAG,IAAI,gBAAgB,OAAO,iBAAiB,OAAO,UAAU,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,IAC9F;AAAA,EACF;AACA,UAAQ,KAAK,eAAG,IAAI,6FAA6F,CAAC;AACpH;AASO,SAAS,6BAA6B,QAAsD;AACjG,QAAM,SAAS,OAAO;AACtB,MAAI,CAAC,OAAQ;AAEb,UAAQ,KAAK;AACb,MAAI,OAAO,SAAS,cAAc;AAChC,UAAM,OAAO,OAAO,SAAS,SAAS,wBAAwB;AAC9D,YAAQ;AAAA,MACN,eAAG,IAAI,+CAA+C,WAAW,gCAAgC,IAAI,EAAE;AAAA,IACzG;AACA;AAAA,EACF;AAEA,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,CAAC,UAAU,WAAW,iBAAiB,GAAY;AACpE,eAAW,SAAS,OAAO,IAAI,EAAE,MAAO,OAAM,KAAK,KAAK,eAAG,MAAM,GAAG,CAAC,IAAI,IAAI,KAAK,KAAK,EAAE;AACzF,eAAW,SAAS,OAAO,IAAI,EAAE,SAAS;AACxC,YAAM,KAAK,KAAK,eAAG,IAAI,QAAG,CAAC,IAAI,IAAI,KAAK,KAAK,GAAG,eAAG,IAAI,8CAA2C,CAAC,EAAE;AAAA,IACvG;AAAA,EACF;AACA,UAAQ;AAAA,IACN,GAAG,WAAW,IAAI,eAAG,OAAO,yCAAsC,OAAO,MAAM,QAAQ,SAAS,SAAS,CAAC,YAAY,CAAC;AAAA,EACzH;AACA,aAAW,QAAQ,MAAO,SAAQ,KAAK,IAAI;AAC3C,UAAQ,KAAK,eAAG,IAAI,KAAK,WAAW,kEAAkE,CAAC;AACzG;AAWO,SAAS,gBAAgB,OAAuC;AACrE,SAAO,MAAM;AAAA,IACX,CAAC,SACC,KAAK,YACL,CAAC,cAAc,KAAK,IAAI,KACxB,KAAK,WAAW,YAChB,KAAK,gBACL,KAAK;AAAA,EACT;AACF;AAMA,SAAS,uBAAuB,OAA6B;AAC3D,QAAM,UAAU,gBAAgB,KAAK;AACrC,MAAI,QAAQ,WAAW,EAAG;AAE1B,UAAQ,KAAK;AACb,UAAQ;AAAA,IACN,GAAG,WAAW,IAAI,eAAG;AAAA,MACnB,GAAG,OAAO,QAAQ,QAAQ,uBAAuB,oBAAoB,CAAC;AAAA,IACxE,CAAC;AAAA,EACH;AACA,UAAQ,KAAK,eAAG,OAAO,8EAA8E,CAAC;AACtG,aAAW,QAAQ,SAAS;AAC1B,YAAQ,KAAK,eAAG,IAAI,YAAO,KAAK,IAAI,EAAE,CAAC;AAAA,EACzC;AACA,UAAQ;AAAA,IACN,eAAG,OAAO,6FAA6F;AAAA,EACzG;AACA,UAAQ,KAAK;AACf;AAOO,SAAS,mBAAmB,QAAqB,OAAqB;AAC3E,eAAa,OAAO,SAAS,KAAK;AAClC,8BAA4B,MAAM;AAClC,+BAA6B,MAAM;AACnC,yBAAuB,OAAO,KAAK;AACrC;;;AE7mBA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,aAAY;;;ACDrB,SAAS,gBAAgB;AACzB,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,SAAAC,QAAO,SAAS,OAAO,cAAc;AAC9C,SAAS,WAAAC,UAAS,QAAAC,OAAM,WAAAC,gBAAe;AACvC,SAAS,iBAAiB;;;ACF1B,SAAS,OAAO,UAAU,iBAAiB;AAC3C,SAAS,SAAS,QAAAC,aAAY;AAGvB,IAAM,gBAAgB;AAqBtB,SAAS,kBAAkB,KAAkC;AAClE,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAM,SAAS,QAAQ,UAAU;AACjC,QAAI,OAAO,WAAW,YAAY,CAAC,kBAAkB,KAAK,MAAM,EAAG,QAAO;AAC1E,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAsB,iBAAiB,KAA2C;AAChF,MAAI;AACF,WAAO,kBAAkB,MAAM,SAASA,MAAK,KAAK,aAAa,GAAG,MAAM,CAAC;AAAA,EAC3E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,iBAAiB,KAAqC;AAC1E,QAAM,WAAW,MAAM,iBAAiB,GAAG;AAC3C,SAAO,WAAW,SAAS,SAAS,OAAO,YAAY,IAAI;AAC7D;AAGA,eAAsB,kBAAkB,KAAa,UAAuC;AAC1F,QAAM,eAAeA,MAAK,KAAK,aAAa;AAE5C,QAAM,MAAM,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AACtD,QAAM,UAAU,cAAc,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAChF;;;ADrDA,IAAM,gBAAgB,UAAU,QAAQ;AAGjC,IAAM,aAAa,KAAK,OAAO;AAMtC,SAAS,iBAAiB,MAAsB;AAC9C,SAAO,KAAK,QAAQ,wBAAwB,CAAC,UAAU;AACrD,UAAM,WAAW,MAAM,WAAW,OAAO,IAAI,UAAU;AACvD,WAAO,GAAG,QAAQ;AAAA,EACpB,CAAC;AACH;AAaA,eAAsB,IAAI,MAAgB,KAAa,UAA6B,CAAC,GAAoB;AACvG,QAAM,MAAM;AAAA,IACV,GAAG,eAAe;AAAA,IAClB,GAAI,QAAQ,aAAa,EAAE,YAAY,OAAO,IAAI,CAAC;AAAA,IACnD,GAAG,QAAQ;AAAA,EACb;AAEA,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,OAAO,MAAM,EAAE,KAAK,KAAK,WAAW,WAAW,CAAC;AACvF,WAAO,OAAO,KAAK;AAAA,EACrB,SAAS,OAAO;AACd,QAAI,QAAQ,aAAc,QAAO;AACjC,QAAI,iBAAiB,OAAO;AAC1B,YAAM,UAAU,iBAAiB,MAAM,OAAO;AAAA,IAChD;AACA,UAAM;AAAA,EACR;AACF;AAGA,eAAsB,SAAS,KAAa,KAAqC;AAC/E,SAAQ,MAAM,IAAI,CAAC,aAAa,MAAM,YAAY,GAAG,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC,KAAM;AAC3F;AAEA,eAAsB,iBAAiB,KAA8B;AACnE,SAAO,IAAI,CAAC,aAAa,gBAAgB,MAAM,GAAG,GAAG;AACvD;AAEA,eAAsB,aAAa,KAAa,QAA+B;AAC7E,QAAM,IAAI,CAAC,UAAU,MAAM,GAAG,GAAG;AACnC;AAKA,eAAsB,eAAe,KAAa,KAA4B;AAC5E,QAAM,IAAI,CAAC,UAAU,YAAY,GAAG,GAAG,GAAG;AAC5C;AAQA,eAAsB,iBAAiB,KAAa,QAAgB,YAAmC;AACrG,QAAM,IAAI,CAAC,UAAU,MAAM,QAAQ,cAAc,UAAU,GAAG,GAAG;AACnE;AAGA,eAAsB,aAAa,KAAa,QAAkC;AAChF,SAAQ,MAAM,SAAS,KAAK,cAAc,MAAM,EAAE,MAAO;AAC3D;AAQA,eAAsB,kBAAkB,KAAa,QAAwC;AAC3F,QAAM,SAAS,MAAM,IAAI,CAAC,YAAY,QAAQ,aAAa,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACzF,MAAI,WAA0B;AAC9B,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,QAAI,KAAK,WAAW,WAAW,EAAG,YAAW,KAAK,MAAM,YAAY,MAAM;AAAA,aACjE,SAAS,qBAAqB,MAAM,GAAI,QAAO;AAAA,EAC1D;AACA,SAAO;AACT;AAQA,eAAsB,kBAAkB,KAAa,QAAgB,KAA4B;AAC/F,QAAM,IAAI,CAAC,SAAS,WAAW,KAAK,GAAG,GAAG,eAAe,MAAM,EAAE,GAAG,GAAG;AACzE;AAGA,eAAsB,aAAa,KAAa,QAA+B;AAC7E,QAAM,IAAI,CAAC,UAAU,MAAM,MAAM,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACjE;AAMA,eAAsB,gBAAgB,KAA4B;AAChE,QAAM,IAAI,CAAC,QAAQ,WAAW,GAAG,KAAK,EAAE,cAAc,MAAM,YAAY,KAAK,CAAC;AAChF;AAgBA,eAAsB,kBAAkB,KAAa,SAAS,IAA4B;AACxF,QAAM,WAAW,MAAM,IAAI,CAAC,aAAa,gBAAgB,wBAAwB,GAAG,MAAM,aAAa,GAAG,KAAK;AAAA,IAC7G,cAAc;AAAA,EAChB,CAAC;AACD,SAAO,YAAY;AACrB;AAWA,eAAsB,kBAAkB,KAAa,QAA0C;AAC7F,QAAM,QAAQ,SAAS,cAAc,MAAM,KAAK;AAChD,QAAM,WAAW,MAAM,kBAAkB,KAAK,MAAM;AACpD,MAAI,CAAC,SAAU,QAAO,EAAE,UAAU,MAAM,OAAO,GAAG,QAAQ,EAAE;AAG5D,QAAM,SAAS,SAAS,MAAM,GAAG,EAAE,CAAC;AACpC,QAAM,IAAI,CAAC,SAAS,MAAM,GAAG,KAAK,EAAE,cAAc,MAAM,YAAY,KAAK,CAAC;AAE1E,QAAM,SAAS,MAAM,IAAI,CAAC,YAAY,gBAAgB,WAAW,GAAG,KAAK,MAAM,QAAQ,EAAE,GAAG,KAAK;AAAA,IAC/F,cAAc;AAAA,EAChB,CAAC;AACD,QAAM,CAAC,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,EAAE,IAAI,CAAC,MAAM,OAAO,SAAS,GAAG,EAAE,KAAK,CAAC;AAClF,SAAO,EAAE,UAAU,OAAO,SAAS,GAAG,QAAQ,UAAU,EAAE;AAC5D;AAQA,eAAsB,WACpB,KACA,QACA,QACA,UAAwC,CAAC,GAC1B;AACf,QAAM,IAAI,CAAC,QAAQ,MAAM,GAAI,QAAQ,iBAAiB,CAAC,oBAAoB,IAAI,CAAC,GAAI,QAAQ,MAAM,GAAG,GAAG;AAC1G;AASA,eAAsB,uBAAuB,KAAa,SAAoC;AAC5F,QAAM,MAAM,MAAM,IAAI,CAAC,YAAY,YAAY,kBAAkB,GAAG,OAAO,QAAQ,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACjH,SAAO,MAAM,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO,IAAI,CAAC;AAClD;AASA,eAAsB,cAAc,KAAa,SAAiB,SAAgC;AAChG,QAAM,SAAS,MAAM,aAAa,KAAK,SAAS,MAAM;AACtD,QAAM,OAAO,MAAM,IAAI,CAAC,aAAa,aAAa,GAAG,GAAG;AACxD,QAAM,SAAS,MAAM,IAAI,CAAC,eAAe,MAAM,MAAM,QAAQ,MAAM,OAAO,GAAG,GAAG;AAChF,QAAM,IAAI,CAAC,SAAS,UAAU,MAAM,GAAG,GAAG;AAC5C;AAWA,eAAsB,aAAa,KAAa,SAAgC;AAC9E,aAAW,QAAQ,CAAC,cAAc,aAAa,YAAY,GAAG;AAC5D,UAAM,OAAO,MAAM,QAAQ,KAAK,IAAI;AACpC,QAAIC,YAAW,IAAI,EAAG,OAAM,OAAO,IAAI;AAAA,EACzC;AACA,QAAM,IAAI,CAAC,UAAU,MAAM,OAAO,GAAG,KAAK,EAAE,YAAY,KAAK,CAAC;AAChE;AAMA,eAAe,QAAQ,KAAa,MAA+B;AACjE,SAAOC,SAAQ,KAAK,MAAM,IAAI,CAAC,aAAa,cAAc,IAAI,GAAG,GAAG,CAAC;AACvE;AAKA,eAAsB,SAAS,KAA4B;AACzD,QAAM,IAAI,CAAC,OAAO,IAAI,GAAG,GAAG;AAC9B;AAKA,eAAsB,gBAAgB,KAA+B;AACnE,SAAQ,MAAM,SAAS,KAAK,YAAY,MAAO;AACjD;AAEA,eAAsB,YAAY,KAAa,KAA8B;AAC3E,SAAO,IAAI,CAAC,aAAa,WAAW,GAAG,GAAG,GAAG;AAC/C;AAEA,eAAsB,0BAA0B,KAA8B;AAC5E,QAAM,SAAS,MAAM,IAAI,CAAC,UAAU,aAAa,GAAG,GAAG;AACvD,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE;AAC5C;AAGA,eAAsB,aAAa,KAAa,YAAoB,KAA4B;AAC9F,QAAM,IAAI,CAAC,UAAU,OAAO,YAAY,GAAG,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACzE,QAAM,IAAI,CAAC,UAAU,WAAW,YAAY,GAAG,GAAG,GAAG;AACvD;AAEA,eAAsB,YAAY,KAAa,YAAmC;AAChF,QAAM,IAAI,CAAC,SAAS,UAAU,GAAG,GAAG;AACtC;AAQA,eAAsB,kBAAkB,KAAa,YAAmC;AACtF,QAAM,IAAI,CAAC,SAAS,YAAY,aAAa,qBAAqB,UAAU,SAAS,GAAG,GAAG;AAC7F;AAMA,IAAM,oBAAoB;AAO1B,eAAsB,wBACpB,KACA,YAC8C;AAC9C,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,SAAS,MAAM,IAAI,CAAC,gBAAgB,2BAA2B,uBAAuB,MAAM,GAAG,KAAK;AAAA,IACxG,cAAc;AAAA,EAChB,CAAC;AACD,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,UAAM,MAAM,KAAK,KAAK;AACtB,QAAI,CAAC,IAAK;AACV,UAAM,MAAM,IAAI,MAAM,OAAO,MAAM;AACnC,QAAI,kBAAkB,KAAK,GAAG,EAAG,QAAO,EAAE,KAAK,IAAI;AAAA,EACrD;AACA,SAAO;AACT;AASA,eAAsB,sBACpB,KACA,YACA,KACyE;AACzE,MAAI,IAAI,WAAW,GAAG,EAAG,QAAO;AAChC,QAAM,SAAS,QAAQ,UAAU,SAAS,GAAG;AAC7C,aAAW,aAAa,CAAC,gBAAgB,UAAU,IAAI,GAAG,IAAI,QAAQ,GAAG,GAAG;AAC1E,UAAM,MAAM,MAAM,SAAS,KAAK,GAAG,SAAS,WAAW;AACvD,QAAI,CAAC,IAAK;AACV,UAAM,UAAU,cAAc,UAAU,kBAAkB,KAAK,GAAG,IAAI,EAAE,KAAK,KAAK,KAAK,OAAO,IAAI;AAClG,WAAO,EAAE,KAAK,QAAQ;AAAA,EACxB;AACA,SAAO;AACT;AAMA,eAAsB,oBACpB,KACA,YACA,WACA,KACkB;AAClB,QAAM,aAAa,MAAM;AAAA,IACvB;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,SAAS;AAAA,MACzB,QAAQ,UAAU;AAAA,MAClB,QAAQ,UAAU;AAAA,IACpB;AAAA,IACA;AAAA,IACA,EAAE,cAAc,KAAK;AAAA,EACvB;AACA,SAAO,eAAe;AACxB;AAEA,eAAsB,cAAc,KAAa,KAAwC;AACvF,QAAM,SAAS;AACf,QAAM,SAAS,MAAM,IAAI,CAAC,OAAO,MAAM,YAAY,MAAM,IAAI,GAAG,GAAG,GAAG;AACtE,QAAM,CAAC,MAAM,SAAS,IAAI,IAAI,OAAO,MAAM,IAAI;AAC/C,SAAO,EAAE,MAAM,SAAS,KAAK;AAC/B;AAGA,eAAsB,oBAAoB,KAAa,SAAiB,OAAgC;AACtG,QAAM,SAAS,MAAM,IAAI,CAAC,YAAY,WAAW,GAAG,OAAO,KAAK,KAAK,EAAE,GAAG,GAAG;AAC7E,SAAO,OAAO,SAAS,OAAO,KAAK,GAAG,EAAE,KAAK;AAC/C;AAMA,eAAsB,mBACpB,KACA,SACA,OACA,OAC6B;AAC7B,QAAM,OAAO,CAAC,OAAO,4BAA4B,aAAa,GAAG,OAAO,KAAK,KAAK,EAAE;AACpF,MAAI,MAAO,MAAK,KAAK,KAAK,KAAK,EAAE;AAEjC,QAAM,SAAS,MAAM,IAAI,MAAM,KAAK,EAAE,cAAc,KAAK,CAAC;AAC1D,MAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,QAAM,UAA8B,CAAC;AACrC,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,QAAI,CAAC,KAAM;AACX,UAAM,CAAC,MAAM,SAAS,IAAI,IAAI,KAAK,MAAM,GAAM;AAC/C,QAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAM;AAChC,YAAQ,KAAK,EAAE,MAAM,SAAS,KAAK,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAaA,eAAsB,kBACpB,KACA,SACA,OACsC;AACtC,QAAM,OAAO,oBAAI,IAA4B;AAC7C,QAAM,SAAS,MAAM,IAAI,CAAC,OAAO,eAAe,uBAAuB,GAAG,OAAO,KAAK,KAAK,EAAE,GAAG,KAAK;AAAA,IACnG,cAAc;AAAA,EAChB,CAAC;AACD,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,cAAc;AAClB,MAAI,cAAc;AAClB,MAAI,mBAAmB;AACvB,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,QAAI,CAAC,KAAM;AACX,UAAM,QAAQ,KAAK,MAAM,iCAAiC;AAC1D,QAAI,OAAO;AACT,oBAAc,MAAM,CAAC;AACrB,yBAAmB,OAAO,MAAM,CAAC,CAAC;AAClC,oBAAc,MAAM,CAAC;AAAA,IACvB,WAAW,eAAe,eAAe,CAAC,KAAK,IAAI,IAAI,GAAG;AAExD,WAAK,IAAI,MAAM,EAAE,MAAM,aAAa,MAAM,aAAa,WAAW,iBAAiB,CAAC;AAAA,IACtF;AAAA,EACF;AACA,SAAO;AACT;AAGA,eAAsB,QAAQ,KAA+B;AAC3D,SAAQ,MAAM,0BAA0B,GAAG,MAAO;AACpD;AAOA,eAAsB,MAAM,KAAa,KAAiE;AACxG,MAAI;AACF,UAAM,IAAI,CAAC,SAAS,WAAW,eAAe,aAAa,GAAG,GAAG,KAAK,EAAE,YAAY,KAAK,CAAC;AAC1F,WAAO,EAAE,SAAS,MAAM,WAAW,CAAC,EAAE;AAAA,EACxC,SAAS,OAAO;AACd,UAAM,YAAY,MAAM,mBAAmB,GAAG;AAC9C,QAAI,UAAU,SAAS,GAAG;AACxB,aAAO,EAAE,SAAS,OAAO,UAAU;AAAA,IACrC;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,mBAAmB,KAAgC;AACvE,QAAM,SAAS,MAAM,IAAI,CAAC,QAAQ,eAAe,iBAAiB,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAChG,MAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,SAAO,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO;AAC1C;AAEA,eAAsB,WAAW,KAA4B;AAC3D,QAAM,IAAI,CAAC,SAAS,SAAS,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC7D;AAEA,eAAsB,gBAAgB,KAAa,KAAa,UAAoC;AAClG,QAAM,SAAS,MAAM,IAAI,CAAC,WAAW,eAAe,KAAK,MAAM,QAAQ,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACrG,SAAO,WAAW;AACpB;AAMA,eAAsB,gBAAgB,KAAa,KAAa,OAAgC;AAC9F,QAAM,IAAI,CAAC,YAAY,KAAK,MAAM,GAAG,KAAK,GAAG,GAAG;AAClD;AAMA,eAAsB,uBAAuB,KAAa,KAAa,UAAiC;AACtG,QAAM,IAAI,CAAC,WAAW,YAAY,GAAG,IAAI,cAAc,MAAM,QAAQ,GAAG,GAAG;AAC7E;AAMA,eAAsB,4BAA4B,KAAa,KAAa,WAAoC;AAC9G,QAAM,YAAY;AAClB,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;AACpD,UAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,SAAS;AAC9C,UAAM,IAAI,CAAC,uBAAuB,WAAW,YAAY,GAAG,IAAI,cAAc,MAAM,GAAG,KAAK,GAAG,GAAG;AAAA,EACpG;AACF;AAMA,eAAsB,mBAAmB,KAAa,KAAmC;AACvF,QAAM,eAAe,CAAC,QAAgB,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO;AACpE,QAAM,CAAC,SAAS,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC3C,IAAI,CAAC,WAAW,MAAM,eAAe,MAAM,GAAG,GAAG,GAAG;AAAA,IACpD,IAAI,CAAC,QAAQ,eAAe,gBAAgB,MAAM,KAAK,IAAI,GAAG,GAAG;AAAA,EACnE,CAAC;AACD,QAAM,UAAU,IAAI,IAAI,aAAa,OAAO,CAAC;AAC7C,SAAO,IAAI,IAAI,aAAa,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC;AAC3E;AAGA,eAAsB,oBAAoB,KAAa,KAAa,OAAoC;AACtG,QAAM,MAAM,MAAM,IAAI,CAAC,uBAAuB,QAAQ,eAAe,gBAAgB,MAAM,KAAK,MAAM,GAAG,KAAK,GAAG,GAAG;AACpH,SAAO,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO;AACvC;AAEA,eAAsB,aAAa,KAAa,MAAc,MAA+B;AAC3F,SAAO,IAAI,CAAC,cAAc,MAAM,IAAI,GAAG,GAAG;AAC5C;AAmBA,eAAsB,eACpB,KACA,SACA,WACkC;AAClC,QAAM,SAAS,MAAM,IAAI,CAAC,aAAa,MAAM,SAAS,kBAAkB,SAAS,SAAS,GAAG,KAAK;AAAA,IAChG,cAAc;AAAA,EAChB,CAAC;AACD,QAAM,UAAU,oBAAI,IAAwB;AAG5C,QAAM,aAAa,CAAC,SAAkB,SAAS,IAAI,OAAO,EAAE,IAAI,OAAO;AAEvE,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AAErC,UAAM,IAAI,KAAK,MAAM,sEAAsE;AAC3F,QAAI,CAAC,EAAG;AACR,UAAM,SAAS,EAAE,CAAC;AAClB,YAAQ,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG;AAAA,MACxB;AAAA,MACA,UAAU,WAAW,EAAE,CAAC,CAAC;AAAA,MACzB,YAAY,WAAW,EAAE,CAAC,CAAC;AAAA,MAC3B,GAAI,WAAW,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC;AAAA,IAC5C,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAaA,eAAsB,YACpB,KACA,SACA,OACA,QAAkB,CAAC,GACa;AAChC,QAAM,OAAO,CAAC,QAAQ,aAAa,gBAAgB,SAAS,KAAK;AACjE,MAAI,MAAM,SAAS,EAAG,MAAK,KAAK,MAAM,GAAG,KAAK;AAC9C,QAAM,MAAM,MAAM,IAAI,MAAM,KAAK,EAAE,cAAc,KAAK,CAAC;AAEvD,QAAM,OAAO,oBAAI,IAAsB;AACvC,aAAW,QAAQ,IAAI,MAAM,IAAI,GAAG;AAClC,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,UAAM,CAAC,GAAG,GAAG,GAAG,IAAI,IAAI,KAAK,MAAM,GAAI;AACvC,UAAM,OAAO,KAAK,KAAK,GAAI;AAC3B,QAAI,CAAC,KAAM;AACX,SAAK,IAAI,MAAM;AAAA,MACb,WAAW,MAAM,MAAM,OAAO,OAAO,CAAC;AAAA,MACtC,WAAW,MAAM,MAAM,OAAO,OAAO,CAAC;AAAA,IACxC,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAGA,eAAsB,mBAAmB,KAAa,KAA2C;AAC/F,QAAM,SAAS,MAAM,IAAI,CAAC,WAAW,MAAM,GAAG,GAAG,GAAG;AACpD,QAAM,SAAS,oBAAI,IAAoB;AAEvC,MAAI,CAAC,OAAQ,QAAO;AAEpB,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,QAAI,CAAC,KAAM;AAEX,UAAM,QAAQ,KAAK,MAAM,6BAA6B;AACtD,QAAI,OAAO;AACT,YAAM,CAAC,EAAE,MAAM,QAAQ,IAAI;AAC3B,aAAO,IAAI,UAAU,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO;AACT;AAMA,eAAsB,MAAM,KAAa,OAAiB,UAAgC,CAAC,GAAkB;AAC3G,QAAM,IAAI,CAAC,MAAM,GAAI,QAAQ,SAAS,CAAC,UAAU,IAAI,CAAC,GAAI,MAAM,MAAM,GAAG,KAAK,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC9G;AAGA,eAAsB,kBAAkB,KAAgC;AACtE,QAAM,SAAS,MAAM,IAAI,CAAC,QAAQ,YAAY,eAAe,iBAAiB,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC5G,SAAO,SAAS,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO,IAAI,CAAC;AACxD;AAGA,eAAsB,MAAM,KAAa,SAAiB,SAAgC;AACxF,QAAM,SAASC,SAAQC,MAAK,KAAK,OAAO,CAAC;AACzC,QAAMC,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AAEvC,QAAM,IAAI,CAAC,MAAM,MAAM,SAAS,OAAO,GAAG,GAAG;AAC/C;AAEA,eAAsB,qBAAqB,KAAa,UAAoC;AAC1F,SAAOJ,YAAWG,MAAK,KAAK,QAAQ,CAAC;AACvC;AAMA,eAAsB,uBAAuB,KAAa,UAAiC;AACzF,QAAM,WAAWA,MAAK,KAAK,QAAQ;AACnC,MAAI;AACF,UAAM,OAAO,QAAQ;AACrB,UAAM,uBAAuB,KAAKD,SAAQ,QAAQ,CAAC;AAAA,EACrD,QAAQ;AAAA,EAER;AACF;AAMA,eAAsB,gBAAgB,KAAa,UAAiC;AAClF,QAAM,MAAM,KAAK,CAAC,QAAQ,CAAC;AAC3B,QAAM,uBAAuB,KAAK,QAAQ;AAC5C;AAMA,eAAe,uBAAuB,KAAa,cAAqC;AACtF,MAAI,CAAC,gBAAgB,iBAAiB,IAAK;AAE3C,QAAM,WAAWC,MAAK,KAAK,YAAY;AACvC,MAAI;AACF,UAAM,UAAU,MAAM,QAAQ,QAAQ;AACtC,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,MAAM,QAAQ;AACpB,YAAM,uBAAuB,KAAKD,SAAQ,YAAY,CAAC;AAAA,IACzD;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAcA,eAAsB,iBAAiB,KAAa,cAAqC;AACvF,QAAM,IAAI,CAAC,cAAc,wBAAwB,YAAY,GAAG,GAAG;AACnE,QAAM,OAAO,MAAM,SAAS,KAAK,MAAM;AACvC,MAAI,KAAM,OAAM,IAAI,CAAC,cAAc,6BAA6B,IAAI,GAAG,GAAG;AAC5E;AAGA,eAAsB,UAAU,KAAa,MAA6B;AACxE,QAAM,IAAI,CAAC,OAAO,MAAM,IAAI,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC5D;AAGA,eAAsB,iBAAiB,KAAqC;AAC1E,SAAO,SAAS,KAAK,sBAAsB;AAC7C;AAQA,eAAsB,kBAAkB,KAAa,KAA2C;AAC9F,QAAM,MAAM,MAAM,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,aAAa,EAAE,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACtF,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,kBAAkB,GAAG;AAC9B;AAGA,eAAsB,sBAAsB,KAAa,KAAqC;AAC5F,QAAM,WAAW,MAAM,kBAAkB,KAAK,GAAG;AACjD,SAAO,WAAW,SAAS,SAAS,OAAO,YAAY,IAAI;AAC7D;AAMA,eAAsB,wBAAwB,KAAa,KAAqC;AAC9F,QAAM,MAAM,MAAM,IAAI,CAAC,QAAQ,GAAG,GAAG,eAAe,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAClF,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI;AACF,UAAM,UAAW,KAAK,MAAM,GAAG,EAA4B;AAC3D,WAAO,OAAO,YAAY,YAAY,UAAU,UAAU;AAAA,EAC5D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAe,mBAAmB,KAAa,KAA+B;AAC5E,SAAQ,MAAM,SAAS,KAAK,GAAG,GAAG,WAAW,MAAO;AACtD;AAGA,eAAe,cAAc,KAAa,KAAqC;AAC7E,QAAM,MAAM,MAAM,IAAI,CAAC,YAAY,mBAAmB,GAAG,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACvF,QAAM,QAAQ,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO;AAC5C,SAAO,MAAM,SAAS,IAAI,MAAM,MAAM,SAAS,CAAC,IAAI;AACtD;AASA,eAAe,oBAAoB,KAAa,SAAyC;AACvF,QAAM,OAAO,MAAM,cAAc,KAAK,OAAO;AAC7C,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,UAAU,MAAM,IAAI,CAAC,QAAQ,MAAM,eAAe,IAAI,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC1F,QAAM,QAAQ,QAAQ,MAAM,kCAAkC;AAC9D,SAAO,QAAQ,MAAM,CAAC,EAAE,YAAY,IAAI;AAC1C;AAQA,eAAe,oBAAoB,KAA+B;AAChE,QAAM,MAAM,MAAM,IAAI,CAAC,aAAa,yBAAyB,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC3F,SAAO,QAAQ;AACjB;AASA,eAAe,oBAAoB,KAA4B;AAC7D,MAAI;AACF,UAAM,IAAI,CAAC,SAAS,aAAa,GAAG,KAAK,EAAE,YAAY,KAAK,CAAC;AAAA,EAC/D,SAAS,OAAO;AACd,UAAM,SAAS,iBAAiB,QAAQ;AAAA;AAAA,EAAO,MAAM,OAAO,KAAK;AACjE,UAAM,IAAI;AAAA,MACR;AAAA;AAAA;AAAA;AAAA;AAAA,mBAGsB,MAAM;AAAA,IAC9B;AAAA,EACF;AACF;AAqBA,eAAsB,eAAe,KAAa,SAAiB,aAAoC;AACrG,MAAI,MAAM,oBAAoB,GAAG,GAAG;AAClC,UAAM,oBAAoB,GAAG;AAAA,EAC/B;AAEA,QAAM,aAAa,MAAM,IAAI,CAAC,cAAc,SAAS,WAAW,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC9F,MAAI,WAAY;AAEhB,QAAM,UAA+C;AAAA,IACnD,MAAM,iBAAiB,GAAG;AAAA,IAC1B,MAAM,sBAAsB,KAAK,OAAO;AAAA,IACxC,MAAM,iBAAiB,GAAG;AAAA,IAC1B,MAAM,oBAAoB,KAAK,OAAO;AAAA,EACxC;AAEA,MAAI,UAAyB;AAC7B,aAAW,UAAU,SAAS;AAC5B,UAAM,MAAM,MAAM,OAAO;AACzB,QAAI,OAAQ,MAAM,mBAAmB,KAAK,GAAG,GAAI;AAC/C,gBAAU;AACV;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR,4CAA4C,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKzD;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,cAAc,KAAK,OAAO;AAC7C,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,uEAAuE;AAElG,QAAM,IAAI,CAAC,WAAW,MAAM,WAAW,MAAM,OAAO,GAAG,GAAG;AAC1D,QAAM,IAAI,CAAC,cAAc,wBAAwB,OAAO,GAAG,GAAG;AAChE;AAGA,eAAsB,WAAW,KAAa,UAAkB,YAAsC;AACpG,MAAI;AACF,UAAM,IAAI,CAAC,cAAc,iBAAiB,UAAU,UAAU,GAAG,GAAG;AACpE,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOA,eAAe,iBAAiB,KAAa,SAAyC;AACpF,QAAM,YAAY,MAAM,iBAAiB,GAAG;AAC5C,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,aAAa,MAAM,SAAS,KAAK,2BAA2B;AAClE,MAAI,YAAY;AACd,UAAM,cAAc,MAAM,SAAS,KAAK,OAAO;AAC/C,QAAI,eAAe,gBAAgB,WAAY,QAAO;AAAA,EACxD;AAEA,SAAO;AACT;AAYA,eAAsB,sBACpB,KACA,SACA,aACuE;AACvE,QAAM,UAAU,MAAM,aAAa,KAAK,SAAS,WAAW;AAE5D,QAAM,WAAY,MAAM,sBAAsB,KAAK,OAAO,KAAO,MAAM,iBAAiB,KAAK,OAAO;AACpG,MAAI,CAAC,UAAU;AACb,WAAO,EAAE,MAAM,SAAS,SAAS,OAAO,WAAW,KAAK;AAAA,EAC1D;AAGA,QAAM,kBAAkB,MAAM,WAAW,KAAK,SAAS,QAAQ;AAC/D,MAAI,mBAAmB,aAAa,SAAS;AAC3C,WAAO,EAAE,MAAM,UAAU,SAAS,MAAM,WAAW,SAAS;AAAA,EAC9D;AAEA,SAAO,EAAE,MAAM,SAAS,SAAS,OAAO,WAAW,SAAS;AAC9D;AAmBA,eAAsB,2BACpB,KACA,SACA,SACA,IACY;AACZ,QAAM,UAAU,MAAM,SAAS,KAAK,OAAO;AAC3C,MAAI,CAAC,WAAW,CAAE,MAAM,mBAAmB,KAAK,OAAO,EAAI,QAAO,GAAG;AAGrE,MAAI,MAAM,WAAW,KAAK,SAAS,OAAO,EAAG,QAAO,GAAG;AAGvD,QAAM,sBAAsB,MAAM,IAAI,CAAC,WAAW,MAAM,OAAO,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC7F,MAAI,oBAAqB,QAAO,GAAG;AAEnC,QAAM,aAAa,MAAM,IAAI,CAAC,OAAO,MAAM,eAAe,OAAO,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC/F,QAAM,UAAU,aAAa,WAAW,MAAM,KAAK,IAAI,CAAC;AAExD,QAAM,IAAI,CAAC,WAAW,MAAM,WAAW,SAAS,GAAG,SAAS,OAAO,GAAG,GAAG;AACzE,MAAI;AACF,WAAO,MAAM,GAAG;AAAA,EAClB,UAAE;AACA,UAAM,IAAI,CAAC,WAAW,MAAM,OAAO,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAAA,EACnE;AACF;;;AE78BA,SAAS,cAAAG,mBAAkB;AAC3B,SAAS,SAAAC,QAAO,YAAAC,WAAU,IAAI,aAAAC,kBAAiB;AAC/C,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAIvB,IAAM,YAAY;AAGlB,IAAM,eAAe;AAG5B,IAAM,UAAU;AAoBhB,SAAS,cAAc,MAAuB;AAC5C,SAAO,KAAK,SAAS,KAAK,KAAK,CAAC,KAAK,SAAS,UAAU;AAC1D;AAGO,SAAS,eAAe,UAA2B;AACxD,SAAO,aAAa,aAAa,SAAS,WAAW,GAAG,SAAS,GAAG;AACtE;AAGA,SAAS,UAAU,OAA2B;AAC5C,MAAI,YAAY;AAChB,SAAO,MAAM,OAAO,CAAC,SAAS;AAC5B,QAAI,CAAC,aAAa,CAAC,KAAK,UAAU,EAAE,WAAW,MAAM,EAAG,QAAO;AAC/D,gBAAY,CAAC,KAAK,SAAS,KAAK;AAChC,WAAO;AAAA,EACT,CAAC;AACH;AAGO,SAAS,UAAU,IAAY,QAAgB,WAAoC;AACxF,QAAM,QAAQ,OAAO,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AACtD,QAAM,QAAQ,MAAM,CAAC,MAAM,QAAQ,MAAM,QAAQ,OAAO,CAAC,IAAI;AAC7D,QAAM,OAAO,oBAAI,IAAoB;AACrC,aAAW,QAAQ,MAAM,MAAM,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,GAAG;AACrD,UAAM,QAAQ,kBAAkB,KAAK,IAAI;AACzC,QAAI,MAAO,MAAK,IAAI,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,EAC/C;AAEA,QAAM,OAAO,UAAU,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,KAAK,IAAI;AACxD,QAAM,SAAS,KACZ,MAAM,SAAS,EACf,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,OAAO;AACjB,QAAM,QAAQ,WAAW,KAAK,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,KAAK;AACzD,QAAM,UAAU,SAAS,OAAO,CAAC,KAAK,CAAC,mBAAmB,KAAK,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,EAAE,QAAQ,aAAa,GAAG,IAAI;AAElH,SAAO;AAAA,IACL;AAAA,IACA,OAAO,SAAS;AAAA,IAChB;AAAA,IACA,cAAc,KAAK,IAAI,cAAc,MAAM;AAAA,IAC3C,iBAAiB,KAAK,IAAI,iBAAiB,MAAM;AAAA,IACjD,QAAQ,KAAK,IAAI,OAAO,KAAK,IAC1B,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,OAAO;AAAA,IACjB,SAAS,UAAU,KAAK,aAAa,KAAK;AAAA,EAC5C;AACF;AAGA,eAAsB,YAAY,KAAa,KAAgC;AAC7E,QAAM,MAAM,MAAM,IAAI,CAAC,WAAW,eAAe,GAAG,GAAG,IAAI,SAAS,EAAE,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACpG,SAAO,IACJ,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,QAAQ,KAAK,IAAI,CAAC,EACnC,KAAK;AACV;AAGA,eAAsB,SAAS,KAAa,KAAa,IAA2C;AAClG,QAAM,SAAS,MAAM,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,SAAS,IAAI,EAAE,YAAY,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AACrG,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,MAAM,IAAI,CAAC,WAAW,eAAe,GAAG,GAAG,IAAI,SAAS,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,cAAc,KAAK,CAAC;AAC5G,SAAO,UAAU,IAAI,QAAQ,MAAM,MAAM,IAAI,EAAE,OAAO,OAAO,CAAC;AAChE;AAGA,eAAsB,eAAe,KAAa,MAAc,IAA+B;AAC7F,QAAM,CAAC,QAAQ,KAAK,IAAI,MAAM,QAAQ,IAAI,CAAC,YAAY,KAAK,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC,CAAC;AACxF,QAAM,QAAQ,IAAI,IAAI,MAAM;AAC5B,SAAO,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;AAC5C;AAGA,eAAsB,YAAY,KAAgC;AAChE,QAAM,OAAOC,MAAK,KAAK,YAAY;AACnC,MAAI,CAACC,YAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,QAAM,SAAS,KAAK,MAAM,MAAMC,UAAS,MAAM,MAAM,CAAC;AACtD,SAAO,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,QAAQ,OAAO,CAAC,OAAqB,OAAO,OAAO,QAAQ,IAAI,CAAC;AAChH;AAGA,eAAsB,aAAa,KAAa,KAA8B;AAC5E,QAAM,OAAOF,MAAK,KAAK,YAAY;AACnC,QAAM,UAAU,CAAC,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,KAAK;AACvC,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,GAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAC9B;AAAA,EACF;AACA,QAAMG,OAAMC,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,QAAMC,WAAU,MAAM,GAAG,KAAK,UAAU,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAC3E;AAGO,SAAS,QAAQ,mBAAuC,QAAgB,IAAgC;AAC7G,SAAO,oBAAoB,GAAG,iBAAiB,SAAS,MAAM,IAAI,SAAS,IAAI,EAAE,eAAe;AAClG;AAMO,SAAS,gBACd,OACA,MACA,SACA,UAAgC,CAAC,GACzB;AACR,QAAM,QAAQ,CAAC,SAAS,IAAI,OAAO,KAAK,aAAa,GAAG,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,OAAO,KAAK,UAAU;AACvG,MAAI,QAAS,OAAM,KAAK,GAAG,OAAO,IAAI,QAAQ,SAAS,WAAW,SAAS,iBAAiB;AAC5F,MAAI,OAAO,EAAG,OAAM,KAAK,GAAG,IAAI,2BAA2B;AAC3D,SAAO,oBAAoB,MAAM,KAAK,QAAK,CAAC;AAC9C;;;AHnJO,SAAS,eAAe,OAAuB;AACpD,SAAO,MAAM,KAAK,EAAE,QAAQ,SAAS,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAC7D;AAMO,SAAS,iBAAiB,UAAkB,SAA4B;AAC7E,SAAO,QAAQ,KAAK,CAAC,WAAW;AAC9B,UAAM,QAAQ,eAAe,MAAM;AACnC,WAAO,aAAa,SAAS,SAAS,WAAW,GAAG,KAAK,GAAG;AAAA,EAC9D,CAAC;AACH;AAMO,SAAS,UAAU,UAAkB,QAAiC;AAC3E,SAAO,eAAe,QAAQ,KAAK,iBAAiB,UAAU,OAAO,WAAW,WAAW,CAAC,CAAC;AAC/F;AAMO,SAAS,SAAS,UAAkB,QAAiC;AAC1E,MAAI,cAAc,QAAQ,EAAG,QAAO;AACpC,SAAO,iBAAiB,UAAU,OAAO,WAAW,UAAU,CAAC,CAAC;AAClE;AAGA,SAAS,aAAa,MAAkE;AACtF,QAAM,UAAU,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,cAAc,EAAE,OAAO,OAAO,CAAC,CAAC;AACrE,QAAM,oBAAoB,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AACzE,SAAO,CAAC,SAAS,CAAC,SAAS,kBAAkB,KAAK,CAAC,UAAU,iBAAiB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC/F;AAOO,SAAS,4BAA4B,OAAuB,SAA2C;AAC5G,QAAM,CAAC,SAAS,SAAS,IAAI,aAAa,OAAO;AACjD,QAAM,SAAS,oBAAI,IAAkC;AAErD,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,KAAK,gBAAgB,cAAc,KAAK,IAAI,KAAK,gBAAgB,KAAK,IAAI,EAAG;AAClF,UAAM,QAAQ,UAAU,KAAK,IAAI;AACjC,QAAI,CAAC,MAAO;AAEZ,UAAM,QAAQ,OAAO,IAAI,KAAK,KAAK,EAAE,OAAO,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS,EAAE;AAC5E,UAAM,MAAM,KAAK,KAAK,IAAI;AAC1B,QAAI,CAAC,KAAK,aAAc,OAAM;AAC9B,QAAI,CAAC,KAAK,iBAAkB,OAAM;AAClC,WAAO,IAAI,OAAO,KAAK;AAAA,EACzB;AAEA,aAAW,SAAS,OAAO,OAAO,EAAG,OAAM,MAAM,KAAK;AACtD,SAAO,QAAQ,QAAQ,CAAC,UAAU,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC;AAC3D;AAOO,SAAS,8BAA8B,OAAiB,QAAkD;AAC/G,QAAM,CAAC,EAAE,SAAS,IAAI,aAAa,CAAC,GAAI,OAAO,WAAW,UAAU,CAAC,GAAI,GAAI,OAAO,WAAW,WAAW,CAAC,CAAE,CAAC;AAC9G,QAAM,SAAS,oBAAI,IAAoC;AAEvD,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,UAAU,IAAI,KAAK;AACjC,UAAM,QAAQ,OAAO,IAAI,KAAK,KAAK,EAAE,OAAO,OAAO,CAAC,EAAE;AACtD,UAAM,MAAM,KAAK,IAAI;AACrB,WAAO,IAAI,OAAO,KAAK;AAAA,EACzB;AAEA,aAAW,SAAS,OAAO,OAAO,EAAG,OAAM,MAAM,KAAK;AACtD,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;AAUA,eAAsB,kBACpB,QACA,UACA,aACmB;AACnB,QAAM,WAAqB,CAAC;AAC5B,QAAM,UAAU,OAAO,WAAW,WAAW,CAAC;AAC9C,QAAM,WAAW,eAAgB,MAAM,SAAS,UAAU,WAAW,IAAK,cAAc;AACxF,QAAM,kBAA4B,CAAC;AAEnC,aAAW,SAAS,OAAO,WAAW,UAAU,CAAC,GAAG;AAClD,UAAM,OAAO,eAAe,KAAK;AACjC,UAAM,eAAe,QAAQ,KAAK,CAAC,WAAW,iBAAiB,MAAM,CAAC,MAAM,CAAC,CAAC;AAC9E,QAAI,OAAO,KAAK,KAAK,EAAG,UAAS,KAAK,wDAAwD,KAAK,EAAE;AAAA,aAC5F,CAACC,YAAWC,MAAK,UAAU,IAAI,CAAC,EAAG,UAAS,KAAK,kBAAkB,KAAK,EAAE;AAAA,aAC1E,aAAc,UAAS,KAAK,sBAAsB,eAAe,YAAY,CAAC,iBAAiB,KAAK,EAAE;AAAA,aACtG,CAAC,SAAU;AAAA,aACX,MAAM,gBAAgB,UAAU,UAAU,IAAI,EAAG,iBAAgB,KAAK,KAAK;AAAA,QAC/E,UAAS,KAAK,gDAAgD,KAAK,EAAE;AAAA,EAC5E;AAEA,MAAI,YAAY,gBAAgB,SAAS,GAAG;AAC1C,UAAM,UAAU,MAAM,oBAAoB,UAAU,UAAU,gBAAgB,IAAI,cAAc,CAAC;AACjG,eAAW,SAAS,iBAAiB;AACnC,UAAI,QAAQ,KAAK,CAAC,YAAY,iBAAiB,SAAS,CAAC,KAAK,CAAC,CAAC,EAAG;AACnE,eAAS,KAAK,uEAAuE,KAAK,EAAE;AAAA,IAC9F;AAAA,EACF;AAEA,aAAW,SAAS,OAAO,WAAW,WAAW,CAAC,GAAG;AACnD,UAAM,OAAO,eAAe,KAAK;AACjC,QAAI,OAAO,KAAK,KAAK,GAAG;AACtB,eAAS,KAAK,kEAAkE,KAAK,EAAE;AAAA,IACzF,WAAW,CAACD,YAAWC,MAAK,UAAU,IAAI,CAAC,GAAG;AAC5C,UAAI,eAAgB,MAAM,gBAAgB,UAAU,aAAa,IAAI,EAAI;AACzE,eAAS,KAAK,4BAA4B,KAAK,EAAE;AAAA,IACnD;AAAA,EACF;AAEA,SAAO;AACT;;;AV3GA,IAAM,MAAM,CAAC,UAAwC,OAAO,UAAU,WAAW,QAAQ;AAGzF,IAAM,OAAO,CAAC,UAA4B,UAAU;AAEpD,SAAS,YAAY,MAA+B,WAAqB,CAAC,GAAmB;AAC3F,QAAM,QAAQ,IAAI,KAAK,KAAK;AAC5B,MAAI,SAAS,UAAU,SAAS,UAAU,UAAU,UAAU,aAAa;AACzE,UAAM,IAAI,MAAM,oBAAoB,KAAK,0CAA0C;AAAA,EACrF;AACA,QAAM,kBAAkB;AAExB,QAAM,MAAM,IAAI,KAAK,GAAG;AACxB,MAAI,SAAS,SAAS,KAAK,CAAC,KAAK;AAC/B,UAAM,IAAI,MAAM,wBAAwB,SAAS,CAAC,CAAC,wDAAwD;AAAA,EAC7G;AAEA,SAAO;AAAA,IACL,SAAS,KAAK,KAAK,OAAO;AAAA,IAC1B,MAAM,KAAK,KAAK,IAAI;AAAA,IACpB,MAAM,KAAK,KAAK,IAAI;AAAA,IACpB,OAAO;AAAA,IACP,MAAM,IAAI,KAAK,IAAI;AAAA,IACnB,OAAO,KAAK,UAAU,aAAa,KAAK,UAAU,WAAW,KAAK,QAAQ;AAAA,IAC1E,KAAK,IAAI,KAAK,GAAG,KAAK;AAAA,IACtB,YAAY,KAAK,KAAK,UAAU;AAAA,IAChC,UAAU,KAAK,KAAK,QAAQ;AAAA,IAC5B,OAAO,IAAI,KAAK,KAAK,KAAK;AAAA,IAC1B,IAAI,KAAK,KAAK,EAAE;AAAA,IAChB,KAAK,KAAK,KAAK,GAAG;AAAA,IAClB,MAAM,IAAI,KAAK,IAAI;AAAA,IACnB,SAAS,IAAI,KAAK,OAAO;AAAA,IACzB;AAAA,IACA,SAAS,MAAM,WAAW;AAAA,IAC1B,MAAM,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,KAAK,OAAO,CAAC,OAAqB,OAAO,OAAO,QAAQ,IAAI;AAAA,EACpG;AACF;AAGA,IAAM,aAA4B,CAAC,UAAU,4CAA4C;AACzF,IAAM,cAA6B,CAAC,kBAAkB,yDAAyD;AAC/G,IAAM,YAA2B,CAAC,eAAe,kEAAkE;AACnH,IAAM,iBAAgC;AAAA,EACpC;AAAA,EACA;AACF;AACA,IAAM,aAA4B,CAAC,iBAAiB,6DAA6D;AAEjH,IAAM,qBAA0C;AAAA,EAC9C;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,MACP,CAAC,UAAU,wDAAwD;AAAA,MACnE;AAAA,MACA,CAAC,mBAAmB,qDAAqD;AAAA,MACzE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,eAAe,CAAC,YAAY,CAAC,QAAQ;AAAA,EACvC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA,CAAC,iBAAiB,wEAAwE;AAAA,MAC1F;AAAA,IACF;AAAA,IACA,eAAe,CAAC,YAAY,CAAC,QAAQ;AAAA,EACvC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,MACP,CAAC,SAAS,0CAA0C;AAAA,MACpD;AAAA,MACA,CAAC,eAAe,yBAAyB;AAAA,MACzC,CAAC,kBAAkB,sEAAsE;AAAA,MACzF,CAAC,cAAc,sEAAsE;AAAA,MACrF,CAAC,mBAAmB,yBAAyB;AAAA,IAC/C;AAAA,IACA,UAAU;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,IACA,eAAe,CAAC,YAAY,CAAC,QAAQ;AAAA,EACvC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,CAAC,CAAC,UAAU,iDAAiD,CAAC;AAAA,EACzE;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,MACP;AAAA,MACA,CAAC,iBAAiB,8EAA8E;AAAA,IAClG;AAAA,IACA,eAAe,CAAC,YAAY,QAAQ;AAAA,EACtC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,CAAC,YAAY,UAAU;AAAA,IAChC,eAAe,CAAC,YAAY,QAAQ;AAAA,EACtC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,MACP,CAAC,iBAAiB,wCAAwC;AAAA,MAC1D,CAAC,iBAAiB,4EAA4E;AAAA,MAC9F,CAAC,QAAQ,0EAA0E;AAAA,IACrF;AAAA,EACF;AACF;AAEA,SAAS,eAAe,YAA4B,UAA+B;AACjF,SAAO;AAAA,IACL,WAAW,WAAW,OAAO,UAAU,KAAK;AAAA,IAC5C,gBAAgB,eAAe,QAAQ;AAAA,EACzC;AACF;AAEA,SAAS,oBAAoB,SAAsB;AAEjD,QAAM,QAAQ,CAAC,SAAiB,KAAK,OAAO,EAAE;AAC9C,QAAM,cAAc,mBACjB,OAAO,CAAC,YAAY,QAAQ,gBAAgB,OAAO,KAAK,IAAI,EAC5D,IAAI,CAAC,aAAa;AAAA,IACjB,OAAO,QAAQ;AAAA,IACf,MAAM,GAAG,MAAM,QAAQ,IAAI,CAAC,GAAG,eAAG,IAAI,QAAQ,WAAW,CAAC;AAAA,EAC5D,EAAE;AAEJ,SAAO;AAAA,IACL,GAAG;AAAA,IACH,EAAE,MAAM,aAAsB,WAAW,aAAa;AAAA,IACtD,EAAE,OAAO,QAAiB,MAAM,eAAG,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,eAAG,IAAI,6BAA6B,CAAC,EAAE,EAAE;AAAA,EACrG;AACF;AAEA,SAAS,kBACP,SACA,YACA,cACA;AACA,QAAM,UAAU,QAAQ,QAAQ,WAAW,IAAI,EAAE,YAAY,WAAW,WAAW;AAEnF,aAAW,UAAU,WAAW,WAAW,CAAC,EAAG,SAAQ,OAAO,GAAG,MAAM;AACvE,MAAI,WAAW,SAAU,SAAQ,SAAS,GAAG,WAAW,QAAQ;AAGhE,UAAQ,OAAO,IAAI,SAAoB;AACrC,UAAM,WAAW,WAAW,WAAY,KAAK,CAAC,IAAiB,CAAC;AAChE,UAAM,OAAQ,WAAW,WAAW,KAAK,CAAC,IAAI,KAAK,CAAC;AACpD,iBAAa;AAAA,MACX,SAAS,WAAW;AAAA,MACpB,SAAS,YAAY,MAAM,QAAQ;AAAA,IACrC,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,aAAa,cAAiE;AACrF,QAAM,UAAU,IAAI,QAAQ,OAAO,EAChC,QAAQ,SAAS,iBAAiB,4BAA4B,EAC9D,MAAM,qBAAqB,EAC3B,WAAW,cAAc,4BAA4B,EACrD,mBAAmB,EACnB;AAAA,IACC;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AAEF,aAAW,cAAc,oBAAoB;AAC3C,sBAAkB,SAAS,YAAY,YAAY;AAAA,EACrD;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAqC;AAC7D,MAAI,KAAK,UAAU,GAAG;AACpB,WAAO,EAAE,SAAS,YAAY,CAAC,CAAC,EAAE;AAAA,EACpC;AAEA,MAAI,YAAiC,EAAE,SAAS,YAAY,CAAC,CAAC,EAAE;AAChE,QAAM,UAAU,aAAa,CAAC,kBAAkB;AAC9C,gBAAY;AAAA,EACd,CAAC;AAED,UAAQ,MAAM,IAAI;AAClB,SAAO;AACT;AAEA,eAAe,iBAAiB,YAA4B,UAAwC;AAClG,QAAM,WAAW,MAAM,OAA6B;AAAA,IAClD,SAAS;AAAA,IACT,SAAS,oBAAoB,eAAe,YAAY,QAAQ,CAAC;AAAA,IACjE,MAAM;AAAA,EACR,CAAC;AAED,MAAI,aAAa,QAAQ;AACvB,YAAQ,KAAK,eAAG,IAAI,YAAY,CAAC;AACjC,YAAQ,KAAK;AACb,IAAAC,SAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,KAAK;AACb,SAAO;AACT;AAEA,SAAS,mBACP,YACA,UACA,WACA,aACe;AACf,SAAO,EAAE,GAAG,YAAY,UAAU,aAAa,SAAS,UAAU,WAAW,WAAW,GAAG,UAAU,QAAQ;AAC/G;AAEA,eAAsB,SAAS,YAA4B,UAA0C;AACnG,QAAM,YAAY,iBAAiBA,SAAQ,IAAI;AAK/C,QAAM,cAAc,UAAU,QAAQ,QAAQ,UAAU,YAAY;AACpE,MAAI,UAAU,QAAQ,QAAQ,UAAU,QAAQ,MAAM,YAAa,aAAY,IAAI;AAEnF,cAAY;AAIZ,QAAM,EAAE,UAAU,IAAI,gBAAgB,WAAW,QAAQ;AACzD,QAAM,WAAW,MAAM,kBAAkB,YAAY,UAAU,SAAS;AACxE,aAAW,WAAW,SAAU,SAAQ,KAAK,GAAG,WAAW,IAAI,OAAO,EAAE;AACxE,MAAI,SAAS,SAAS,EAAG,SAAQ,KAAK;AAEtC,MAAI,CAAC,UAAU,SAAS;AACtB,cAAU,UAAU,MAAM,iBAAiB,YAAY,QAAQ;AAAA,EACjE;AAEA,SAAO,mBAAmB,YAAY,UAAU,WAAW,SAAS;AACtE;;;AclSA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,MAAAC,WAAU;AACnB,SAAS,QAAAC,aAAY;;;ACKd,SAAS,uBAAuB,SAA2C;AAChF,QAAM,UAAU,QAAQ,KAAK;AAC7B,QAAM,QAAQ,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,CAAC,MAAO,QAAO;AAEnB,SAAO;AAAA,IACL,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,IACtB,OAAO,OAAO,MAAM,CAAC,KAAK,CAAC;AAAA,IAC3B,OAAO,OAAO,MAAM,CAAC,KAAK,CAAC;AAAA,EAC7B;AACF;AAGO,SAAS,gBAAgB,MAAyB,OAAkC;AACzF,MAAI,KAAK,UAAU,MAAM,MAAO,QAAO,KAAK,QAAQ,MAAM;AAC1D,MAAI,KAAK,UAAU,MAAM,MAAO,QAAO,KAAK,QAAQ,MAAM;AAC1D,SAAO,KAAK,QAAQ,MAAM;AAC5B;AAGO,SAAS,aAAa,SAA0B;AACrD,SAAO,wBAAwB,KAAK,QAAQ,KAAK,CAAC;AACpD;AAMO,SAAS,sBAAsB,MAAc,OAAuB;AACzE,QAAM,IAAI,uBAAuB,IAAI;AACrC,QAAM,IAAI,uBAAuB,KAAK;AACtC,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC;AAC7C,SAAO,gBAAgB,GAAG,CAAC,KAAK,OAAO,aAAa,KAAK,CAAC,IAAI,OAAO,aAAa,IAAI,CAAC;AACzF;AAOO,SAAS,qBAAqB,SAAiB,OAAwB;AAC5E,SAAO,MAAM,MAAM,IAAI,EAAE,KAAK,CAAC,gBAAgB;AAC7C,UAAM,cAAc,CAAC,GAAG,YAAY,SAAS,6DAA6D,CAAC;AAC3G,QAAI,YAAY,WAAW,EAAG,QAAO;AACrC,WAAO,YAAY,MAAM,CAAC,CAAC,EAAE,WAAW,KAAK,KAAK,MAAM;AACtD,YAAM,QAAQ,sBAAsB,SAAS,KAAK;AAClD,UAAI,aAAa,KAAM,QAAO,SAAS;AACvC,UAAI,aAAa,KAAM,QAAO,SAAS;AACvC,UAAI,aAAa,IAAK,QAAO,QAAQ;AACrC,UAAI,aAAa,IAAK,QAAO,QAAQ;AACrC,aAAO,UAAU;AAAA,IACnB,CAAC;AAAA,EACH,CAAC;AACH;AAMO,SAAS,eAAe,MAAc,IAAqB;AAChE,QAAM,IAAI,uBAAuB,IAAI;AACrC,QAAM,IAAI,uBAAuB,EAAE;AACnC,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,MAAI,EAAE,UAAU,EAAE,MAAO,QAAO;AAChC,MAAI,EAAE,QAAQ,EAAG,QAAO;AACxB,MAAI,EAAE,UAAU,EAAE,MAAO,QAAO;AAChC,SAAO,EAAE,UAAU,KAAK,EAAE,UAAU,EAAE;AACxC;;;ACxEA,IAAM,cAAc;AAGpB,eAAsB,qBAAqB,UAAkB,KAAqC;AAChG,QAAM,SAAS,MAAM,IAAI,CAAC,QAAQ,GAAG,GAAG,eAAe,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC;AAC1F,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI;AACF,UAAM,MAAM,KAAK,MAAM,MAAM;AAI7B,WAAO,IAAI,kBAAkB,WAAW,KAAK,IAAI,eAAe,WAAW,KAAK;AAAA,EAClF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,mBAAmB,SAAiB,OAA8B;AAChF,MAAI,iBAAiB,KAAK,KAAK,EAAG,QAAO;AACzC,QAAM,WAAW,uBAAuB,KAAK;AAC7C,QAAM,UAAU,uBAAuB,OAAO;AAC9C,MAAI,CAAC,YAAY,CAAC,WAAW,gBAAgB,SAAS,QAAQ,KAAK,EAAG,QAAO;AAC7E,SAAO;AAAA,IACL,kBAAkB,WAAW,IAAI,KAAK,aAAa,OAAO;AAAA,IAC1D,oDAAoD,WAAW,IAAI,KAAK;AAAA,EAC1E,EAAE,KAAK,IAAI;AACb;;;ACpCA,SAAS,MAAoC,WAAAC,UAA0B,cAAAC,mBAAkB;AAezF,IAAM,YAAY,CAAC,UAAU,SAAS;AAGtC,SAAS,kBAAkB,MAAwB,YAAwB,QAAQ,GAAqB;AACtG,MAAI,CAAC,QAAQ,QAAQ,EAAG,QAAO;AAC/B,MAAI,KAAK,0BAA0B,IAAI,KAAK,KAAK,eAAe,IAAI,KAAK,KAAK,sBAAsB,IAAI,GAAG;AACzG,WAAO,kBAAkB,KAAK,cAAc,GAAG,YAAY,QAAQ,CAAC;AAAA,EACtE;AACA,MAAI,KAAK,aAAa,IAAI,GAAG;AAC3B,WAAO;AAAA,MACL,WAAW,uBAAuB,KAAK,QAAQ,CAAC,GAAG,eAAe;AAAA,MAClE;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,iBAAiB,YAA6D;AACrF,aAAW,QAAQ,WAAW,qBAAqBC,YAAW,cAAc,GAAG;AAC7E,QAAI,KAAK,cAAc,EAAE,QAAQ,MAAM,eAAgB;AACvD,UAAM,MAAM,kBAAkB,KAAK,aAAa,EAAE,CAAC,GAAG,UAAU;AAChE,QAAI,KAAK,0BAA0B,GAAG,EAAG,QAAO;AAAA,EAClD;AACA,QAAM,WAAW,WAAW,oBAAoB,CAAC,eAAe,CAAC,WAAW,eAAe,CAAC;AAC5F,QAAM,QAAQ,kBAAkB,UAAU,cAAc,GAAG,UAAU;AACrE,SAAO,KAAK,0BAA0B,KAAK,IAAI,QAAQ;AACzD;AAMA,SAAS,aAAa,QAAiC,MAAc,YAAiD;AACpH,aAAW,YAAY,OAAO,cAAc,GAAG;AAC7C,QAAI,KAAK,qBAAqB,QAAQ,GAAG;AACvC,UAAI,SAAS,QAAQ,EAAE,QAAQ,kBAAkB,EAAE,MAAM,KAAM;AAC/D,aAAO,kBAAkB,SAAS,eAAe,GAAG,UAAU,KAAK;AAAA,IACrE;AACA,QAAI,KAAK,8BAA8B,QAAQ,KAAK,SAAS,QAAQ,MAAM,MAAM;AAC/E,aAAO,kBAAkB,SAAS,YAAY,GAAG,UAAU,KAAK;AAAA,IAClE;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,kBAAkB,MAA6B;AACtD,MAAI,CAAC,KAAK,yBAAyB,IAAI,EAAG,QAAO;AACjD,QAAM,UAAoB,CAAC;AAC3B,aAAW,WAAW,KAAK,YAAY,GAAG;AACxC,QAAI,KAAK,gBAAgB,OAAO,KAAK,KAAK,gCAAgC,OAAO,GAAG;AAClF,cAAQ,KAAK,QAAQ,gBAAgB,CAAC;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,oBAAoB,QAAiC,YAAyC;AACrG,QAAM,WAAW,aAAa,QAAQ,YAAY,UAAU;AAC5D,MAAI,aAAa,OAAW,QAAO,CAAC,GAAG,yBAAyB;AAChE,MAAI,CAAC,YAAY,CAAC,KAAK,0BAA0B,QAAQ,EAAG,QAAO;AACnE,QAAM,OAAO,aAAa,UAAU,mBAAmB,UAAU;AACjE,MAAI,SAAS,OAAW,QAAO,CAAC,GAAG,yBAAyB;AAC5D,SAAO,OAAO,kBAAkB,IAAI,IAAI;AAC1C;AAOO,SAAS,mBAAmB,QAAsC;AACvE,MAAI;AACF,UAAM,UAAU,IAAIC,SAAQ,EAAE,uBAAuB,MAAM,qBAAqB,KAAK,CAAC;AACtF,UAAM,aAAa,QAAQ,iBAAiB,mBAAmB,MAAM;AACrE,UAAM,SAAS,iBAAiB,UAAU;AAC1C,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,QAAuB;AAAA,MAC3B,QAAQ,CAAC;AAAA,MACT,SAAS,CAAC;AAAA,MACV,iBAAiB,oBAAoB,QAAQ,UAAU;AAAA,IACzD;AACA,UAAM,YAAY,aAAa,QAAQ,aAAa,UAAU;AAC9D,QAAI,cAAc,OAAW,QAAO;AACpC,QAAI,CAAC,aAAa,CAAC,KAAK,0BAA0B,SAAS,EAAG,QAAO;AAErE,eAAW,OAAO,WAAW;AAC3B,YAAM,OAAO,aAAa,WAAW,KAAK,UAAU;AACpD,UAAI,SAAS,OAAW;AACxB,YAAM,UAAU,OAAO,kBAAkB,IAAI,IAAI;AACjD,UAAI,CAAC,QAAS,QAAO;AACrB,YAAM,GAAG,IAAI;AAAA,IACf;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWO,SAAS,kBACd,MACA,UACA,MAC6E;AAC7E,QAAM,OAAO,CAAC,QAAyD;AACrE,UAAM,UAAU,IAAI,IAAI,KAAK,GAAG,EAAE,IAAI,cAAc,EAAE,OAAO,OAAO,CAAC;AACrE,UAAM,cAAc,IAAI,IAAI,SAAS,GAAG,EAAE,IAAI,cAAc,EAAE,OAAO,OAAO,CAAC;AAC7E,UAAM,cAAc,KAAK,GAAG,EAAE,IAAI,cAAc,EAAE,OAAO,OAAO;AAChE,WAAO;AAAA,MACL,OAAO,CAAC,GAAG,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,QAAQ,IAAI,KAAK,KAAK,CAAC,iBAAiB,OAAO,WAAW,CAAC;AAAA,MACtG,SAAS,CAAC,GAAG,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,YAAY,IAAI,KAAK,KAAK,YAAY,SAAS,KAAK,CAAC;AAAA,IAChG;AAAA,EACF;AACA,QAAM,WAAW,MAA2B;AAC1C,UAAM,CAAC,UAAU,cAAc,QAAQ,IAAI,CAAC,KAAK,iBAAiB,SAAS,iBAAiB,KAAK,eAAe;AAChH,QAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,SAAU,QAAO,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,EAAE;AAC7E,WAAO;AAAA,MACL,OAAO,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,SAAS,GAAG,KAAK,CAAC,SAAS,SAAS,GAAG,CAAC;AAAA,MACpG,SAAS,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,SAAS,GAAG,KAAK,SAAS,SAAS,GAAG,CAAC;AAAA,IACvG;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,KAAK,QAAQ,GAAG,SAAS,KAAK,SAAS,GAAG,iBAAiB,SAAS,EAAE;AACzF;AAQA,eAAsB,yBACpB,UACA,cACA,aACA,YAC8C;AAE9C,QAAM,CAAC,YAAY,cAAc,IAAI,MAAM,QAAQ;AAAA,IACjD,CAAC,cAAc,WAAW,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,WAAW,EAAE,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC,CAAC;AAAA,EACnH;AACA,MAAI,eAAe,eAAgB,QAAO;AAE1C,QAAM,OAAO,aAAa,mBAAmB,UAAU,IAAI;AAC3D,MAAI,CAAC,KAAM,QAAO,EAAE,MAAM,cAAc,MAAM,OAAO;AACrD,QAAM,WAAW,iBAAiB,mBAAmB,cAAc,IAAI;AACvE,MAAI,CAAC,SAAU,QAAO,EAAE,MAAM,cAAc,MAAM,WAAW;AAE7D,QAAM,OAAsB;AAAA,IAC1B,QAAQ,WAAW,WAAW,UAAU,CAAC;AAAA,IACzC,SAAS,WAAW,WAAW,WAAW,CAAC;AAAA,IAC3C,iBAAiB,WAAW,SAAS,mBAAmB;AAAA,EAC1D;AACA,QAAM,UAAU,kBAAkB,MAAM,UAAU,IAAI;AACtD,QAAMC,SAAQ,OAAO,OAAO,OAAO,EAAE,OAAO,CAAC,GAAG,SAAS,IAAI,KAAK,MAAM,SAAS,KAAK,QAAQ,QAAQ,CAAC;AACvG,SAAOA,SAAQ,IAAI,EAAE,MAAM,WAAW,GAAG,QAAQ,IAAI;AACvD;;;AC5KA,SAAS,oBAAoB,UAA2B;AACtD,SAAO,CAAC,cAAc,QAAQ,KAAK,CAAC,gBAAgB,QAAQ;AAC9D;AAKA,eAAsB,YACpB,UACA,UACA,aACA,cACA,YACA,YACyB;AACzB,eAAa,mCAAmC;AAEhD,QAAM,CAAC,YAAY,gBAAgB,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,IACjE,mBAAmB,UAAU,QAAQ;AAAA,IACrC,mBAAmB,UAAU,WAAW;AAAA,IACxC,mBAAmB,UAAU,YAAY;AAAA,EAC3C,CAAC;AAGD,QAAM,kBAAkB,MAAM,eAAe,UAAU,cAAc,WAAW;AAChF,QAAM,cAAc,MAAM,eAAe,UAAU,cAAc,QAAQ;AAGzE,QAAM,kBAAkB,oBAAI,IAAoB;AAChD,aAAW,CAAC,SAAS,MAAM,KAAK,iBAAiB;AAC/C,QAAI,OAAO,WAAW,OAAO,OAAO,SAAS;AAC3C,sBAAgB,IAAI,OAAO,SAAS,OAAO;AAAA,IAC7C;AAAA,EACF;AAEA,QAAM,WAAW,oBAAI,IAAI,CAAC,GAAG,WAAW,KAAK,GAAG,GAAG,eAAe,KAAK,GAAG,GAAG,gBAAgB,KAAK,CAAC,CAAC;AAEpG,QAAM,eAAe,oBAAI,IAAI,CAAC,GAAG,gBAAgB,KAAK,GAAG,GAAG,YAAY,KAAK,GAAG,GAAG,gBAAgB,KAAK,CAAC,CAAC;AAG1G,QAAM,kBAAkB,IAAI,IAAI,eAAe,OAAO,CAAC;AAEvD;AAAA,IACE,aAAa,aAAa,IAAI,mBAAmB,SAAS,OAAO,aAAa,IAAI;AAAA,EACpF;AAEA,QAAM,gBAAgC,CAAC;AACvC,QAAM,kBAAkB,oBAAI,IAAY;AAGxC,QAAM,mBAAmB,oBAAI,IAAY;AACzC,MAAI,YAAY;AAEhB,aAAW,YAAY,UAAU;AAC/B,QAAI,gBAAgB,IAAI,QAAQ,EAAG;AAEnC,UAAM,SAAS,WAAW,IAAI,QAAQ;AACtC,UAAM,aAAa,eAAe,IAAI,QAAQ;AAE9C,UAAM,gBAAgB,WAAW,UAAU,QAAQ;AACnD,UAAM,eAAe,WAAW,SAAS,QAAQ;AAEjD,UAAM,iBAAiB,gBAAgB,IAAI,QAAQ;AACnD,UAAM,mBAAmB,gBAAgB,WAAW,OAAO,eAAe;AAE1E,UAAM,gBAAgB,gBAAgB,IAAI,QAAQ;AAElD,UAAM,OAAO,CAACC,SAAoB,QAA+B,CAAC,MAChE,cAAc,KAAK;AAAA,MACjB,MAAM;AAAA,MACN,QAAAA;AAAA,MACA,WAAW;AAAA,MACX,UAAU;AAAA,MACV,cAAc;AAAA,MACd,kBAAkB;AAAA,MAClB,GAAG;AAAA,IACL,CAAC;AAEH,QAAI,CAAC,aAAa,IAAI,QAAQ,KAAK,UAAU,YAAY;AACvD,WAAK,WAAW;AAChB;AAAA,IACF;AAEA;AACA,QAAI,YAAY,QAAQ,GAAG;AACzB,mBAAa,aAAa,SAAS,IAAI,aAAa,IAAI,mBAAmB;AAAA,IAC7E;AAEA,UAAM,WAAW,WAAW,IAAI,QAAQ,KAAK;AAC7C,UAAM,eAAe,eAAe,IAAI,QAAQ,KAAK;AACrD,UAAM,WAAW,WAAW,IAAI,QAAQ,KAAK;AAE7C,QAAI;AACJ,QAAI;AAEJ,QAAI,oBAAoB,eAAe,SAAS;AAC9C,YAAM,UAAU,eAAe;AAC/B,YAAM,gBAAgB,WAAW,IAAI,OAAO;AAC5C,YAAM,cAAc,WAAW,IAAI,OAAO,KAAK;AAC/C,YAAM,cAAc,WAAW,IAAI,OAAO,KAAK;AAE/C,sBAAgB,IAAI,OAAO;AAE3B,YAAM,kBAAkB,gBAAgB;AAIxC,YAAM,gBAAgB,WAAW,SAAS,OAAO;AAEjD,UAAIC;AACJ,UAAI,gBAAgB,iBAAiB,WAAW,UAAU,OAAO,GAAG;AAElE,iBAAS;AAET,YAAI,mBAAmB,iBAAiB,aAAa;AACnD,UAAAA,mBAAkB;AAClB,2BAAiB,IAAI,QAAQ;AAAA,QAC/B;AAAA,MACF,WAAW,CAAC,eAAe;AAEzB,iBAAS;AAAA,MACX,WAAW,iBAAiB;AAE1B,iBAAS;AACT,sBAAc;AAAA,MAChB,OAAO;AAEL,iBAAS;AACT,sBAAc;AAAA,MAChB;AAIA,YAAMC,gBAAe,iBAAiB,CAAC,mBAAmB,oBAAoB,QAAQ;AAEtF,WAAK,QAAQ,EAAE,kBAAkB,MAAM,aAAa,iBAAAD,kBAAiB,cAAcC,iBAAgB,OAAU,CAAC;AAC9G;AAAA,IACF;AAGA,QAAI,eAAe;AACjB,sBAAgB,IAAI,QAAQ;AAC5B;AAAA,IACF;AAEA,QAAI,eAAe;AACjB,eAAS;AAAA,IACX,WAAW,CAAC,UAAU,YAAY;AAIhC,YAAM,iBAAiB,aAAa,QAAQ,iBAAiB;AAC7D,eAAS,gBAAgB,iBAAiB,YAAY;AAAA,IACxD,WAAW,UAAU,CAAC,YAAY;AAChC,UAAI,aAAa,MAAM;AAErB,iBAAS,eAAe,UAAU;AAAA,MACpC,OAAO;AAKL,iBAAS,YAAY,gBAAgB,IAAI,QAAQ,IAAI,WAAW;AAAA,MAClE;AAAA,IACF,WAAW,aAAa,cAAc;AACpC,eAAS;AAAA,IACX,OAAO;AACL,YAAM,cAAc,aAAa;AACjC,YAAMD,mBAAkB,iBAAiB;AAEzC,UAAI,eAAeA,kBAAiB;AAClC,iBAAS,eAAe,WAAW;AAAA,MACrC,WAAW,eAAe,CAACA,kBAAiB;AAC1C,iBAAS,eAAe,UAAU;AAAA,MACpC,OAAO;AACL,iBAAS;AAAA,MACX;AAAA,IACF;AAOA,UAAM,mBACH,gBAAgB,kBAAkB,cAAc,iBAAiB,YAAY,aAAa;AAK7F,UAAM,eACJ,iBAAiB,oBAAoB,QAAQ,KAAK,iBAAiB,YAAY,aAAa;AAE9F,SAAK,QAAQ,EAAE,iBAAiB,mBAAmB,QAAW,cAAc,gBAAgB,OAAU,CAAC;AAAA,EACzG;AAGA,QAAM,UAAU,cAAc,OAAO,CAAC,SAAS,KAAK,mBAAmB,CAAC,iBAAiB,IAAI,KAAK,IAAI,CAAC;AACvG,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,IACjC;AACA,eAAW,QAAQ,SAAS;AAC1B,YAAM,QAAQ,KAAK,IAAI,KAAK,IAAI;AAChC,UAAI,SAAS,MAAM,cAAc,QAAQ,MAAM,cAAc,MAAM;AACjE,aAAK,uBAAuB,MAAM,YAAY,MAAM;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAKA,QAAM,QAAQ,cAAc;AAAA,IAC1B,CAAC,SACC,KAAK,WAAW,WAChB,KAAK,YACL,CAAC,KAAK,aACN,KAAK,gBACL,KAAK,oBACL,WAAW,IAAI,KAAK,IAAI,MAAM,eAAe,IAAI,KAAK,IAAI;AAAA,EAC9D;AACA,MAAI,MAAM,SAAS,GAAG;AAEpB,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,IAC/B;AACA,eAAW,QAAQ,OAAO;AACxB,YAAM,YAAY,KAAK,IAAI,KAAK,IAAI,GAAG;AACvC,UAAI,cAAc,QAAQ,cAAc,OAAW,MAAK,sBAAsB;AAAA,IAChF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,eAAsB,iBACpB,UACA,OACA,cACA,UACA,aACe;AACf,QAAM,WAAW,MAAM,kBAAkB,UAAU,cAAc,QAAQ;AACzE,QAAM,eAAe,MAAM,kBAAkB,UAAU,cAAc,WAAW;AAChF,QAAM,aAAa,CAAC,MAAoB,SAAqC;AAC3E,QAAI,CAAC,KAAM;AACX,SAAK,YAAY,KAAK;AACtB,SAAK,YAAY,KAAK;AACtB,SAAK,gBAAgB,KAAK;AAAA,EAC5B;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,WAAW,YAAa;AAEjC,QAAI,KAAK,WAAW,WAAW,KAAK,WAAW,WAAW;AACxD,iBAAW,MAAM,SAAS,IAAI,KAAK,IAAI,CAAC;AAAA,IAC1C,WAAW,KAAK,WAAW,UAAU;AACnC,iBAAW,MAAM,aAAa,IAAI,KAAK,IAAI,CAAC;AAAA,IAC9C,WAAW,KAAK,WAAW,cAAc,KAAK,WAAW,YAAY,KAAK,iBAAiB;AAEzF,iBAAW,MAAM,SAAS,IAAI,KAAK,IAAI,CAAC;AACxC,YAAM,OAAO,aAAa,IAAI,KAAK,IAAI;AACvC,UAAI,MAAM;AACR,aAAK,oBAAoB,KAAK;AAC9B,aAAK,oBAAoB,KAAK;AAC9B,aAAK,iBAAiB,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AACF;;;AJrNO,IAAM,uBAAN,cAAmC,MAAM;AAAC;AAM1C,IAAM,6BAAN,cAAyC,MAAM;AAAA,EAC3C;AAAA,EAET,YAAY,QAAiC;AAC3C;AAAA,MACE;AAAA,QACE;AAAA,QACA,kDAAkD,WAAW;AAAA,QAC7D;AAAA,MACF,EAAE,KAAK,IAAI;AAAA,IACb;AACA,SAAK,SAAS;AAAA,EAChB;AACF;AAGO,SAAS,iBAAiB,WAAkC;AACjE,QAAM,QAAQ,UAAU,MAAM,6CAA6C;AAC3E,SAAO,QAAQ,sBAAsB,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK;AAChE;AAGA,SAAS,gBAAgB,MAA6B;AACpD,SAAO,KAAK,aAAa,KAAK;AAChC;AAGA,SAAS,eAAe,QAA0C;AAChE,SAAO;AAAA,IACL,WAAW,CAAC,SAAS,UAAU,MAAM,MAAM;AAAA,IAC3C,UAAU,CAAC,SAAU,OAAO,WAAW,cAAc,IAAI,IAAI,SAAS,MAAM,MAAM;AAAA,EACpF;AACF;AAOA,eAAe,iBACb,UACA,aACA,cACA,QACA,YAMC;AACD,eAAa,oBAAoB;AACjC,QAAM,gBAAgB,MAAM;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,MAAM;AAAA,IACrB;AAAA,EACF;AAIA,QAAM,oBAA8B,CAAC;AACrC,QAAM,mBAA6B,CAAC;AACpC,aAAW,QAAQ,eAAe;AAChC,QAAI,KAAK,WAAW,eAAe,KAAK,WAAW,QAAS;AAC5D,QAAI,KAAK,aAAc,KAAK,YAAY,CAAC,KAAK,aAAc;AAC1D,OAAC,KAAK,eAAe,oBAAoB,kBAAkB,KAAK,KAAK,IAAI;AAAA,IAC3E;AAAA,EACF;AAKA,eAAa,2BAA2B;AACxC,QAAM,2BAA2B,UAAU,QAAQ,cAAc,MAAM,MAAM,UAAU,WAAW,CAAC;AAEnG,MAAI,kBAAkB,SAAS,GAAG;AAChC,iBAAa,mBAAmB,kBAAkB,MAAM,0BAA0B;AAClF,UAAM,gBAAgB,UAAU,QAAQ,iBAAiB;AAAA,EAC3D;AACA,MAAI,iBAAiB,SAAS,GAAG;AAC/B,iBAAa,kBAAkB,iBAAiB,MAAM,mBAAmB;AACzE,UAAM,MAAM,UAAU,gBAAgB;AACtC,eAAW,YAAY,kBAAkB;AACvC,YAAM,uBAAuB,UAAU,QAAQ;AAAA,IACjD;AAAA,EACF;AAGA,aAAW,QAAQ,eAAe;AAChC,UAAM,EAAE,MAAM,UAAU,QAAQ,aAAa,IAAI;AACjD,QAAI,WAAW,eAAe,WAAW,WAAW,gBAAgB,IAAI,EAAG;AAE3E,QAAI,WAAW,YAAY;AAEzB,mBAAa,UAAK,QAAQ,qCAAqC;AAC/D;AAAA,IACF;AAEA,QAAI,WAAW,UAAU;AACvB,UAAI,CAAC,cAAc;AACjB,qBAAa,UAAK,QAAQ,mCAAmC;AAC7D,cAAM,gBAAgB,UAAU,aAAa,CAAC,QAAQ,CAAC;AAAA,MACzD,WAAW,CAAC,KAAK,kBAAkB;AAEjC,qBAAa,UAAK,QAAQ,kCAAkC;AAC5D,cAAM,gBAAgB,UAAU,QAAQ;AAAA,MAC1C,OAAO;AAGL,qBAAa,UAAK,QAAQ,+BAA+B;AACzD,cAAM,gBAAgB,UAAU,aAAa,CAAC,QAAQ,CAAC;AAAA,MACzD;AACA;AAAA,IACF;AAEA,QAAI,WAAW,WAAW;AACxB,YAAM,gBAAgB,UAAU,QAAQ;AACxC;AAAA,IACF;AAEA,QAAI,WAAW,aAAa,KAAK,aAAa;AAE5C,YAAM,UAAU,KAAK;AACrB,YAAM,gBAAgB,MAAM,qBAAqB,UAAU,OAAO;AAClE,YAAM,gBAAgB,MAAM,qBAAqB,UAAU,QAAQ;AAEnE,UAAI,iBAAiB,CAAC,eAAe;AACnC,qBAAa,UAAK,OAAO,WAAM,QAAQ,gCAAgC;AACvE,YAAI;AACF,gBAAM,MAAM,UAAU,SAAS,QAAQ;AAAA,QACzC,QAAQ;AAEN,gBAAM,gBAAgB,UAAU,OAAO;AACvC,gBAAM,gBAAgB,UAAU,aAAa,CAAC,QAAQ,CAAC;AAAA,QACzD;AAAA,MACF,WAAW,iBAAiB,eAAe;AAEzC,qBAAa,UAAK,OAAO,WAAM,QAAQ,oCAAoC;AAC3E,cAAM,gBAAgB,UAAU,OAAO;AACvC,cAAM,gBAAgB,UAAU,aAAa,CAAC,QAAQ,CAAC;AAAA,MACzD,OAAO;AAEL,qBAAa,UAAK,QAAQ,oCAAoC;AAC9D,cAAM,gBAAgB,UAAU,aAAa,CAAC,QAAQ,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAIA,QAAM,qBAAqB,IAAI,IAAI,cAAc,OAAO,CAAC,SAAS,KAAK,eAAe,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;AAGhH,aAAW,YAAY,MAAM,mBAAmB,QAAQ,GAAG;AACzD,QAAI,CAAC,UAAU,UAAU,MAAM,KAAK,CAAC,eAAe,MAAM,EAAE,SAAS,QAAQ,EAAG;AAEhF,QAAI,MAAM,gBAAgB,UAAU,QAAQ,QAAQ,GAAG;AACrD,mBAAa,UAAK,QAAQ,qCAAqC;AAC/D,YAAM,gBAAgB,UAAU,QAAQ,CAAC,QAAQ,CAAC;AAClD,yBAAmB,IAAI,QAAQ;AAAA,IACjC,OAAO;AACL,mBAAa,UAAK,QAAQ,8CAA8C;AACxE,YAAM,gBAAgB,UAAU,QAAQ;AAAA,IAC1C;AAAA,EACF;AAEA,QAAM,qBAAqB,MAAM,mBAAmB,QAAQ;AAC5D,QAAM,uBAAuB,IAAI,IAAI,kBAAkB;AACvD,QAAM,kBAAkB,cACrB,OAAO,CAAC,SAAS,KAAK,WAAW,cAAc,CAAC,qBAAqB,IAAI,KAAK,IAAI,CAAC,EACnF,IAAI,CAAC,SAAS,KAAK,IAAI;AAI1B,QAAM,iBAAiB,MAAM,kBAAkB,QAAQ;AACvD,QAAM,oBAAoB,eAAe,OAAO,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC;AAC3E,MAAI,kBAAkB,SAAS,GAAG;AAChC,iBAAa,eAAe,kBAAkB,MAAM,kCAAkC;AACtF,UAAM,MAAM,UAAU,mBAAmB,EAAE,QAAQ,KAAK,CAAC;AACzD,eAAW,YAAY,mBAAmB;AACxC,YAAM,uBAAuB,UAAU,QAAQ;AAAA,IACjD;AAAA,EACF;AAEA,SAAO,EAAE,oBAAoB,eAAe,iBAAiB,oBAAoB,CAAC,GAAG,kBAAkB,EAAE;AAC3G;AAEA,SAAS,iBAAiB,OAAwC;AAChE,QAAM,UAA2B;AAAA,IAC/B,SAAS;AAAA,IACT,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,WAAW,eAAe,cAAc,KAAK,IAAI,GAAG;AAC3D,cAAQ;AACR;AAAA,IACF;AAEA,YAAQ,KAAK,MAAM;AAAA,EACrB;AAEA,SAAO;AACT;AAkBA,SAAS,0BACP,UACA,QACA,SACA,aACA,UACQ;AACR,QAAM,WAAW,SAAS,WACtB,cAAc,SAAS,QAAQ,KAAK,SAAS,KAAK,WAAW,SAAS,MAAM,aAC5E;AACJ,QAAM,cACJ,gBAAgB,IACZ,yBACA,KAAK,WAAW,sBAAsB,gBAAgB,IAAI,KAAK,GAAG;AAExE,SAAO,CAAC,GAAG,QAAQ,IAAI,KAAK,MAAM,MAAM,OAAO,GAAG,QAAQ,IAAI,WAAW,EAAE,KAAK,IAAI;AACtF;AASA,eAAe,iBACb,UACA,QACA,YACA,WACA,KAC+C;AAC/C,QAAM,WAAW,MAAM,sBAAsB,UAAU,YAAY,GAAG;AACtE,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR,UAAU,GAAG,mFACR,OAAO,SAAS,WAAW;AAAA,IAClC;AAAA,EACF;AACA,MAAI,CAAE,MAAM,oBAAoB,UAAU,YAAY,WAAW,SAAS,GAAG,GAAI;AAC/E,UAAM,IAAI;AAAA,MACR,UAAU,GAAG,MAAM,SAAS,IAAI,MAAM,GAAG,CAAC,CAAC,eAAe,SAAS;AAAA,IAErE;AAAA,EACF;AACA,SAAO,SAAS,UAAU,EAAE,KAAK,SAAS,QAAQ,KAAK,YAAY,SAAS,QAAQ,IAAI,IAAI,EAAE,KAAK,SAAS,IAAI;AAClH;AAOA,eAAe,gBACb,QACA,YACA,QAC0B;AAC1B,QAAM,EAAE,SAAS,IAAI;AAErB,eAAa,4BAA4B;AACzC,QAAM,CAAC,QAAQ,SAAS,aAAa,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,IACvE,iBAAiB,QAAQ;AAAA,IACzB,YAAY,UAAU,MAAM;AAAA,IAC5B,0BAA0B,QAAQ;AAAA,IAClC,kBAAkB,QAAQ;AAAA,EAC5B,CAAC;AACD,WAAS,kBAAkB,0BAA0B,UAAU,QAAQ,SAAS,aAAa,cAAc,CAAC;AAE5G,eAAa,+BAA+B;AAC5C,QAAM,EAAE,OAAO,aAAa,UAAU,IAAI,gBAAgB,OAAO,QAAQ;AACzE,QAAM,aAAa;AAEnB,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,aAAa,UAAU,YAAY,OAAO,SAAS,WAAW;AAEpE,eAAa,sBAAsB,UAAU,MAAM;AACnD,QAAM,YAAY,UAAU,UAAU;AAKtC,MAAI,cAAc;AAClB,MAAI;AACJ,MAAI,OAAO,KAAK;AACd,UAAM,kBAAkB,UAAU,UAAU;AAC5C,UAAM,SAAS,MAAM,iBAAiB,UAAU,QAAQ,YAAY,WAAW,OAAO,GAAG;AACzF,kBAAc,OAAO;AACrB,iBAAa,OAAO;AAAA,EACtB,WAAW,UAAU,WAAW;AAC9B,UAAM,kBAAkB,UAAU,UAAU;AAC5C,UAAM,SAAS,MAAM,wBAAwB,UAAU,UAAU;AACjE,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,sCAAsC,UAAU,4CAA4C,SAAS,mBAClF,OAAO,SAAS,WAAW;AAAA,MAChD;AAAA,IACF;AACA,kBAAc,OAAO;AACrB,iBAAa,OAAO;AAAA,EACtB;AACA,QAAM,gBAAgB,eAAe,OAAO,MAAM,SAAS,OAAO,GAAG,KAAK;AAI1E,SAAO,cAAc;AACrB,WAAS,qBAAqB,GAAG,aAAa,WAAM,OAAO,SAAS,WAAW,EAAE;AAGjF,QAAM,WAAW,MAAM,qBAAqB,UAAU,WAAW;AACjE,QAAM,cAAc,WAAW,mBAAmB,SAAS,QAAQ,IAAI;AACvE,MAAI,YAAa,OAAM,IAAI,MAAM,WAAW;AAK5C,eAAa,uBAAuB;AACpC,QAAM,eAAe,UAAU,QAAQ,WAAW;AAElD,QAAM,oBAAoB,iBAAiB,OAAO,SAAS,WAAW,KAAK;AAG3E,QAAM,aAAa,MAAM,sBAAsB,UAAU,QAAQ,WAAW,GAAG;AAC/E,QAAM,WAAW,OAAO,WAAW,MAAM,aAAa,UAAU,QAAQ,WAAW,IAAI;AAEvF,QAAM,iBAAiB,MAAM,cAAc,UAAU,WAAW;AAIhE,MAAI,eAAe,SAAS,aAAc,MAAM,WAAW,UAAU,eAAe,MAAM,SAAS,GAAI;AACrG,UAAM,CAAC,eAAe,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,MACnD,YAAY,UAAU,eAAe,IAAI;AAAA,MACzC,YAAY,UAAU,SAAS;AAAA,IACjC,CAAC;AACD,UAAM,OAAO,OAAO,MAChB,wBACA,aACE,wCAAwC,SAAS,0DACjD,0BAA0B,SAAS,gBAAgB,SAAS;AAClE,UAAM,IAAI;AAAA,MACR,YAAY,aAAa,KAAK,aAAa,mCAAmC,SAAS;AAAA,EACd,IAAI;AAAA,IAC/E;AAAA,EACF;AACA,QAAM,cAAc,MAAM,oBAAoB,UAAU,WAAW,WAAW;AAC9E,QAAM,kBACJ,cAAc,IAAI,MAAM,mBAAmB,UAAU,WAAW,aAAa,eAAe,IAAI,CAAC;AAEnG,WAAS,oBAAoB,4BAA4B,aAAa,iBAAiB,iBAAiB,CAAC;AAEzG,SAAO,EAAE,aAAa,YAAY,WAAW,UAAU,mBAAmB,eAAe;AAC3F;AASA,eAAe,yBAAyB,QAAuB,KAAqC;AAClG,MAAI,OAAO,WAAY;AACvB,QAAM,SAAS,MAAM,yBAAyB,OAAO,UAAU,IAAI,WAAW,IAAI,aAAa,MAAM,EAAE;AAAA,IACrG,MAAM;AAAA,EACR;AACA,MAAI,QAAQ,SAAS,UAAW,OAAM,IAAI,2BAA2B,MAAM;AAC7E;AAGA,SAAS,WAAW,QAAuB,KAAsB;AAC/D,SAAO;AAAA,IACL,gBAAgB,OAAO,SAAS,kBAAkB;AAAA,IAClD,aAAa,IAAI;AAAA,IACjB,aAAa,IAAI;AAAA,IACjB,mBAAmB,IAAI;AAAA,IACvB,gBAAgB,IAAI;AAAA,EACtB;AACF;AASA,eAAe,oBACb,QACA,KACA,OACA,oBAGA;AACA,QAAM,EAAE,SAAS,IAAI;AACrB,MAAI;AACF,UAAM,CAAC,SAAS,aAAa,iBAAiB,IAAI,MAAM,QAAQ,IAAI;AAAA,MAClE,YAAY,UAAU,IAAI,SAAS;AAAA;AAAA,MAEnC,YAAY,UAAU,IAAI,eAAe,IAAI;AAAA,MAC7C,yBAAyB,UAAU,IAAI,WAAW,IAAI,aAAa,MAAM;AAAA,IAC3E,CAAC;AACD,WAAO;AAAA,MACL,mBAAmB,GAAG,OAAO,KAAK,WAAW;AAAA,MAC7C;AAAA,MACA,wBAAwB,4BAA4B,OAAO,OAAO,WAAW,WAAW,CAAC,CAAC;AAAA,MAC1F,0BAA0B,8BAA8B,oBAAoB,MAAM;AAAA,IACpF;AAAA,EACF,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAcA,eAAe,iBAAiB,QAAuB,KAAyD;AAC9G,QAAM,EAAE,SAAS,IAAI;AACrB,MAAI;AACF,UAAM,CAAC,OAAO,SAAS,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,MAClD,YAAY,UAAU,IAAI,WAAW;AAAA,MACrC,eAAe,UAAU,IAAI,WAAW,IAAI,WAAW;AAAA,MACvD,YAAY,QAAQ;AAAA,IACtB,CAAC;AACD,WAAO,EAAE,OAAO,MAAM,QAAQ,SAAS,SAAS,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,EAAE;AAAA,EACzF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,YAAY,OAAsE;AACzF,SAAO,QAAQ,EAAE,gBAAgB,EAAE,OAAO,MAAM,OAAO,SAAS,MAAM,SAAS,MAAM,MAAM,QAAQ,OAAO,EAAE,IAAI,CAAC;AACnH;AAMA,eAAe,uBAAuB,UAAkB,QAAsC;AAC5F,MAAI,CAACE,YAAWC,MAAK,UAAU,SAAS,CAAC,EAAG;AAC5C,QAAM,IAAI,CAAC,MAAM,MAAM,MAAM,oBAAoB,MAAM,SAAS,GAAG,QAAQ;AAC3E,QAAMC,IAAGD,MAAK,UAAU,SAAS,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACpE,WAAS,mBAAmB,WAAW,SAAS,2DAA2D;AAC7G;AAMA,eAAe,aACb,QACA,KACA,YACA,QACsB;AACtB,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,EAAE,aAAa,YAAY,UAAU,mBAAmB,eAAe,IAAI;AAGjF,QAAM,yBAAyB,QAAQ,GAAG;AAE1C,QAAM,QAAQ,MAAM,iBAAiB,QAAQ,GAAG;AAEhD,QAAM,EAAE,oBAAoB,eAAe,iBAAiB,mBAAmB,IAAI,MAAM;AAAA,IACvF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,UAAU,iBAAiB,aAAa;AAC9C,QAAM,SAAS,cAAc,OAAO,CAAC,SAAS,CAAC,UAAU,YAAY,SAAS,EAAE,SAAS,KAAK,MAAM,CAAC,EAAE;AAEvG,QAAM,gBAAgB,cAAc,OAAO,CAAC,SAAS,sBAAsB,SAAS,KAAK,MAAM,CAAC,EAAE;AAIlG,QAAM,eAA6B;AAAA,IACjC,UAAU;AAAA,MACR,MAAM,oBAAoB,kBAAkB,QAAQ,uBAAuB,EAAE,IAAI;AAAA,MACjF,OAAO,aAAa,YAAY;AAAA,MAChC,QAAQ,eAAe;AAAA,MACvB,SAAS,cAAc;AAAA,MACvB,KAAK,oBACD,aACE,GAAG,iBAAiB,iBAAiB,UAAU,KAC/C,GAAG,iBAAiB,WAAW,eAAe,IAAI,KACpD;AAAA,MACJ,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,IACnC;AAAA,EACF;AACA,QAAM,kBAAkB,YAAY;AAClC,UAAM,iBAAiB,UAAU,eAAe,IAAI;AACpD,UAAM,kBAAkB,UAAU,YAAY;AAC9C,UAAM,UAAU,UAAU,aAAa;AAEvC,QAAI,OAAO;AACT,YAAM,aAAa,UAAU,MAAM,OAAO;AAC1C,YAAM,UAAU,UAAU,YAAY;AAAA,IACxC;AACA,UAAM,uBAAuB,UAAU,MAAM;AAAA,EAC/C;AAIA,MAAI,mBAAmB,SAAS,GAAG;AACjC,UAAM,gBAAgB;AACtB;AAAA,MACE;AAAA,MACA,4BAA4B,mBAAmB,QAAQ,iBAAiB,EAAE,SAAS,GAAG,GAAG;AAAA,IAC3F;AAAA,EACF,WAAW,gBAAgB,GAAG;AAC5B,UAAM,QAAQ,SAAS,IAAI,GAAG,MAAM,yBAAyB;AAC7D,UAAM,gBAAgB;AACtB,aAAS,UAAU,GAAG,KAAK,6BAA6B;AAAA,EAC1D,OAAO;AAEL,UAAM,WAAW,QAAQ;AACzB,aAAS,cAAc,6BAA6B;AAAA,EACtD;AAEA,SAAO;AAAA,IACL,SAAS,mBAAmB,WAAW;AAAA,IACvC,OAAO;AAAA,IACP;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,GAAG,WAAW,QAAQ,GAAG;AAAA,IACzB,GAAI,MAAM,oBAAoB,QAAQ,KAAK,eAAe,kBAAkB;AAAA,IAC5E,GAAG,YAAY,KAAK;AAAA,EACtB;AACF;AAGA,eAAe,kBACb,QACA,KACA,YACA,QACsB;AACtB,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,QAAQ,MAAM,iBAAiB,QAAQ,GAAG;AAEhD,eAAa,oBAAoB;AACjC,QAAM,gBAAgB,MAAM;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,eAAe,MAAM;AAAA,IACrB;AAAA,EACF;AACA,QAAM,iBAAiB,UAAU,eAAe,IAAI,WAAW,QAAQ,IAAI,WAAW;AACtF,QAAM,qBAAqB,cAAc,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAC3F,QAAM,UAAU,MAAM,oBAAoB,QAAQ,KAAK,eAAe,kBAAkB;AACxF,WAAS,qBAAqB,GAAG,cAAc,MAAM,8CAA8C;AAEnG,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS,iBAAiB,aAAa;AAAA;AAAA,IAEvC,WAAW,cAAc,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IACjF;AAAA,IACA,GAAG,WAAW,QAAQ,GAAG;AAAA,IACzB,GAAG;AAAA,IACH,GAAG,YAAY,KAAK;AAAA,EACtB;AACF;AAOA,eAAsB,qBAAqB,QAAuB,OAAsC;AACtG,QAAM,aAA+B,CAAC,YAAY,YAAY,OAAO;AACrE,QAAM,SAAuB,CAAC,OAAO,WAAW;AAC9C,mBAAe,OAAO,MAAM;AAC5B,kBAAc,KAAK;AAAA,EACrB;AACA,QAAM,MAAM,MAAM,gBAAgB,QAAQ,YAAY,MAAM;AAC5D,SAAO,QAAQ,aAAa,QAAQ,KAAK,YAAY,MAAM,IAAI,kBAAkB,QAAQ,KAAK,YAAY,MAAM;AAClH;;;AKrsBA,SAAS,cAAc,iBAAiB;AACxC,SAAS,SAAAE,QAAO,aAAAC,kBAAiB;AACjC,SAAS,WAAAC,UAAS,QAAAC,aAAY;AA8B9B,IAAM,cAAc;AAGpB,IAAM,oBAAoB;AAG1B,eAAe,qBAAqB,QAAuB,KAA4B;AACrF,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,UAAU,YAAY,CAAC,CAAE,MAAM,SAAS,UAAU,GAAG,GAAG,WAAW;AACzE,MAAI,MAAM,QAAQ,EAAG;AACrB,QAAM,aAAa,UAAU,yBAAyB,OAAO,SAAS,WAAW;AACjF,QAAM,YAAY,UAAU,uBAAuB;AACnD,MAAI,CAAE,MAAM,QAAQ;AAClB,UAAM,IAAI,MAAM,mBAAmB,IAAI,MAAM,GAAG,CAAC,CAAC,2BAA2B,uBAAuB,GAAG;AAC3G;AAGA,eAAe,gBAAgB,QAA+C;AAC5E,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,MAAO,MAAM,iBAAiB,QAAQ,KAAO,MAAM,sBAAsB,UAAU,MAAM;AAC/F,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,qBAAqB,QAAQ,GAAG;AACtC,SAAO;AACT;AAGA,eAAe,gBAAgB,QAAwE;AACrG,MAAI;AACF,UAAM,MAAM,MAAM,gBAAgB,MAAM;AACxC,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,CAAC,KAAK,OAAO,IAAI,MAAM,QAAQ,IAAI,CAAC,YAAY,OAAO,UAAU,GAAG,GAAG,YAAY,OAAO,QAAQ,CAAC,CAAC;AAC1G,WAAO,IAAI,SAAS,KAAK,QAAQ,SAAS,IAAI,EAAE,OAAO,IAAI,QAAQ,MAAM,QAAQ,OAAO,IAAI;AAAA,EAC9F,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAsB,wBAAwB,QAAuB,QAAqC;AACxG,QAAM,QAAQ,QAAQ;AACtB,MAAI,OAAO;AACT,QAAI,MAAM,UAAU,EAAG;AACvB,YAAQ,KAAK;AACb,YAAQ;AAAA,MACN,eAAG,IAAI,gBAAgB,MAAM,OAAO,MAAM,MAAM,MAAM,QAAQ,QAAQ,EAAE,QAAQ,OAAO,YAAY,UAAU,CAAC,CAAC;AAAA,IACjH;AACA;AAAA,EACF;AACA,QAAM,SAAS,MAAM,gBAAgB,MAAM;AAC3C,MAAI,CAAC,OAAQ;AACb,UAAQ,KAAK;AACb,UAAQ,KAAK,eAAG,IAAI,gBAAgB,OAAO,OAAO,OAAO,IAAI,CAAC,CAAC;AACjE;AAGA,SAAS,UAAU,OAAe,MAAqB,KAA+B;AACpF,QAAM,OAAO;AAAA,IACX,KAAK,UAAU,YAAY;AAAA,IAC3B,KAAK,eAAe,kBAAkB;AAAA,IACtC,KAAK,kBAAkB,eAAe;AAAA,EACxC,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AACZ,UAAQ,KAAK,GAAG,KAAK,KAAK,KAAK,KAAK,KAAK,eAAG,IAAI,IAAI,IAAI,GAAG,CAAC,EAAE;AAC9D,UAAQ,KAAK,eAAG,IAAI,eAAe,KAAK,EAAE,EAAE,CAAC;AAC7C,MAAI,KAAK,QAAS,SAAQ,KAAK,MAAM,KAAK,OAAO,EAAE;AACnD,UAAQ,KAAK,eAAG,IAAI,yCAAyC,KAAK,EAAE,EAAE,CAAC;AACvE,MAAI,IAAK,SAAQ,KAAK,eAAG,IAAI,eAAe,GAAG,EAAE,CAAC;AAClD,MAAI,KAAK,QAAS,SAAQ,KAAK,eAAG,IAAI,wCAAwC,KAAK,EAAE,EAAE,CAAC;AACxF,UAAQ,KAAK;AACf;AAMA,eAAe,gBACb,QACA,KACA,IACmE;AACnE,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,OAAO,MAAM,SAAS,UAAU,KAAK,EAAE;AAC7C,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,sBAAsB,EAAE,iBAAiB,IAAI,MAAM,GAAG,CAAC,CAAC,EAAE;AAErF,QAAM,SAAS,MAAM,IAAI,CAAC,WAAW,MAAM,eAAe,GAAG,GAAG,IAAI,SAAS,IAAI,EAAE,EAAE,GAAG,QAAQ,GAC7F,MAAM,IAAI,EACV,OAAO,OAAO;AACjB,QAAM,SAASC,MAAK,aAAa,EAAE;AACnC,aAAW,QAAQ,OAAO;AAExB,UAAM,UAAU,aAAa,OAAO,CAAC,QAAQ,GAAG,GAAG,IAAI,SAAS,IAAI,EAAE,IAAI,IAAI,EAAE,GAAG;AAAA,MACjF,KAAK;AAAA,MACL,WAAW;AAAA,IACb,CAAC;AACD,UAAM,OAAOA,MAAK,UAAU,QAAQ,IAAI;AACxC,UAAMC,OAAMC,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,UAAMC,WAAU,MAAM,OAAO;AAAA,EAC/B;AACA,SAAO,EAAE,MAAM,QAAQ,MAAM;AAC/B;AAGA,eAAe,YAAY,QAAuB,KAAa,IAA2B;AACxF,QAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,gBAAgB,QAAQ,KAAK,EAAE;AAErE,UAAQ,KAAK,GAAG,SAAS,cAAc,MAAM,MAAM,eAAe,MAAM,GAAG;AAC3E,UAAQ,KAAK,eAAG,IAAI,kBAAkB,SAAS,IAAI,EAAE,0BAA0B,CAAC;AAChF,MAAI,KAAK,SAAS;AAChB,YAAQ,KAAK,eAAG,IAAI,mBAAmB,MAAM,IAAI,KAAK,OAAO,cAAc,KAAK,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC;AAClG,YAAQ,KAAK,eAAG,IAAI,mFAAmF,EAAE,EAAE,CAAC;AAAA,EAC9G;AACF;AAMA,eAAe,QAAQ,QAAuB,KAAa,IAA2B;AACpF,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,EAAE,MAAM,OAAO,IAAI,MAAM,gBAAgB,QAAQ,KAAK,EAAE;AAC9D,MAAI,CAAC,KAAK,SAAS;AACjB,UAAM,IAAI;AAAA,MACR,mBAAmB,EAAE,+FAA+F,EAAE;AAAA,IACxH;AAAA,EACF;AACA,QAAM,SAASH,MAAK,QAAQ,KAAK,OAAO;AACxC,QAAM,OAAO,OAAO,SAAS,SAAS,OAAO,UAAU,CAAC,aAAa,GAAG,KAAK,KAAK;AAElF,QAAM,iBAAkB,MAAM,iBAAiB,QAAQ,KAAM;AAC7D,QAAM,qBAAqB,QAAQ,cAAc;AACjD,QAAM,YAAY,MAAM,mBAAmB,UAAU,cAAc;AAEnE,UAAQ,KAAK,eAAG,IAAI,yBAAyB,MAAM,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;AACxE,UAAQ,KAAK;AACb,QAAM,QAAQ,UAAU,QAAQ,CAAC,QAAQ,OAAO,QAAQ,GAAG,IAAI,GAAG,EAAE,KAAK,UAAU,OAAO,UAAU,CAAC;AACrG,MAAI,MAAM,MAAO,OAAM,IAAI,MAAM,8BAA8B,MAAM,MAAM,OAAO,EAAE;AAGpF,QAAM,iBAAiB,MAAM,mBAAmB,UAAU,cAAc;AACxE,QAAM,WAAW,CAAC,GAAG,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,eAAe,IAAI,IAAI,CAAC,EAAE,KAAK;AACjF,QAAM,4BAA4B,UAAU,gBAAgB,QAAQ;AAEpE,QAAM,gBAAgB,eAAe,MAAM,GAAG,CAAC;AAC/C,UAAQ,KAAK;AACb,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,KAAK,GAAG,SAAS,aAAa,SAAS,MAAM,wBAAwB,aAAa,EAAE;AAC5F,YAAQ,KAAK,eAAG,IAAI,iFAAiF,CAAC;AACtG,eAAW,QAAQ,SAAS,MAAM,GAAG,iBAAiB,EAAG,SAAQ,KAAK,eAAG,IAAI,OAAO,IAAI,EAAE,CAAC;AAC3F,QAAI,SAAS,SAAS,mBAAmB;AACvC,cAAQ,KAAK,eAAG,IAAI,aAAa,SAAS,SAAS,iBAAiB,OAAO,CAAC;AAAA,IAC9E;AAAA,EACF,OAAO;AACL,YAAQ,KAAK,eAAG,IAAI,iCAAiC,aAAa,8BAA8B,CAAC;AAAA,EACnG;AAEA,MAAI,MAAM,WAAW,EAAG,OAAM,IAAI,MAAM,gCAAgC,MAAM,UAAU,SAAS,EAAE;AACnG,MAAI,CAAC,OAAO,SAAS,QAAQ;AAC3B,UAAM,QAAQ,CAAC,WAAW,GAAG,KAAK,KAAK,EAAE,KAAK,GAAG;AACjD,YAAQ,KAAK,eAAG,IAAI,mDAAmD,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,EAC1F;AACF;AAGA,eAAe,UAAU,QAAuB,KAAa,SAAmB,KAA8B;AAC5G,QAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,QAAM,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;AAChD,aAAW,MAAM,IAAK,MAAK,OAAO,EAAE;AACpC,QAAM,aAAa,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;AAC7C,QAAM,SAAS,IAAI,SAAS,QAAQ;AACpC,MAAI,SAAS,EAAG,SAAQ,KAAK,GAAG,SAAS,aAAa,MAAM,qBAAqB;AACjF,MAAI,QAAQ,SAAS,EAAG,SAAQ,KAAK,eAAG,IAAI,4BAA4B,QAAQ,KAAK,IAAI,CAAC,EAAE,CAAC;AAC7F,UAAQ,KAAK,eAAG,IAAI,iBAAiB,MAAM,YAAY,OAAO,UAAU,GAAG,GAAG,QAAQ,KAAK,IAAI,CAAC,CAAC;AACnG;AAGA,eAAsB,WAAW,QAAsC;AACrE,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,MAAM,MAAM,gBAAgB,MAAM;AACxC,MAAI,CAAC,KAAK;AACR,YAAQ,KAAK,eAAG,IAAI,qFAAqF,CAAC;AAC1G;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,YAAY,QAAQ;AAC1C,QAAM,YAAY,iBAAiB,OAAO,SAAS,WAAW,KAAK;AACnE,QAAM,QAAQ,CAAC,OAAe,QAAQ,WAAW,KAAK,EAAE;AAExD,MAAI,OAAO,MAAM,OAAQ,QAAO,UAAU,QAAQ,KAAK,SAAS,OAAO,IAAI;AAC3E,MAAI,OAAO,IAAK,QAAO,QAAQ,QAAQ,KAAK,OAAO,GAAG;AACtD,MAAI,OAAO,QAAS,QAAO,YAAY,QAAQ,KAAK,OAAO,OAAO;AAElE,MAAI,OAAO,MAAM;AACf,UAAM,SAAS,MAAM,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,SAAS,IAAI,OAAO,IAAI,YAAY,GAAG,UAAU;AAAA,MAC3F,cAAc;AAAA,IAChB,CAAC;AACD,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,sBAAsB,OAAO,IAAI,iBAAiB,IAAI,MAAM,GAAG,CAAC,CAAC,EAAE;AAChG,UAAM,MAAM,MAAM,OAAO,IAAI;AAC7B,QAAI,IAAK,SAAQ,KAAK,eAAG,IAAI,GAAG,CAAC;AACjC,YAAQ,KAAK,MAAM;AACnB;AAAA,EACF;AAEA,QAAM,MAAM,OAAO,MAAM,MAAM,YAAY,UAAU,GAAG,IAAI;AAC5D,QAAM,SAAS,MAAM,QAAQ,IAAI,IAAI,IAAI,CAAC,OAAO,SAAS,UAAU,KAAK,EAAE,CAAC,CAAC,GAAG;AAAA,IAC9E,CAAC,MAAM,MACL,QAAQ;AAAA,MACN,IAAI,IAAI,CAAC;AAAA,MACT,OAAO,GAAG,IAAI,CAAC,CAAC;AAAA,MAChB,SAAS;AAAA,MACT,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,OAAO,CAAC;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACJ;AACA,QAAM,SAAS,MAAM,YAAY,UAAU,GAAG,GAAG;AAEjD,MAAI,OAAO,MAAM;AACf,UAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,UAAM,MAAM;AAAA,MACV,gBAAgB;AAAA,MAChB;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,OAAO,MAAM,IAAI,CAAC,UAAU;AAAA,QAC1B,GAAG;AAAA,QACH,MAAM,KAAK,UAAU,YAAY;AAAA,QACjC,MAAM,KAAK,IAAI,KAAK,EAAE;AAAA,QACtB,KAAK,MAAM,KAAK,EAAE,KAAK;AAAA,MACzB,EAAE;AAAA,IACJ;AACA,gBAAY,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AACxC;AAAA,EACF;AAEA,UAAQ,KAAK,eAAG,IAAI,gBAAgB,OAAO,QAAQ,MAAM,CAAC,CAAC;AAC3D,MAAI,MAAM,WAAW,EAAG;AACxB,UAAQ,KAAK;AACb,aAAW,CAAC,GAAG,IAAI,KAAK,MAAM,QAAQ,EAAG,WAAU,IAAI,GAAG,MAAM,MAAM,KAAK,EAAE,CAAC;AAC9E,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,KAAK,eAAG,IAAI,mEAAmE,CAAC;AACxF,YAAQ,KAAK,eAAG,IAAI,+BAA+B,QAAQ,KAAK,GAAG,CAAC,EAAE,CAAC;AAAA,EACzE;AACF;;;AC9QA,IAAM,gBAAmE;AAAA,EACvE,KAAK,oBAAI,IAAI,CAAC,SAAS,WAAW,UAAU,CAAC;AAAA,EAC7C,MAAM,oBAAI,IAAI,CAAC,WAAW,UAAU,CAAC;AAAA,EACrC,WAAW,oBAAI,IAAI,CAAC,OAAO,CAAC;AAC9B;AAQA,SAAS,cAAc,QAAqB,OAA2D;AACrG,QAAM,WAAW,cAAc,KAAK;AACpC,MAAI,UAAU,OAAQ,QAAO,OAAO,MAAM,OAAO,CAAC,MAAM,SAAS,IAAI,EAAE,MAAM,CAAC;AAC9E,QAAM,mBAAmB,OAAO,mBAAmB,SAAS;AAC5D,SAAO,OAAO,MAAM;AAAA,IAClB,CAAC,MACC,SAAS,IAAI,EAAE,MAAM,KACrB,EAAE,oBAAoB,QACtB,EAAE,iBAAiB,QAClB,oBAAoB,EAAE,SAAS;AAAA,EACpC;AACF;AAEA,eAAsB,WAAW,QAA6C;AAC5E,gBAAc,sBAAsB;AAEpC,QAAM,SAAS,MAAM,qBAAqB,QAAQ,KAAK;AAEvD,iBAAe;AAEf,QAAM,cAAc,cAAc,QAAQ,OAAO,SAAS,KAAK;AAE/D,MAAI,OAAO,MAAM;AACf,UAAM,YAAY,OAAO,mBAAmB,SAAS,YAAY,OAAO,oBAAoB;AAC5F,UAAM,MAAM,YAAY,IAAI,CAAC,OAAO;AAAA,MAClC,MAAM,EAAE;AAAA,MACR,QAAQ,EAAE;AAAA,MACV,WAAW,EAAE,aAAa;AAAA,MAC1B,eAAe,EAAE,iBAAiB;AAAA,MAClC,mBAAmB,EAAE,qBAAqB;AAAA,MAC1C,gBAAgB,EAAE,kBAAkB;AAAA,MACpC,iBAAiB,EAAE,mBAAmB;AAAA,MACtC,sBAAsB,EAAE,wBAAwB;AAAA,MAChD,qBAAqB,EAAE,uBAAuB;AAAA,MAC9C,cAAc,EAAE,gBAAgB;AAAA;AAAA,MAEhC,mBACE,aAAa,EAAE,SAAS,cACpB,EAAE,QAAQ,UAAU,QAAQ,SAAS,UAAU,SAAS,iBAAiB,UAAU,gBAAgB,IACnG;AAAA,IACR,EAAE;AACF,gBAAY,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AACxC,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,MAAM;AACf,eAAW,QAAQ,aAAa;AAC9B,kBAAY,KAAK,IAAI;AAAA,IACvB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,cAA2B;AAAA,IAC/B,mBAAmB,OAAO;AAAA,IAC1B,gBAAgB,OAAO;AAAA,IACvB,cAAc,OAAO,SAAS;AAAA,IAC9B,UAAU,OAAO;AAAA,EACnB;AAGA,0BAAwB,OAAO,OAAO,aAAa,MAAM;AAEzD,qBAAmB,QAAQ,kBAAkB;AAE7C,QAAM,wBAAwB,QAAQ,MAAM;AAE5C,UAAQ,KAAK;AAEb,SAAO;AACT;;;AC3FA,SAAS,aAAAI,kBAAiB;AAC1B,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,YAAAC,WAAU,QAAAC,QAAM,YAAAC,iBAAgB;AACzC,SAAS,UAAU,WAAAC,UAAS,iBAAiB;;;ACN7C,SAAS,YAAAC,iBAAgB;AACzB,SAAS,aAAAC,kBAAiB;AAI1B,IAAMC,iBAAgBC,WAAUC,SAAQ;AA6CjC,SAAS,WAAW,eAAkD;AAC3E,MAAI,CAAC,cAAe,QAAO;AAE3B,MAAI,MAAM;AAEV,MAAI,IAAI,WAAW,MAAM,GAAG;AAC1B,UAAM,IAAI,MAAM,CAAC;AAAA,EACnB;AAEA,MAAI,IAAI,SAAS,MAAM,GAAG;AACxB,UAAM,IAAI,MAAM,GAAG,EAAE;AAAA,EACvB;AAEA,MAAI,IAAI,WAAW,QAAQ,GAAG;AAC5B,UAAM,IAAI,QAAQ,UAAU,UAAU;AAAA,EACxC;AAEA,SAAO;AACT;AAGA,SAAS,gBAAgB,SAA2C;AAClE,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,WAAO,OAAO,aAAa,gBAAgB,OAAO,aAAa;AAAA,EACjE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,eAAe,SAAuC;AACpE,MAAI,CAAC,gBAAgB,OAAO,EAAG,QAAO;AACtC,SAAO,GAAG,OAAO;AACnB;AAGO,SAAS,qBAAqB,SAAiB,QAAyB;AAC7E,QAAM,OAAO,uBAAuB,OAAO;AAC3C,QAAM,KAAK,uBAAuB,MAAM;AACxC,SAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,QAAQ,KAAK;AAC3C;AAGA,eAAsB,QAAQ,MAAgB,KAAuE;AACnH,MAAI;AACF,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAMF,eAAc,QAAQ,MAAM;AAAA,MAC3D,UAAU;AAAA,MACV,WAAW,KAAK,OAAO;AAAA,MACvB;AAAA,IACF,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,QAAQ,OAAO;AAAA,EACpC,SAAS,OAAO;AAEd,UAAM,EAAE,SAAS,IAAI,SAAS,GAAG,IAAI;AACrC,WAAO,EAAE,IAAI,OAAO,QAAQ,QAAQ,UAAU,SAAS,SAAS,OAAO,KAAK,EAAE;AAAA,EAChF;AACF;AAQA,eAAsB,YAAY,MAAgB,KAA+B;AAC/E,MAAI;AACF,WAAO,KAAK,OAAO,MAAM,QAAQ,CAAC,GAAG,MAAM,kBAAkB,GAAG,GAAG,GAAG,MAAM;AAAA,EAC9E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,aAAa,KAA0C;AAC3E,QAAM,SAAU,MAAM,YAAY,CAAC,SAAS,QAAQ,GAAG,GAAG;AAC1D,MAAI,CAAC,UAAU,OAAO,OAAO,eAAe,YAAY,OAAO,eAAe,KAAM,QAAO;AAC3F,SAAO;AACT;AAGA,eAAsB,kBAAkB,MAAc,KAAqD;AACzG,QAAM,QAAQ,MAAM,YAAY,CAAC,QAAQ,MAAM,QAAQ,QAAQ,GAAG,GAAG;AACrE,SAAO,SAAS,OAAO,UAAU,WAAY,QAAmC;AAClF;AAGA,IAAM,YAAmD;AAAA,EACvD,UAAU,eAAG,IAAI,QAAG;AAAA,EACpB,MAAM,eAAG,IAAI,QAAG;AAAA,EAChB,UAAU,eAAG,OAAO,QAAG;AAAA,EACvB,KAAK,eAAG,KAAK,QAAG;AAAA,EAChB,MAAM,eAAG,KAAK,QAAG;AACnB;AAEO,SAAS,YAAY,UAAyC;AACnE,SAAO,UAAU,QAAQ,KAAK,eAAG,KAAK,QAAG;AAC3C;AAGO,SAAS,eAAeG,MAAa,QAAwB;AAClE,MAAIA,KAAI,UAAU,OAAQ,QAAOA;AACjC,QAAM,WAAW;AACjB,QAAM,cAAc,SAAS,SAAS;AACtC,QAAM,aAAa,KAAK,KAAK,cAAc,CAAC;AAC5C,QAAM,YAAY,KAAK,MAAM,cAAc,CAAC;AAC5C,SAAOA,KAAI,MAAM,GAAG,UAAU,IAAI,WAAWA,KAAI,MAAM,CAAC,SAAS;AACnE;AAGO,SAAS,iBAAiB,YAA8B;AAC7D,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,MAAI,WAAW,WAAW,EAAG,QAAO,WAAW,CAAC;AAChD,SAAO,GAAG,WAAW,CAAC,CAAC,KAAK,WAAW,SAAS,CAAC;AACnD;;;ACnGO,IAAM,aAAsC,CAAC,YAAY,QAAQ,YAAY,OAAO,MAAM;AAO1F,SAAS,gBAAgB,KAAsB;AAEpD,MAAI,UAAU,KAAK,GAAG,EAAG,QAAO;AAChC,SAAO,IAAI,QAAQ,KAAK,CAAC,IAAI;AAC/B;AAGO,SAAS,eAAe,KAAqB;AAClD,QAAM,QAAQ,IAAI,MAAM,cAAc,EAAE,GAAG,EAAE,KAAK;AAClD,QAAM,KAAK,MAAM,QAAQ,KAAK,CAAC;AAC/B,SAAO,KAAK,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI;AACvC;AAGO,SAAS,sBAAsB,OAAyD;AAC7F,QAAM,KAAK,MAAM,YAAY,GAAG;AAChC,MAAI,MAAM,EAAG,QAAO;AACpB,QAAM,UAAU,MAAM,MAAM,KAAK,CAAC;AAClC,SAAO,iCAAiC,KAAK,OAAO,IAAI,EAAE,MAAM,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,IAAI;AAClG;AAGO,SAAS,oBAAoB,OAAgC;AAClE,SAAO,OAAO,OAAO,MAAM,UAAU,EAAE,IAAI,CAAC,aAAa;AACvD,UAAM,SAAS,SAAS,YAAY,CAAC,GAAG,QAAQ,CAAC,YAAY,QAAQ,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,MAAM,GAAG,CAAC;AAC/G,WAAO;AAAA,MACL,MAAM,SAAS,sBAAsB,SAAS,OAAO,OAAO,SAAS,EAAE;AAAA,MACvE,QAAQ,SAAS;AAAA,MACjB,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS;AAAA,MAChB,WAAW,CAAC,GAAG,IAAI,KAAK,SAAS,YAAY,CAAC,GAAG,IAAI,CAAC,YAAY,QAAQ,OAAO,CAAC,CAAC;AAAA,MACnF,KAAK,CAAC,GAAG,IAAI,IAAI,MAAM,IAAI,CAAC,UAAU,MAAM,MAAM,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,MACvE,QAAQ,MAAM,KAAK,CAAC,UAAU,MAAM,WAAW,CAAC;AAAA,IAClD;AAAA,EACF,CAAC;AACH;AAGA,IAAM,eAAe,CAAC,MAAc,SAAiB,UACnD,MAAM,MAAM,KAAK,MAAM,MAAM,UAAU,IAAI,IAAI,OAAO,KAAK,EAAE;AAG/D,SAAS,cAAc,MAAc,SAAiB,OAA2B;AAC/E,QAAM,WAAW,MAAM,SAAS;AAChC,MAAI,SAAS,SAAS,IAAI,KAAK,SAAS,SAAS,GAAG,IAAI,IAAI,OAAO,EAAE,EAAG,QAAO;AAC/E,QAAM,MAAM,aAAa,MAAM,SAAS,KAAK;AAC7C,SAAO,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,oBAAoB;AAC/D;AAGA,SAAS,OAAO,QAAgB,SAA0B;AACxD,QAAM,OAAO,OAAO,QAAQ,gBAAgB,EAAE;AAC9C,MAAI,sBAAsB,MAAM,OAAO,IAAI,EAAG,QAAO;AACrD,SAAO,OAAO,KAAK,EAAE,WAAW,GAAG,KAAK,CAAC,eAAe,MAAM,OAAO;AACvE;AAGA,IAAM,oBAAoB,CAAC,QAAgB,aACzC,OAAO,QAAQ,SAAS,SAAS,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,gBAAgB,GAAG,KAAK,eAAe,GAAG,MAAM,MAAM;AAMtG,SAAS,kBACd,QACA,OACwB;AACxB,QAAM,WAAW,OAAO,KAAK,MAAM,UAAU,MAAM,KAAK,CAAC,CAAC;AAC1D,SAAO,OAAO;AAAA,IACZ,kBAAkB,QAAQ,MAAM,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,MAAM,SAAS,KAAK,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC,CAAC;AAAA,EAC1G;AACF;AAQO,SAAS,aAAa,OAAkC;AAC7D,QAAM,UAAU,IAAI,IAAI,MAAM,SAAS,YAAY;AACnD,QAAM,WAAW,IAAI,QAAQ,MAAM,YAAY,CAAC,aAAa,SAAS,MAAM;AAC5E,QAAM,QAAwB,CAAC;AAE/B,aAAW,CAAC,QAAQ,UAAU,KAAK,UAAU;AAC3C,UAAM,WAAW,OAAO,KAAK,MAAM,UAAU,MAAM,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,MAAM,KAAK,CAAC,CAAC;AACvF,UAAM,SAAS,SAAS,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK,qBAAqB;AAClF,UAAM,aAAa,CAAC,MAAc,CAAC,WAAW,KAAK,CAAC,aAAa,qBAAqB,GAAG,SAAS,KAAK,CAAC;AAExG,UAAM,QAAQ,CAAC,aAA2C;AACxD,YAAM,UAAU,CAAC,GAAG,SAAS,SAAS,EAAE,KAAK,qBAAqB,EAAE,GAAG,EAAE,KAAK;AAC9E,YAAM,aAAa,OAAO;AAAA,QACxB,CAAC,MAAM,sBAAsB,GAAG,OAAO,IAAI,KAAK,CAAC,qBAAqB,GAAG,SAAS,KAAK;AAAA,MACzF;AACA,YAAM,cAAc,WAAW,OAAO,CAAC,MAAM,cAAc,QAAQ,GAAG,KAAK,CAAC;AAC5E,YAAM,OAAO,CAAC,UAAoB,MAAM,KAAK,UAAU,KAAK,MAAM,CAAC;AACnE,aAAO,KAAK,WAAW,KAAK,KAAK,UAAU;AAAA,IAC7C;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,IAAI,QAAQ,YAAY,KAAK,GAAG;AACzD,YAAM,YAAY,CAAC,GAAG,IAAI,IAAI,MAAM,QAAQ,CAAC,aAAa,SAAS,SAAS,CAAC,CAAC,EAAE,KAAK,qBAAqB;AAC1G,YAAM,QAAQ,MAAM,IAAI,CAAC,aAAa,SAAS,IAAI;AACnD,YAAM,aAAa,MAAM,MAAM,CAAC,SAAS,QAAQ,IAAI,IAAI,CAAC;AAC1D,YAAM,WAAW,CAAC,CAAC,OAAO,UAAU,KAAK,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEtE,UAAI,SAAiB,EAAE,MAAM,OAAO;AACpC,UAAI,WAAqB,aAAa,YAAY;AAClD,UAAI,YAAoC,CAAC;AAEzC,UAAI,KAAK;AACP,cAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,QAAQ,KAAK,KAAK,IAAI,IAAS,CAAC;AACrF,iBAAS,cAAc,QAAQ,KAAK,KAAK,IACrC,EAAE,MAAM,YAAY,QAAQ,KAAK,SAAS,IAC1C,EAAE,MAAM,SAAS,QAAQ,KAAK,UAAU,SAAS;AAErD,oBAAY,OAAO;AAAA,UACjB,CAAC,GAAG,IAAI,IAAI,MAAM,IAAI,CAAC,aAAa,SAAS,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU;AACnE,kBAAM,MAAM,GAAG,MAAM,IAAI,KAAK;AAC9B,kBAAM,OAAO,MAAM,SAAS,UAAU,GAAG;AAEzC,mBAAO,CAAC,KAAK,QAAQ,OAAO,MAAM,GAAG,IAAI,OAAO,IAAI,GAAG,EAAE;AAAA,UAC3D,CAAC;AAAA,QACH;AAEA,YAAI,OAAO,SAAS,YAAY;AAC9B,cAAI,kBAAkB,QAAQ,MAAM,QAAQ,EAAE,KAAK,CAAC,CAAC,EAAE,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC,EAAG,YAAW;AAAA,mBAE3F,cAAc,CAAC,SAAU,YAAW;AAAA,QAC/C;AAAA,MACF;AAEA,YAAM,KAAK;AAAA,QACT;AAAA,QACA,UAAU,WAAW,KAAK,CAAC,aAAa,MAAM,KAAK,CAAC,aAAa,SAAS,aAAa,QAAQ,CAAC,KAAK;AAAA,QACrG;AAAA,QACA,WAAW,UAAU,CAAC,KAAK;AAAA,QAC3B,KAAK,CAAC,GAAG,IAAI,IAAI,MAAM,QAAQ,CAAC,aAAa,SAAS,GAAG,CAAC,CAAC;AAAA,QAC3D,QAAQ,MAAM,KAAK,CAAC,aAAa,SAAS,MAAM;AAAA,QAChD;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,MAAM;AAAA,IACX,CAAC,GAAG,MAAM,WAAW,QAAQ,EAAE,QAAQ,IAAI,WAAW,QAAQ,EAAE,QAAQ,KAAK,EAAE,OAAO,cAAc,EAAE,MAAM;AAAA,EAC9G;AACF;AAOO,SAAS,aAAa,OAAgD;AAC3E,SAAO,MAAM,SAAS,mBAAmB,OAAO,CAAC,UAAU;AACzD,UAAM,YAAY,sBAAsB,KAAK;AAE7C,QAAI,CAAC,aAAa,CAAC,MAAM,UAAU,UAAU,IAAI,EAAG,QAAO;AAC3D,WAAO,aAAa,UAAU,MAAM,UAAU,SAAS,KAAK,IAAI,MAAM,oBAAoB;AAAA,EAC5F,CAAC;AACH;;;AC9OA,SAAwB,OAAO,UAAU,OAAO,qBAAmC;AAYnF,IAAM,SAAS,CAAC,UACd,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAK,QAAoC,CAAC;AAEtG,IAAM,eAAe,CAAC,UACpB,OAAO,YAAY,OAAO,QAAQ,OAAO,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC;AAE9F,IAAM,aAAa,CAAC,UAA8B,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,CAAC;AAMvF,SAAS,kBAAkB,SAAgC;AAChE,QAAM,MAAM,cAAc,OAAO;AACjC,MAAI,IAAI,OAAO,SAAS,EAAG,OAAM,IAAI,MAAM,IAAI,OAAO,CAAC,EAAE,OAAO;AAChE,QAAM,WAAW,OAAO,IAAI,KAAK,CAAC;AAClC,SAAO;AAAA,IACL,WAAW,aAAa,SAAS,SAAS;AAAA,IAC1C,oBAAoB,WAAW,SAAS,wBAAwB;AAAA,IAChE,cAAc,WAAW,OAAO,SAAS,WAAW,EAAE,WAAW;AAAA,EACnE;AACF;AAGO,SAAS,aAAa,SAAiB,KAAsB;AAClE,SAAO,OAAO,cAAc,OAAO,EAAE,KAAK,CAAC,EAAE,GAAG;AAClD;AAGO,SAAS,eAAe,SAA2B;AACxD,SAAO,OAAO,OAAO,aAAa,OAAO,cAAc,OAAO,EAAE,KAAK,CAAC,EAAE,mBAAmB,CAAC;AAC9F;AAEA,IAAM,QAAQ,CAAC,SAAmC,OAAO,SAAS,KAAK,GAAG,IAAI,KAAK,IAAI,QAAQ,KAAK,GAAG;AAEvG,IAAM,WAAW,CAAC,SAA0B,OAAO,SAAS,IAAI,IAAI,KAAK,QAAQ,IAAI;AAGrF,SAAS,aAAa,KAAc,QAA0B;AAC5D,QAAM,OAAO,IAAI,MAAM,IAAI,KAAK;AAChC,QAAM,YAAY,KAAK,MAAM,CAAC,KAAK,MAAM,MAAM,KAAK,KAAK,IAAI,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC;AACvF,SAAO;AACP,MAAI,UAAW,KAAI,MAAM,KAAK,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE,cAAc,MAAM,CAAC,CAAC,CAAC;AAC1E;AAGA,SAAS,MAAM,KAAe,MAAyB;AACrD,MAAI,KAAK,WAAW,GAAG;AACrB,QAAI,CAAC,MAAM,IAAI,QAAQ,EAAG,KAAI,WAAW,IAAI,WAAW,CAAC,CAAC;AAC1D,WAAO,IAAI;AAAA,EACb;AACA,QAAM,SAAS,MAAM,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AAC3C,QAAM,MAAM,KAAK,KAAK,SAAS,CAAC;AAChC,QAAM,WAAW,OAAO,IAAI,KAAK,IAAI;AACrC,MAAI,MAAM,QAAQ,GAAG;AAEnB,QAAI,SAAS,MAAM,WAAW,EAAG,UAAS,OAAO;AACjD,WAAO;AAAA,EACT;AACA,QAAM,UAAU,IAAI,WAAW,CAAC,CAAC;AACjC,eAAa,QAAQ,MAAM,OAAO,IAAI,KAAK,OAAO,CAAC;AACnD,SAAO;AACT;AAGA,SAAS,QAAQ,KAAe,MAAgB,SAAuC;AACrF,MAAI,CAAC,MAAM,IAAI,MAAM,IAAI,CAAC,KAAK,OAAO,KAAK,OAAO,EAAE,WAAW,EAAG;AAElE,QAAM,MAAM,MAAM,KAAK,IAAI;AAC3B,eAAa,KAAK,MAAM;AACtB,eAAW,OAAO,IAAI,MAAM,IAAI,KAAK,EAAG,KAAI,EAAE,OAAO,SAAU,KAAI,OAAO,GAAG;AAC7E,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,EAAG,KAAI,IAAI,KAAK,KAAK;AAAA,EACxE,CAAC;AACD,MAAI,IAAI,MAAM,WAAW,EAAG,KAAI,SAAS,IAAI;AAC/C;AAGA,SAAS,SAAS,KAAe,MAAgB,SAAyB;AACxE,QAAM,UAAU,IAAI,MAAM,IAAI;AAC9B,MAAI,CAAC,MAAM,OAAO,GAAG;AACnB,QAAI,QAAQ,WAAW,EAAG;AAC1B,UAAM,SAAS,MAAM,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AAC3C,iBAAa,QAAQ,MAAM,OAAO,IAAI,KAAK,KAAK,SAAS,CAAC,GAAG,IAAI,WAAW,OAAO,CAAC,CAAC;AACrF;AAAA,EACF;AAEA,UAAQ,QAAQ,QAAQ,MAAM,OAAO,CAAC,SAAS,QAAQ,SAAS,SAAS,IAAI,CAAC,CAAC;AAC/E,QAAM,UAAU,IAAI,IAAI,QAAQ,MAAM,IAAI,QAAQ,CAAC;AACnD,aAAW,SAAS,QAAS,KAAI,CAAC,QAAQ,IAAI,KAAK,EAAG,SAAQ,IAAI,IAAI,WAAW,KAAK,CAAC;AACvF,MAAI,QAAQ,MAAM,WAAW,EAAG,KAAI,SAAS,IAAI;AAAA,MAC5C,SAAQ,OAAO;AACtB;AAMO,SAAS,mBAAmB,SAAiB,MAA6B;AAC/E,QAAM,MAAM,cAAc,OAAO;AACjC,UAAQ,KAAK,CAAC,WAAW,GAAG,KAAK,SAAS;AAC1C,WAAS,KAAK,CAAC,0BAA0B,GAAG,KAAK,kBAAkB;AACnE,WAAS,KAAK,CAAC,eAAe,aAAa,GAAG,KAAK,YAAY;AAE/D,QAAM,cAAc,IAAI,MAAM,CAAC,aAAa,CAAC;AAC7C,MAAI,MAAM,WAAW,KAAK,YAAY,MAAM,WAAW,EAAG,KAAI,SAAS,CAAC,aAAa,CAAC;AAEtF,SAAO,IAAI,SAAS,EAAE,WAAW,GAAG,aAAa,KAAK,CAAC;AACzD;;;ACrHA,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,QAAQ,cAAAC,aAAY,WAAW,aAAa,gBAAAC,eAAc,QAAQ,qBAAqB;AAChG,SAAS,cAAc;AACvB,SAAS,WAAAC,UAAS,QAAAC,OAAM,YAAAC,iBAAgB;AACxC,SAAS,SAAS,UAAAC,eAAc;AA0BhC,IAAM,iBAAiB;AACvB,IAAM,YAAY;AAGlB,IAAM,mBAAmB,CAAC,gBAAgB,WAAW,UAAU,eAAe;AAY9E,IAAM,SAAS,CAAC,MAAc,WAAW,OAAgBC,YAAW,IAAI,IAAIC,cAAa,MAAM,MAAM,IAAI;AAEzG,IAAM,QAAQ,CAAC,GAAW,MAAcC,UAAS,GAAG,IAAI,QAAgB,GAAG,CAAC,IAAI,MAAM,IAAI,OAAOA,OAAM;AAEvG,IAAM,aAAa,CAAC,SAAgC,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO;AAM/F,IAAM,gBAAgB,CAAC,SACrB,KAAK,aAAa,UAAU,KAAK,OAAO,SAAS,cAAc,KAAK,OAAO,YAAY,KAAK;AAE9F,IAAM,cAAc,CAAC,GAA2B,MAC9C,OAAO,KAAK,CAAC,EAAE,WAAW,OAAO,KAAK,CAAC,EAAE,UAAU,OAAO,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,KAAK,MAAM,EAAE,GAAG,MAAM,KAAK;AAM/G,eAAe,cAAc,UAAkB,eAAwC;AACrF,QAAM,UAAU,YAAYC,MAAK,OAAO,GAAG,cAAc,CAAC;AAC1D,QAAM,WAAa,MAAM,YAAY,CAAC,MAAM,MAAM,WAAW,MAAM,QAAQ,GAAG,QAAQ,KAAM,CAAC;AAG7F,QAAM,QAAQ;AAAA,IACZ,GAAG;AAAA,IACH,GAAG,eAAe,aAAa;AAAA,IAC/B,GAAG,SAAS,IAAI,CAAC,YAAYA,MAAKC,UAAS,UAAU,QAAQ,IAAI,GAAG,cAAc,CAAC;AAAA,EACrF;AACA,aAAW,QAAQ,IAAI,IAAI,KAAK,GAAG;AACjC,QAAI,KAAK,WAAW,IAAI,KAAK,CAACJ,YAAWG,MAAK,UAAU,IAAI,CAAC,EAAG;AAChE,cAAUE,SAAQF,MAAK,SAAS,IAAI,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;AAC3D,WAAOA,MAAK,UAAU,IAAI,GAAGA,MAAK,SAAS,IAAI,CAAC;AAAA,EAClD;AACA,SAAO;AACT;AAGA,eAAe,eACb,SACA,eACA,UAC+C;AAC/C,gBAAcA,MAAK,SAAS,cAAc,GAAG,mBAAmB,eAAe,QAAQ,CAAC;AACxF,QAAM,SAAS,MAAM,QAAQ,CAAC,WAAW,mBAAmB,wBAAwB,kBAAkB,GAAG,OAAO;AAChH,SAAO,OAAO,KAAK,EAAE,MAAM,OAAOA,MAAK,SAAS,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,MAAM,GAAG,OAAO,MAAM,GAAG,KAAK,EAAE;AACrH;AAGA,SAAS,eAAe,MAAc,MAAwB;AAC5D,QAAM,UAAU,KAAK,QAAQ,wBAAwB,MAAM;AAC3D,QAAM,WAAW,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,UAAU,OAAO,qBAAqB,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,MAAM,CAAC,CAAC;AACnH,SAAO,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AAC9B;AAGA,SAAS,aAAa,MAA4B;AAChD,MAAI,KAAK,OAAO,SAAS,OAAQ,QAAO,KAAK;AAC7C,SAAO,GAAG,KAAK,SAAS,WAAM,KAAK,OAAO,MAAM,GAAG,WAAW,IAAI,IAAI,YAAO,EAAE;AACjF;AAGA,SAAS,SAAS,MAAoB,iBAAiC;AACrE,MAAI,KAAK,OAAO,SAAS,OAAQ,QAAO;AACxC,MAAI,KAAK,OAAO,SAAS;AACvB,WAAO,iBAAiB,KAAK,OAAO,QAAQ,qBAAqB,eAAe;AAClF,MAAI,KAAK,aAAa,UAAW,QAAO;AACxC,SAAO;AACT;AAEA,SAAS,WAAW,OAAe,OAAuB,iBAA+B;AACvF,MAAI,MAAM,WAAW,EAAG;AACxB,QAAM,YAAY,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC;AACnF,QAAM,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,aAAa,IAAI,EAAE,MAAM,CAAC;AAE/E,UAAQ,KAAK,eAAG,KAAK,GAAG,KAAK,KAAK,MAAM,MAAM,GAAG,CAAC;AAClD,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,eAAG,MAAM,eAAe,KAAK,QAAQ,SAAS,EAAE,OAAO,SAAS,CAAC;AAC9E,UAAM,SAAS,GAAG,iBAAiB,KAAK,GAAG,CAAC,GAAG,KAAK,SAAS,cAAc,EAAE;AAC7E,UAAM,OAAO,CAAC,QAAQ,SAAS,MAAM,eAAe,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK;AACjF,YAAQ;AAAA,MACN,GAAG,YAAY,KAAK,QAAQ,CAAC,IAAI,IAAI,KAAK,KAAK,SAAS,OAAO,CAAC,CAAC,KAAK,aAAa,IAAI,EAAE,OAAO,YAAY,CAAC,KAAK,eAAG,IAAI,IAAI,CAAC;AAAA,IAChI;AAAA,EACF;AACA,UAAQ,KAAK;AACf;AAEA,SAAS,aAAa,OAAe,MAAmD;AACtF,MAAI,KAAK,WAAW,EAAG;AACvB,QAAM,YAAY,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,IAAI,MAAM,KAAK,MAAM,CAAC,CAAC;AAC7E,UAAQ,KAAK,eAAG,KAAK,GAAG,KAAK,KAAK,KAAK,MAAM,GAAG,CAAC;AACjD,aAAW,CAAC,MAAM,MAAM,KAAK,MAAM;AACjC,YAAQ,KAAK,GAAG,eAAG,MAAM,QAAG,CAAC,IAAI,eAAG,MAAM,eAAe,MAAM,SAAS,EAAE,OAAO,SAAS,CAAC,CAAC,KAAK,eAAG,IAAI,MAAM,CAAC,EAAE;AAAA,EACnH;AACA,UAAQ,KAAK;AACf;AAGA,SAAS,cAAc,KAAa,OAAuB,UAA0B;AACnF,QAAM,SAAS,eAAe,GAAG;AACjC,QAAM,OAAO,MAAM,KAAK,CAAC,cAAc,UAAU,WAAW,MAAM;AAClE,MAAI,KAAM,QAAO,KAAK,OAAO,SAAS,SAAS,kCAAkC;AACjF,QAAM,WAAW,eAAe,UAAU,MAAM;AAChD,SAAO,SAAS,SAAS,IAAI,eAAe,SAAS,KAAK,IAAI,CAAC,gBAAgB;AACjF;AAGA,eAAe,OAAO,OAAuB,iBAA8C;AACzF,QAAM,YAAwB,CAAC;AAE/B,aAAW,QAAQ,OAAO;AACxB,UAAM,EAAE,OAAO,IAAI;AACnB,UAAM,OAAO,OAAO,SAAS,SAAS,KAAK,GAAG,KAAK,SAAS,WAAM,OAAO,MAAM;AAE/E,QAAI,CAAC,cAAc,IAAI,GAAG;AACxB,gBAAU,KAAK,EAAE,MAAM,QAAQ,KAAK,aAAa,YAAY,WAAW,WAAW,CAAC;AAAA,IACtF,WAAW,OAAO,SAAS,QAAQ;AACjC,YAAM,SAAS,MAAM,QAAQ;AAAA,QAC3B,SAAS,GAAG,KAAK,MAAM,iCAAiC,KAAK,MAAM,KAAK,IAAI,CAAC;AAAA,QAC7E,SAAS;AAAA,MACX,CAAC;AACD,gBAAU,KAAK,EAAE,MAAM,QAAQ,SAAS,WAAW,OAAO,CAAC;AAAA,IAC7D,WAAW,OAAO,SAAS,SAAS;AAClC,YAAM,SAAS,MAAMG,QAAe;AAAA,QAClC,SAAS,GAAG,KAAK,MAAM,SAAS,OAAO,MAAM,kBAAkB,OAAO,QAAQ,qBAAqB,eAAe;AAAA,QAClH,SAAS;AAAA,UACP,EAAE,MAAM,yBAAyB,OAAO,OAAO;AAAA,UAC/C,EAAE,MAAM,2DAA2D,OAAO,WAAW;AAAA,QACvF;AAAA,MACF,CAAC;AACD,gBAAU,KAAK,EAAE,MAAM,QAAQ,SAAS,WAAW,aAAa,GAAG,KAAK,MAAM,IAAI,OAAO,MAAM,KAAK,OAAU,CAAC;AAAA,IACjH,OAAO;AACL,YAAM,UAAU,KAAK,SACjB,cAAc,IAAI,SAAS,KAAK,IAAI,CAAC,CAAC,4BACtC,iBAAiB,IAAI,eAAe,iBAAiB,KAAK,GAAG,CAAC;AAClE,YAAM,SAAS,MAAMA,QAAe;AAAA,QAClC,SAAS,GAAG,KAAK,MAAM,KAAK,OAAO;AAAA,QACnC,SAAS;AAAA,UACP,EAAE,MAAM,KAAK,SAAS,0CAA0C,cAAc,OAAO,OAAO;AAAA,UAC5F,EAAE,MAAM,sBAAsB,OAAO,WAAW;AAAA,UAChD,EAAE,MAAM,uBAAuB,OAAO,SAAS;AAAA,QACjD;AAAA,MACF,CAAC;AACD,gBAAU,KAAK,EAAE,MAAM,OAAO,CAAC;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,YAAY,WAAuB,MAA8B,UAAmC;AAC3G,QAAM,aAAa,UAAU,OAAO,CAAC,aAAa,SAAS,WAAW,UAAU;AAChF,SAAO;AAAA,IACL,WAAW,EAAE,GAAG,MAAM,GAAG,OAAO,OAAO,CAAC,GAAG,GAAG,WAAW,IAAI,CAAC,aAAa,SAAS,KAAK,SAAS,CAAC,EAAE;AAAA,IACrG,oBAAoB,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,UAAU,GAAG,WAAW,QAAQ,CAAC,aAAa,SAAS,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAAA,IAC3G,cAAc,UACX,OAAO,CAAC,aAAa,SAAS,WAAW,QAAQ,EACjD,QAAQ,CAAC,aAAa,SAAS,KAAK,KAAK;AAAA,EAC9C;AACF;AAGA,SAAS,WAAW,OAAe,QAAkB,OAAyB;AAC5E,QAAM,UAAU,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,SAAS,KAAK,CAAC,EAAE;AACjE,QAAM,QAAQ,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,KAAK,CAAC,EAAE;AAC/D,QAAM,QAAQ,CAAC,UAAU,GAAG,OAAO,aAAa,IAAI,QAAQ,GAAG,KAAK,WAAW,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC5G,QAAM,SAAS,QAAQ,GAAG,OAAO,MAAM,WAAM,MAAM,MAAM,KAAK,OAAO,MAAM,MAAM;AACjF,SAAO,KAAK,MAAM,OAAO,CAAC,CAAC,KAAK,OAAO,OAAO,CAAC,CAAC,KAAK,eAAG,IAAI,SAAS,WAAW,CAAC;AACnF;AAMA,eAAsB,gBAAgB,UAAkB,SAA4C;AAClG,QAAM,gBAAgB,OAAOH,MAAK,UAAU,cAAc,CAAC;AAC3D,QAAM,gBAAgB,OAAOA,MAAK,UAAU,SAAS,CAAC;AACtD,MAAI;AACJ,MAAI;AACF,eAAW,kBAAkB,aAAa;AAAA,EAC5C,SAAS,OAAO;AACd,YAAQ;AAAA,MACN,GAAG,eAAG,IAAI,QAAG,CAAC,IAAI,cAAc,uBAAuB,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAAA,IACvG;AACA;AAAA,EACF;AACA,QAAM,YAAY,OAAO,KAAK,SAAS,SAAS,EAAE,OAAO,eAAe;AACxE,QAAM,UAAU,OAAO,YAAY,OAAO,QAAQ,SAAS,SAAS,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,gBAAgB,GAAG,CAAC,CAAC;AAE9G,QAAM,UAAU;AAAA,IACd,UAAU,SAAS,IACf,yBAAyB,MAAM,UAAU,QAAQ,gBAAgB,CAAC,QAClE;AAAA,EACN;AACA,QAAM,OAAO,CAAC,SAAiB,SAAS,OAAa;AACnD,YAAQ,KAAK;AACb,YAAQ,MAAM,GAAG,eAAG,IAAI,QAAG,CAAC,IAAI,OAAO,EAAE;AACzC,QAAI,OAAQ,SAAQ,MAAM,eAAG,IAAI,OAAO,MAAM,IAAI,EAAE,MAAM,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC;AAC1E,YAAQ,KAAK,eAAG,IAAI,8BAA8B,CAAC;AACnD,YAAQ,KAAK;AAAA,EACf;AAEA,QAAM,UAAU,MAAM,cAAc,UAAU,aAAa;AAC3D,MAAI;AAEF,UAAM,OAAO,MAAM,eAAe,SAAS,eAAe,EAAE,GAAG,UAAU,WAAW,SAAS,cAAc,CAAC,EAAE,CAAC;AAC/G,QAAI,WAAW,KAAM,QAAO,KAAK,+DAA+D,KAAK,KAAK;AAE1G,gBAAY,iCAAiC;AAC7C,UAAM,QAAQ,MAAM,aAAa,OAAO;AACxC,QAAI,CAAC,MAAO,QAAO,KAAK,sDAAsD;AAC9E,UAAM,aAAa,oBAAoB,KAAK;AAE5C,gBAAY,YAAY,MAAM,WAAW,QAAQ,YAAY,YAAY,CAAC,0BAA0B;AACpG,UAAM,oBAAoB,SAAS,mBAAmB,QAAQ,CAAC,UAAU,sBAAsB,KAAK,GAAG,QAAQ,CAAC,CAAC;AACjH,UAAM,QAAQ,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,WAAW,IAAI,CAAC,aAAa,SAAS,MAAM,GAAG,GAAG,iBAAiB,CAAC,CAAC;AACnG,UAAM,QAAQ,MAAM,QAAQ,IAAI,MAAM,IAAI,CAAC,SAAS,kBAAkB,MAAM,QAAQ,CAAC,CAAC;AACtF,UAAM,YAA0C,OAAO;AAAA,MACrD,MAAM,IAAI,CAAC,MAAM,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,MAAM,MAAM;AAAA,IACxE;AAEA,UAAM,aAAa,WAAW,IAAI,CAAC,aAAa,SAAS,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC;AAClG,QAAI,WAAW,SAAS,EAAG,QAAO,KAAK,mCAAmC,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE;AAE/G,UAAM,aAAa,OAAO,UAAU,MAAM,QAAQ,CAAC,UAAU,OAAO,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,EAAE;AAC/G,UAAM,oBAAoB,OAAO,MAAM,UAAU,IAAI,IAAI;AACzD,UAAM,kBAAkB,KAAK,MAAM,oBAAoB,EAAE;AACzD,UAAM,YAAY,EAAE,YAAY,WAAW,UAAU,mBAAmB,KAAK,KAAK,IAAI,EAAE;AACxF,UAAM,QAAQ,aAAa,SAAS;AACpC,UAAM,WAAW,aAAa,SAAS;AACvC,YAAQ,KAAK;AAEb,UAAM,UAAU,UAAU;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AACD,QAAI,CAAC,QAAQ,OAAO;AAClB,UAAI,QAAS,SAAQ,KAAK,eAAG,IAAI,6BAA6B,CAAC;AAC/D,cAAQ,KAAK;AACb;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,kBAAY,MAAM,OAAO,OAAO,eAAe;AAAA,IACjD,QAAQ;AACN,cAAQ,KAAK,eAAG,IAAI,yCAAyC,CAAC;AAC9D;AAAA,IACF;AAEA,UAAM,OAAO,UAAU,OAAO,CAAC,aAAa,SAAS,WAAW,MAAM,EAAE,IAAI,CAAC,aAAa,SAAS,KAAK,MAAM;AAC9G,UAAM,OAAO,OAAO,OAAO,CAAC,GAAG,SAAS,GAAG,KAAK,IAAI,CAAC,WAAW,kBAAkB,QAAQ,SAAS,CAAC,CAAC;AACrG,UAAM,OAAO,YAAY,WAAW,MAAM,QAAQ;AAClD,UAAM,WAAW,mBAAmB,eAAe,IAAI;AAEvD,QAAI,aAAa,eAAe;AAC9B,YAAM,QAAQ,GAAG,MAAM,UAAU,QAAQ,UAAU,CAAC,SAAM,KAAK,aAAa,MAAM;AAClF,cAAQ,KAAK,GAAG,SAAS,kCAAkC,eAAG,IAAI,QAAK,KAAK,EAAE,CAAC,EAAE;AACjF,gBAAU,IAAI;AACd;AAAA,IACF;AAEA,UAAM,YAAY,MAAY;AAC5B,cAAQ,KAAK,eAAG,KAAK,cAAc,CAAC;AACpC,cAAQ,KAAK,WAAW,aAAa,WAAW,OAAO,KAAK,KAAK,SAAS,EAAE,OAAO,eAAe,CAAC,CAAC;AACpG,cAAQ,KAAK,WAAW,YAAY,SAAS,oBAAoB,KAAK,kBAAkB,CAAC;AACzF,cAAQ,KAAK,WAAW,WAAW,SAAS,cAAc,KAAK,YAAY,CAAC;AAC5E,cAAQ,KAAK;AAAA,IACf;AAGA,QAAI,YAAY,KAAK,WAAW,SAAS,SAAS,GAAG;AACnD,oBAAcA,MAAK,UAAU,cAAc,GAAG,QAAQ;AACtD,cAAQ,KAAK,GAAG,SAAS,IAAI,cAAc,YAAY,eAAG,IAAI,yBAAsB,CAAC,EAAE;AACvF,gBAAU,IAAI;AACd,gBAAU;AACV;AAAA,IACF;AAEA,UAAM,iBAAiB,cAAc,oCAAoC;AACzE,UAAM,SAAS,MAAM,eAAe,SAAS,eAAe,IAAI;AAChE,mBAAe,KAAK;AACpB,QAAI,WAAW,OAAQ,QAAO,KAAK,yDAAyD,OAAO,KAAK;AAExG,kBAAcA,MAAK,UAAU,cAAc,GAAG,QAAQ;AACtD,kBAAcA,MAAK,UAAU,SAAS,GAAG,OAAO,IAAI;AACpD,UAAM,UAAUI,WAAU,QAAQ,CAAC,SAAS,GAAG,EAAE,KAAK,UAAU,OAAO,UAAU,CAAC;AAClF,YAAQ,KAAK;AACb,QAAI,QAAQ,WAAW,GAAG;AACxB,oBAAcJ,MAAK,UAAU,cAAc,GAAG,aAAa;AAC3D,oBAAcA,MAAK,UAAU,SAAS,GAAG,aAAa;AACtD,cAAQ,MAAM,GAAG,eAAG,IAAI,QAAG,CAAC,mCAAmC,QAAQ,MAAM,GAAG;AAChF,cAAQ,KAAK,eAAG,IAAI,KAAK,cAAc,QAAQ,SAAS,mDAAmD,CAAC;AAC5G,cAAQ,KAAK;AACb;AAAA,IACF;AAGA,UAAM,WAAW,MAAM,aAAa,QAAQ;AAC5C,UAAM,WAAW,WAAW,CAAC,GAAG,IAAI,IAAI,oBAAoB,QAAQ,EAAE,IAAI,CAAC,aAAa,SAAS,MAAM,CAAC,CAAC,IAAI;AAC7G,YAAQ,KAAK,GAAG,SAAS,aAAa,SAAS,WAAW,IAAI,IAAI,eAAG,IAAI,MAAG,CAAC,iBAAiB,EAAE,EAAE;AAClG,cAAU,QAAQ;AAElB,cAAU;AAAA,EACZ,UAAE;AACA,YAAQ,KAAK;AACb,WAAO,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAClD;AACF;AAEA,SAAS,UAAU,SAAyB;AAC1C,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,KAAK,GAAG,WAAW,IAAI,MAAM,QAAQ,QAAQ,SAAS,CAAC,oBAAoB,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EACzG;AACA,UAAQ,KAAK;AACf;AAGA,SAAS,UAAU,MAQP;AACV,QAAM,EAAE,OAAO,UAAU,gBAAgB,IAAI;AAC7C,QAAM,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,aAAa,SAAS;AAC/D,QAAM,YAAY,MAAM,OAAO,aAAa;AAC5C,QAAM,QAAQ,MAAM,OAAO,CAAC,SAAS,KAAK,aAAa,SAAS,CAAC,cAAc,IAAI,CAAC;AACpF,QAAM,UAAU,MAAM,OAAO,CAAC,SAAS,KAAK,aAAa,SAAS;AAElE,QAAM,cAAc,IAAI;AAAA,IACtB,MAAM,QAAQ,CAAC,SAAU,KAAK,aAAa,YAAY,CAAC,IAAI,OAAO,KAAK,KAAK,SAAS,CAAE;AAAA,EAC1F;AAEA,QAAM,UAAU,IAAI,IAAI,UAAU,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC;AAC5D,QAAM,mBAAmB,KAAK,UAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY,IAAI,GAAG,KAAK,CAAC,QAAQ,IAAI,eAAe,GAAG,CAAC,CAAC,EAC1E,IAAI,CAAC,QAA0B,CAAC,KAAK,cAAc,KAAK,OAAO,KAAK,QAAQ,CAAC,CAAC;AAEjF,QAAM,gBAAgB,IAAI,IAAI,KAAK,WAAW,IAAI,CAAC,aAAa,SAAS,IAAI,CAAC;AAC9E,QAAM,aAAa,IAAI,IAAI,CAAC,GAAG,MAAM,GAAG,KAAK,EAAE,QAAQ,CAAC,SAAS,KAAK,KAAK,CAAC;AAC5E,QAAM,iBAAiB,SAAS,aAC7B,OAAO,CAAC,SAAS,CAAC,cAAc,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,EACjE,IAAI,CAAC,SAA2B,CAAC,MAAM,WAAW,IAAI,IAAI,IAAI,uBAAuB,mBAAmB,CAAC;AAE5G,UAAQ,KAAK,eAAG,KAAK,UAAU,CAAC;AAChC,UAAQ,KAAK,OAAO;AACpB,MAAI,MAAM,WAAW,KAAK,iBAAiB,WAAW,KAAK,eAAe,WAAW,GAAG;AACtF,YAAQ,KAAK,GAAG,SAAS,2BAA2B;AACpD,YAAQ,KAAK;AACb,WAAO;AAAA,EACT;AAEA,aAAW,iBAAiB,MAAM,eAAe;AACjD,aAAW,iBAAiB,OAAO,eAAe;AAClD,aAAW,oBAAoB,WAAW,eAAe;AACzD,aAAW,WAAW,SAAS,eAAe;AAC9C,eAAa,oBAAoB,gBAAgB;AACjD,eAAa,kBAAkB,cAAc;AAE7C,QAAM,eAAe,OAAO,KAAK,KAAK,OAAO,EAAE;AAC/C,MAAI,eAAe,GAAG;AACpB,YAAQ,KAAK,eAAG,IAAI,GAAG,MAAM,cAAc,UAAU,CAAC,6CAA6C,CAAC;AAAA,EACtG;AACA,MAAI,MAAM,KAAK,UAAU,GAAG;AAC1B,YAAQ,KAAK,eAAG,IAAI,mEAA8D,CAAC;AAAA,EACrF;AACA,UAAQ,KAAK;AACb,SAAO,MAAM,SAAS,UAAU,SAAS,iBAAiB,SAAS,eAAe,SAAS;AAC7F;;;AJ9YA,SAAS,2BAA0E;AACjF,QAAM,QAAQ,oBAAI,IAAqC;AACvD,SAAO,CAAC,aAAa;AACnB,QAAI,SAAS,MAAM,IAAI,QAAQ;AAC/B,QAAI,WAAW,QAAW;AACxB,UAAI;AACF,iBAAS,KAAK,MAAMK,cAAaC,OAAK,UAAU,cAAc,GAAG,MAAM,CAAC;AAAA,MAC1E,QAAQ;AACN,iBAAS;AAAA,MACX;AACA,YAAM,IAAI,UAAU,UAAU,IAAI;AAAA,IACpC;AACA,WAAO,UAAU;AAAA,EACnB;AACF;AAEA,eAAsB,SAAS,QAAsC;AACnE,QAAM,EAAE,SAAS,IAAI;AAErB,QAAM,UAAU,cAAc,mCAAmC;AACjE,MAAI;AAEF,UAAM,CAAC,UAAU,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,MAChD,YAAY,CAAC,MAAM,YAAY,UAAU,QAAQ,GAAG,QAAQ;AAAA,MAC5D,aAAa,QAAQ;AAAA,IACvB,CAAC;AACD,QAAI,CAAC,UAAU;AACb,kBAAY,+DAA+D;AAC3E,cAAQ,KAAK,GAAG,WAAW,wDAAwD;AACnF;AAAA,IACF;AACA,UAAM,mBAAmB;AACzB,UAAM,eAAe,OAAO,KAAK,gBAAgB;AAEjD,QAAI,aAAa,WAAW,GAAG;AAC7B,qBAAe,6BAA6B;AAC5C,cAAQ,KAAK;AACb,YAAM,gBAAgB,UAAU,EAAE,OAAO,CAAC,OAAO,KAAK,CAAC;AACvD;AAAA,IACF;AAEA,UAAM,aAAa,cAAc,oBAAoB,WAAW,IAAI,CAAC;AACrE,UAAM,aAAa,CAAC,SAClB,WAAW,KAAK,CAAC,aAAa,WAAW,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE,aAAa,QAAQ,CAAC,KAAK;AACzG,UAAM,mBAAmB,yBAAyB;AAElD,UAAM,mBAA0C,aAAa,IAAI,CAAC,SAAS;AACzE,YAAM,MAAM,iBAAiB,IAAI;AACjC,YAAM,UAAU,WAAW,IAAI,gBAAgB,YAAY,GAAG;AAG9D,YAAM,WAAqB,CAAC;AAC5B,iBAAW,KAAK,IAAI,mBAAmB;AACrC,cAAM,OAAO,iBAAiB,EAAE,QAAQ,IAAI,IAAI,cAAc,IAAI,IAAI,KAAK;AAC3E,YAAI,QAAQ,CAAC,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,GAAG;AACnF,mBAAS,KAAK,EAAE,IAAI;AAAA,QACtB;AAAA,MACF;AAEA,aAAO;AAAA,QACL;AAAA,QACA,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI;AAAA,QACZ,mBAAmB,IAAI;AAAA,QACvB,OAAO,IAAI,mBAAmB;AAAA,QAC9B,eAAe,qBAAqB,IAAI,SAAS,IAAI,MAAM;AAAA,QAC3D;AAAA,QACA;AAAA,QACA,aAAa,eAAe,OAAO;AAAA,QACnC,UAAU,WAAW,IAAI;AAAA,MAC3B;AAAA,IACF,CAAC;AAED,qBAAiB,KAAK,CAAC,GAAG,MAAM;AAC9B,YAAM,aAAa,eAAe,CAAC,EAAE,cAAc,eAAe,CAAC,CAAC;AACpE,UAAI,eAAe,EAAG,QAAO;AAC7B,aAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,IACpC,CAAC;AAED,YAAQ,KAAK;AAEb,yBAAqB,kBAAkB,QAAQ;AAC/C,YAAQ,KAAK;AAGb,UAAM,UAAU,OAAO,OAAO,YAAY,MAAM,iBAAiB,kBAAkB,QAAQ;AAC3F,QAAI,YAAY,YAAa;AAC7B,QAAI,YAAY,UAAU;AACxB,cAAQ,KAAK,GAAG,WAAW,4DAA4D;AACvF;AAAA,IACF;AACA,UAAM,gBAAgB,UAAU,EAAE,OAAO,CAAC,OAAO,KAAK,CAAC;AAAA,EACzD,UAAE;AACA,YAAQ,KAAK;AAAA,EACf;AACF;AAGA,IAAM,iBAAiB,CAAC,QAAqC,iBAAiB,IAAI,kBAAkB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAEtH,SAAS,qBAAqB,kBAAyC,UAAwB;AAC7F,QAAM,UAAU;AAChB,QAAM,eAAe;AACrB,QAAM,qBAAqB;AAC3B,QAAM,aAAa,KAAK;AAAA,IACtB;AAAA,IACA,KAAK,IAAI,GAAG,GAAG,iBAAiB,IAAI,CAAC,MAAM,EAAE,KAAK,UAAU,EAAE,QAAQ,QAAQ,SAAS,EAAE,CAAC;AAAA,EAC5F;AACA,QAAM,gBAAgB,KAAK,IAAI,GAAG,GAAG,iBAAiB,IAAI,CAAC,MAAM,EAAE,QAAQ,MAAM,CAAC;AAClF,QAAM,eAAe,KAAK,IAAI,GAAG,GAAG,iBAAiB,IAAI,CAAC,MAAM,EAAE,OAAO,MAAM,CAAC;AAChF,QAAM,mBAAmB,KAAK;AAAA,IAC5B;AAAA,IACA,KAAK,IAAI,IAAI,GAAG,iBAAiB,IAAI,CAAC,MAAM,eAAe,CAAC,EAAE,MAAM,CAAC;AAAA,EACvE;AAGA,QAAM,SAAS;AAAA,IACb;AAAA,IACA,eAAG,KAAK,UAAU,OAAO,UAAU,CAAC;AAAA,IACpC,eAAG,KAAK,UAAU,OAAO,aAAa,CAAC;AAAA,IACvC,eAAG,KAAK,SAAS,OAAO,YAAY,CAAC;AAAA,IACrC,eAAG,KAAK,KAAK,OAAO,gBAAgB,CAAC;AAAA,IACrC,eAAG,KAAK,OAAO;AAAA,EACjB,EAAE,KAAK,GAAG;AAEV,UAAQ,KAAK,MAAM;AAEnB,aAAW,OAAO,kBAAkB;AAClC,UAAM,gBAAgB,IAAI,WAAW,YAAY,IAAI,QAAQ,IAAI;AAEjE,UAAM,WAAW,IAAI,QAAQ,GAAG,IAAI,IAAI,GAAG,OAAO,KAAK,IAAI;AAC3D,UAAM,cAAc,eAAe,UAAU,UAAU;AACvD,UAAM,OAAO,eAAG,MAAM,YAAY,OAAO,UAAU,CAAC;AAEpD,UAAM,UAAU,eAAG,IAAI,IAAI,QAAQ,OAAO,aAAa,CAAC;AACxD,UAAM,aAAa,IAAI,OAAO,OAAO,YAAY;AACjD,UAAM,SAAS,IAAI,gBAAgB,eAAG,KAAK,eAAG,MAAM,UAAU,CAAC,IAAI,eAAG,MAAM,UAAU;AAEtF,UAAM,aAAa,eAAG,IAAI,eAAe,eAAe,GAAG,GAAG,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;AAExG,UAAM,QAAkB,CAAC;AACzB,QAAI,IAAI,aAAa;AACnB,YAAM,KAAK,UAAU,eAAG,KAAK,KAAK,GAAG,IAAI,WAAW,CAAC;AAAA,IACvD;AACA,QAAI,IAAI,SAAS;AACf,YAAM,KAAK,UAAU,eAAG,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC;AAAA,IACpD;AAEA,UAAM,WAAW,MAAM,SAAS,IAAI,MAAM,KAAK,GAAG,IAAI,eAAG,IAAI,KAAK;AAElE,YAAQ,KAAK,GAAG,aAAa,IAAI,IAAI,IAAI,OAAO,IAAI,MAAM,IAAI,UAAU,IAAI,QAAQ,EAAE;AAAA,EACxF;AAGA,UAAQ,KAAK;AACb,QAAM,eAAe,oBAAI,IAAiD;AAC1E,aAAW,OAAO,kBAAkB;AAClC,eAAW,EAAE,MAAM,SAAS,KAAK,IAAI,mBAAmB;AACtD,YAAM,gBAAgB,QAAQC,UAAS,QAAQ;AAC/C,YAAM,WAAW,aAAa,IAAI,aAAa;AAC/C,UAAI,UAAU;AACZ,iBAAS;AAAA,MACX,OAAO;AACL,qBAAa,IAAI,eAAe,EAAE,UAAU,OAAO,EAAE,CAAC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACA,QAAM,mBAAmB,CAAC,GAAG,aAAa,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;AAC5F,QAAM,sBAAsB,KAAK,IAAI,GAAG,GAAG,iBAAiB,IAAI,CAAC,CAAC,IAAI,MAAM,KAAK,MAAM,CAAC;AACxF,aAAW,CAAC,eAAe,EAAE,UAAU,OAAAC,OAAM,CAAC,KAAK,kBAAkB;AACnE,UAAMC,mBAAkBH,OAAK,UAAU,cAAc;AACrD,UAAM,eAAeI,UAAS,UAAUD,gBAAe;AACvD,UAAM,aAAa,cAAc,OAAO,mBAAmB;AAC3D,YAAQ;AAAA,MACN,KAAK,eAAG,IAAI,QAAG,CAAC,IAAI,UAAU,KAAK,UAAU,cAAc,UAAUA,gBAAe,EAAE,CAAC,IAAI,eAAG,IAAI,GAAGD,MAAK,EAAE,CAAC;AAAA,IAC/G;AAAA,EACF;AACF;AAGA,SAAS,mBACP,UACsE;AACtE,QAAM,aAAa,CAAC,QAA6B;AAC/C,UAAM,SAAS,IAAI,QAAQ,eAAG,IAAI,QAAQ,IAAI;AAC9C,UAAM,UAAU,GAAG,eAAG,IAAI,IAAI,OAAO,CAAC,WAAM,eAAG,MAAM,IAAI,MAAM,CAAC;AAChE,UAAM,gBACJ,IAAI,SAAS,SAAS,IAAI,KAAK,WAAW,IAAI,eAAG,IAAI,aAAa,IAAI,SAAS,KAAK,IAAI,CAAC,EAAE,CAAC,KAAK;AACnG,WAAO;AAAA,MACL,MAAM,GAAG,IAAI,IAAI,GAAG,MAAM,KAAK,OAAO,GAAG,aAAa;AAAA,MACtD,OAAO,IAAI;AAAA,MACX,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,SAAS,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS,CAAC;AAC3D,QAAM,UAAU,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC;AAE9D,QAAM,UAAgF,CAAC;AAEvF,MAAI,OAAO,SAAS,GAAG;AACrB,YAAQ,KAAK,IAAI,UAAU,eAAG,OAAO,wBAAc,OAAO,MAAM,gBAAM,CAAC,CAAC;AACxE,YAAQ,KAAK,GAAG,OAAO,IAAI,UAAU,CAAC;AAAA,EACxC;AACA,MAAI,QAAQ,SAAS,GAAG;AACtB,QAAI,OAAO,SAAS,EAAG,SAAQ,KAAK,IAAI,UAAU,eAAG,IAAI,0BAAgB,QAAQ,MAAM,gBAAM,CAAC,CAAC;AAC/F,YAAQ,KAAK,GAAG,QAAQ,IAAI,UAAU,CAAC;AAAA,EACzC;AAEA,SAAO;AACT;AAGA,eAAe,iBAAiB,UAAiC,UAA0C;AACzG,MAAI;AACJ,MAAI;AACF,kBAAc,MAAMG,SAAQ,EAAE,SAAS,oBAAoB,SAAS,KAAK,CAAC;AAAA,EAC5E,QAAQ;AACN,WAAO;AAAA,EACT;AACA,UAAQ,KAAK;AACb,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,UAAU,mBAAmB,QAAQ;AAE3C,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,SAAS;AAAA,MACxB,SAAS;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,MAAM;AAAA,MACN,OAAO;AAAA,QACL,MAAM;AAAA,UACJ,QAAQ;AAAA,QACV;AAAA,QACA,OAAO;AAAA,UACL,WAAW,CAAC,SAAiB;AAAA,UAC7B,aAAa,CAAC,SAA6B;AACzC,kBAAM,OAAO,KAAK,IAAI,CAAC,CAAC,KAAK,MAAM,MAAwB,GAAG,eAAG,IAAI,GAAG,CAAC,IAAI,MAAM,EAAE;AACrF,mBAAO,KAAK,KAAK,IAAI;AAAA,UACvB;AAAA,UACA,uBAAuB,CAAC,oBACtB,eAAG,IAAI,GAAG,gBAAgB,MAAM,WAAW,gBAAgB,WAAW,IAAI,MAAM,EAAE,WAAW;AAAA,QACjG;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,SAAO,eAAe,UAAU,UAAU,QAAQ;AACpD;AAGA,eAAe,eACb,UACA,UACA,kBACwB;AACxB,UAAQ,KAAK;AACb,UAAQ,KAAK,eAAG,MAAM,mBAAc,iBAAiB,MAAM,WAAW,iBAAiB,WAAW,IAAI,MAAM,EAAE,EAAE,CAAC;AACjH,UAAQ,KAAK;AAEb,QAAM,gBAAgB,SAAS,OAAO,CAAC,MAAM,iBAAiB,SAAS,EAAE,IAAI,KAAK,EAAE,aAAa;AACjG,MAAI,cAAc,SAAS,GAAG;AAC5B,UAAM,aAAa,cAAc,IAAI,CAAC,MAAM,eAAG,KAAK,EAAE,IAAI,CAAC,EAAE,KAAK,IAAI;AACtE,QAAI;AACF,YAAM,UAAU,MAAMA,SAAQ;AAAA,QAC5B,SAAS,GAAG,cAAc,MAAM,gBAAgB,cAAc,SAAS,IAAI,MAAM,EAAE,cAAc,UAAU;AAAA,QAC3G,SAAS;AAAA,MACX,CAAC;AACD,UAAI,CAAC,SAAS;AACZ,gBAAQ,KAAK,eAAG,IAAI,oBAAoB,CAAC;AACzC,gBAAQ,KAAK;AACb,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,kBAAkB,wBAAwB,QAAQ;AAExD,QAAM,oBAAoB,oBAAI,IAAsB;AACpD,aAAW,WAAW,kBAAkB;AACtC,UAAM,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO;AACnD,QAAI,CAAC,IAAK;AAEV,eAAW,EAAE,MAAM,UAAU,KAAK,IAAI,mBAAmB;AACvD,YAAM,QAAQ,kBAAkB,IAAI,SAAS;AAC7C,UAAI,MAAO,OAAM,KAAK,OAAO;AAAA,UACxB,mBAAkB,IAAI,WAAW,CAAC,OAAO,CAAC;AAAA,IACjD;AAAA,EACF;AAKA,aAAW,CAAC,WAAW,IAAI,KAAK,mBAAmB;AACjD,UAAM,UAAU,KAAK,KAAK,IAAI;AAC9B,YAAQ,KAAK,GAAG,eAAG,KAAK,QAAG,CAAC,IAAI,eAAG,KAAK,SAAS,CAAC,KAAK,eAAG,IAAI,OAAO,CAAC,EAAE;AAAA,EAC1E;AAEA,UAAQ,KAAK;AAEb,QAAM,0BAA0B,iBAAiB,OAAO,CAAC,YAAY,gBAAgB,IAAI,OAAO,CAAC;AAEjG,MAAI,wBAAwB,SAAS,GAAG;AACtC,YAAQ,KAAK,eAAG,IAAI,kCAAkC,wBAAwB,KAAK,IAAI,CAAC,EAAE,CAAC;AAC3F,UAAM,kBAAkBC,WAAU,QAAQ,CAAC,MAAM,MAAM,GAAG,uBAAuB,GAAG;AAAA,MAClF,KAAK;AAAA,MACL,OAAO;AAAA,IACT,CAAC;AAED,YAAQ,KAAK;AACb,QAAI,gBAAgB,WAAW,GAAG;AAChC,cAAQ,MAAM,eAAG,IAAI,kDAA6C,gBAAgB,MAAM,GAAG,CAAC;AAC5F,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,SAASA,WAAU,QAAQ,CAAC,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,EAAE,KAAK,UAAU,OAAO,UAAU,CAAC;AAEnH,UAAQ,KAAK;AACb,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,MAAM,eAAG,IAAI,mCAA8B,OAAO,MAAM,GAAG,CAAC;AACpE,WAAO;AAAA,EACT;AACA,UAAQ,KAAK,eAAG,MAAM,UAAK,iBAAiB,MAAM,WAAW,iBAAiB,SAAS,IAAI,MAAM,EAAE,UAAU,CAAC;AAC9G,UAAQ,KAAK;AACb,SAAO;AACT;AAEA,SAAS,wBAAwB,UAA+B;AAC9D,QAAM,gBAAgBN,OAAK,UAAU,qBAAqB;AAC1D,MAAI;AACF,UAAM,UAAUD,cAAa,eAAe,MAAM;AAClD,WAAO,IAAI,IAAI,OAAO,KAAK,aAAa,SAAS,SAAS,KAAK,CAAC,CAAC,CAAC;AAAA,EACpE,QAAQ;AACN,WAAO,oBAAI,IAAI;AAAA,EACjB;AACF;;;AKpXA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,UAAAQ,eAAc;;;ACbvB,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,aAAAC,YAAW,iBAAAC,sBAAqB;AACzC,SAAS,UAAAC,eAAc;AACvB,SAAS,YAAAC,WAAU,QAAAC,cAAY;AAC/B,OAAOC,cAAa;AAYb,SAAS,YACd,KACA,OACA,UACA,UAAkC,CAAC,GAC3B;AACR,QAAM,OAAO,CAAC,QAAQ,YAAY;AAClC,MAAI,QAAQ,UAAW,MAAK,KAAK,uBAAuB,gBAAgB,QAAQ,SAAS,GAAG;AAC5F,OAAK,KAAK,OAAO,MAAM,QAAQ;AAE/B,MAAI;AACF,WAAOC,cAAa,OAAO,MAAM,EAAE,KAAK,WAAW,WAAW,CAAC;AAAA,EACjE,SAAS,OAAO;AACd,UAAM,SAAU,MAA8B,QAAQ,SAAS,EAAE,KAAK;AACtE,UAAM,IAAI,MAAM,UAAU,kBAAkB,QAAQ,EAAE;AAAA,EACxD;AACF;AAcA,SAAS,WAAW,MAAsB;AACxC,SAAO,KAAK,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,QAAQ;AACvG;AAUA,eAAsB,eAAe,OAAe,MAAqC;AAGvF,QAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,mBAAmB;AAE7D,QAAM,EAAE,gBAAgB,IAAI,MAAM,iBAAiB;AAAA,IACjD;AAAA,IACA,SAAS;AAAA,MACP,WAAW;AAAA,MACX,WAAW;AAAA,MACX,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,mBAAmB;AAAA,IACrB;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,GAAG,WAAW,KAAK,QAAQ,CAAC,SAAM,WAAW,KAAK,QAAQ,CAAC,OAAO,WAAW,KAAK,QAAQ,CAAC;AACzG,QAAM,OAAO,KAAK,OAAO,2BAAwB,WAAW,KAAK,IAAI,CAAC,YAAY;AAElF,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,SAKA,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UA+BJ,WAAW,KAAK,QAAQ,CAAC;AAAA,wBACX,WAAW,KAAK,QAAQ,CAAC,kBAAQ,WAAW,KAAK,QAAQ,CAAC,IAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxF,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAMjB;AAIA,SAAS,mBAAmB,QAAsB;AAChD,MAAI;AACF,IAAAA,cAAaC,SAAQ,aAAa,WAAW,SAAS,YAAY,CAAC,MAAM,GAAG,EAAE,OAAO,SAAS,CAAC;AAAA,EACjG,QAAQ;AAAA,EAER;AACF;AAWA,eAAsB,kBAAkB,OAAe,MAAoB,UAAmC;AAC5G,QAAM,OAAO,MAAM,eAAe,OAAO,IAAI;AAE7C,QAAM,MAAMC,OAAKC,QAAO,GAAG,cAAcC,UAAS,QAAQ,CAAC,EAAE;AAC7D,EAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,QAAM,UAAUH,OAAK,KAAK,GAAG,KAAK,SAAS,QAAQ,aAAa,GAAG,CAAC,OAAO;AAE3E,EAAAI,eAAc,SAAS,IAAI;AAC3B,qBAAmB,OAAO;AAC1B,SAAO;AACT;;;ACxJA,SAAS,UAAAC,eAAc;AACvB,SAAS,WAAAC,UAAS,QAAAC,QAAM,WAAAC,gBAAe;AAoBvC,eAAe,eAAe,UAAkB,KAAmC;AACjF,QAAM,MAAM,MAAM,IAAI,CAAC,WAAW,MAAM,eAAe,GAAG,GAAG,QAAQ;AACrE,SAAO,IAAI,IAAI,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO,CAAC;AAChD;AAUA,eAAsB,yBACpB,UACA,SACA,SACA,QACA,gBAA0B,CAAC,GACH;AAExB,QAAM,aAAa,MAAM,IAAI,CAAC,cAAc,SAAS,OAAO,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC,GAAG,KAAK,KAAK;AAE5G,QAAM,aAAa;AAAA,IACjB,WAAW,CAAC,SAAiB,UAAU,MAAM,MAAM,KAAK,iBAAiB,MAAM,aAAa;AAAA,IAC5F,UAAU,CAAC,SAAiB,SAAS,MAAM,MAAM;AAAA,EACnD;AAGA,QAAM,WAAW,MAAM,YAAY,UAAU,SAAS,SAAS,WAAW,UAAU;AACpF,QAAM,iBAAiB,UAAU,UAAU,WAAW,SAAS,OAAO;AAKtE,QAAM,YAAY,MAAM,eAAe,UAAU,OAAO;AACxD,QAAM,WAAW,oBAAI,IAAY,CAAC,GAAG,CAAC;AACtC,aAAW,KAAK,WAAW;AACzB,QAAI,MAAMC,SAAQ,CAAC;AACnB,WAAO,QAAQ,KAAK;AAClB,eAAS,IAAI,GAAG;AAChB,YAAMA,SAAQ,GAAG;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,QAAuB,CAAC;AAC9B,aAAW,QAAQ,UAAU;AAE3B,QAAI,KAAK,WAAW,YAAY,KAAK,WAAW,WAAY;AAC5D,QAAI,KAAK,aAAa,KAAK,SAAU;AAErC,UAAM,UAAU,KAAK;AACrB,UAAM,SAAS,KAAK;AAEpB,QAAI;AACJ,QAAI,WAAW,CAAC,QAAQ;AACtB,aAAO;AAAA,IACT,WAAW,CAAC,WAAW,QAAQ;AAG7B,UAAI,CAAC,SAAS,IAAIA,SAAQ,KAAK,IAAI,CAAC,EAAG;AACvC,aAAO;AAAA,IACT,OAAO;AACL,aAAO;AAAA,IACT;AAGA,UAAM,YAAY,KAAK,WAAW,aAAa,KAAK,oBAAoB,KAAK;AAC7E,UAAM,YAAY,KAAK,WAAW,aAAa,KAAK,oBAAoB,KAAK;AAC7E,UAAM,KAAK,EAAE,MAAM,KAAK,MAAM,MAAM,QAAQ,KAAK,QAAQ,WAAW,UAAU,CAAC;AAAA,EACjF;AAEA,SAAO;AACT;AAMA,eAAe,aACb,UACA,KACA,UACgD;AAChD,QAAM,OAAO,MAAM,IAAI,CAAC,WAAW,KAAK,MAAM,QAAQ,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC;AACzF,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,QAAQ,KAAK,MAAM,8BAA8B;AACvD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,CAAC,EAAE,MAAM,MAAM,IAAI,IAAI;AAC7B,MAAI,SAAS,OAAQ,QAAO;AAE5B,MAAI,SAAS,YAAY,SAAS,SAAU,QAAO;AACnD,SAAO,EAAE,MAAM,KAAK;AACtB;AAUA,eAAsB,mBACpB,UACA,SACA,SACA,OACA,UACqD;AACrD,QAAM,SAAS,WAAW,QAAQ;AAGlC,QAAM,SAASC,SAAQ,UAAU,MAAM,IAAI,CAAC,aAAa,WAAW,GAAG,QAAQ,CAAC;AAChF,QAAM,WAAWC,OAAK,QAAQ,qBAAqB,SAAS,QAAQ,YAAY,GAAG,CAAC,EAAE;AACtF,QAAM,WAAW,EAAE,gBAAgB,SAAS;AAE5C,MAAI;AAEF,UAAM,IAAI,CAAC,aAAa,OAAO,GAAG,UAAU,EAAE,KAAK,SAAS,CAAC;AAE7D,UAAM,eAAyB,CAAC;AAGhC,eAAW,EAAE,MAAM,KAAK,KAAK,OAAO;AAClC,UAAI,SAAS,WAAW;AACtB,cAAM,IAAI,CAAC,gBAAgB,YAAY,IAAI,GAAG,UAAU,EAAE,KAAK,UAAU,cAAc,KAAK,CAAC;AAC7F,qBAAa,KAAK,aAAa,IAAI,EAAE;AACrC;AAAA,MACF;AACA,YAAM,OAAO,MAAM,aAAa,UAAU,SAAS,IAAI;AACvD,UAAI,CAAC,KAAM;AACX,YAAM,YAAY,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AACnD,YAAM,IAAI,CAAC,gBAAgB,SAAS,aAAa,eAAe,SAAS,GAAG,UAAU,EAAE,KAAK,SAAS,CAAC;AACvG,mBAAa,KAAK,IAAI;AAAA,IACxB;AAEA,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO,EAAE,QAAQ,aAAa;AAAA,IAChC;AAGA,UAAM,WAAW,MAAM,IAAI,CAAC,YAAY,GAAG,UAAU,EAAE,KAAK,SAAS,CAAC;AACtE,UAAM,aAAa,MAAM,IAAI,CAAC,aAAa,OAAO,GAAG,QAAQ;AAC7D,UAAM,aAAa,aAAa,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI;AAC9D,UAAM,gBAAgB,WAAW,QAAQ,MAAM,aAAa,MAAM;AAAA;AAAA,EAAa,UAAU;AACzF,UAAM,aAAa,MAAM,IAAI,CAAC,eAAe,UAAU,MAAM,YAAY,MAAM,aAAa,GAAG,QAAQ;AAGvG,UAAM,IAAI,CAAC,cAAc,cAAc,MAAM,IAAI,UAAU,GAAG,QAAQ;AAEtE,WAAO,EAAE,QAAQ,aAAa;AAAA,EAChC,UAAE;AACA,IAAAC,QAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,EAClC;AACF;;;AC1LA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,WAAAC,UAAS,WAAAC,gBAAe;AAWjC,eAAsB,oBAAoB,UAAmC;AAC3E,QAAM,YAAY,MAAM,IAAI,CAAC,aAAa,kBAAkB,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC;AAC/F,SAAO,YAAYC,SAAQC,SAAQ,UAAU,SAAS,CAAC,IAAI;AAC7D;AAeO,SAAS,iBAAiB,MAAkB,UAAkB,gBAAgB,OAAsB;AACzG,QAAM,eAAeA,SAAQ,UAAU,KAAK,SAAS;AAGrD,MAAI,CAAC,aAAa,WAAWA,SAAQ,UAAU,IAAI,CAAC,GAAG;AACrD,WAAO,EAAE,MAAM,cAAc,OAAO,OAAO,OAAO,yCAAyC;AAAA,EAC7F;AACA,MAAI,CAACC,YAAW,YAAY,EAAG,QAAO,EAAE,MAAM,cAAc,OAAO,OAAO,OAAO,sBAAsB;AACvG,MAAI,CAACA,YAAW,GAAG,YAAY,OAAO,EAAG,QAAO,EAAE,MAAM,cAAc,OAAO,OAAO,OAAO,uBAAuB;AAClH,MAAI,iBAAiB,CAACA,YAAW,GAAG,YAAY,IAAI,WAAW,EAAE,GAAG;AAClE,WAAO,EAAE,MAAM,cAAc,OAAO,OAAO,OAAO,WAAW,WAAW,GAAG;AAAA,EAC7E;AAEA,SAAO,EAAE,MAAM,cAAc,OAAO,KAAK;AAC3C;AAOO,SAAS,iBAAiB,QAAsB;AACrD,UAAQ,KAAK,eAAG,OAAO,8CAA8C,CAAC;AACtE,UAAQ,KAAK,eAAG,IAAI,MAAM,CAAC;AAC3B,UAAQ,KAAK,eAAG,IAAI,kFAAkF,CAAC;AACzG;;;AHcA,IAAM,gBAAgB,aAAiD,CAAC,QAAQ,SAAS;AACvF,QAAM,EAAE,WAAW,IAAI,SAAS,QAAQ,KAAK,SAAS,IAAI;AAE1D,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,OAAO,KAAK;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,CAAC;AACtC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,EAAE;AAC7C,QAAM,CAAC,cAAc,eAAe,IAAI,SAA0B,MAAM;AAExE,cAAY,OAAO,QAAQ;AACzB,UAAM,OAAO,MAAM,SAAS;AAE5B,QAAI,MAAM,WAAW,GAAG;AACtB,UAAI,WAAW,GAAG,KAAK,IAAI,SAAS,KAAK;AACvC,wBAAgB,MAAM;AACtB,aAAK,CAAC,CAAC;AAAA,MACT;AACA;AAAA,IACF;AAEA,QAAI,IAAI,SAAS,KAAK;AACpB,sBAAgB,MAAM;AACtB,WAAK,CAAC,CAAC;AACP;AAAA,IACF;AAEA,QAAI,WAAW,GAAG,GAAG;AACnB,YAAM,WAAW,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO;AAC9C,UAAI,SAAS,WAAW,GAAG;AACzB,qBAAa,6CAA6C;AAC1D;AAAA,MACF;AACA,sBAAgB,MAAM;AACtB,WAAK,QAAQ;AACb;AAAA,IACF;AAGA,QAAI,IAAI,QAAQ,QAAQ,GAAG,GAAG;AAC5B,gBAAU,CAAC;AACX,mBAAa,EAAE;AACf;AAAA,IACF;AACA,QAAI,IAAI,QAAQ,UAAU,GAAG,GAAG;AAC9B,gBAAU,IAAI;AACd,mBAAa,EAAE;AACf;AAAA,IACF;AACA,QAAI,QAAQ,GAAG,GAAG;AAChB,gBAAU,UAAU,IAAI,IAAI,SAAS,CAAC;AACtC,mBAAa,EAAE;AACf;AAAA,IACF;AACA,QAAI,UAAU,GAAG,GAAG;AAClB,gBAAU,UAAU,OAAO,OAAO,SAAS,CAAC;AAC5C,mBAAa,EAAE;AACf;AAAA,IACF;AAEA,QAAI,WAAW,GAAG,GAAG;AACnB,eAAS,MAAM,IAAI,CAAC,MAAM,MAAO,MAAM,SAAS,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,QAAQ,IAAI,IAAK,CAAC;AAC5F;AAAA,IACF;AAGA,QAAI,IAAI,SAAS,KAAK;AACpB,YAAM,EAAE,KAAK,IAAI,MAAM,MAAM;AAC7B,UAAI;AACF,cAAM,QAAQ,YAAY,KAAK,GAAG,OAAO,KAAK,MAAM,IAAI,IAAI;AAC5D,YAAI,MAAM,WAAW,EAAG,QAAO,aAAa,kBAAkB,IAAI,EAAE;AACpE,cAAM,kBAAkB,MAAM,SAAS,GAAG,EAAE,UAAU,MAAM,UAAU,SAAS,UAAU,SAAS,GAAG,GAAG;AACxG,qBAAa,UAAU,IAAI,aAAa;AAAA,MAC1C,SAAS,OAAO;AACd,qBAAa,gBAAgB,aAAa,KAAK,CAAC,EAAE;AAAA,MACpD;AACA;AAAA,IACF;AAEA,QAAI,IAAI,SAAS,KAAK;AACpB,YAAM,aAAa,MAAM,MAAM,CAAC,SAAS,KAAK,OAAO;AACrD,eAAS,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,CAAC;AACjE,mBAAa,aAAa,mBAAmB,cAAc;AAC3D;AAAA,IACF;AAAA,EACF,CAAC;AAGD,MAAI,iBAAiB,QAAQ;AAC3B,UAAM,UAAU,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO;AAC7C,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO,GAAG,SAAS,IAAI,QAAQ,MAAM;AAAA,IACvC;AACA,WAAO,GAAG,SAAS;AAAA,EACrB;AAGA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,GAAG,SAAS;AAAA,EACrB;AAGA,QAAM,eAAe,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AAEpD,QAAM,OAAO,cAAc;AAAA,IACzB;AAAA,IACA;AAAA,IACA,WAAW,EAAE,MAAM,SAAS,GAAG;AAC7B,YAAMC,YAAW,KAAK,UAAU,eAAG,MAAM,QAAG,IAAI,eAAG,IAAI,QAAG;AAC1D,YAAM,SAAS,WAAW,eAAG,KAAK,QAAG,IAAI;AACzC,YAAM,WAAW,KAAK,SAAS,YAAY,eAAG,OAAO,oBAAiB,IAAI;AAC1E,YAAM,WAAW,KAAK,SAAS,YAAY,eAAG,OAAO,QAAQ,IAAI;AACjE,YAAM,YAAY,KAAK,WAAW,aAAa,eAAG,OAAO,kBAAa,IAAI;AAC1E,YAAM,YAAY,KAAK,YAAY,eAAG,IAAI,SAAM,KAAK,SAAS,EAAE,IAAI;AACpE,YAAM,OAAO,GAAG,MAAM,IAAIA,SAAQ,IAAI,KAAK,IAAI,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS;AAC7F,aAAO,WAAW,eAAG,KAAK,IAAI,IAAI;AAAA,IACpC;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AAED,QAAM,YACJ,eAAe,IAAI,GAAG,MAAM,MAAM,WAAW,eAAG,MAAM,GAAG,YAAY,WAAW,CAAC,KAAK,GAAG,MAAM,MAAM;AACvG,QAAM,SAAS,GAAG,eAAG,KAAK,QAAG,CAAC,IAAI,OAAO,OAAO,IAAI,eAAG,IAAI,IAAI,SAAS,GAAG,CAAC;AAE5E,QAAM,OAA2B;AAAA,IAC/B,CAAC,gBAAM,UAAU;AAAA,IACjB,CAAC,KAAK,iBAAiB;AAAA,IACvB,CAAC,KAAK,gBAAgB;AAAA,IACtB,CAAC,SAAS,QAAQ;AAAA,IAClB,CAAC,UAAK,QAAQ;AAAA,IACd,CAAC,KAAK,MAAM;AAAA,EACd;AACA,QAAM,WAAW,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,eAAG,KAAK,CAAC,CAAC,IAAI,eAAG,IAAI,CAAC,CAAC,EAAE,EAAE,KAAK,eAAG,IAAI,QAAK,CAAC;AAEtF,QAAM,aAAa,YAAY,KAAK,eAAG,IAAI,SAAS,CAAC,KAAK;AAE1D,QAAM,QAAQ,CAAC,QAAQ,MAAM,YAAY,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,EAAE,QAAQ;AACtF,SAAO,GAAG,KAAK;AACjB,CAAC;AAOD,eAAe,WAAW,QAAuB,WAAgE;AAC/G,MAAI,OAAO,MAAM;AACf,UAAM,QAAQ,UAAU,KAAK,CAAC,MAAM,EAAE,KAAK,SAAS,OAAO,IAAI;AAC/D,QAAI,CAAC,OAAO,OAAO;AACjB,YAAM,IAAI,MAAM,SAAS,OAAO,IAAI,kCAAkC;AAAA,IACxE;AACA,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,MAAM;AACf,UAAM,aAAa,UAAU,OAAO,CAAC,MAAM,EAAE,KAAK;AAClD,QAAI,WAAW,WAAW,EAAG,OAAM,IAAI,MAAM,2BAA2B;AACxE,QAAI,WAAW,SAAS,EAAG,OAAM,IAAI,MAAM,6DAA6D;AACxG,WAAO,WAAW,CAAC;AAAA,EACrB;AAEA,QAAM,UAAU,UAAU,IAAI,CAAC,OAAO;AAAA,IACpC,OAAO,EAAE,KAAK;AAAA,IACd,MAAM,EAAE,QACJ,GAAG,EAAE,KAAK,IAAI,KAAK,eAAG,IAAI,IAAI,EAAE,KAAK,UAAU,KAAK,EAAE,KAAK,SAAS,EAAE,CAAC,KACvE,GAAG,EAAE,KAAK,IAAI,KAAK,eAAG,IAAI,EAAE,KAAK,SAAS,CAAC;AAAA,IAC/C,UAAU,EAAE,QAAQ,QAAS,EAAE,SAAS;AAAA,EAC1C,EAAE;AACF,QAAM,SAAS,MAAMC,QAAe;AAAA,IAClC,SAAS;AAAA,IACT;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AACD,QAAM,WAAW,UAAU,KAAK,CAAC,MAAM,EAAE,KAAK,SAAS,MAAM;AAC7D,MAAI,CAAC,SAAU,SAAQ,KAAK,eAAG,IAAI,mBAAmB,CAAC;AACvD,SAAO;AACT;AAGA,eAAe,YAAY,WAAmB,SAAyD;AACrG,QAAM,MAAM,MAAM,IAAI,CAAC,OAAO,MAAM,sBAAsB,OAAO,GAAG,WAAW,EAAE,cAAc,KAAK,CAAC;AACrG,QAAM,CAAC,MAAM,QAAQ,MAAM,GAAG,CAAC,GAAG,OAAO,SAAS,IAAI,IAAI,MAAM,GAAI;AACpE,SAAO,EAAE,KAAK,KAAK;AACrB;AASA,eAAsB,iBAAiB,QAAsC;AAC3E,QAAM,QAAQ,OAAO,SAAS,CAAC;AAE/B,MAAI,MAAM,WAAW,GAAG;AACtB,qBAAiB,uCAAuC;AACxD;AAAA,EACF;AAIA,QAAM,UAAU,MAAM,iBAAiB,OAAO,QAAQ;AAKtD,MAAI,YAAY,gBAAgB;AAC9B,YAAQ;AAAA,MACN,GAAG,WAAW,IAAI,eAAG,OAAO,uBAAuB,cAAc,GAAG,CAAC,IAAI,eAAG,IAAI,4BAA4B,OAAO,GAAG,CAAC;AAAA,IACzH;AACA,YAAQ;AAAA,MACN,KAAK,eAAG,IAAI,gEAAgE,cAAc,2BAA2B,CAAC;AAAA,IACxH;AACA,YAAQ,KAAK,EAAE;AAAA,EACjB;AAEA,QAAM,eAAe,MAAM,oBAAoB,OAAO,QAAQ;AAC9D,QAAM,YAAY,MAAM,IAAI,CAACC,UAAS,iBAAiBA,OAAM,YAAY,CAAC;AAE1E,QAAM,eAAe,MAAM,WAAW,QAAQ,SAAS;AACvD,MAAI,CAAC,aAAc;AAEnB,QAAM,EAAE,MAAM,aAAa,IAAI;AAC/B,QAAM,WAAW,KAAK;AAEtB,gBAAc,+BAA+B;AAC7C,QAAM,WAA0B,CAAC;AACjC,MAAI,aAAuE;AAC3E,MAAI,SAAS;AAEb,MAAI;AAEF,UAAM,IAAI,CAAC,SAAS,KAAK,aAAa,cAAc,KAAK,UAAU,GAAG,OAAO,QAAQ;AACrF,UAAM,UAAU,MAAM,IAAI,CAAC,aAAa,YAAY,GAAG,OAAO,QAAQ;AACtE,UAAM,OAAO,MAAM,YAAY,OAAO,UAAU,OAAO;AACvD,iBAAa,EAAE,YAAY,KAAK,YAAY,KAAK,KAAK,KAAK,MAAM,KAAK,KAAK;AAG3E,QAAI,gBAA0B,CAAC;AAC/B,QAAI;AACF,YAAM,aAAa,MAAM,WAAW,YAAY;AAChD,sBAAgB,WAAW,WAAW,WAAW,CAAC;AAAA,IACpD,QAAQ;AAAA,IAER;AAEA,UAAM,QAAQ,MAAM,yBAAyB,OAAO,UAAU,SAAS,SAAS,QAAQ,aAAa;AACrG,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,QAAQ,MAAM,mBAAmB,OAAO,UAAU,SAAS,SAAS,OAAO,QAAQ;AACzF,UAAI,MAAM,aAAa,SAAS,GAAG;AACjC,iBAAS,MAAM;AACf,cAAM,OAAO,MAAM,YAAY,OAAO,UAAU,SAAS,MAAM;AAC/D,mBAAW,QAAQ,OAAO;AACxB,gBAAM,EAAE,YAAY,MAAM,YAAY,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AACvE,mBAAS,KAAK,EAAE,GAAG,MAAM,WAAW,WAAW,SAAS,MAAM,CAAC;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,gBAAY,kBAAkB,QAAQ,EAAE;AACxC,YAAQ,KAAK,eAAG,IAAI,YAAO,aAAa,KAAK,CAAC,EAAE,CAAC;AACjD;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,GAAG;AACzB,mBAAe,wBAAwB;AACvC;AAAA,EACF;AAIA,WAAS,KAAK,CAAC,GAAG,OAAO,EAAE,aAAa,MAAM,EAAE,aAAa,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAE/F,iBAAe,GAAG,SAAS,MAAM,eAAe,QAAQ,EAAE;AAI1D,MAAI,YAAY;AACd,YAAQ;AAAA,MACN,KAAK,eAAG,IAAI,GAAG,QAAQ,0BAA0B,WAAW,UAAU,OAAO,WAAW,GAAG,KAAK,WAAW,IAAI,8CAA8C,CAAC;AAAA,IAChK;AAAA,EACF;AAGA,MAAI,OAAO,MAAM;AACf,UAAM,MAAM,SAAS,IAAI,CAAC,UAAU;AAAA,MAClC,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK,SAAS,YAAY,YAAY;AAAA,MAC5C,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,IAClB,EAAE;AACF,gBAAY,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AACxC;AAAA,EACF;AAEA,UAAQ,KAAK;AACb,UAAQ,KAAK,OAAO;AAEpB,QAAM,WAAW,MAAM,cAAc;AAAA,IACnC,SAAS,sBAAsB,QAAQ;AAAA,IACvC,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,OAAO;AAAA,IACZ,UAAU;AAAA,EACZ,CAAC;AAED,MAAI,SAAS,WAAW,GAAG;AACzB,YAAQ,KAAK;AACb;AAAA,EACF;AAGA,gBAAc,YAAY,SAAS,MAAM,WAAW;AACpD,QAAM,gBAAgB,eAAe,OAAO,QAAQ;AAEpD,MAAI,UAAU;AACd,QAAM,SAAmB,CAAC;AAE1B,aAAW,QAAQ,UAAU;AAC3B,QAAI;AAEF,UAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,WAAW,GAAG,GAAG;AACzD,eAAO,KAAK,GAAG,KAAK,IAAI,6BAA6B;AACrD;AAAA,MACF;AACA,UAAI,KAAK,SAAS,WAAW;AAC3B,YAAI,eAAe;AACjB,gBAAM,uBAAuB,OAAO,UAAU,KAAK,IAAI;AAAA,QACzD,OAAO;AACL,gBAAM,MAAM,OAAO,UAAU,CAAC,KAAK,IAAI,CAAC;AAAA,QAC1C;AAAA,MACF,OAAO;AACL,YAAI,eAAe;AACjB,gBAAM,uBAAuB,OAAO,UAAU,QAAQ,KAAK,IAAI;AAAA,QACjE,OAAO;AACL,gBAAM,gBAAgB,OAAO,UAAU,QAAQ,CAAC,KAAK,IAAI,CAAC;AAAA,QAC5D;AAAA,MACF;AACA;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,GAAG,KAAK,IAAI,KAAK,aAAa,KAAK,CAAC,EAAE;AAAA,IACpD;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,GAAG;AACrB,gBAAY,WAAW,OAAO,IAAI,SAAS,MAAM,WAAW,OAAO,MAAM,UAAU;AACnF,eAAW,OAAO,QAAQ;AACxB,cAAQ,KAAK,eAAG,IAAI,YAAO,GAAG,EAAE,CAAC;AAAA,IACnC;AAAA,EACF,OAAO;AACL,mBAAe,WAAW,OAAO,UAAU,eAAG,IAAI,gBAAgB,eAAe,UAAU,CAAC,EAAE;AAAA,EAChG;AAGA,UAAQ,KAAK;AACb,UAAQ;AAAA,IACN,eAAG;AAAA,MACD,gBACI,6EACA;AAAA,IACN;AAAA,EACF;AACA,UAAQ,KAAK;AACf;;;AIpbA,SAAS,WAAAC,gBAAe;AACxB,OAAOC,cAAa;AACpB,SAAS,aAAAC,YAAW,UAAAC,eAAc;;;ACAlC,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,UAAAC,eAAc;;;ACDvB,SAAS,aAAAC,kBAAiB;AAiBnB,SAAS,cAAuB;AACrC,SAAOA,WAAU,MAAM,CAAC,WAAW,GAAG,EAAE,OAAO,SAAS,CAAC,EAAE,WAAW;AACxE;AAGA,SAAS,MAAM,KAAa,MAA0B;AACpD,QAAM,SAASA,WAAU,MAAM,MAAM,EAAE,KAAK,UAAU,QAAQ,OAAO,CAAC,UAAU,QAAQ,MAAM,EAAE,CAAC;AACjG,QAAM,SAAS,GAAG,OAAO,UAAU,EAAE,GAAG,OAAO,UAAU,EAAE,GAAG,KAAK;AACnE,SAAO,EAAE,IAAI,OAAO,WAAW,GAAG,OAAO;AAC3C;AAMO,SAAS,gBAAgB,KAAa,QAAiC;AAC5E,QAAM,EAAE,IAAI,OAAO,IAAI,MAAM,KAAK;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,CAAC,MAAM,CAAC,OAAQ,QAAO,CAAC;AAE5B,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,MAAM;AAAA,EAC5B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,OAAO,OAAO,CAAC,OAAO,GAAG,YAAY,WAAW,GAAG,MAAM,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC1G;AAGO,SAAS,cAAc,KAAa,KAAsB,UAAsC,CAAC,GAAa;AACnH,SAAO,MAAM,KAAK,CAAC,MAAM,SAAS,OAAO,GAAG,GAAG,YAAY,GAAI,QAAQ,eAAe,CAAC,iBAAiB,IAAI,CAAC,CAAE,CAAC;AAClH;AAGO,SAAS,QAAQ,KAAa,KAAgC;AACnE,SAAO,MAAM,KAAK,CAAC,MAAM,SAAS,OAAO,GAAG,CAAC,CAAC;AAChD;;;ACtDA,SAAS,cAAAC,cAAY,gBAAAC,eAAc,iBAAAC,sBAAqB;AACxD,SAAS,QAAAC,cAAY;;;ACNrB,SAAS,cAAAC,aAAY,gBAAAC,eAAc,gBAAgB;AACnD,SAAS,QAAAC,cAAY;AAwBrB,IAAM,iBAAiB,OAAO;AAE9B,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;AAGA,SAAS,eAAe,UAA0B;AAChD,MAAI;AACF,QAAI,SAAS,QAAQ,EAAE,OAAO,eAAgB,QAAO;AACrD,UAAM,OAAOC,cAAa,UAAU,MAAM;AAC1C,WAAO,KAAK,SAAS,IAAI,IAAI,KAAK;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,UAAkB,MAA0B;AAC9D,MAAI;AACJ,SAAO,EAAE,MAAM,OAAO,MAAM,MAAM,MAAO,SAAS,eAAeC,OAAK,UAAU,IAAI,CAAC,EAAG;AAC1F;AAEA,eAAe,iBAAiB,UAAkB,KAAa,MAA+C;AAC5G,MAAI;AACF,WAAO,KAAK,MAAM,MAAM,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,IAAI,EAAE,GAAG,QAAQ,CAAC,EAAE,WAAW,CAAC;AAAA,EACjF,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAGA,eAAe,cACb,UACA,aACA,SACA,MACuB;AACvB,MAAI;AACJ,MAAI;AACF,kBAAc,KAAK,MAAMD,cAAaC,OAAK,UAAU,IAAI,GAAG,MAAM,CAAC,EAAE,WAAW,CAAC;AAAA,EACnF,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,QAAM,cAAc,MAAM,iBAAiB,UAAU,SAAS,IAAI;AAClE,QAAM,kBAAkB,MAAM,iBAAiB,UAAU,aAAa,IAAI;AAE1E,SAAO,OAAO,QAAQ,WAAW,EAC9B,OAAO,CAAC,CAAC,MAAM,KAAK,MAAM,UAAU,YAAY,IAAI,KAAK,UAAU,gBAAgB,IAAI,CAAC,EACxF,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,aAAa,IAAI,KAAK,MAAM,MAAM,MAAM,EAAE;AAC7F;AAGA,SAAS,SAAS,UAAkB,UAAkB,MAAwB;AAC5E,QAAM,WAAW,KAAK,MAAM,GAAG,EAAE,IAAI;AACrC,aAAW,OAAO,CAACA,OAAK,UAAU,QAAQ,GAAG,QAAQ,GAAG;AACtD,UAAM,WAAWA,OAAK,KAAK,gBAAgB,MAAM,cAAc;AAC/D,QAAI,CAACC,YAAW,QAAQ,EAAG;AAC3B,QAAI;AACF,YAAM,EAAE,IAAI,IAAI,KAAK,MAAMF,cAAa,UAAU,MAAM,CAAC;AACzD,UAAI,OAAO,QAAQ,SAAU,QAAO,CAAC,QAAQ;AAC7C,aAAO,OAAO,OAAO,QAAQ,WAAW,OAAO,KAAK,GAAG,IAAI,CAAC;AAAA,IAC9D,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AACA,SAAO,CAAC,QAAQ;AAClB;AAMA,SAAS,gBAAgB,UAAkB,UAAkB,MAAwB;AACnF,QAAM,aAAa,CAAC,IAAI;AACxB,QAAM,QAAQ,KAAK,MAAM,gBAAgB;AACzC,MAAI,MAAO,YAAW,KAAK,MAAM,CAAC,EAAE,SAAS,IAAI,IAAI,IAAI,MAAM,CAAC,EAAE,QAAQ,MAAM,GAAG,CAAC,KAAK,MAAM,CAAC,CAAC;AAEjG,QAAM,WAAW,WAAW,IAAI,CAAC,cAAc,IAAI,OAAO,WAAW,aAAa,SAAS,CAAC,sBAAsB,CAAC;AACnH,aAAW,OAAO,SAAS,UAAU,UAAU,IAAI,GAAG;AACpD,aAAS,KAAK,IAAI,OAAO,uBAAuB,aAAa,GAAG,CAAC,uBAAuB,GAAG,CAAC;AAAA,EAC9F;AACA,SAAO;AACT;AAGA,SAAS,cAAc,MAAsB;AAC3C,SAAO,IAAI,OAAO,kDAAkD,aAAa,IAAI,CAAC,uBAAuB,GAAG;AAClH;AAOA,eAAsB,cAAc,UAAkB,aAAqB,SAAqC;AAC9G,QAAM,OAAO,MAAM,IAAI,CAAC,QAAQ,eAAe,MAAM,mBAAmB,WAAW,GAAG,QAAQ;AAC9F,QAAM,UAAwB,CAAC;AAE/B,aAAW,QAAQ,KAAK,MAAM,IAAI,EAAE,OAAO,OAAO,GAAG;AACnD,QAAI,cAAc,IAAI,EAAG,SAAQ,KAAK,GAAI,MAAM,cAAc,UAAU,aAAa,SAAS,IAAI,CAAE;AAAA,aAC3F,CAAC,cAAc,IAAI,EAAG,SAAQ,KAAK,WAAW,UAAU,IAAI,CAAC;AAAA,EACxE;AAEA,QAAM,SAAS,CAAC,QAAsB,aACpC,OAAO,KAAK,CAAC,WAAW,SAAS,KAAK,CAAC,YAAY,QAAQ,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG;AAEpF,SAAO;AAAA,IACL,aAAa,CAAC,UAAU,SACtB;AAAA,MACE,WAAW,QAAQ,OAAO,CAAC,WAAW,iBAAiB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI;AAAA,MACnF,gBAAgB,UAAU,UAAU,IAAI;AAAA,IAC1C;AAAA,IACF,YAAY,CAAC,SAAS,OAAO,SAAS,CAAC,cAAc,IAAI,CAAC,CAAC;AAAA,EAC7D;AACF;;;AD3GA,SAAS,gBAAgB,iBAAyB,aAA8B;AAC9E,MAAI,oBAAoB,YAAa,QAAO;AAE5C,QAAM,YAAY,uBAAuB,eAAe;AACxD,QAAM,cAAc,uBAAuB,WAAW;AAEtD,MAAI,CAAC,aAAa,CAAC,YAAa,QAAO;AAEvC,SAAO,gBAAgB,WAAW,WAAW,IAAI;AACnD;AAsBA,IAAM,kBAAiD;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAaA,SAAS,YACP,YACA,gBACA,YACA,EAAE,aAAa,MAAM,SAAS,gBAAgB,MAAM,IAAwB,CAAC,GAC9C;AAC/B,MAAI,CAAC,eAAgB,QAAO;AAE5B,QAAM,SAAS,EAAE,GAAI,cAAc,CAAC,EAAG;AACvC,QAAM,OAAO,cAAc,CAAC;AAC5B,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAAoB,CAAC;AAC3B,QAAM,OAAkC,CAAC;AAEzC,aAAW,CAAC,MAAM,aAAa,KAAK,OAAO,QAAQ,cAAc,GAAG;AAClE,UAAM,YAAY,OAAO,IAAI;AAE7B,QAAI,cAAc,QAAW;AAE3B,UAAI,QAAQ,KAAM;AAClB,aAAO,IAAI,IAAI;AACf,YAAM,KAAK,IAAI;AAAA,IACjB,WAAW,cAAc,eAAe;AAAA,IACxC,WAAW,KAAK,IAAI,MAAM,WAAW;AAEnC,aAAO,IAAI,IAAI;AACf,cAAQ,KAAK,IAAI;AAAA,IACnB,WAAW,cAAc,gBAAgB,eAAe,SAAS,GAAG;AAElE,aAAO,IAAI,IAAI;AACf,cAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,EAEF;AAGA,aAAW,CAAC,MAAM,SAAS,KAAK,OAAO,QAAQ,MAAM,GAAG;AACtD,QAAI,QAAQ,eAAgB;AAC5B,QAAI,KAAK,IAAI,MAAM,UAAa,KAAK,IAAI,MAAM,UAAW;AAC1D,UAAM,SAAS,UAAU,IAAI;AAC7B,QAAI,QAAQ;AACV,WAAK,KAAK,EAAE,MAAM,OAAO,CAAC;AAC1B;AAAA,IACF;AACA,WAAO,OAAO,IAAI;AAClB,YAAQ,KAAK,IAAI;AAAA,EACnB;AAEA,QAAM,OAAO,gBACT,kBAAkB,OAAO,KAAK,MAAM,GAAG,OAAO,KAAK,cAAc,CAAC,IAClE,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AACzD,QAAM,UAAU,OAAO,YAAY,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,OAAO,IAAI,CAAC,CAAC,CAAC;AAC3E,QAAM,UAAU,MAAM,SAAS,QAAQ,SAAS,QAAQ,SAAS;AACjE,SAAO,EAAE,QAAQ,SAAS,SAAS,OAAO,SAAS,SAAS,KAAK;AACnE;AAMA,SAAS,kBAAkB,UAAoB,cAAkC;AAC/E,QAAM,WAAW,IAAI,IAAI,YAAY;AACrC,QAAM,gBAAgB,oBAAI,IAAkC;AAC5D,MAAI;AACJ,aAAW,OAAO,UAAU;AAC1B,QAAI,SAAS,IAAI,GAAG,EAAG,UAAS;AAAA,QAC3B,eAAc,IAAI,QAAQ,CAAC,GAAI,cAAc,IAAI,MAAM,KAAK,CAAC,GAAI,GAAG,CAAC;AAAA,EAC5E;AAEA,QAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,QAAM,UAAU,CAAC,GAAI,cAAc,IAAI,MAAS,KAAK,CAAC,CAAE;AACxD,aAAW,OAAO,cAAc;AAC9B,QAAI,QAAQ,IAAI,GAAG,EAAG,SAAQ,KAAK,GAAG;AACtC,YAAQ,KAAK,GAAI,cAAc,IAAI,GAAG,KAAK,CAAC,CAAE;AAAA,EAChD;AACA,SAAO;AACT;AAGA,SAAS,aAAa,OAAkD;AACtE,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,SAAO,OAAO,KAAK,KAAK,EAAE,MAAM,CAAC,SAAS,KAAK,WAAW,GAAG,CAAC;AAChE;AAOA,SAAS,iBACP,aACA,iBACoF;AACpF,MAAI,CAAC,aAAa,eAAe,EAAG,QAAO;AAC3C,MAAI,gBAAgB,UAAa,CAAC,aAAa,WAAW,EAAG,QAAO;AAEpE,QAAM,SAAS,EAAE,GAAI,eAAe,CAAC,EAAG;AACxC,QAAM,QAAQ,OAAO,KAAK,eAAe,EAAE,OAAO,CAAC,SAAS,EAAE,QAAQ,OAAO;AAC7E,aAAW,QAAQ,MAAO,QAAO,IAAI,IAAI,gBAAgB,IAAI;AAE7D,SAAO,EAAE,QAAQ,SAAS,MAAM,SAAS,GAAG,MAAM;AACpD;AAMA,SAAS,cACP,UACA,cACA,UAC+D;AAC/D,MAAI,CAAC,aAAc,QAAO;AAE1B,QAAM,SAA2C,EAAE,GAAI,YAAY,CAAC,EAAG;AACvE,MAAI,UAAU;AAGd,aAAW,OAAO,CAAC,aAAa,qBAAqB,GAAY;AAC/D,UAAM,SAAS,YAAY,OAAO,GAAG,GAAG,aAAa,GAAG,GAAG,WAAW,GAAG,GAAG,EAAE,YAAY,QAAQ,YAAY,CAAC;AAC/G,QAAI,QAAQ,SAAS;AACnB,aAAO,GAAG,IAAI,OAAO;AACrB,gBAAU;AAAA,IACZ;AAAA,EACF;AAGA,MAAI,aAAa,mBAAmB;AAClC,UAAM,WAAY,OAAO,qBAAqB,CAAC;AAC/C,UAAM,eAAe,aAAa;AAElC,eAAW,CAAC,KAAK,WAAW,KAAK,OAAO,QAAQ,YAAY,GAAG;AAC7D,UAAI,EAAE,OAAO,WAAW;AACtB,iBAAS,GAAG,IAAI;AAChB,kBAAU;AAAA,MACZ,OAAO;AACL,mBAAW,CAAC,QAAQ,QAAQ,KAAK,OAAO,QAAQ,WAAW,GAAG;AAC5D,cAAI,EAAE,UAAU,SAAS,GAAG,IAAI;AAC9B,qBAAS,GAAG,EAAE,MAAM,IAAI;AACxB,sBAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,oBAAoB;AAAA,EAC7B;AAGA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACvD,QAAI,CAAC,aAAa,uBAAuB,mBAAmB,EAAE,SAAS,GAAG,EAAG;AAC7E,QAAI,EAAE,OAAO,SAAS;AACpB,aAAO,GAAG,IAAI;AACd,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ,QAAQ;AAC3B;AAUA,SAAS,gBACP,UACA,cACA,UAC+E;AAC/E,QAAM,WAAW,CAAC,UAAoB,OAAO,UAAU,WAAW,QAAQ;AAC1E,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,WAAW,SAAS,YAAY;AACtC,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI,SAAS,OAAW,QAAO,EAAE,OAAO,UAAU,QAAQ,QAAQ;AAClE,MAAI,SAAS,SAAS,QAAQ,EAAG,QAAO;AACxC,SAAO,EAAE,OAAO,UAAU,QAAQ,aAAa,SAAY,YAAY,UAAU;AACnF;AAOA,SAAS,eAAe,KAAkB,KAAa,OAAsB;AAC3E,MAAI,OAAO,KAAK;AACd,QAAI,GAAG,IAAI;AACX;AAAA,EACF;AACA,QAAM,UAAU,OAAO,QAAQ,GAAG;AAClC,QAAM,QAAQ,KAAK,IAAI,GAAG,CAAC,QAAQ,WAAW,SAAS,EAAE,IAAI,CAAC,SAAS,QAAQ,UAAU,CAAC,CAAC,CAAC,MAAM,MAAM,IAAI,CAAC,CAAC;AAC9G,UAAQ,OAAO,QAAQ,GAAG,GAAG,CAAC,KAAK,KAAK,CAAC;AACzC,aAAW,QAAQ,OAAO,KAAK,GAAG,EAAG,QAAO,IAAI,IAAI;AACpD,SAAO,OAAO,KAAK,OAAO,YAAY,OAAO,CAAC;AAChD;AAGA,SAAS,gBAAgB,UAAsC;AAC7D,MAAI,CAACG,aAAW,QAAQ,EAAG,QAAO;AAClC,MAAI;AACF,WAAO,KAAK,MAAMC,cAAa,UAAU,MAAM,CAAC;AAAA,EAClD,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,gBAAgB,QAAQ,KAAK,aAAa,KAAK,CAAC,EAAE;AAAA,EACpE;AACF;AAGA,SAAS,gBAAgB,cAA8B;AACrD,SAAO,eAAe,GAAG,YAAY,kBAAkB;AACzD;AAGA,eAAe,qBACb,UACA,KACA,cACoD;AACpD,MAAI;AACF,UAAM,MAAM,MAAM,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,gBAAgB,YAAY,CAAC,EAAE,GAAG,QAAQ;AACnF,WAAO,EAAE,KAAK,MAAM,KAAK,MAAM,GAAG,EAAE;AAAA,EACtC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAe,yBAAyB,UAAkB,aAAwC;AAChG,QAAM,SAAS,MAAM,IAAI,CAAC,WAAW,MAAM,eAAe,WAAW,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC;AACxG,SAAO,OACJ,MAAM,IAAI,EACV,OAAO,CAAC,MAAM,EAAE,SAAS,eAAe,KAAK,MAAM,cAAc,EACjE,IAAI,CAAC,MAAO,MAAM,iBAAiB,KAAK,EAAE,QAAQ,iBAAiB,EAAE,CAAE;AAC5E;AAMA,eAAe,iBAAiB,UAAkB,aAA6C;AAC7F,MAAI;AACF,YAAQ,MAAM,sBAAsB,UAAU,QAAQ,WAAW,GAAG,QAAQ;AAAA,EAC9E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYA,eAAe,gBACb,QACA,SACA,OACA,cACA,YACkE;AAClE,QAAM,EAAE,UAAU,YAAY,IAAI;AAClC,QAAM,UAAoB,CAAC;AAC3B,QAAM,OAAiB,CAAC;AACxB,QAAM,aAAa,gBAAgB,YAAY;AAC/C,QAAM,UAAUC,OAAK,UAAU,UAAU;AAEzC,QAAM,UAAU,gBAAgB,OAAO;AACvC,QAAM,WAAW,MAAM,qBAAqB,UAAU,aAAa,YAAY;AAC/E,QAAM,UAAU,WAAW,MAAM,qBAAqB,UAAU,SAAS,YAAY,IAAI,OAAO;AAEhG,MAAI,CAAC,SAAU,QAAO,EAAE,SAAS,OAAO,SAAS,KAAK;AAEtD,MAAI,CAAC,SAAS;AACZ,UAAM,mBAAmB,iBAAiB,MAAMF,aAAWE,OAAK,UAAU,YAAY,CAAC;AACvF,QAAI,WAAW,CAAC,oBAAoB,UAAU,YAAY,MAAM,EAAG,QAAO,EAAE,SAAS,OAAO,SAAS,KAAK;AAC1G,IAAAC,eAAc,SAAS,SAAS,IAAI,SAAS,IAAI,IAAI,SAAS,MAAM,GAAG,SAAS,GAAG;AAAA,GAAM,MAAM;AAC/F,WAAO,EAAE,SAAS,MAAM,SAAS,CAAC,sCAAsC,GAAG,KAAK;AAAA,EAClF;AAEA,QAAM,cAAc,SAAS;AAC7B,MAAI,UAAU;AAEd,QAAM,OAAO,gBAAgB,QAAQ,MAAM,YAAY,MAAM,SAAS,IAAI;AAC1E,MAAI,MAAM;AACR,QAAI,KAAK,UAAU,OAAW,QAAO,QAAQ;AAAA,QACxC,gBAAe,SAAS,QAAQ,KAAK,KAAK;AAC/C,cAAU;AACV,YAAQ,KAAK,SAAS,KAAK,MAAM,EAAE;AAAA,EACrC;AAEA,aAAW,OAAO,YAAY;AAC5B,QAAI,QAAQ,QAAQ;AAClB,YAAMC,UAAS,cAAc,QAAQ,MAAM,YAAY,MAAM,SAAS,IAAI;AAC1E,UAAIA,SAAQ,SAAS;AACnB,gBAAQ,OAAOA,QAAO;AACtB,kBAAU;AACV,gBAAQ,KAAK,cAAc;AAAA,MAC7B;AACA;AAAA,IACF;AAEA,QAAI,QAAQ,kBAAkB;AAE5B,YAAM,WAAW,CAAC,QAAuB,MAAM,GAAG,IAAI,EAAE,CAAC,GAAG,GAAG,OAAO,IAAI,GAAG,CAAC,EAAE,IAAI;AACpF,YAAMA,UAAS,YAAY,SAAS,OAAO,GAAG,SAAS,WAAW,GAAG,SAAS,OAAO,CAAC;AACtF,UAAIA,SAAQ,SAAS;AACnB,gBAAQ,GAAG,IAAIA,QAAO,OAAO,GAAG;AAChC,kBAAU;AACV,gBAAQ,KAAK,GAAG,GAAG,KAAKA,QAAO,MAAM,SAAS,IAAI,UAAU,SAAS,EAAE;AAAA,MACzE;AACA;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW;AAGrB,YAAMA,UAAS,iBAAiB,QAAQ,SAAS,YAAY,OAAO;AACpE,UAAIA,SAAQ,SAAS;AACnB,gBAAQ,UAAUA,QAAO;AACzB,kBAAU;AACV,gBAAQ,KAAK,GAAGA,QAAO,MAAM,IAAI,CAAC,SAAS,WAAW,IAAI,SAAS,CAAC;AAAA,MACtE;AACA;AAAA,IACF;AAGA,UAAM,YAAY,QAAQ,GAAG;AAC7B,UAAM,gBAAgB,YAAY,GAAG;AACrC,UAAM,YAAY,UAAU,GAAG;AAE/B,QAAI;AACJ,QAAI,SAAS,QAAQ,UAAW,WAAU,CAAC,SAAS,MAAM,WAAW,IAAI;AAAA,aAChE,SAAS,gBAAgB,SAAS,GAAG,EAAG,WAAU,CAAC,SAAS,MAAM,YAAY,cAAc,IAAI;AACzG,UAAM,YAAY,QAAQ;AAC1B,UAAM,SAAS,YAAY,WAAW,eAAe,WAAW;AAAA,MAC9D,YAAY,CAAC;AAAA,MACb;AAAA,MACA,eAAe;AAAA,IACjB,CAAC;AACD,SAAK,KAAK,IAAI,QAAQ,QAAQ,CAAC,GAAG,IAAI,CAAC,EAAE,MAAM,OAAO,MAAM,GAAG,GAAG,IAAI,IAAI,aAAa,MAAM,EAAE,CAAC;AAChG,QAAI,QAAQ,SAAS;AACnB,cAAQ,GAAG,IAAI,OAAO;AACtB,gBAAU;AACV,cAAQ;AAAA,QACN,GAAG,OAAO,MAAM,IAAI,CAAC,SAAS,GAAG,GAAG,IAAI,IAAI,SAAS;AAAA,QACrD,GAAG,OAAO,QAAQ,IAAI,CAAC,SAAS,GAAG,GAAG,IAAI,IAAI,WAAW;AAAA,QACzD,GAAG,OAAO,QAAQ,IAAI,CAAC,SAAS,GAAG,GAAG,IAAI,IAAI,WAAW;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAS,CAAAD,eAAc,SAAS,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAEnF,SAAO,EAAE,SAAS,SAAS,KAAK;AAClC;AAYA,eAAsB,YAAY,QAAuB,UAA0C,CAAC,GAAkB;AACpH,gBAAc,+BAA+B;AAE7C,QAAM,aAAa,OAAO,SAAS,mBAAmB;AACtD,QAAM,gBAAgB,IAAI,IAAI,QAAQ,mBAAmB,CAAC,CAAC;AAE3D,QAAM,UAAU,MAAM,iBAAiB,OAAO,UAAU,OAAO,WAAW;AAE1E,QAAM,QAAQ,UAAU,MAAM,cAAc,OAAO,UAAU,OAAO,aAAa,OAAO,IAAI;AAC5F,QAAM,YAAY,MAAM,yBAAyB,OAAO,UAAU,OAAO,WAAW;AACpF,QAAM,UAAiE,CAAC;AACxE,QAAM,UAAoB,CAAC;AAE3B,aAAW,YAAY,WAAW;AAChC,UAAM,aAAa,gBAAgB,QAAQ;AAI3C,QAAI,cAAc,IAAI,UAAU,GAAG;AACjC,cAAQ,KAAK,UAAU;AACvB;AAAA,IACF;AAEA,gBAAY,WAAW,YAAY,MAAM,kBAAkB;AAE3D,UAAM,EAAE,SAAS,SAAS,MAAAE,MAAK,IAAI,MAAM,gBAAgB,QAAQ,SAAS,OAAO,UAAU,UAAU;AACrG,QAAI,WAAWA,MAAK,SAAS,EAAG,SAAQ,KAAK,EAAE,MAAM,YAAY,SAAS,MAAAA,MAAK,CAAC;AAAA,EAClF;AAEA,QAAM,eAAe,QAAQ,OAAO,CAAC,EAAE,QAAQ,MAAM,QAAQ,SAAS,CAAC,EAAE;AACzE,iBAAe,yBAAyB,GAAG,OAAO,cAAc,oBAAoB,oBAAoB,CAAC,UAAU;AAEnH,aAAW,EAAE,MAAM,QAAQ,KAAK,SAAS;AACvC,QAAI,QAAQ,WAAW,EAAG;AAC1B,YAAQ,KAAK,KAAK,IAAI,EAAE;AACxB,eAAW,UAAU,QAAS,SAAQ,KAAK,OAAO,eAAG,IAAI,MAAM,CAAC,EAAE;AAAA,EACpE;AAGA,QAAM,OAAO,QAAQ,QAAQ,CAAC,EAAE,MAAM,MAAAA,MAAK,MAAMA,MAAK,IAAI,CAAC,UAAU,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;AACxF,QAAM,OAAO,KAAK,WAAW,IAAI,OAAO;AACxC,gBAAc,QAAQ,OAAO,KAAK,QAAQ,SAAS,SAAS,CAAC,0CAA0C,IAAI,KAAK,IAAI;AACpH;AAAA,IACE,WAAW,QAAQ,MAAM;AAAA,IACzB;AAAA,EACF;AACF;AAGA,SAAS,cAAc,QAAgB,SAAyB;AAC9D,MAAI,QAAQ,WAAW,EAAG;AAC1B,UAAQ,KAAK;AACb,UAAQ,KAAK,GAAG,WAAW,IAAI,eAAG,OAAO,MAAM,CAAC,EAAE;AAClD,aAAW,SAAS,QAAS,SAAQ,KAAK,OAAO,eAAG,IAAI,QAAG,CAAC,IAAI,KAAK,EAAE;AACzE;;;AFjbA,eAAe,kBAAkB,UAAkB,MAAc,eAAwC;AAEvG,MAAI,CAAE,MAAM,aAAa,UAAU,IAAI,GAAI;AACzC,UAAM,YAAY,UAAU,QAAQ,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACpD,YAAQ,KAAK,eAAG,IAAI,IAAI,IAAI,+CAA+C,IAAI,IAAI,CAAC;AACpF,WAAO,UAAU,IAAI;AAAA,EACvB;AAEA,QAAM,EAAE,UAAU,OAAO,OAAO,IAAI,MAAM,kBAAkB,UAAU,IAAI;AAE1E,MAAI,CAAC,UAAU;AACb,YAAQ,KAAK,eAAG,IAAI,IAAI,IAAI,mDAAmD,CAAC;AAChF,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,KAAK,SAAS,GAAG;AAC3B,UAAM,IAAI;AAAA,MACR,IAAI,IAAI,wBAAwB,QAAQ,MAAM,KAAK,WAAW,MAAM;AAAA,aACpD,IAAI,WAAW,QAAQ;AAAA,IACzC;AAAA,EACF;AAEA,MAAI,SAAS,GAAG;AACd,UAAM,WAAW,kBAAkB,OAAO,OAAO,MAAM,kBAAkB,UAAU,IAAI;AACvF,QAAI,UAAU;AACZ,cAAQ;AAAA,QACN,eAAG,IAAI,IAAI,IAAI,QAAQ,MAAM,YAAY,QAAQ,wBAAwB,QAAQ,wBAAwB;AAAA,MAC3G;AACA,aAAO;AAAA,IACT;AACA,YAAQ,KAAK,eAAG,IAAI,oBAAoB,IAAI,SAAS,QAAQ,MAAM,MAAM,aAAa,CAAC;AACvF,QAAI,kBAAkB,KAAM,OAAM,gBAAgB,QAAQ;AAAA,QACrD,OAAM,kBAAkB,UAAU,MAAM,QAAQ;AACrD,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,GAAG;AACb,YAAQ,KAAK,eAAG,IAAI,IAAI,IAAI,QAAQ,KAAK,wBAAwB,QAAQ,2BAA2B,CAAC;AAAA,EACvG;AACA,SAAO;AACT;AAGA,eAAe,yBAAyB,QAAqD;AAC3F,QAAM,EAAE,UAAU,SAAS,IAAI;AAC/B,QAAM,OAAO,mBAAmB,QAAQ;AACxC,QAAM,cAAc,MAAM,iBAAiB,QAAQ;AACnD,QAAM,eAAe,MAAM,cAAc,UAAU,MAAM,GAAG;AAE5D,UAAQ,KAAK,eAAG,IAAI,aAAa,IAAI,MAAM,CAAC;AAC5C,QAAM,aAAa,MAAM,kBAAkB,UAAU,MAAM,WAAW;AAEtE,QAAM,kBAAkB,yBAAyB;AAEjD,UAAQ,KAAK,eAAG,IAAI,mCAAmC,eAAe,WAAW,UAAU,MAAM,CAAC;AAClG,UAAQ,KAAK;AACb,QAAM,iBAAiB,UAAU,iBAAiB,UAAU;AAE5D,SAAO,EAAE,iBAAiB,MAAM,aAAa,YAAY;AAC3D;AAQA,eAAe,eAAe,UAAkB,MAA+B;AAC7E,MAAI,CAAE,MAAM,aAAa,UAAU,IAAI,EAAI,QAAO,UAAU,IAAI;AAChE,QAAM,WAAW,MAAM,kBAAkB,UAAU,IAAI;AACvD,SAAO,YAAa,MAAM,WAAW,UAAU,MAAM,QAAQ,IAAK,WAAW;AAC/E;AAOA,eAAe,aAAa,UAAkB,MAA+B;AAC3E,QAAM,WAAW,MAAM,kBAAkB,UAAU,IAAI;AACvD,MAAI,UAAU;AACZ,YAAQ,KAAK,eAAG,IAAI,IAAI,IAAI,uBAAuB,QAAQ,mBAAmB,IAAI,mBAAmB,CAAC;AACtG,UAAM,eAAe,UAAU,IAAI;AACnC,WAAO,gBAAgB,IAAI;AAAA,EAC7B;AAEA,UAAQ,KAAK,eAAG,IAAI,sBAAsB,IAAI,MAAM,CAAC;AACrD,QAAM,aAAa,UAAU,IAAI;AACjC,QAAM,gBAAgB,QAAQ,EAAE,MAAM,MAAM;AAAA,EAAC,CAAC;AAC9C,SAAO,YAAY,IAAI;AACzB;AAGA,eAAsB,QACpB,QACA,SAGsB;AACtB,gBAAc,kBAAkB;AAEhC,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,qBAAqB,QAAQ,IAAI;AAAA,EAClD,SAAS,OAAO;AAGd,mBAAe;AACf,QAAI,iBAAiB,4BAA4B;AAC/C,mCAA6B,EAAE,mBAAmB,MAAM,OAAO,CAAC;AAChE,cAAQ,KAAK;AAAA,IACf;AACA,UAAM;AAAA,EACR;AAEA,MAAI,OAAO,SAAS;AAClB,mBAAe;AAAA,EACjB,OAAO;AACL,gBAAY,+BAA+B;AAAA,EAC7C;AAGA,qBAAmB,QAAQ,eAAe;AAC1C,MAAI,OAAO,UAAU;AACnB,YAAQ,KAAK,eAAG,OAAO,0FAAqF,CAAC;AAC7G,YAAQ,KAAK;AAAA,EACf;AAEA,QAAM,SAAS,OAAO,MAAM,KAAK,CAAC,SAAS,sBAAsB,SAAS,KAAK,MAAM,CAAC;AACtF,QAAM,eACJ,SAAS,gBAAgB,OAAO,UAAU,WAAW,KAAK,SAAS,QAAQ,eAAe;AAC5F,oBAAkB,QAAQ,EAAE,aAAa,CAAC;AAE1C,QAAM,wBAAwB,QAAQ,MAAM;AAE5C,SAAO;AACT;AAGA,IAAM,gBAAgB;AAStB,eAAe,uBAAuB,UAAkB,aAAsC;AAC5F,QAAM,WAAW,MAAM,YAAY,UAAU,WAAW,EAAE,MAAM,MAAM,EAAE;AACxE,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,WAAW,MAAM,iBAAiB,QAAQ;AAChD,QAAM,UACJ,UAAU,SAAS,WAAY,MAAM,wBAAwB,UAAU,WAAW,EAAE,MAAM,MAAM,IAAI;AACtG,SAAO,UAAU,GAAG,aAAa,KAAK,QAAQ,QAAQ,MAAM,EAAE,CAAC,KAAK,QAAQ,MAAM,GAAG,aAAa,IAAI,QAAQ;AAChH;AAMA,SAAS,cAAc,SAAiB,UAA2B;AACjE,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,QAAQ,QAAQ,uBAAuB,KAAK,QAAQ,KAAK;AAClE;AAqBO,SAAS,gBAAgB,OAAgC;AAC9D,QAAM,EAAE,UAAU,SAAS,SAAS,OAAO,SAAS,YAAY,MAAM,IAAI;AAC1E,QAAM,YAAY,WAAW,sBAAsB,QAAQ,KAAK;AAChE,QAAM,QAAQ,CAAC,QAAgB,IAAI,MAAM,GAAG,CAAC;AAC7C,QAAM,YAAY,CAAC,QACjB,YAAY,MAAM,MAAM,GAAG,CAAC,OAAO,SAAS,WAAW,GAAG,MAAM,KAAK,MAAM,GAAG,CAAC;AAEjF,QAAM,eAAe,YAAY,IAAI,QAAQ,KAAK,SAAS,MAAM;AACjE,QAAM,gBAAgB,UAAU,MAAM,QAAQ,QAAQ,MAAM,EAAE,CAAC,MAAM;AACrE,QAAM,QAAQ,CAAC,kBAAkB,YAAY,OAAO,UAAU,KAAK,CAAC,GAAG,aAAa,GAAG;AAEvF,MAAI,aAAa,KAAK,SAAS;AAC7B,UAAM,UAAU,YAAY,eAAe,SAAS,YAAY,MAAM,OAAO,CAAC,MAAM,MAAM,KAAK,CAAC,OAAO;AACvG,UAAM,KAAK,IAAI,KAAK,UAAU,mBAAmB,eAAe,IAAI,KAAK,GAAG,qBAAqB,OAAO,KAAK,EAAE;AAC/G,QAAI,aAAa,QAAQ,OAAQ,OAAM,KAAK,WAAM,aAAa,QAAQ,MAAM,8BAA8B;AAC3G,eAAW,UAAU,SAAS;AAC5B,YAAM,KAAK,KAAK,UAAU,OAAO,IAAI,CAAC,IAAI,cAAc,OAAO,SAAS,QAAQ,CAAC,EAAE;AAAA,IACrF;AAAA,EACF;AAEA,MAAI,SAAS,MAAM,QAAQ,GAAG;AAC5B,UAAM,EAAE,OAAO,KAAK,IAAI;AACxB,QAAI,KAAK,WAAW,EAAG,OAAM,KAAK,IAAI,4BAA4B,KAAK,WAAW;AAAA,SAC7E;AACH,YAAM;AAAA,QACJ;AAAA,QACA,wBAAwB,KAAK,IAAI,GAAG,QAAQ,KAAK,MAAM,CAAC,OAAO,KAAK;AAAA,QACpE;AAAA,MACF;AACA,iBAAW,QAAQ;AACjB,cAAM,KAAK,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,KAAK,KAAK,GAAG,MAAM,KAAK,KAAK,OAAO,KAAK,EAAE,KAAK;AAAA,IAC7F;AAAA,EACF;AAEA,SAAO,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA;AAC5B;AAOA,eAAe,yBAAyB,UAAkB,MAA2C;AACnG,QAAM,WAAW,MAAM,kBAAkB,UAAU,MAAM;AACzD,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,QAAQ,SAAS,SAAS,OAAO,YAAY;AAInD,QAAM,UACH,MAAM,sBAAsB,UAAU,IAAI,KAAO,MAAM,aAAa,UAAU,MAAM,KAAK,EAAE,MAAM,MAAM,IAAI;AAC9G,QAAM,UAAU,SAAS,SAAS,WAAY,MAAM,wBAAwB,UAAU,KAAK,EAAE,MAAM,MAAM,IAAI;AAE7G,QAAM,aAAa,UAAU,MAAM,oBAAoB,UAAU,SAAS,KAAK,EAAE,MAAM,MAAM,CAAC,IAAI;AAClG,QAAM,UAAU,WAAW,aAAa,IAAI,MAAM,mBAAmB,UAAU,SAAS,OAAO,eAAe,IAAI,CAAC;AAEnH,QAAM,QAAQ,MAAM,gBAAgB,UAAU,OAAO,SAAS,SAAS,IAAI,EAAE,MAAM,MAAM,MAAS;AAClG,SAAO,gBAAgB,EAAE,UAAU,SAAS,SAAS,MAAM,SAAS,SAAS,OAAO,SAAS,YAAY,MAAM,CAAC;AAClH;AAGA,eAAe,gBAAgB,UAAkB,OAAe,UAAsD;AACpH,QAAM,YAAY,WAAW,sBAAsB,QAAQ,KAAK;AAChE,QAAM,CAAC,KAAK,OAAO,IAAI,MAAM,QAAQ,IAAI,CAAC,YAAY,UAAU,KAAK,GAAG,YAAY,QAAQ,CAAC,CAAC;AAC9F,QAAM,OAAO,MAAM,QAAQ;AAAA,IACzB,QAAQ,IAAI,OAAO,QAAQ;AAAA,MACzB;AAAA,MACA,QAAQ,MAAM,SAAS,UAAU,OAAO,EAAE,IAAI,SAAS;AAAA,MACvD,KAAK,QAAQ,WAAW,OAAO,EAAE;AAAA,IACnC,EAAE;AAAA,EACJ;AACA,SAAO,EAAE,OAAO,IAAI,QAAQ,KAAK;AACnC;AAGA,SAAS,kBAAkB,QAAgB,MAAc,QAAQ,eAAqB;AACpF,UAAQ,KAAK,eAAG,IAAI,yBAAyB,IAAI,WAAW,MAAM,aAAa,KAAK,UAAU,CAAC;AACjG;AAQA,eAAe,kBAAkB,UAAkB,QAAgB,MAAgC;AACjG,QAAM,eAAe,MAAM,uBAAuB,UAAU,IAAI;AAChE,MAAI,aAAa,WAAW,EAAG,QAAO;AAGtC,QAAM,UAAU,MAAM,uBAAuB,UAAU,GAAG,aAAa,CAAC,CAAC,IAAI;AAE7E,UAAQ;AAAA,IACN,eAAG;AAAA,MACD,IAAI,MAAM,cAAc,aAAa,MAAM;AAAA,IAC7C;AAAA,EACF;AACA,UAAQ,KAAK,eAAG,IAAI,eAAe,MAAM,wCAAwC,CAAC;AAClF,QAAM,cAAc,UAAU,MAAM,OAAO;AAC3C,SAAO;AACT;AAOA,eAAe,eAAe,QAAuB,QAA+B;AAClF,QAAM,EAAE,UAAU,SAAS,IAAI;AAC/B,QAAM,OAAO,mBAAmB,QAAQ;AAExC,QAAM,UAAU,MAAM,eAAe,UAAU,IAAI;AAEnD,QAAM,YAAY,MAAM,kBAAkB,UAAU,QAAQ,OAAO;AACnE,MAAI;AACJ,MAAI,WAAW;AAKf,QAAM,kBAAkB,MAAM,iBAAiB,QAAQ,IAAI,SAAS;AACpE,QAAM,UAAU,iBAAiB,MAAM,uBAAuB,UAAU,cAAc,IAAI;AAE1F,UAAQ,KAAK,eAAG,IAAI,YAAY,MAAM,gBAAgB,CAAC;AACvD,MAAI;AACF,UAAM,WAAW,UAAU,UAAU,QAAQ,EAAE,gBAAgB,UAAU,CAAC;AAAA,EAC5E,SAAS,OAAO;AACd,YAAQ,KAAK,eAAG,OAAO,gBAAgB,aAAa,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,qBAAqB,CAAC;AAC/F,YAAQ,KAAK,eAAG,IAAI,wBAAwB,MAAM,EAAE,CAAC;AACrD,sBAAkB,QAAQ,MAAM,OAAO;AACvC;AAAA,EACF;AAEA,MAAI,YAAY,GAAG;AACjB,YAAQ,KAAK,eAAG,IAAI,2BAA2B,CAAC;AAChD,UAAM,SAAS,MAAM,yBAAyB,UAAU,OAAO;AAC/D,UAAM,WAAW,SAAS,CAAC,UAAU,MAAM,IAAI,CAAC,QAAQ;AACxD,UAAM,KAAKC,WAAU,MAAM,CAAC,MAAM,UAAU,UAAU,MAAM,UAAU,QAAQ,WAAW,SAAS,GAAG,QAAQ,GAAG;AAAA,MAC9G,KAAK;AAAA,MACL,UAAU;AAAA,MACV,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,IAClC,CAAC;AACD,YAAQ,GAAG,GAAG,UAAU,EAAE;AAAA,EAAK,GAAG,UAAU,EAAE,GAAG,MAAM,gBAAgB,IAAI,CAAC;AAC5E,eAAW,GAAG,WAAW;AACzB,QAAI,CAAC,UAAU;AACb,cAAQ,KAAK,eAAG,OAAO,2EAA2E,CAAC;AACnG,UAAI,MAAO,SAAQ,KAAK,eAAG,IAAI,KAAK,KAAK,EAAE,CAAC;AAC5C,wBAAkB,QAAQ,MAAM,OAAO;AAAA,IACzC;AAAA,EACF,OAAO;AACL,YAAQ,KAAK,eAAG,OAAO,uCAAuC,CAAC;AAC/D,sBAAkB,QAAQ,MAAM,OAAO;AAAA,EACzC;AAEA,QAAM,WAAW,MAAM,aAAa,UAAU,IAAI;AAElD,UAAQ,KAAK;AACb,MAAI,OAAO;AACT,YAAQ,KAAK,GAAG,SAAS,sBAAsB,WAAW,WAAW,OAAO,EAAE;AAC9E,YAAQ,KAAK,eAAG,IAAI,KAAK,KAAK,wBAAqB,QAAQ,EAAE,CAAC;AAAA,EAChE,OAAO;AACL,YAAQ,KAAK,GAAG,SAAS,qBAAqB;AAC9C,YAAQ,KAAK,eAAG,IAAI,MAAM,MAAM,mBAAmB,QAAQ,EAAE,CAAC;AAAA,EAChE;AACA,QAAM,wBAAwB,MAAM;AACtC;AAOA,SAAS,kBAAkB,UAA2B;AACpD,aAAW,QAAQ,CAAC,CAAC,SAAS,GAAG,CAAC,OAAO,CAAC,GAAG;AAC3C,YAAQ,KAAK,eAAG,IAAI,gBAAgB,KAAK,KAAK,GAAG,CAAC,KAAK,CAAC;AACxD,UAAM,SAASA,WAAU,QAAQ,MAAM,EAAE,KAAK,UAAU,OAAO,UAAU,CAAC;AAC1E,QAAI,OAAO,WAAW,EAAG,QAAO;AAAA,EAClC;AACA,SAAO;AACT;AAYA,eAAe,2BAA2B,UAAkB,QAA4C;AACtG,MAAI,OAAO,gBAAgB,OAAQ,OAAM,eAAe,UAAU,OAAO,WAAW;AAAA,MAC/E,OAAM,aAAa,UAAU,OAAO,WAAW;AACpD,QAAM,aAAa,UAAU,OAAO,eAAe;AACrD;AAQA,eAAe,wBAAwB,UAAkB,QAA+C;AACtG,QAAM,SACH,MAAM,iBAAiB,QAAQ,MAAO,OAAO,mBAC9C,CAAE,MAAM,gBAAgB,QAAQ,KAC/B,MAAM,QAAQ,QAAQ;AACzB,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,2BAA2B,UAAU,MAAM;AACjD,QAAM,QAAQ,OAAO,gBAAgB,SAAS,MAAM,OAAO,YAAY,MAAM,GAAG,CAAC,CAAC,KAAK,OAAO,OAAO,WAAW;AAChH,UAAQ,KAAK,eAAG,IAAI,uBAAuB,OAAO,eAAe,WAAW,KAAK,GAAG,CAAC;AACrF,SAAO;AACT;AAQA,eAAe,aAAa,QAAkD;AAC5E,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,SAAS,MAAM,yBAAyB,MAAM;AAEpD,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,QAAQ,QAAQ,EAAE,cAAc,OAAO,gBAAgB,CAAC;AAAA,EACzE,SAAS,OAAO;AACd,UAAM,YAAY,MAAM,wBAAwB,UAAU,MAAM,EAAE,MAAM,MAAM,KAAK;AAGnF,QAAI,aAAa,iBAAiB,wBAAwB,CAAC,OAAO,KAAK;AACrE,aAAO,EAAE,QAAQ,QAAQ,QAAQ,MAAM,QAAQ;AAAA,IACjD;AACA,UAAM;AAAA,EACR;AAEA,MAAI,OAAO,SAAS,qBAAqB,OAAO;AAG9C,UAAM,YAAY,QAAQ,EAAE,iBAAiB,OAAO,UAAU,CAAC;AAAA,EACjE;AAEA,MAAI,OAAO,UAAU,SAAS,EAAG,QAAO,EAAE,QAAQ,aAAa,OAAO;AAItE,MAAI,CAAE,MAAM,gBAAgB,QAAQ,GAAI;AACtC,UAAM,2BAA2B,UAAU,MAAM;AACjD,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAEA,SAAO,EAAE,QAAQ,UAAU,OAAO;AACpC;AAMA,eAAe,gBAAgB,QAAuB,QAA+B;AACnF,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,YAAY,MAAM,mBAAmB,QAAQ;AAEnD,UAAQ,KAAK;AACb,MAAI,UAAU,SAAS,GAAG;AACxB,YAAQ,KAAK,eAAG,OAAO,GAAG,UAAU,MAAM,+BAA+B,MAAM,IAAI,CAAC;AACpF,eAAW,QAAQ,UAAW,SAAQ,KAAK,eAAG,IAAI,KAAK,IAAI,EAAE,CAAC;AAC9D,YAAQ,KAAK,eAAG,IAAI,uFAAuF,CAAC;AAC5G;AAAA,EACF;AAGA,QAAM,SAAS,QAAQ;AAEvB,MAAI,CAAC,kBAAkB,QAAQ,GAAG;AAChC,YAAQ,KAAK;AACb,YAAQ;AAAA,MACN,eAAG,OAAO,8FAA8F;AAAA,IAC1G;AACA;AAAA,EACF;AAGA,QAAM,UAAU,MAAM,uBAAuB,UAAU,YAAY;AACnE,QAAM,SAAS,QAAQ;AACvB,QAAM,aAAa,UAAU,OAAO;AACpC,UAAQ,KAAK;AACb,UAAQ,KAAK,eAAG,MAAM,0BAA0B,MAAM,SAAS,OAAO,IAAI,CAAC;AAC3E,UAAQ,KAAK,eAAG,IAAI,eAAe,MAAM,oBAAoB,CAAC;AAC9D,UAAQ,KAAK,eAAG,IAAI,yEAAyE,CAAC;AAC9F,UAAQ,KAAK,eAAG,IAAI,0DAA0D,CAAC;AAC/E,QAAM,wBAAwB,MAAM;AACtC;AAQA,eAAe,iBAAiB,QAAuB,MAAuD;AAC5G,QAAM,EAAE,UAAU,SAAS,IAAI;AAC/B,QAAM,OAAO,mBAAmB,QAAQ;AACxC,QAAM,CAAC,QAAQ,GAAG,UAAU,IAAI;AAEhC,UAAQ,KAAK;AACb,UAAQ,KAAK,eAAG,IAAI,mBAAmB,OAAO,MAAM,UAAU,IAAI,MAAM,CAAC;AACzE,QAAM,SAAS,cAAc,UAAU,OAAO,QAAQ,EAAE,cAAc,KAAK,CAAC;AAC5E,MAAI,CAAC,OAAO,IAAI;AACd,YAAQ,KAAK;AACb,YAAQ,KAAK,eAAG,OAAO,oBAAoB,OAAO,MAAM,sDAAsD,CAAC;AAC/G,QAAI,OAAO,OAAQ,SAAQ,KAAK,eAAG,IAAI,OAAO,OAAO,QAAQ,OAAO,IAAI,CAAC,CAAC;AAC1E,YAAQ,KAAK,eAAG,IAAI,KAAK,OAAO,GAAG,EAAE,CAAC;AACtC,WAAO;AAAA,EACT;AACA,UAAQ,KAAK,GAAG,SAAS,YAAY,OAAO,MAAM,EAAE;AAEpD,QAAM,aAAa,UAAU,OAAO,WAAW;AAE/C,aAAW,MAAM,YAAY;AAC3B,YAAQ,KAAK,eAAG,IAAI,YAAY,GAAG,MAAM,kCAAkC,OAAO,MAAM,KAAK,CAAC;AAC9F,YAAQ,UAAU,GAAG,MAAM;AAC3B,UAAM,aAAa,UAAU,GAAG,WAAW;AAAA,EAC7C;AAEA,SAAO;AACT;AAOA,eAAe,uBAAuB,QAAuD;AAC3F,QAAM,EAAE,SAAS,IAAI;AAErB,MAAI,CAAC,YAAY,KAAK,CAAC,QAAQ,OAAO,MAAO,QAAO;AAEpD,QAAM,OAAO,gBAAgB,UAAU,mBAAmB;AAC1D,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,OAAO,KAAK,SAAS;AAC3B,UAAQ,KAAK;AACb,UAAQ;AAAA,IACN,GAAG,WAAW,IAAI,eAAG,OAAO,GAAG,OAAO,GAAG,KAAK,MAAM,0BAA0B,uBAAuB,2BAA2B,CAAC;AAAA,EACnI;AACA,aAAW,MAAM,MAAM;AACrB,YAAQ,KAAK,eAAG,IAAI,MAAM,GAAG,MAAM,KAAK,GAAG,KAAK,EAAE,CAAC;AACnD,YAAQ,KAAK,eAAG,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC;AAAA,EAC3C;AACA,UAAQ,KAAK,eAAG,IAAI,4DAA4D,OAAO,UAAU,OAAO,WAAW,CAAC;AACpH,UAAQ,KAAK;AAEb,QAAM,SAAS,MAAMC,QAAwC;AAAA,IAC3D,SAAS;AAAA,IACT,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,MAAM,SAAS,OAAO,SAAS,IAAI,KAAK,CAAC,EAAE,MAAM,EAAE,uBAAuB,eAAG,IAAI,eAAe,CAAC;AAAA,MACnG;AAAA,MACA,EAAE,OAAO,YAAY,MAAM,qBAAqB,eAAG,IAAI,+CAA+C,CAAC,GAAG;AAAA,MAC1G,EAAE,OAAO,UAAU,MAAM,eAAG,IAAI,QAAQ,EAAE;AAAA,IAC5C;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AAED,MAAI,WAAW,SAAU,QAAO;AAChC,MAAI,WAAW,WAAY,QAAO;AAClC,SAAO,iBAAiB,QAAQ,IAAI;AACtC;AAMA,eAAsB,eAAe,QAAsC;AACzE,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,gBAAgB,MAAM,iBAAiB,QAAQ;AACrD,QAAM,eAAe,sBAAsB,aAAa;AAGxD,MAAI,gBAAiB,MAAM,gBAAgB,QAAQ,GAAI;AACrD,UAAM,gBAAgB,QAAQ,aAAa;AAC3C;AAAA,EACF;AAIA,MAAI,cAAc;AAChB,QAAI,CAAE,MAAM,QAAQ,QAAQ,GAAI;AAC9B,cAAQ,KAAK;AACb,cAAQ;AAAA,QACN,eAAG;AAAA,UACD,gBAAgB,aAAa;AAAA;AAAA,QAE/B;AAAA,MACF;AACA;AAAA,IACF;AACA,UAAM,eAAe,QAAQ,aAAa;AAC1C;AAAA,EACF;AAGA,MAAI,CAAE,MAAM,QAAQ,QAAQ,GAAI;AAC9B,UAAM,IAAI,MAAM,mFAAmF;AAAA,EACrG;AACA,MAAK,MAAM,uBAAuB,MAAM,MAAO,SAAU;AAEzD,QAAM,UAAU,MAAM,aAAa,MAAM;AACzC,UAAQ,KAAK;AAEb,MAAI,QAAQ,WAAW,QAAQ;AAC7B,QAAI,QAAQ,QAAQ;AAClB,cAAQ,KAAK,eAAG,MAAM,uEAAuE,CAAC;AAC9F,iBAAW,QAAQ,QAAQ,OAAO,MAAM,IAAI,EAAG,SAAQ,KAAK,eAAG,IAAI,KAAK,IAAI,EAAE,CAAC;AAAA,IACjF,OAAO;AACL,cAAQ,KAAK,eAAG,MAAM,oDAAoD,CAAC;AAAA,IAC7E;AACA;AAAA,EACF;AAEA,QAAM,EAAE,gBAAgB,IAAI,QAAQ;AACpC,MAAI,QAAQ,WAAW,aAAa;AAClC,YAAQ,KAAK,GAAG,WAAW,IAAI,eAAG,OAAO,iBAAiB,eAAe,kCAAkC,CAAC,EAAE;AAC9G,YAAQ,KAAK,eAAG,IAAI,mBAAmB,CAAC;AACxC,YAAQ,KAAK,eAAG,IAAI,yFAAyF,CAAC;AAC9G,YAAQ,KAAK,eAAG,IAAI,0FAA0F,CAAC;AAC/G;AAAA,EACF;AAEA,QAAM,gBAAgB,QAAQ,eAAe;AAC/C;;;AD3qBA,eAAe,iBAAiB,UAAuC;AACrE,QAAM,CAAC,QAAQ,OAAO,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,IACjD,iBAAiB,QAAQ,EAAE,MAAM,MAAM,SAAS;AAAA,IAChD,0BAA0B,QAAQ,EAAE,MAAM,MAAM,CAAC;AAAA,IACjD,iBAAiB,QAAQ;AAAA,EAC3B,CAAC;AAED,MAAI,WAAqD;AACzD,MAAI,SAAS;AACX,UAAM,aAAa,MAAM,cAAc,UAAU,OAAO,EAAE,MAAM,MAAM,IAAI;AAC1E,eAAW,EAAE,MAAM,YAAY,QAAQ,WAAW,SAAS,YAAY,WAAW,GAAG;AAAA,EACvF;AAEA,SAAO,EAAE,QAAQ,OAAO,SAAS;AACnC;AAEA,SAAS,iBAAiB,MAAc,QAAmC;AACzE,MAAI,CAAC,OAAQ,QAAO;AAGpB,MAAI;AACJ,MAAI,OAAO,UAAU;AACnB,UAAM,MACJ,OAAO,SAAS,QAAQ,SAAS,KAAK,GAAG,OAAO,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,WAAM,OAAO,SAAS;AACrG,eAAW,eAAG,IAAI,GAAG,OAAO,SAAS,IAAI,EAAE;AAC3C,QAAI,IAAK,aAAY,eAAG,IAAI,KAAK,GAAG,GAAG;AAAA,EACzC,OAAO;AACL,eAAW,eAAG,IAAI,cAAc;AAAA,EAClC;AAEA,QAAM,YAAY,OAAO,QAAQ,IAAI,eAAG,OAAO,GAAG,OAAO,KAAK,cAAc,IAAI;AAEhF,QAAM,QAAQ,CAAC,MAAM,eAAG,IAAI,IAAI,OAAO,MAAM,GAAG,GAAG,QAAQ;AAC3D,MAAI,UAAW,OAAM,KAAK,SAAS;AAEnC,SAAO,MAAM,KAAK,eAAG,IAAI,QAAK,CAAC;AACjC;AAGA,eAAe,iBACb,OACA,UACoE;AACpE,QAAM,YAAY,MAAM,IAAI,CAAC,SAAS,iBAAiB,MAAM,UAAU,IAAI,CAAC;AAE5E,QAAM,gBAAgB,MAAM,QAAQ;AAAA,IAClC,UACG,OAAO,CAAC,MAAM,EAAE,KAAK,EACrB,IAAI,OAAO,MAAM;AAChB,YAAM,SAAS,MAAM,iBAAiB,EAAE,YAAY;AACpD,aAAO,EAAE,MAAM,EAAE,KAAK,WAAW,OAAO;AAAA,IAC1C,CAAC;AAAA,EACL;AACA,QAAM,YAAY,IAAI,IAAI,cAAc,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtE,SAAO,UAAU,IAAI,CAAC,MAAM;AAC1B,QAAI,CAAC,EAAE,OAAO;AACZ,aAAO;AAAA,QACL,OAAO,EAAE,KAAK;AAAA,QACd,MAAM,GAAG,EAAE,KAAK,IAAI,KAAK,eAAG,IAAI,EAAE,KAAK,SAAS,CAAC;AAAA,QACjD,UAAU,EAAE;AAAA,MACd;AAAA,IACF;AACA,WAAO;AAAA,MACL,OAAO,EAAE,KAAK;AAAA,MACd,MAAM,iBAAiB,EAAE,KAAK,MAAM,UAAU,IAAI,EAAE,KAAK,SAAS,KAAK,IAAI;AAAA,IAC7E;AAAA,EACF,CAAC;AACH;AAGA,eAAe,SAAS,QAAuB,MAAkB,UAAiC;AAChG,UAAQ,KAAK;AACb,UAAQ,KAAK,eAAG,KAAK,cAAc,KAAK,IAAI,KAAK,CAAC;AAClD,UAAQ,KAAK,eAAG,IAAI,SAAS,QAAQ,EAAE,CAAC;AACxC,UAAQ,KAAK;AAEb,QAAM,aAAa,MAAM,WAAW,QAAQ;AAC5C,QAAM,eAAe;AAAA,IACnB,GAAG;AAAA,IACH;AAAA,IACA,aAAa,gBAAgB,WAAW,QAAQ,EAAE;AAAA,IAClD,SAAS;AAAA,IACT,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,SAAS,QAAsC;AACnE,QAAM,QAAQ,OAAO,SAAS,CAAC;AAE/B,MAAI,MAAM,WAAW,GAAG;AACtB,qBAAiB,2BAA2B;AAC5C;AAAA,EACF;AAGA,MAAI,OAAO,MAAM;AACf,UAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI;AACtD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,SAAS,OAAO,IAAI,uBAAuB;AAAA,IAC7D;AACA,UAAM,eAAeC,SAAQ,MAAM,oBAAoB,OAAO,QAAQ,GAAG,MAAM,SAAS;AACxF,UAAM,SAAS,QAAQ,OAAO,YAAY;AAC1C;AAAA,EACF;AAGA,QAAM,eAAe,MAAM,oBAAoB,OAAO,QAAQ;AAC9D,SAAO,MAAM;AACX,UAAM,UAAU,MAAM,iBAAiB,OAAO,YAAY;AAC1D,UAAM,cAAc,CAAC,GAAG,SAAS,IAAIC,WAAU,YAAY,GAAG,EAAE,OAAO,SAAS,MAAM,eAAG,IAAI,MAAM,EAAE,CAAC;AAEtG,UAAM,eAAe,MAAMC,QAAe;AAAA,MACxC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AAED,QAAI,iBAAiB,SAAS;AAC5B,MAAAC,SAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,mBAAmBH,SAAQ,cAAc,YAAY;AAC3D,UAAM,eAAe,MAAM,KAAK,CAAC,MAAM,EAAE,cAAc,YAAY;AACnE,QAAI,CAAC,cAAc;AACjB,cAAQ,MAAM,eAAG,IAAI,SAAS,YAAY,uBAAuB,CAAC;AAClE;AAAA,IACF;AAEA,UAAM,SAAS,QAAQ,cAAc,gBAAgB;AAErD,YAAQ,KAAK;AAAA,EACf;AACF;;;AK1JA,SAAS,YAAAI,iBAAgB;AACzB,SAAS,QAAAC,cAAY;;;ACHrB,SAAS,cAAAC,cAAY,gBAAAC,eAAc,YAAAC,iBAAgB;AACnD,SAAS,QAAAC,QAAM,YAAAC,WAAU,OAAAC,YAAW;AAuBpC,IAAM,qBAAqB,IAAI,KAAK,KAAK,KAAK;AAG9C,SAAS,SAAS,KAAoC;AACpD,MAAI,OAAO,QAAQ,YAAY,CAAC,OAAO,SAAS,GAAG,EAAG,QAAO,eAAG,IAAI,KAAK;AAEzE,QAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,CAAC;AAC/B,MAAI,OAAO,GAAI,QAAO,eAAG,MAAM,KAAK;AACpC,MAAI,OAAO,GAAI,QAAO,eAAG,OAAO,KAAK;AACrC,SAAO,eAAG,IAAI,KAAK;AACrB;AAGA,SAAS,UAAU,IAAoB;AACrC,QAAM,OAAO,KAAK,MAAM,MAAM,KAAK,KAAK,KAAK,IAAK;AAClD,MAAI,QAAQ,EAAG,QAAO,GAAG,IAAI,OAAO,SAAS,IAAI,KAAK,GAAG;AACzD,QAAM,QAAQ,KAAK,MAAM,MAAM,KAAK,KAAK,IAAK;AAC9C,MAAI,SAAS,EAAG,QAAO,GAAG,KAAK,QAAQ,UAAU,IAAI,KAAK,GAAG;AAC7D,QAAM,OAAO,KAAK,MAAM,MAAM,KAAK,IAAK;AACxC,SAAO,GAAG,IAAI,UAAU,SAAS,IAAI,KAAK,GAAG;AAC/C;AAGO,SAAS,qBAAqB,UAAwB;AAC3D,QAAM,OAAOC,OAAK,UAAU,aAAa,uBAAuB;AAChE,MAAI;AACJ,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAIC,aAAW,IAAI,GAAG;AACpB,QAAI;AACF,gBAAUC,UAAS,IAAI,EAAE;AACzB,gBAAU,KAAK,MAAMC,cAAa,MAAM,MAAM,CAAC;AAAA,IACjD,QAAQ;AACN,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,MAAI,CAAC,WAAW,CAAC,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC,QAAQ,QAAQ,OAAO,GAAG;AACpE,YAAQ,KAAK,eAAG,KAAK,UAAU,CAAC;AAChC,YAAQ,KAAK,eAAG,OAAO,KAAK,OAAO,oCAAoC,CAAC;AACxE,YAAQ,KAAK;AACb;AAAA,EACF;AAEA,QAAM,QAAQ,KAAK,IAAI,IAAI;AAC3B,QAAM,QAAQ,QAAQ;AAGtB,QAAM,aAAa,oBAAI,IAAgD;AACvE,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,QAAQ,QAAS;AACrB,UAAM,MAAMC,UAAS,UAAU,GAAG;AAClC,QAAI,IAAI,WAAW,IAAI,EAAG;AAC1B,UAAM,MAAM,IAAI,MAAMC,IAAG,EAAE,CAAC;AAC5B,UAAM,MAAM,WAAW,IAAI,GAAG,KAAK,EAAE,SAAS,GAAG,OAAO,EAAE;AAC1D,QAAI,WAAW,MAAM,MAAM;AAC3B,QAAI,SAAS,MAAM,MAAM;AACzB,eAAW,IAAI,KAAK,GAAG;AAAA,EACzB;AAGA,QAAM,WAAW,UAAU,KAAK;AAChC,UAAQ,KAAK,eAAG,KAAK,UAAU,GAAG,eAAG,IAAI,YAAY,QAAQ,GAAG,CAAC;AACjE,MAAI,OAAO;AACT,YAAQ,KAAK,eAAG,OAAO,gEAA2D,CAAC;AAAA,EACrF;AAGA,QAAM,QAAQ,QAAQ;AACtB,UAAQ;AAAA,IACN,KAAK,eAAG,KAAK,SAAS,CAAC,WACZ,SAAS,MAAM,MAAM,GAAG,CAAC,IAAI,eAAG,IAAI,IAAI,MAAM,MAAM,OAAO,IAAI,MAAM,MAAM,KAAK,GAAG,CAAC,WACpF,SAAS,MAAM,UAAU,GAAG,CAAC,cAC1B,SAAS,MAAM,SAAS,GAAG,CAAC;AAAA,EAC5C;AAGA,QAAM,OAAO,CAAC,GAAG,WAAW,QAAQ,CAAC,EAClC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,KAAK,EAAE,QAAS,MAAM,EAAE,UAAW,EAAE,QAAQ,GAAG,GAAG,EAAE,EAAE,EACjF,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG;AAE/B,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,MAAM,GAAG,CAAC;AAC9D,aAAW,KAAK,MAAM;AACpB,YAAQ,KAAK,OAAO,EAAE,IAAI,OAAO,SAAS,CAAC,KAAK,SAAS,EAAE,GAAG,CAAC,IAAI,eAAG,IAAI,IAAI,EAAE,OAAO,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE;AAAA,EAC1G;AACA,UAAQ,KAAK;AACf;;;ADjGO,IAAM,mBAAmB,oBAAI,IAAI,CAAC,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,QAAQ,SAAS,OAAO,MAAM,CAAC;AA6BhH,eAAsB,qBAAqB,UAA+C;AACxF,QAAM,UAAU,MAAMC,UAASC,OAAK,UAAU,qBAAqB,GAAG,MAAM;AAC5E,QAAM,WAAW,aAAa,SAAS,UAAU;AAEjD,UAAQ,MAAM,QAAQ,QAAQ,IAAI,SAAS,IAAI,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY;AAE5E,QAAI,QAAQ,SAAS,IAAI,GAAG;AAC1B,YAAM,OAAO,QAAQ,MAAM,GAAG,EAAE;AAChC,aAAO,EAAE,MAAM,GAAG,IAAI,MAAM,QAAQ,GAAG,IAAI,IAAI;AAAA,IACjD;AACA,WAAO,EAAE,MAAM,SAAS,QAAQ,GAAG,OAAO,IAAI;AAAA,EAChD,CAAC;AACH;AAEO,SAAS,aAAa,UAAgC;AAC3D,MACE,SAAS,SAAS,QAAQ,KAC1B,SAAS,SAAS,QAAQ,KAC1B,SAAS,SAAS,SAAS,KAC3B,SAAS,SAAS,QAAQ,KAC1B,SAAS,WAAW,QAAQ,KAC5B,SAAS,SAAS,aAAa,GAC/B;AACA,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,SAAS,WAAW,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,MACE,SAAS,SAAS,OAAO,KACzB,SAAS,SAAS,OAAO,KACzB,SAAS,SAAS,OAAO,KACzB,SAAS,WAAW,UAAU,KAC9B,SAAS,SAAS,WAAW,KAC7B,SAAS,SAAS,OAAO,KACzB,SAAS,SAAS,cAAc,GAChC;AACA,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,SAAS,OAAO,KAAK,SAAS,SAAS,QAAQ,GAAG;AAC7D,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAGO,SAAS,aAAa,UAAkB,UAAsC;AACnF,aAAW,OAAO,UAAU;AAC1B,QAAI,IAAI,KAAK,SAAS,IAAI,GAAG;AAC3B,UAAI,SAAS,WAAW,IAAI,MAAM,GAAG;AAEnC,cAAM,OAAO,SAAS,MAAM,IAAI,OAAO,MAAM;AAC7C,cAAM,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC;AAChC,YAAI,QAAQ;AACV,iBAAO,GAAG,IAAI,MAAM,GAAG,MAAM;AAAA,QAC/B;AAAA,MACF;AAAA,IACF,WAAW,SAAS,WAAW,IAAI,MAAM,GAAG;AAC1C,aAAO,IAAI;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;AAGA,IAAM,kBAAkB,CAAC,GAAG,gBAAgB,EAAE,IAAI,CAAC,QAAQ,KAAK,GAAG,EAAE;AAGrE,eAAe,aAAa,UAAwC;AAElE,QAAM,SAAS,MAAM,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,GAAG,eAAe,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC;AAEvG,QAAM,WAAW,MAAM,qBAAqB,QAAQ;AAGpD,QAAM,UAA2C,CAAC;AAClD,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,QAAI,CAAC,KAAM;AACX,UAAMC,OAAM,KAAK,YAAY,GAAG;AAChC,QAAIA,SAAQ,GAAI;AAChB,YAAQ,KAAK,EAAE,MAAM,KAAK,MAAM,GAAGA,IAAG,GAAG,KAAK,OAAO,SAAS,KAAK,MAAMA,OAAM,CAAC,GAAG,EAAE,EAAE,CAAC;AAAA,EAC1F;AAEA,QAAM,WAAW,OAAO;AAAA,IACtB,MAAM,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,IACzB,SAAS,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,IAC5B,WAAW,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,IAC9B,MAAM,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,IACzB,OAAO,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,EAC5B;AACA,QAAM,aAAa,SAAS;AAC5B,QAAM,WAAW,oBAAI,IAA0B;AAC/C,MAAI,WAAW;AAEf,aAAW,EAAE,MAAM,IAAI,KAAK,SAAS;AACnC,UAAM,WAAW,aAAa,IAAI;AAClC,eAAW,QAAQ,EAAE;AACrB,eAAW,QAAQ,EAAE,OAAO;AAC5B,gBAAY;AAEZ,UAAM,MAAM,aAAa,MAAM,QAAQ;AACvC,QAAI,QAAQ,SAAS,IAAI,GAAG;AAC5B,QAAI,CAAC,OAAO;AACV,cAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,YAAY,SAAS,EAAE;AACnD,eAAS,IAAI,KAAK,KAAK;AAAA,IACzB;AACA,UAAM;AACN,UAAM,OAAO;AACb,UAAM,WAAW,QAAQ,EAAE;AAC3B,UAAM,WAAW,QAAQ,EAAE,OAAO;AAAA,EACpC;AAEA,QAAM,iBAAiB,OAAO;AAAA,IAC5B,CAAC,GAAG,SAAS,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,WAAW,MAAM,MAAM,EAAE,CAAC,EAAE,WAAW,MAAM,GAAG;AAAA,EAC9F;AAEA,SAAO,EAAE,OAAO,QAAQ,QAAQ,UAAU,YAAY,UAAU,eAAe;AACjF;AAEA,SAAS,IAAI,GAAW,QAAQ,GAAW;AACzC,SAAO,OAAO,CAAC,EAAE,SAAS,KAAK;AACjC;AAEA,SAAS,UAAU,GAAmB;AACpC,MAAI,KAAK,IAAM,QAAO,IAAI,IAAI,KAAM,QAAQ,CAAC,CAAC;AAC9C,SAAO,OAAO,CAAC;AACjB;AAEA,SAAS,OAAO,OAAe,OAAuB;AACpD,QAAM,OAAQ,QAAQ,QAAS,KAAK,QAAQ,CAAC;AAC7C,SAAO,GAAG,IAAI,SAAS,CAAC,CAAC;AAC3B;AAEA,SAAS,WAAW,OAAoB,SAAwB;AAC9D,UAAQ,KAAK;AACb,UAAQ;AAAA,IACN,KAAK,eAAG,KAAK,aAAa,OAAO,EAAE,CAAC,CAAC,KAAK,OAAO,MAAM,KAAK,CAAC,KAAK,eAAG,IAAI,IAAI,CAAC,GAAG,gBAAgB,EAAE,KAAK,GAAG,CAAC,GAAG,CAAC;AAAA,EAClH;AACA,UAAQ,KAAK,KAAK,eAAG,KAAK,eAAe,CAAC,KAAK,eAAG,KAAK,UAAU,MAAM,QAAQ,CAAC,CAAC,EAAE;AACnF,UAAQ,KAAK;AAEb,QAAM,aAAyD;AAAA,IAC7D,CAAC,mBAAmB,MAAM,WAAW,KAAK;AAAA,IAC1C,CAAC,QAAQ,MAAM,WAAW,IAAI;AAAA,IAC9B,CAAC,WAAW,MAAM,WAAW,OAAO;AAAA,IACpC,CAAC,aAAa,MAAM,WAAW,SAAS;AAAA,IACxC,CAAC,QAAQ,MAAM,WAAW,IAAI;AAAA,EAChC;AACA,aAAW,CAAC,OAAO,IAAI,KAAK,YAAY;AACtC,YAAQ;AAAA,MACN,KAAK,IAAI,KAAK,KAAK,CAAC,IAAI,eAAG,IAAI,OAAO,KAAK,OAAO,MAAM,KAAK,CAAC,CAAC,KAAK,MAAM,OAAO,EAAE,CAAC,IAAI,eAAG,KAAK,UAAU,KAAK,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,eAAG,IAAI,OAAO,KAAK,KAAK,MAAM,QAAQ,CAAC,CAAC;AAAA,IAC/K;AAAA,EACF;AAEA,UAAQ,KAAK;AACb,UAAQ,KAAK,OAAO;AACpB,UAAQ,KAAK;AAEb,QAAM,SAAS,UACX,KAAK,GAAG,OAAO,CAAC,CAAC,KAAK,UAAU,OAAO,EAAE,CAAC,IAAI,MAAM,SAAS,CAAC,CAAC,IAAI,OAAO,SAAS,CAAC,CAAC,IAAI,QAAQ,SAAS,CAAC,CAAC,IAAI,MAAM,SAAS,CAAC,CAAC,IAAI,OAAO,SAAS,CAAC,CAAC,IAAI,MAAM,SAAS,CAAC,CAAC,KAC5K;AACJ,UAAQ,KAAK,eAAG,IAAI,MAAM,CAAC;AAC3B,QAAM,EAAE,MAAM,IAAI,MAAM;AACxB,aAAW,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,KAAK,OAAO,QAAQ,MAAM,QAAQ,GAAG;AACtE,QAAI,EAAE,MAAM,UAAU,EAAG;AAEzB,UAAM,OAAO,UACT,eAAG,IAAI,IAAI,EAAE,MAAM,KAAK,CAAC,IACzB,GAAG,IAAI,EAAE,MAAM,KAAK,CAAC,IAAI,eAAG,IAAI,OAAO,EAAE,MAAM,OAAO,MAAM,KAAK,CAAC,CAAC;AACvE,UAAM,OAAO,UACT,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,eAAG,IAAI,IAAI,IAAI,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,KACpG,KAAK,eAAG,IAAI,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,CAAC,CAAC;AAC/C,YAAQ,KAAK,KAAK,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC,IAAI,eAAG,KAAK,UAAU,EAAE,MAAM,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE;AAAA,EACpG;AAEA,UAAQ,KAAK;AACf;AAEA,eAAsB,SAAS,QAAsC;AACnE,QAAM,EAAE,SAAS,IAAI;AAErB,gBAAc,mBAAmB;AACjC,QAAM,QAAQ,MAAM,aAAa,QAAQ;AACzC,iBAAe,2BAA2B;AAE1C,aAAW,OAAO,OAAO,OAAO;AAChC,UAAQ,KAAK;AACb,uBAAqB,QAAQ;AAC/B;;;AEzLA,IAAM,YAAY,CAAC,SAAsB,SAAS,SAAS,UAAU;AAErE,IAAM,gBAAgB,oBAAI,IAAI,CAAC,MAAM,KAAK,CAAC;AAG3C,IAAM,YAAY,oBAAI,IAAI,CAAC,kBAAkB,qBAAqB,aAAa,YAAY,WAAW,CAAC;AAGvG,IAAM,iBAAiB,CAAC,GAAG,gBAAgB,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,WAAW,MAAM,CAAC;AAM7E,SAAS,eAAe,UAA8B;AAC3D,QAAM,OAAO,SAAS,MAAM,SAAS,YAAY,GAAG,IAAI,CAAC;AACzD,MAAI,UAAU,IAAI,IAAI,EAAG,QAAO;AAEhC,QAAM,WAAW,aAAa,QAAQ;AACtC,MAAI,aAAa,QAAS,QAAO;AAEjC,QAAM,MAAM,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC,IAAI;AACzE,MAAI,cAAc,IAAI,GAAG,EAAG,QAAO;AACnC,SAAO,iBAAiB,IAAI,GAAG,IAAI,WAAW;AAChD;AAMO,SAAS,aAAa,MAA2B;AACtD,QAAM,OAAO,KAAK,KAAK;AACvB,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,WAAW,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,KAAK,GAAG;AACpG,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAGO,SAAS,aAAa,QAA8B;AACzD,QAAM,QAAsB,CAAC;AAC7B,aAAWC,WAAU,OAAO,MAAM,IAAI,GAAG;AACvC,QAAI,CAACA,QAAQ;AACb,UAAM,CAAC,OAAO,SAAS,GAAG,IAAI,IAAIA,QAAO,MAAM,GAAI;AACnD,UAAM,OAAO,KAAK,KAAK,GAAI;AAC3B,QAAI,CAAC,KAAM;AAEX,UAAM,KAAK;AAAA,MACT;AAAA,MACA,MAAM,eAAe,IAAI;AAAA,MACzB,OAAO,OAAO,SAAS,OAAO,EAAE,KAAK;AAAA,MACrC,SAAS,OAAO,SAAS,SAAS,EAAE,KAAK;AAAA,IAC3C,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAOO,SAAS,iBACd,OACA,WACiC;AACjC,QAAM,UAA2C;AAAA,IAC/C,MAAM,EAAE,OAAO,GAAG,SAAS,EAAE;AAAA,IAC7B,UAAU,EAAE,OAAO,GAAG,SAAS,EAAE;AAAA,IACjC,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE;AAAA,EAChC;AAEA,MAAI,UAAU;AACd,MAAI,YAAY;AAEhB,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,QAAI,YAAY,GAAG;AAEjB,UAAI,KAAK,WAAW,IAAI,EAAG;AAC3B;AACA,UAAI,CAAC,QAAS;AACd,YAAM,SAAS,KAAK,WAAW,GAAG,IAAI,UAAU;AAChD,cAAQ,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM;AAC3C;AAAA,IACF;AAGA,QAAI,KAAK,WAAW,aAAa,GAAG;AAClC,gBAAU;AACV;AAAA,IACF;AAEA,QAAI,KAAK,WAAW,QAAQ,KAAK,KAAK,WAAW,QAAQ,GAAG;AAC1D,gBAAU,UAAU,KAAK,MAAM,CAAC,CAAC;AACjC;AAAA,IACF;AAEA,UAAM,OAAO,0CAA0C,KAAK,IAAI;AAChE,QAAI,KAAM,aAAY,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC;AAAA,EAClE;AAEA,SAAO;AACT;AAMA,eAAsB,mBAAmB,UAAkB,OAAqC;AAC9F,QAAM,WAAW,MAAM,SAAS,UAAU,GAAG,KAAK,WAAW;AAC7D,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,gBAAgB,KAAK,sDAAsD;AAE1G,QAAM,YAAY,MAAM,IAAI,CAAC,cAAc,UAAU,MAAM,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC;AAC9F,MAAI,CAAC,UAAW,OAAM,IAAI,MAAM,8CAA8C,KAAK,GAAG;AAEtF,QAAM,QAAQ,CAAC,WAAW,MAAM;AAChC,QAAM,QAAQ,aAAa,MAAM,IAAI,CAAC,QAAQ,aAAa,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,CAAC;AACrG,QAAM,SAAS,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC;AAElE,QAAM,YAAY,OAAmB,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,EAAE;AACtE,QAAM,QAAwC;AAAA,IAC5C,QAAQ,UAAU;AAAA,IAClB,MAAM,UAAU;AAAA,IAChB,SAAS,UAAU;AAAA,IACnB,WAAW,UAAU;AAAA,IACrB,MAAM,UAAU;AAAA,IAChB,MAAM,UAAU;AAAA,IAChB,OAAO,UAAU;AAAA,EACnB;AACA,QAAM,QAAQ,UAAU;AACxB,QAAM,WAA+B,MAAM,qBAAqB,QAAQ,EAAE,MAAM,MAAM,CAAC,CAAC;AACxF,QAAM,YAAY,oBAAI,IAAwB;AAE9C,QAAM,MAAM,CAAC,QAAoB,SAAqB;AACpD,WAAO;AACP,WAAO,SAAS,KAAK;AACrB,WAAO,WAAW,KAAK;AAAA,EACzB;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,OAAO,IAAI;AACf,QAAI,MAAM,KAAK,IAAI,GAAG,IAAI;AAC1B,QAAI,KAAK,SAAS,SAAU;AAE5B,UAAM,MAAM,aAAa,KAAK,MAAM,QAAQ;AAC5C,UAAM,QAAQ,UAAU,IAAI,GAAG,KAAK,UAAU;AAC9C,QAAI,OAAO,IAAI;AACf,cAAU,IAAI,KAAK,KAAK;AAAA,EAC1B;AAGA,QAAM,QAAQ,MAAM;AAAA,IAClB,CAAC,QAAQ,OAAO,gBAAgB,cAAc,GAAG,OAAO,MAAM,GAAG,eAAe,IAAI,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;AAAA,IACxG;AAAA,IACA,EAAE,cAAc,KAAK;AAAA,EACvB;AACA,QAAM,gBACJ,MAAM,OAAO,QAAQ,KAAK,CAAC,QAAQ,OAAO,iBAAiB,OAAO,CAAC,SAAS,OAAO,IAAI,IAAI,MAAM,QAAQ;AAE3G,QAAM,kBAAkB,OAAO;AAAA,IAC7B,CAAC,GAAG,UAAU,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;AAAA,EAC3F;AAEA,QAAM,SAAS,MAAM,IAAI,CAAC,aAAa,gBAAgB,MAAM,GAAG,QAAQ;AACxE,QAAM,SAAS,MAAM,IAAI,CAAC,UAAU,aAAa,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC;AAEpF,SAAO;AAAA,IACL;AAAA,IACA,WAAW,UAAU,MAAM,GAAG,CAAC;AAAA,IAC/B,MAAM,WAAW,SAAS,MAAM,IAAI,CAAC,aAAa,WAAW,MAAM,GAAG,QAAQ,IAAI;AAAA,IAClF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,MAAM,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,IAC3E,aAAa,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE;AAAA,EAClD;AACF;AAEA,SAAS,IAAI,QAA4B;AACvC,SAAO,OAAO,QAAQ,OAAO;AAC/B;AAGA,SAAS,OAAO,GAAmB;AACjC,SAAO,IAAI,IAAI,IAAI,CAAC,KAAK,OAAO,CAAC;AACnC;AAGA,SAAS,aAAa,OAAgD;AACpE,SAAQ,OAAO,QAAQ,MAAM,KAAK,EAC/B,OAAO,CAAC,CAAC,EAAE,MAAM,MAAM,OAAO,QAAQ,CAAC,EACvC,KAAK,CAAC,GAAG,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC;AAGA,SAAS,cAAc,OAAuC;AAC5D,SAAO,MACJ,OAAO,CAAC,CAAC,EAAE,MAAM,MAAM,OAAO,QAAQ,KAAK,OAAO,UAAU,CAAC,EAC7D,IAAI,CAAC,CAAC,OAAO,MAAM,MAAM,GAAG,KAAK,IAAI,OAAO,IAAI,MAAM,CAAC,CAAC,EAAE,EAC1D,KAAK,IAAI;AACd;AAMO,SAAS,eAAe,OAA4B;AACzD,QAAM,MAAM,CAAC,OAAe,WAC1B,KAAK,KAAK,MAAM,OAAO,KAAK,MAAM,OAAO,OAAO,KAAK,CAAC,MAAM,OAAO,CAAC,OAAO,OAAO,CAAC,MAAM,OAAO,IAAI,MAAM,CAAC,CAAC;AAC9G,QAAM,aAAa,CAAC,SAAiB,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AAEhF,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA,GAAG,aAAa,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,MAAM,MAAM,IAAI,SAAS,SAAS,SAAS,WAAW,UAAU,IAAI,CAAC,GAAG,MAAM,CAAC;AAAA,IAClH,mBAAmB,MAAM,MAAM,KAAK,UAAU,OAAO,MAAM,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC,MAAM,MAAM,OAAO,CAAC,UAAU,OAAO,IAAI,MAAM,KAAK,CAAC,CAAC;AAAA,EACjJ;AAEA,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM,eAAe;AACvB,UAAM,UAAU,cAAc,OAAO,QAAQ,MAAM,aAAa,CAAC;AACjE,QAAI,QAAS,OAAM,KAAK,4BAA4B,OAAO,GAAG;AAAA,EAChE;AACA,QAAM,YAAY,cAAc,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrE,MAAI,UAAW,OAAM,KAAK,4BAA4B,SAAS,GAAG;AAElE,SAAO,MAAM,SAAS,IAAI,CAAC,GAAG,OAAO,IAAI,GAAG,KAAK,EAAE,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI;AACjF;AAGA,SAAS,iBAAiB,OAAoB,SAAwB;AACpE,QAAM,UAAU,CAAC,OAAe,QAAoB,UAClD,KAAK,MAAM,SAAS,CAAC,CAAC,IAAI,OAAO,OAAO,KAAK,EAAE,SAAS,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,OAAO,EAAE,SAAS,CAAC,CAAC,IAAI,eAAG,KAAK,OAAO,IAAI,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK;AAEzJ,UAAQ,KAAK;AACb,UAAQ,KAAK,eAAG,IAAI,KAAK,QAAQ,SAAS,CAAC,CAAC,IAAI,QAAQ,SAAS,CAAC,CAAC,IAAI,UAAU,SAAS,CAAC,CAAC,IAAI,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC;AACpH,aAAW,CAAC,MAAM,MAAM,KAAK,aAAa,KAAK,GAAG;AAChD,YAAQ,KAAK,QAAQ,OAAO,OAAO,KAAK,GAAG,QAAQ,UAAU,IAAI,CAAC,CAAC;AAAA,EACrE;AACA,UAAQ,KAAK,QAAQ,OAAO,MAAM,MAAM,KAAK,GAAG,MAAM,OAAO,eAAG,KAAK,OAAO,CAAC,CAAC;AAE9E,MAAI,MAAM,iBAAiB,MAAM,MAAM,OAAO,QAAQ,GAAG;AACvD,YAAQ,KAAK;AACb,YAAQ,KAAK,eAAG,IAAI,2BAA2B,CAAC;AAChD,eAAW,CAAC,SAAS,MAAM,KAAK,OAAO,QAAQ,MAAM,aAAa,GAAG;AACnE,cAAQ,KAAK,QAAQ,IAAI,QAAQ,OAAO,CAAC;AAAA,IAC3C;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,QAAQ,MAAM,eAAe;AACrD,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,KAAK;AACb,YAAQ,KAAK,eAAG,IAAI,2BAA2B,CAAC;AAChD,eAAW,CAAC,MAAM,MAAM,KAAK,UAAU;AACrC,cAAQ,KAAK,QAAQ,OAAO,OAAO,KAAK,GAAG,QAAQ,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,MAAI,SAAS;AACX,YAAQ,KAAK;AACb,YAAQ,KAAK,OAAO;AACpB,YAAQ,KAAK;AACb,eAAW,QAAQ,MAAM,OAAO;AAC9B,cAAQ,KAAK,QAAQ,IAAI,MAAM,GAAG,KAAK,IAAI,KAAK,eAAG,IAAI,UAAU,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;AAAA,IACjF;AAAA,EACF;AAEA,MAAI,MAAM,cAAc,GAAG;AACzB,YAAQ,KAAK;AACb,YAAQ;AAAA,MACN,eAAG,IAAI,KAAK,MAAM,WAAW,oBAAoB,MAAM,gBAAgB,IAAI,QAAQ,OAAO,cAAc;AAAA,IAC1G;AAAA,EACF;AAEA,UAAQ,KAAK;AACf;AAGA,eAAsB,eAAe,QAAuB,OAA8B;AACxF,gBAAc,2BAA2B;AACzC,QAAM,QAAQ,MAAM,mBAAmB,OAAO,UAAU,KAAK;AAC7D,iBAAe,gBAAgB,MAAM,IAAI,kBAAkB,MAAM,KAAK,KAAK,MAAM,SAAS,GAAG;AAE7F,MAAI,MAAM,MAAM,UAAU,GAAG;AAC3B,YAAQ,KAAK,eAAG,IAAI,6BAA6B,MAAM,KAAK,EAAE,CAAC;AAC/D;AAAA,EACF;AAEA,MAAI,OAAO,IAAI;AACb,gBAAY,eAAe,KAAK,CAAC;AACjC,QAAI,MAAM,cAAc,EAAG,SAAQ,KAAK,eAAG,IAAI,GAAG,MAAM,WAAW,sCAAsC,CAAC;AAC1G;AAAA,EACF;AAEA,mBAAiB,OAAO,OAAO,OAAO;AACxC;;;AtClUA,SAAS,cAAsB;AAC7B,QAAM,UAAU,OAAO,iBAAiB;AACxC,MAAI,SAAS;AACX,UAAM,WAAWC,SAAQ,OAAO;AAChC,QAAI,CAACC,aAAW,QAAQ,KAAK,CAACC,UAAS,QAAQ,EAAE,YAAY,GAAG;AAC9D,YAAM,IAAI,MAAM,6CAA6C,QAAQ,EAAE;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AAEA,MAAI,MAAMC,SAAQ,IAAI;AAEtB,MAAI,IAAI,SAAS,YAAY,KAAK,IAAI,SAAS,cAAc,GAAG;AAC9D,UAAMH,SAAQ,KAAK,OAAO;AAAA,EAC5B;AAEA,SAAO;AACT;AAOA,SAAS,UAAU,UAAwB;AACzC,MAAI,CAACC,aAAWG,OAAK,UAAU,MAAM,CAAC,GAAG;AACvC,UAAM,IAAI,MAAM,yBAAyB,QAAQ,EAAE;AAAA,EACrD;AACF;AAGA,IAAM,WAA6E;AAAA,EACjF,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AAAA,EACP,eAAe;AAAA,EACf,OAAO,OAAO,WAAW;AACvB,QAAI,OAAO,MAAM,CAAC,OAAO,MAAO,OAAM,IAAI,MAAM,8BAA8B;AAC9E,QAAI,CAAC,OAAO,MAAO,QAAO,SAAS,MAAM;AACzC,WAAO,eAAe,QAAQ,OAAO,KAAK;AAAA,EAC5C;AACF;AAEA,SAAS,yBAAkC;AACzC,SACED,SAAQ,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,QAAQ,eAAe,QAAQ,IAAI,KAC3GA,SAAQ,KAAK,CAAC,MAAM;AAExB;AAEA,eAAe,OAAsB;AACnC,MAAI;AACF,UAAM,WAAW,YAAY;AAE7B,QAAI,uBAAuB,GAAG;AAC5B,YAAM,SAAS,EAAE,UAAU,EAAE,aAAa,IAAI,gBAAgB,OAAO,EAAE,GAAqB,QAAQ;AACpG;AAAA,IACF;AAEA,UAAM,aAAa,MAAM,WAAW,QAAQ;AAE5C,UAAM,SAAS,MAAM,SAAS,YAAY,QAAQ;AAGlD,QAAI,CAAC,CAAC,SAAS,SAAS,iBAAiB,OAAO,EAAE,SAAS,OAAO,OAAO,GAAG;AAC1E,gBAAU,QAAQ;AAAA,IACpB;AAEA,UAAM,SAAS,OAAO,OAAO,EAAE,MAAM;AAErC,YAAQ,KAAK;AAAA,EACf,SAAS,OAAO;AACd,YAAQ,MAAM;AACd,YAAQ,MAAM,GAAG,eAAG,IAAI,QAAG,CAAC,IAAI,aAAa,KAAK,CAAC,EAAE;AACrD,IAAAA,SAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK;","names":["existsSync","statSync","join","resolve","process","process","process","process","process","existsSync","join","z","join","pad","existsSync","z","resolve","process","process","resolve","count","existsSync","join","existsSync","mkdir","dirname","join","resolve","join","existsSync","resolve","dirname","join","mkdir","existsSync","mkdir","readFile","writeFile","dirname","join","join","existsSync","readFile","mkdir","dirname","writeFile","existsSync","join","process","existsSync","rm","join","Project","SyntaxKind","SyntaxKind","Project","count","status","upstreamChanged","upstreamOnly","existsSync","join","rm","mkdir","writeFile","dirname","join","join","mkdir","dirname","writeFile","spawnSync","readFileSync","basename","join","relative","confirm","execFile","promisify","execFileAsync","promisify","execFile","str","spawnSync","existsSync","readFileSync","dirname","join","relative","select","existsSync","readFileSync","plural","join","relative","dirname","select","spawnSync","readFileSync","join","basename","count","packageJsonPath","relative","confirm","spawnSync","select","execFileSync","mkdirSync","writeFileSync","tmpdir","basename","join","process","execFileSync","process","join","tmpdir","basename","mkdirSync","writeFileSync","rmSync","dirname","join","resolve","dirname","resolve","join","rmSync","existsSync","dirname","resolve","dirname","resolve","existsSync","checkbox","select","fork","resolve","process","Separator","select","spawnSync","select","spawnSync","existsSync","readFileSync","writeFileSync","join","existsSync","readFileSync","join","readFileSync","join","existsSync","existsSync","readFileSync","join","writeFileSync","result","kept","spawnSync","select","resolve","Separator","select","process","readFile","join","existsSync","readFileSync","statSync","join","relative","sep","join","existsSync","statSync","readFileSync","relative","sep","readFile","join","sep","record","resolve","existsSync","statSync","process","join"]}