@cellajs/cli 0.4.2 → 0.6.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/README.md +171 -113
- package/dist/config.d.ts +15 -11
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/index.js +1471 -818
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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/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/review-page.ts","../src/utils/diff.ts","../src/services/analyze.ts","../src/services/audit.ts","../src/utils/audit-utils.ts","../src/utils/local-tools.ts","../src/utils/runtimes.ts","../src/utils/security-plan.ts","../src/utils/workspace-yaml.ts","../src/services/audit-security.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, 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 and runtime pins, 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 /** `<merge-base>..<upstream>` range of short SHAs: what upstream changed since the last sync, for the review page. */\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/** 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/** Files with `status`, managed files left out: the list each analyze file group prints. */\nexport function filesWithStatus(files: AnalyzedFile[], status: FileStatus): AnalyzedFile[] {\n return files.filter((f) => f.status === status && !isManagedFile(f.path));\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 config = statusConfig[status];\n const title = options?.title ?? `${config.icon} ${config.label}`;\n printFileSection(filesWithStatus(files, status), 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 review what upstream changed 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/** 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.\n */\nexport function printAnalysisFileGroups(files: AnalyzedFile[], linkOptions: LinkOptions): 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: PROTECTED_BEHIND_HINT,\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 console.info(pc.dim(` ${PROTECTED_BEHIND_HINT}`));\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/**\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. 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 }\n console.info(pc.dim(' the fork left these untouched and ignored paths never sync: review 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.2\",\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.28.7\",\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 } 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 * 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, 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 range the review page diffs upstream's\n * changes over. Report only, read from refs (the merge state is irrelevant); a failure here yields\n * no report and never fails the run.\n */\nasync function upstreamOnlyReports(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n files: AnalyzedFile[],\n): Promise<Pick<MergeResult, 'upstreamDiffRange' | 'upstreamOverrides' | 'ignoredUpstreamChanges'>> {\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 };\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)),\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);\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 * Review page: one browser page per analyze or sync run, holding the diff of every file the run\n * asks you to review, under the same sections the terminal prints.\n */\n\nimport { basename } from 'node:path';\nimport process from 'node:process';\nimport { pathToFileURL } from 'node:url';\nimport type { MergeResult } from '../config/types';\nimport pc from '../utils/colors';\nimport { type DiffPageSection, gitDiffFile, openInBrowser, writeDiffPage } from '../utils/diff';\nimport {\n createSpinner,\n filesWithStatus,\n findMaskingPins,\n findProtectedBehind,\n hyperlink,\n plural,\n spinnerSuccess,\n} from '../utils/display';\n\n/** Diffs on one page at most: each costs ~60 ms to render and ~85 KB of page. The rest are listed by path. */\nconst MAX_PAGE_FILES = 50;\n\n/** Larger patches are listed instead of rendered: highlighting them stalls the run. */\nconst MAX_PATCH_BYTES = 512 * 1024;\n\n/** The files of one terminal list, and the `from..to` refs their diffs run over. */\nexport interface ReviewSection {\n title: string;\n /** What the diffs show and why the files are listed */\n hint: string;\n range: string;\n paths: string[];\n}\n\n/**\n * The review page's sections for a run, from the same lists the terminal prints. Sync shows the\n * upstream changes it did not bring in; analyze adds pinned files missing upstream lines and the\n * fork's own changes to files that still sync. Empty sections are left out, and so is every\n * section when the engine could not resolve the sync range.\n */\nexport function reviewSections(result: MergeResult, command: 'analyze' | 'sync'): ReviewSection[] {\n const [base, upstream] = result.upstreamDiffRange?.split('..') ?? [];\n if (!base || !upstream) return [];\n const sinceSync = `${base}..${upstream}`;\n\n const dropped: ReviewSection =\n command === 'sync'\n ? {\n title: 'protected files kept the fork version',\n hint: 'What upstream changed in these files since the last sync. The fork kept its own version, so none of it arrived: adopt what you need.',\n range: sinceSync,\n paths: result.protectedConflicts ?? [],\n }\n : {\n title: 'protected but behind upstream',\n hint: 'What upstream changed in these files since the last sync. They are pinned or ignored, so the sync keeps the fork version and none of it arrives: adopt what you need.',\n range: sinceSync,\n paths: findProtectedBehind(result.files).map((file) => file.path),\n };\n\n const sections: ReviewSection[] = [\n dropped,\n {\n title: 'ignored paths changed upstream',\n hint: 'What upstream changed under ignored paths since the last sync. The fork left these files untouched, and ignored paths never sync.',\n range: sinceSync,\n paths: (result.ignoredUpstreamChanges ?? []).flatMap((group) => group.paths),\n },\n {\n title: 'pinned files that match the previous upstream',\n hint: 'What upstream changed in these files since the last sync. The fork copy still equals the previous upstream, so the pin only drops these changes: unpin to take them.',\n range: sinceSync,\n paths: findMaskingPins(result.files).map((file) => file.path),\n },\n ];\n\n if (command === 'analyze') {\n sections.push(\n {\n title: 'protected in fork, upstream lines absent',\n hint: \"The fork's version against upstream's, both as they are now: added lines are upstream content the fork does not have, dropped by an earlier sync or removed on purpose.\",\n range: `HEAD..${upstream}`,\n paths: filesWithStatus(result.files, 'ahead')\n .filter((file) => (file.upstreamLinesAbsent ?? 0) > 0)\n .map((file) => file.path),\n },\n {\n title: 'drifted from upstream',\n hint: 'What the fork changed in these files since the last sync. They are not pinned or ignored, so upstream changes still merge into them.',\n range: `${base}..HEAD`,\n paths: filesWithStatus(result.files, 'drifted').map((file) => file.path),\n },\n );\n }\n\n return sections.filter((section) => section.paths.length > 0);\n}\n\n/**\n * Write the review page for `sections` and return its path with the number of diffs on it.\n * Files past the page limit, oversized patches and patches without a text hunk (binary, mode\n * only) are listed by path. Undefined when no file has a diff.\n */\nexport async function writeReviewPage(\n forkPath: string,\n sections: ReviewSection[],\n meta: { command: 'analyze' | 'sync'; range: string },\n): Promise<{ path: string; diffs: number } | undefined> {\n const [base, upstream] = meta.range.split('..');\n let diffs = 0;\n const pageSections: DiffPageSection[] = [];\n\n for (const section of sections) {\n const pageSection: DiffPageSection = { title: section.title, hint: section.hint, files: [], omitted: [] };\n for (const path of section.paths) {\n if (diffs >= MAX_PAGE_FILES) {\n pageSection.omitted?.push(path);\n continue;\n }\n const patch = gitDiffFile(forkPath, section.range, path);\n if (patch.length === 0) continue;\n if (patch.length > MAX_PATCH_BYTES || !patch.includes('\\n@@ ')) {\n pageSection.omitted?.push(path);\n continue;\n }\n pageSection.files.push({ path, patch: patch.toString() });\n diffs++;\n }\n if (pageSection.files.length > 0 || pageSection.omitted?.length) pageSections.push(pageSection);\n }\n\n if (diffs === 0) return undefined;\n const page = await writeDiffPage(\n pageSections,\n { title: `${meta.command} review`, note: `${basename(forkPath)} · last sync ${base} → upstream ${upstream}` },\n forkPath,\n `${meta.command}-review`,\n );\n return { path: page, diffs };\n}\n\n/**\n * After an analyze or sync report: write the review page and print where it is. Sync opens it in\n * the browser when stdout is a terminal, since the upstream changes it lists did not arrive.\n * Silent when there is nothing to review; a failure prints nothing and never fails the run.\n */\nexport async function reportReviewPage(\n forkPath: string,\n result: MergeResult,\n command: 'analyze' | 'sync',\n): Promise<void> {\n const sections = reviewSections(result, command);\n if (sections.length === 0 || !result.upstreamDiffRange) return;\n\n createSpinner('writing review page...');\n let page: Awaited<ReturnType<typeof writeReviewPage>>;\n try {\n page = await writeReviewPage(forkPath, sections, { command, range: result.upstreamDiffRange });\n } catch {\n page = undefined;\n }\n spinnerSuccess();\n if (!page) return;\n\n const opened = command === 'sync' && process.stdout.isTTY === true && openInBrowser(page.path);\n console.info();\n console.info(\n `${pc.cyan('⧈')} review page with ${plural(page.diffs, 'diff')}${opened ? ', opened in the browser' : ''}:`,\n );\n console.info(pc.dim(` ${hyperlink(page.path, pathToFileURL(page.path).href)}`));\n}\n","/**\n * Diff helpers: a single-file `git diff`, and diffs rendered as a self-contained HTML page that\n * opens in the default browser. Used by the contributions service and the review page.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { 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 with standard a/ b/ prefixes, which the HTML renderer's patch\n * parser requires; empty when the file is identical.\n */\nexport function gitDiffFile(cwd: string, range: string, filePath: string): Buffer {\n try {\n return execFileSync('git', ['diff', '--no-color', range, '--', filePath], { 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/** One file on a diff page: its path and its unified diff, with standard a/ b/ prefixes. */\nexport interface DiffPageFile {\n path: string;\n patch: string;\n}\n\n/** A group of files on a diff page, under an optional title and a line saying what the diffs show. */\nexport interface DiffPageSection {\n title?: string;\n hint?: string;\n files: DiffPageFile[];\n /** Paths of files listed without a diff (binary, too large, or past the page limit) */\n omitted?: string[];\n}\n\n/** The page header: a title, plus dim context after it. */\ninterface DiffPageMeta {\n title: string;\n /** Extra context shown after the title (e.g. 'cella ← → myfork') */\n note?: string;\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\n/**\n * Render diffs as a complete, self-contained HTML document: one block per file, grouped in\n * sections, with a section index at the top when there is more than one.\n *\n * Highlighting and diff layout come from `@pierre/diffs` (Shiki-based), rendered server-side to\n * static HTML: no scripts, no external requests, adapts to the viewer's light/dark preference.\n * Patches must use standard a/ b/ prefixes, as `gitDiffFile` returns them.\n */\nexport async function renderDiffPage(sections: DiffPageSection[], 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 renderFile = async (file: DiffPageFile) => {\n const { prerenderedHTML } = await preloadPatchDiff({\n patch: file.patch,\n options: {\n diffStyle: 'split',\n themeType: 'system',\n lineDiffType: 'word-alt',\n hunkSeparators: 'line-info',\n overflow: 'wrap',\n },\n });\n // Declarative shadow DOM: the library's CSS targets :host, which only matches inside a\n // shadow root (its browser component renders into one).\n return `<div class=\"diff-shell\"><template shadowrootmode=\"open\">\\n${prerenderedHTML}\\n</template></div>`;\n };\n\n const blocks: string[] = [];\n for (const [index, section] of sections.entries()) {\n const files: string[] = [];\n for (const file of section.files) files.push(await renderFile(file));\n const count = section.files.length + (section.omitted?.length ?? 0);\n const title = section.title\n ? `<h2>${escapeHtml(section.title)} <span class=\"count\">· ${count} ${count === 1 ? 'file' : 'files'}</span></h2>`\n : '';\n const hint = section.hint ? `<p class=\"hint\">${escapeHtml(section.hint)}</p>` : '';\n const omitted = section.omitted?.length\n ? `<p class=\"hint\">Not shown here (binary, too large, or past the page limit):</p><ul class=\"omitted\">${section.omitted\n .map((path) => `<li><code>${escapeHtml(path)}</code></li>`)\n .join('')}</ul>`\n : '';\n blocks.push(`<section id=\"section-${index + 1}\">${title}${hint}${files.join('\\n')}${omitted}</section>`);\n }\n\n const titled = sections.filter((section) => section.title);\n const index =\n titled.length > 1\n ? `<nav><ol>${sections\n .map((section, i) =>\n section.title\n ? `<li><a href=\"#section-${i + 1}\">${escapeHtml(section.title)}</a> <span class=\"count\">· ${\n section.files.length + (section.omitted?.length ?? 0)\n }</span></li>`\n : '',\n )\n .join('')}</ol></nav>`\n : '';\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>${escapeHtml(meta.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; z-index: 1;\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 .note { margin-left: auto; font-size: 0.8rem; opacity: 0.7; }\n main { max-width: 1400px; margin: 1rem auto; padding: 0 1rem 2rem; }\n nav ol { margin: 0 0 1.5rem; padding-left: 1.25rem; line-height: 1.7; }\n nav a { color: inherit; }\n section { scroll-margin-top: 4rem; }\n h2 { font-size: 1.05rem; margin: 2rem 0 0.25rem; }\n .count { font-weight: normal; opacity: 0.6; }\n .hint { margin: 0 0 1rem; font-size: 0.9rem; opacity: 0.75; max-width: 80ch; }\n .diff-shell {\n border: 1px solid light-dark(#e2e2e2, #2a2a2a);\n border-radius: 8px; overflow: hidden;\n background: light-dark(#fff, #161616);\n margin-bottom: 1rem;\n }\n .omitted { font-size: 0.85rem; opacity: 0.8; }\n .omitted code { font-family: ui-monospace, monospace; }\n</style>\n</head>\n<body>\n<header>\n <span class=\"brand\">⧈ cella diff</span>\n <code>${escapeHtml(meta.title)}</code>\n ${note}\n</header>\n<main>\n${index}\n${blocks.join('\\n')}\n</main>\n</body>\n</html>`;\n}\n\n/**\n * Render a diff page and write it to `<git dir>/cella-diff/<name>.html`. Inside the git dir the\n * page never reaches a commit and goes with the checkout; the path is stable per name, so a\n * rerun overwrites it and a browser refresh shows the latest render.\n *\n * @returns Absolute path of the written HTML file.\n */\nexport async function writeDiffPage(\n sections: DiffPageSection[],\n meta: DiffPageMeta,\n repoPath: string,\n name: string,\n): Promise<string> {\n const html = await renderDiffPage(sections, meta);\n const gitDir = execFileSync('git', ['rev-parse', '--absolute-git-dir'], { cwd: repoPath, encoding: 'utf8' }).trim();\n const dir = join(gitDir, 'cella-diff');\n mkdirSync(dir, { recursive: true });\n const outPath = join(dir, `${name.replace(/[^\\w.-]+/g, '-')}.html`);\n writeFileSync(outPath, html);\n return outPath;\n}\n\n/**\n * Open a file or URL with `open` (macOS) or `xdg-open`. Best-effort: a missing or failing opener\n * is not fatal, it returns false (e.g. a headless environment without a browser).\n */\nexport function openInBrowser(target: string): boolean {\n try {\n execFileSync(process.platform === 'darwin' ? 'open' : 'xdg-open', [target], { stdio: 'ignore' });\n return true;\n } catch {\n return false;\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';\nimport { reportReviewPage } from './review-page';\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);\n\n printEngineReports(result, 'analysis summary');\n await reportReviewPage(config.forkPath, result, 'analyze');\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 * One table and one checkbox for outdated packages and runtime pins (Node, pnpm, image tags). The\n * picked updates become file edits that the security pass (see audit-security.ts) stages, checks\n * and writes, so the workspace changes once and only with a single install. Below the table, the\n * security fixes this machine's own Node, pnpm and gh miss (see local-tools.ts).\n */\n\nimport { readFileSync } from 'node:fs';\nimport { basename, join, relative } from 'node:path';\nimport { checkbox, Separator } from '@inquirer/prompts';\nimport type { RuntimeConfig } from '../config/types';\nimport {\n type EnhancedPackageInfo,\n editJsonText,\n formatDependents,\n getReleasesUrl,\n getRepoUrl,\n getVulnIcon,\n middleTruncate,\n type OutdatedPackage,\n outdatedPackageName,\n readReleaseAgeMinutes,\n rewriteSpecifier,\n runPnpmAudit,\n runPnpmJson,\n} from '../utils/audit-utils';\nimport pc from '../utils/colors';\nimport { createSpinner, hyperlink, spinnerFail, spinnerSuccess, warningMark } from '../utils/display';\nimport { getEnv } from '../utils/env';\nimport { type LocalToolCheck, planLocalTools, readLocalTools } from '../utils/local-tools';\nimport {\n applyRuntimeUpdate,\n fetchRuntimeFeeds,\n missingNodeImages,\n pinLocation,\n planRuntimeUpdates,\n type RuntimeUpdate,\n readRuntimePins,\n} from '../utils/runtimes';\nimport { advisoriesFromAudit, SEVERITIES } from '../utils/security-plan';\nimport { isBreakingJump } from '../utils/versions';\nimport { readTopLevel } from '../utils/workspace-yaml';\nimport { runSecurityPass, type WorkspaceEdits } from './audit-security';\n\n/** The manifest sections an update rewrites, as `pnpm up --latest` does. */\nconst DEPENDENCY_SECTIONS = ['dependencies', 'devDependencies', 'optionalDependencies'] as const;\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 packages and runtimes...');\n try {\n const pins = await readRuntimePins(forkPath);\n const now = Date.now();\n // --long adds each package's latest manifest, which holds its repository URL.\n const [outdated, auditResult, releaseAgeMinutes, feeds, machine] = await Promise.all([\n runPnpmJson(['-r', 'outdated', '--json', '--long'], forkPath),\n runPnpmAudit(forkPath),\n readReleaseAgeMinutes(forkPath),\n fetchRuntimeFeeds(pins, forkPath, now),\n readLocalTools(forkPath, now),\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\n const runtimes = planRuntimeUpdates(pins, feeds, { releaseAgeMinutes, now });\n const localTools = planLocalTools(machine, { releaseAgeMinutes, now });\n const rows = [\n ...packageRows(outdated as Record<string, OutdatedPackage>, auditResult ? advisoriesFromAudit(auditResult) : []),\n ...runtimes.updates.map(runtimeRow),\n ];\n\n if (rows.length === 0) {\n spinnerSuccess('all packages and runtimes are up to date');\n printNotes(forkPath, runtimes.unchecked);\n console.info();\n printLocalTools(localTools);\n await runSecurityPass(forkPath, { apply: !config.list, releaseAgeMinutes });\n return;\n }\n\n spinner.stop();\n printOutdatedResults(rows, forkPath);\n printNotes(forkPath, runtimes.unchecked);\n console.info();\n printLocalTools(localTools);\n\n // --list is the non-interactive mode: report only, no prompts and no writes.\n if (config.list) {\n await runSecurityPass(forkPath, { apply: false, releaseAgeMinutes });\n return;\n }\n\n const selected = await promptForUpdates(rows);\n if (!selected) return;\n const { edits, bumped } = await planEdits(forkPath, rows, selected, pins.nodeImageSuffixes);\n if (await runSecurityPass(forkPath, { apply: true, releaseAgeMinutes, edits })) printNext(bumped);\n } finally {\n spinner.stop();\n }\n}\n\n/** The outdated packages as table rows, sorted by the workspaces that depend on them. */\nfunction packageRows(outdated: Record<string, OutdatedPackage>, advisories: ReturnType<typeof advisoriesFromAudit>) {\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 rows: EnhancedPackageInfo[] = Object.entries(outdated).map(([key, pkg]) => {\n const name = outdatedPackageName(key);\n const repoUrl = getRepoUrl(pkg.latestManifest?.repository?.url);\n // pnpm leaves `current` out for a dependency that is not installed.\n const current = pkg.current ?? 'missing';\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 key,\n name,\n current,\n latest: pkg.latest,\n dependentPackages: pkg.dependentPackages,\n isDev: pkg.dependencyType === 'devDependencies',\n breaking: isBreakingJump(current, pkg.latest),\n pinnedIn,\n repoUrl,\n releasesUrl: getReleasesUrl(repoUrl),\n severity: severityOf(name),\n };\n });\n\n return rows.sort((a, b) => inText(a).localeCompare(inText(b)) || a.name.localeCompare(b.name));\n}\n\nfunction runtimeRow(update: RuntimeUpdate): EnhancedPackageInfo {\n return {\n key: `runtime:${update.file}:${update.name}`,\n name: update.name,\n current: update.current,\n latest: update.target,\n dependentPackages: [],\n isDev: false,\n breaking: isBreakingJump(update.current, update.target),\n pinnedIn: [],\n repoUrl: null,\n releasesUrl: update.releasesUrl,\n severity: update.severity,\n runtime: update,\n };\n}\n\nconst isRed = (row: EnhancedPackageInfo): boolean => row.severity === 'critical' || row.severity === 'high';\n\n/** The \"in\" column: where a runtime is pinned, or the workspaces that depend on the package, as \"first +N\". */\nconst inText = (row: EnhancedPackageInfo): string =>\n row.runtime ? pinLocation(row.runtime.file) : formatDependents(row.dependentPackages.map((d) => d.name));\n\nfunction printOutdatedResults(rows: EnhancedPackageInfo[], forkPath: string): void {\n const DEV_TAG = ' (dev)';\n const RUNTIME_TAG = ' (runtime)';\n const MAX_NAME_LEN = 35;\n const MAX_DEPENDENTS_LEN = 15;\n const tag = (row: EnhancedPackageInfo) => (row.runtime ? RUNTIME_TAG : row.isDev ? DEV_TAG : '');\n const maxNameLen = Math.min(MAX_NAME_LEN, Math.max(7, ...rows.map((p) => p.name.length + tag(p).length)));\n const maxCurrentLen = Math.max(7, ...rows.map((p) => p.current.length));\n const maxLatestLen = Math.max(6, ...rows.map((p) => p.latest.length));\n const maxDependentsLen = Math.min(MAX_DEPENDENTS_LEN, Math.max(10, ...rows.map((p) => inText(p).length)));\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 rows) {\n const vulnIndicator = pkg.severity ? getVulnIcon(pkg.severity) : ' ';\n\n const displayName = middleTruncate(`${pkg.name}${tag(pkg)}`, 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.breaking ? pc.bold(pc.green(latestText)) : pc.green(latestText);\n\n const dependents = pc.dim(middleTruncate(inText(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 rows) {\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 packages pnpm holds back (`updateConfig.ignoreDependencies`), and the runtimes whose feed did not answer. */\nfunction printNotes(forkPath: string, unchecked: string[]): void {\n let held: string[] = [];\n try {\n const updateConfig = readTopLevel(readFileSync(join(forkPath, 'pnpm-workspace.yaml'), 'utf8'), 'updateConfig');\n const ignored = (updateConfig as { ignoreDependencies?: unknown } | undefined)?.ignoreDependencies;\n held = Array.isArray(ignored) ? ignored.map(String) : [];\n } catch {\n // No workspace file: nothing is held.\n }\n if (held.length > 0) console.info(` ${pc.dim(`held: ${held.join(', ')} · pnpm-workspace.yaml updateConfig`)}`);\n if (unchecked.length > 0)\n console.info(` ${pc.dim(`not checked, no answer from the feed: ${unchecked.join(', ')}`)}`);\n}\n\n/** The tools this machine works with, each with the security fixes it misses and how to get them. */\nfunction printLocalTools(checks: LocalToolCheck[]): void {\n const width = Math.max(...checks.map((tool) => `${tool.name} ${tool.version}`.length));\n console.info(pc.bold('this machine'));\n for (const tool of checks) {\n const label = `${tool.name} ${tool.version}`.padEnd(width);\n const detail = tool.severity\n ? `${tool.note} ${pc.dim('·')} ${tool.fix}`\n : pc.dim(tool.note || 'no missing security fixes');\n console.info(`${tool.severity ? getVulnIcon(tool.severity) : ' '} ${label} ${detail}`);\n }\n console.info();\n}\n\n/** The grouped checkbox choices: runtimes, pinned packages, then the regular ones. A red dot starts ticked. */\nfunction buildUpdateChoices(\n rows: EnhancedPackageInfo[],\n): Array<{ name: string; value: string; checked: boolean } | Separator> {\n const makeChoice = (row: EnhancedPackageInfo) => {\n const devTag = row.isDev ? pc.dim(' (dev)') : '';\n const version = `${pc.red(row.current)} → ${pc.green(row.latest)}`;\n const notes = [\n row.breaking ? pc.bold('breaking') : '',\n row.runtime?.note ? pc.dim(row.runtime.note) : '',\n row.pinnedIn.length > 0 ? `${warningMark} ${pc.dim(`pinned in ${row.pinnedIn.join(', ')}`)}` : '',\n ].filter(Boolean);\n return {\n name: `${row.name}${devTag} ${version}${notes.length > 0 ? ` ${notes.join(' ')}` : ''}`,\n value: row.key,\n checked: isRed(row),\n };\n };\n\n const runtimes = rows.filter((p) => p.runtime);\n const pinned = rows.filter((p) => !p.runtime && p.pinnedIn.length > 0);\n const regular = rows.filter((p) => !p.runtime && p.pinnedIn.length === 0);\n\n const choices: Array<{ name: string; value: string; checked: boolean } | Separator> = [];\n\n if (runtimes.length > 0) {\n choices.push(new Separator(pc.yellow(`── runtimes (${runtimes.length}) ──`)));\n choices.push(...runtimes.map(makeChoice));\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 (choices.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/** The one prompt of the update step; null when it was cancelled. Submitting with nothing ticked skips the updates. */\nasync function promptForUpdates(rows: EnhancedPackageInfo[]): Promise<string[] | null> {\n try {\n const selected = await checkbox({\n message: `toggle what to update ${pc.dim('· enter with nothing ticked skips')}`,\n choices: buildUpdateChoices(rows),\n required: false,\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} selected`),\n },\n },\n });\n console.info();\n return selected;\n } catch {\n return null;\n }\n}\n\n/** The text of a runtime bump in the summary, e.g. `engines.node 26.12.1`. */\nfunction bumpText(update: RuntimeUpdate): string {\n if (update.pin.kind === 'node') return `engines.node ${update.target}`;\n if (update.pin.kind === 'pnpm') return `packageManager pnpm@${update.target}`;\n return update.pin.to;\n}\n\n/**\n * The selected updates as file contents, printed as one line per changed file. A dependency's\n * specifier keeps its prefix; one the audit cannot rewrite is left as written with a warning. A\n * Node bump waits until Docker Hub has every `node:<version><suffix>` image the Dockerfiles build from.\n */\nasync function planEdits(\n forkPath: string,\n rows: EnhancedPackageInfo[],\n selected: string[],\n nodeImageSuffixes: string[],\n): Promise<{ edits: WorkspaceEdits; bumped: RuntimeUpdate[] }> {\n const contents = new Map<string, { content: string; resolves: boolean }>();\n const summary = new Map<string, string[]>();\n const bumped: RuntimeUpdate[] = [];\n const edit = (file: string, label: string, item: string, resolves: boolean, change: (content: string) => string) => {\n const entry = contents.get(file) ?? { content: readFileSync(join(forkPath, file), 'utf8'), resolves: false };\n const next = change(entry.content);\n if (next === entry.content) return;\n contents.set(file, { content: next, resolves: entry.resolves || resolves });\n summary.set(label, [...(summary.get(label) ?? []), item]);\n };\n\n const chosen = rows.filter((row) => selected.includes(row.key));\n for (const row of chosen) {\n if (row.runtime) continue;\n for (const { name: dependent, location } of row.dependentPackages) {\n const file = relative(forkPath, join(location, 'package.json'));\n edit(file, dependent || file, row.name, true, (content) =>\n editJsonText(content, (json) => {\n for (const section of DEPENDENCY_SECTIONS) {\n const deps = json[section] as Record<string, string> | undefined;\n const spec = deps?.[row.name];\n if (!deps || spec === undefined) continue;\n const next = rewriteSpecifier(spec, row.latest);\n if (next) deps[row.name] = next;\n else console.info(`${warningMark} ${row.name} in ${dependent || file} left as written: ${spec}`);\n }\n }),\n );\n }\n }\n\n for (const row of chosen) {\n const update = row.runtime;\n if (!update) continue;\n if (update.pin.kind === 'node') {\n const missing = await missingNodeImages(update.target, nodeImageSuffixes);\n if (missing.length > 0) {\n console.info(`${warningMark} node ${update.target} skipped: ${missing.join(', ')} is not on docker hub yet`);\n continue;\n }\n }\n edit(update.file, update.file, bumpText(update), false, (content) => applyRuntimeUpdate(content, update));\n bumped.push(update);\n }\n\n for (const [label, items] of summary) {\n console.info(`${pc.cyan('↑')} ${pc.bold(label)}: ${pc.dim(items.join(', '))}`);\n }\n if (summary.size > 0) console.info();\n\n const edits: WorkspaceEdits = { manifests: {}, files: {} };\n for (const [file, { content, resolves }] of contents) {\n (resolves ? edits.manifests : edits.files)[file] = content;\n }\n return { edits, bumped };\n}\n\n/** The steps a runtime bump leaves to the developer: this machine's Node, and a local build of each changed image. */\nfunction printNext(bumped: RuntimeUpdate[]): void {\n const steps: Array<[command: string, why: string]> = [];\n const node = bumped.find((update) => update.pin.kind === 'node');\n if (node && process.version !== `v${node.target}`) {\n const command = getEnv('VOLTA_HOME') ? `volta install node@${node.target}` : `switch to node ${node.target}`;\n steps.push([command, `this machine runs ${process.version.slice(1)}`]);\n }\n for (const update of bumped) {\n if (update.pin.kind === 'image') steps.push([`docker build -f ${update.file} .`, 'check that the image builds']);\n }\n if (steps.length === 0) return;\n\n const width = Math.max(...steps.map(([command]) => command.length));\n console.info(pc.bold('next'));\n for (const [command, why] of steps) console.info(` ${pc.dim('•')} ${command.padEnd(width)} ${pc.dim(why)}`);\n console.info();\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 type { RuntimeUpdate } from './runtimes';\n\nconst execFileAsync = promisify(execFile);\n\n/** One package in `pnpm -r outdated --json --long`. */\nexport interface OutdatedPackage {\n /** Missing for a dependency that is not installed. */\n current?: string;\n latest: string;\n dependencyType: 'dependencies' | 'devDependencies';\n dependentPackages: Array<{ name: string; location: string }>;\n latestManifest?: { repository?: { url?: string } };\n}\n\n/**\n * The package name of a `pnpm -r outdated --json` key. pnpm keys a name that has several entries\n * (another installed version or dependency type) as `name@current (dev)`.\n */\nexport function outdatedPackageName(key: string): string {\n const name = key.split(' ')[0];\n const at = name.indexOf('@', 1);\n return at === -1 ? name : name.slice(0, at);\n}\n\nexport interface EnhancedPackageInfo {\n /** The checkbox value: pnpm's outdated key for a package, `runtime:<file>:<name>` for a runtime pin. */\n key: string;\n /** The package name as a manifest lists it, or the runtime's name. */\n name: string;\n current: string;\n latest: string;\n dependentPackages: OutdatedPackage['dependentPackages'];\n isDev: boolean;\n /** The update leaves the range a caret allows: another major, or another minor below 1.0. */\n breaking: 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 /** Set for a runtime pin (Node, pnpm, an image tag) shown among the packages. */\n runtime?: RuntimeUpdate;\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/** 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/** pnpm's `minimumReleaseAge` in minutes; 0 when it is unset or unreadable. */\nexport async function readReleaseAgeMinutes(cwd: string): Promise<number> {\n const minutes = Number.parseInt((await runPnpm(['config', 'get', 'minimumReleaseAge'], cwd)).stdout, 10);\n return Number.isNaN(minutes) ? 0 : minutes;\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 // A failed lookup still prints JSON, as `{ \"error\": … }`.\n return times && typeof times === 'object' && !('error' in times) ? (times as Record<string, string>) : null;\n}\n\n/**\n * JSON text after `change` ran on its parsed value, written back with the file's own indent and\n * final newline, the way pnpm writes a manifest.\n */\nexport function editJsonText(content: string, change: (json: Record<string, unknown>) => void): string {\n const json = JSON.parse(content) as Record<string, unknown>;\n change(json);\n const indent = content.match(/^[ \\t]+(?=\")/m)?.[0] ?? ' ';\n return `${JSON.stringify(json, null, indent)}${content.endsWith('\\n') ? '\\n' : ''}`;\n}\n\n/**\n * The specifier that moves a dependency to `latest` and keeps its prefix (`^`, `~` or exact), as\n * `pnpm up --latest` writes it; null for one the audit leaves as written (`workspace:`, `catalog:`,\n * `npm:` aliases, operator ranges, tags).\n */\nexport function rewriteSpecifier(spec: string, latest: string): string | null {\n const match = spec.match(/^([\\^~]?)\\d+(?:\\.\\d+){0,2}(?:-[0-9A-Za-z.-]+)?$/);\n return match ? `${match[1]}${latest}` : 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 tools this machine works on the workspace with: the Node that runs it, the pnpm a terminal\n * starts, and gh. Each is checked for the security fixes it misses. The audit only reports them,\n * with the upgrade command that fits how the tool was installed.\n */\n\nimport { execFile } from 'node:child_process';\nimport { existsSync, realpathSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { delimiter, dirname, join, sep } from 'node:path';\nimport { promisify } from 'node:util';\nimport { fetchPublishTimes, type VulnerabilitySeverity } from './audit-utils';\nimport { plural } from './display';\nimport { getEnv } from './env';\nimport {\n type BulkAdvisory,\n fetchJson,\n fetchNodeReleases,\n fetchPnpmAdvisories,\n type NodeRelease,\n newestAged,\n} from './runtimes';\nimport { SEVERITIES } from './security-plan';\nimport { compareVersionStrings, isPrerelease, parseComparableVersion, satisfiesComparators } from './versions';\n\nconst execFileAsync = promisify(execFile);\n\n/** How a tool was installed, read from the path its binary resolves to. */\ntype Installer = 'volta' | 'brew' | null;\n\ninterface InstalledTool {\n version: string;\n installer: Installer;\n}\n\n/** The tools found on this machine, null when not installed, with their feeds; a feed that did not answer is null. */\nexport interface LocalTools {\n node: InstalledTool & { releases: NodeRelease[] | null };\n pnpm: (InstalledTool & { published: Record<string, string> | null; advisories: BulkAdvisory[] | null }) | null;\n /** `advisories` holds the severity of each advisory OSV lists against the installed version. */\n gh:\n | (InstalledTool & {\n releases: Array<{ version: string; publishedAt: number }> | null;\n advisories: VulnerabilitySeverity[] | null;\n })\n | null;\n}\n\n/** One tool as the audit shows it. */\nexport interface LocalToolCheck {\n name: string;\n version: string;\n /** The highest severity among the fixes the version misses; null when it misses none or was not checked. */\n severity: VulnerabilitySeverity | null;\n /** What it misses (`5 advisories, 1 high`), why it was not checked, or empty. */\n note: string;\n /** The command that gets the fixes (`update to <version>` for an install the audit cannot tell); empty when nothing is missed. */\n fix: string;\n}\n\n/** The first `name` binary on PATH outside `node_modules/.bin` folders and the folders in `skip`. */\nfunction findOnPath(name: string, skip: string[] = []): string | null {\n for (const dir of (getEnv('PATH') ?? '').split(delimiter)) {\n if (!dir || skip.includes(dir) || dir.endsWith(`node_modules${sep}.bin`)) continue;\n if (existsSync(join(dir, name))) return join(dir, name);\n }\n return null;\n}\n\nfunction installerOf(file: string): Installer {\n let real = file;\n try {\n real = realpathSync(file);\n } catch {\n // A broken link: read the path as found.\n }\n if (real.includes(`${sep}.volta${sep}`)) return 'volta';\n return /[\\\\/](Cellar|homebrew|linuxbrew)[\\\\/]/.test(real) ? 'brew' : null;\n}\n\n/** The first x.y.z in a binary's `--version` output; null when it does not run. */\nasync function versionOf(file: string, cwd?: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(file, ['--version'], { encoding: 'utf8', timeout: 10_000, cwd });\n return stdout.match(/\\d+\\.\\d+\\.\\d+/)?.[0] ?? null;\n } catch {\n return null;\n }\n}\n\nasync function readNode(now: number): Promise<LocalTools['node']> {\n const version = process.version.slice(1);\n const major = parseComparableVersion(version)?.major ?? 0;\n return { version, installer: installerOf(process.execPath), releases: await fetchNodeReleases(major, now) };\n}\n\n/**\n * The pnpm a terminal starts, asked outside any project. A pnpm that switched to the workspace's\n * `packageManager` puts its own folder first on PATH, so the folder of the running pnpm is skipped.\n */\nasync function readPnpm(cwd: string): Promise<LocalTools['pnpm']> {\n const running = getEnv('npm_execpath');\n const file = findOnPath('pnpm', running ? [dirname(running)] : []);\n const version = file && (await versionOf(file, tmpdir()));\n if (!file || !version) return null;\n const [published, advisories] = await Promise.all([fetchPublishTimes('pnpm', cwd), fetchPnpmAdvisories(version)]);\n return { version, installer: installerOf(file), published, advisories };\n}\n\n/**\n * The severity of each advisory OSV lists against a Go module version; null when OSV does not\n * answer. OSV lists an advisory under its GHSA id and its GO id, and only the GHSA entry carries a\n * severity; one without a GHSA entry counts as moderate.\n */\nasync function fetchOsvSeverities(module: string, version: string): Promise<VulnerabilitySeverity[] | null> {\n const answer = await fetchJson('https://api.osv.dev/v1/query', {\n method: 'POST',\n body: JSON.stringify({ package: { name: module, ecosystem: 'Go' }, version }),\n });\n if (!answer) return null;\n type OsvVuln = { id: string; aliases?: string[]; database_specific?: { severity?: string } };\n const byGhsa = new Map<string, VulnerabilitySeverity>();\n for (const vuln of (answer as { vulns?: OsvVuln[] }).vulns ?? []) {\n const id = [vuln.id, ...(vuln.aliases ?? [])].find((alias) => alias.startsWith('GHSA-')) ?? vuln.id;\n const severity = SEVERITIES.find((level) => level === vuln.database_specific?.severity?.toLowerCase());\n if (severity || !byGhsa.has(id)) byGhsa.set(id, severity ?? 'moderate');\n }\n return [...byGhsa.values()];\n}\n\nasync function readGh(): Promise<LocalTools['gh']> {\n const file = findOnPath('gh');\n const version = file && (await versionOf(file));\n if (!file || !version) return null;\n const [list, advisories] = await Promise.all([\n fetchJson('https://api.github.com/repos/cli/cli/releases?per_page=30'),\n fetchOsvSeverities('github.com/cli/cli/v2', version),\n ]);\n const releases = Array.isArray(list)\n ? list.flatMap((entry) => {\n const { tag_name, published_at } = entry as { tag_name?: string; published_at?: string };\n const publishedAt = Date.parse(published_at ?? '');\n return tag_name && !Number.isNaN(publishedAt) ? [{ version: tag_name.replace(/^v/, ''), publishedAt }] : [];\n })\n : null;\n return { version, installer: installerOf(file), releases, advisories };\n}\n\n/** Node, pnpm and gh as installed on this machine, with their release and advisory feeds, in parallel. */\nexport async function readLocalTools(cwd: string, now: number): Promise<LocalTools> {\n const [node, pnpm, gh] = await Promise.all([readNode(now), readPnpm(cwd), readGh()]);\n return { node, pnpm, gh };\n}\n\n/** The command that moves a tool to `target`; Homebrew picks its own version. */\nfunction upgradeCommand(name: string, installer: Installer, target: string | undefined): string {\n if (installer === 'brew') return `brew upgrade ${name}`;\n if (!target) return 'no fixed release older than the release age yet';\n if (installer === 'volta') return `volta install ${name}@${target}`;\n return name === 'pnpm' ? `pnpm self-update ${target}` : `update to ${target}`;\n}\n\n/** The line for one tool; `missed` is null when its feed did not answer. */\nfunction toCheck(\n name: 'node' | 'pnpm' | 'gh',\n tool: InstalledTool,\n missed: VulnerabilitySeverity[] | null,\n target: string | undefined,\n noun: [singular: string, plural: string],\n): LocalToolCheck {\n if (!missed)\n return { name, version: tool.version, severity: null, note: 'not checked, no answer from the feed', fix: '' };\n if (missed.length === 0) return { name, version: tool.version, severity: null, note: '', fix: '' };\n const high = missed.filter((severity) => severity === 'critical' || severity === 'high').length;\n return {\n name,\n version: tool.version,\n severity: SEVERITIES.find((severity) => missed.includes(severity)) ?? null,\n note: `${plural(missed.length, ...noun)}${high > 0 && high < missed.length ? `, ${high} high` : ''}`,\n fix: upgradeCommand(name, tool.installer, target),\n };\n}\n\n/**\n * The security fixes each tool misses, and the version that has them: the newest one in its major\n * older than the release age. For pnpm that is the newest version no advisory affects, in its\n * major when one there has every fix.\n */\nexport function planLocalTools(\n tools: LocalTools,\n options: { releaseAgeMinutes: number; now: number },\n): LocalToolCheck[] {\n const cutoff = options.now - options.releaseAgeMinutes * 60 * 1000;\n const { node, pnpm, gh } = tools;\n\n const nodeTarget = node.releases ? newestAged(node.version, node.releases, cutoff) : undefined;\n const securityReleases = (node.releases ?? []).filter(\n (release) =>\n release.security &&\n nodeTarget &&\n compareVersionStrings(release.version, node.version) > 0 &&\n compareVersionStrings(release.version, nodeTarget.version) <= 0,\n );\n const checks = [\n toCheck(\n 'node',\n node,\n node.releases && securityReleases.map((): VulnerabilitySeverity => 'high'),\n nodeTarget?.version,\n ['security release', 'security releases'],\n ),\n ];\n\n if (pnpm) {\n const affecting = (version: string) =>\n (pnpm.advisories ?? []).filter((advisory) => satisfiesComparators(version, advisory.vulnerable_versions));\n const fixed = Object.entries(pnpm.published ?? {})\n .map(([version, time]) => ({ version, publishedAt: Date.parse(time) }))\n .filter(\n (release) =>\n parseComparableVersion(release.version) &&\n !isPrerelease(release.version) &&\n release.publishedAt <= cutoff &&\n compareVersionStrings(release.version, pnpm.version) > 0 &&\n affecting(release.version).length === 0,\n )\n .sort((a, b) => compareVersionStrings(b.version, a.version));\n const major = parseComparableVersion(pnpm.version)?.major;\n const target = fixed.find((release) => parseComparableVersion(release.version)?.major === major) ?? fixed[0];\n const missed = pnpm.advisories && pnpm.published && affecting(pnpm.version).map((advisory) => advisory.severity);\n checks.push(toCheck('pnpm', pnpm, missed, target?.version, ['advisory', 'advisories']));\n }\n\n if (gh) {\n const target = gh.releases ? newestAged(gh.version, gh.releases, cutoff) : undefined;\n checks.push(toCheck('gh', gh, gh.advisories, target?.version, ['advisory', 'advisories']));\n }\n\n return checks;\n}\n","/**\n * Runtime pins for the audit: the Node and pnpm versions the root package.json pins, and the image\n * tags of the Dockerfiles, checked against their release feeds. Reading, planning and rewriting\n * are pure; the fetches never throw, so a feed that does not answer only leaves its runtime out.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { basename, dirname, join } from 'node:path';\nimport { editJsonText, fetchPublishTimes, type VulnerabilitySeverity } from './audit-utils';\nimport { git } from './git';\nimport { compareVersionStrings, isPrerelease, parseComparableVersion, satisfiesComparators } from './versions';\n\n/** An image tag in a Dockerfile `FROM` line. */\nexport interface ImagePin {\n file: string;\n /** Zero-based line of the `FROM`. */\n line: number;\n /** The image as written, e.g. `caddy` or `bitnami/redis`. */\n image: string;\n tag: string;\n}\n\n/** What the workspace pins: exact versions only, since a range already follows its line. */\nexport interface RuntimePins {\n node: string | null;\n pnpm: string | null;\n images: ImagePin[];\n /** Suffixes of `FROM node:${…}<suffix>` lines (`-alpine`): the images a Node bump needs to exist. */\n nodeImageSuffixes: string[];\n}\n\n/** A Node release from nodejs.org, with the time it was published. */\nexport interface NodeRelease {\n version: string;\n publishedAt: number;\n security: boolean;\n}\n\n/** An image tag on Docker Hub and when it was last pushed. */\nexport interface HubTag {\n name: string;\n pushedAt: number;\n}\n\n/** An npm advisory, reduced to its vulnerable range and severity. */\nexport interface BulkAdvisory {\n vulnerable_versions: string;\n severity: VulnerabilitySeverity;\n}\n\n/** What the feeds answered; null where a feed did not answer. */\nexport interface RuntimeFeeds {\n node: NodeRelease[] | null;\n pnpm: { published: Record<string, string>; advisories: BulkAdvisory[] } | null;\n /** Per image pin, in the order of {@link RuntimePins.images}. */\n images: Array<{ pinned: HubTag | null; tags: HubTag[] } | null>;\n}\n\n/** How a pin moves, and what the audit shows about it. */\nexport interface RuntimeUpdate {\n name: string;\n current: string;\n target: string;\n /** Where it is pinned, relative to the workspace root. */\n file: string;\n /** A red dot for a security fix, a yellow dot for a tag that stopped getting pushes. */\n severity: 'high' | 'moderate' | null;\n note: string;\n releasesUrl: string;\n pin: { kind: 'node' } | { kind: 'pnpm' } | { kind: 'image'; line: number; ref: string; to: string };\n}\n\nconst DAY = 24 * 60 * 60 * 1000;\n\n/** A tag without a push for this long, while a newer line got one, gets no more fixes. */\nconst FROZEN_AFTER = 180 * DAY;\nconst RECENT_PUSH = 30 * DAY;\n\nconst EXACT_VERSION = /^\\d+\\.\\d+\\.\\d+$/;\n\nconst FROM_LINE = /^\\s*FROM\\s+(?:--platform=\\S+\\s+)?(\\S+)(?:\\s+AS\\s+(\\S+))?\\s*$/i;\n\n/** `FROM node:${NODE_VERSION}-alpine`: the version comes from a build argument. */\nconst NODE_ARG_TAG = /^(?:docker\\.io\\/)?(?:library\\/)?node:\\$\\{?\\w+\\}?([\\w.-]*)$/;\n\n/** A tag naming at least a minor (`2.8`, `2.8.4`), with an optional suffix (`-alpine`). */\nconst MINOR_TAG = /^(\\d+(?:\\.\\d+){1,2})(-[\\w.-]+)?$/;\n\nconst isDockerfile = (path: string): boolean => /(^|\\.)Dockerfile$|^Dockerfile\\./i.test(basename(path));\n\n/** The image pins and Node build-argument suffixes in one Dockerfile. */\nexport function parseDockerfile(file: string, content: string): { images: ImagePin[]; nodeImageSuffixes: string[] } {\n const images: ImagePin[] = [];\n const nodeImageSuffixes: string[] = [];\n const stages = new Set<string>();\n\n content.split('\\n').forEach((text, line) => {\n const match = text.match(FROM_LINE);\n if (!match) return;\n const [, ref, stage] = match;\n const fromStage = stages.has(ref.toLowerCase());\n if (stage) stages.add(stage.toLowerCase());\n if (fromStage || ref.includes('@')) return;\n\n const nodeArg = ref.match(NODE_ARG_TAG);\n if (nodeArg) {\n nodeImageSuffixes.push(nodeArg[1]);\n return;\n }\n if (ref.includes('$')) return;\n\n const slash = ref.lastIndexOf('/');\n const colon = ref.lastIndexOf(':');\n if (colon <= slash) return;\n let image = ref.slice(0, colon);\n const tag = ref.slice(colon + 1);\n const host = image.includes('/') ? image.split('/')[0] : '';\n if (host === 'docker.io') image = image.slice(host.length + 1).replace(/^library\\//, '');\n else if (host.includes('.') || host.includes(':') || host === 'localhost') return;\n if (image === 'scratch') return;\n images.push({ file, line, image, tag });\n });\n\n return { images, nodeImageSuffixes };\n}\n\n/** The exact Node and pnpm pins of the root package.json, and the image tags of every tracked Dockerfile. */\nexport async function readRuntimePins(forkPath: string): Promise<RuntimePins> {\n let manifest: { engines?: { node?: string }; packageManager?: string } = {};\n try {\n manifest = JSON.parse(readFileSync(join(forkPath, 'package.json'), 'utf8'));\n } catch {\n // No root manifest: nothing pinned there.\n }\n const node = manifest.engines?.node?.trim() ?? '';\n const pnpm = manifest.packageManager?.match(/^pnpm@(\\d+\\.\\d+\\.\\d+)(?:\\+.*)?$/)?.[1] ?? null;\n\n const tracked = (await git(['ls-files', '-z'], forkPath, { ignoreErrors: true })).split('\\0').filter(isDockerfile);\n const images: ImagePin[] = [];\n const nodeImageSuffixes = new Set<string>();\n for (const file of tracked) {\n let content: string;\n try {\n content = readFileSync(join(forkPath, file), 'utf8');\n } catch {\n continue;\n }\n const parsed = parseDockerfile(file, content);\n images.push(...parsed.images);\n for (const suffix of parsed.nodeImageSuffixes) nodeImageSuffixes.add(suffix);\n }\n\n return {\n node: EXACT_VERSION.test(node) ? node : null,\n pnpm,\n images,\n nodeImageSuffixes: [...nodeImageSuffixes],\n };\n}\n\n/** The parsed JSON answer of a URL; null for an error status, a timeout or unparsable output. */\nexport async function fetchJson(url: string, init?: RequestInit): Promise<unknown> {\n try {\n const response = await fetch(url, { ...init, signal: AbortSignal.timeout(10_000) });\n return response.ok ? await response.json() : null;\n } catch {\n return null;\n }\n}\n\nconst hubRepository = (image: string): string => (image.includes('/') ? image : `library/${image}`);\n\nconst hubTag = (entry: unknown): HubTag | null => {\n const { name, last_updated } = (entry ?? {}) as { name?: string; last_updated?: string };\n const pushedAt = Date.parse(last_updated ?? '');\n return name && !Number.isNaN(pushedAt) ? { name, pushedAt } : null;\n};\n\n/**\n * Node releases from nodejs.org. The index gives a release day only, so a release from the last\n * two days, where the day alone cannot settle the release age, gets its exact time from the\n * Last-Modified header of its checksum file (the end of its day when that does not answer).\n */\nexport async function fetchNodeReleases(major: number, now: number): Promise<NodeRelease[] | null> {\n const index = await fetchJson('https://nodejs.org/dist/index.json');\n if (!Array.isArray(index)) return null;\n const releases = index\n .map((entry) => entry as { version?: string; date?: string; security?: boolean })\n .filter((entry) => entry.version && parseComparableVersion(entry.version)?.major === major)\n .map((entry) => ({\n version: String(entry.version).replace(/^v/, ''),\n publishedAt: Date.parse(entry.date ?? ''),\n security: entry.security === true,\n }))\n .filter((release) => !Number.isNaN(release.publishedAt));\n\n await Promise.all(\n releases\n .filter((release) => now - release.publishedAt < 2 * DAY)\n .map(async (release) => {\n try {\n const response = await fetch(`https://nodejs.org/dist/v${release.version}/SHASUMS256.txt`, {\n method: 'HEAD',\n signal: AbortSignal.timeout(10_000),\n });\n const modified = Date.parse(response.headers.get('last-modified') ?? '');\n release.publishedAt = Number.isNaN(modified) ? release.publishedAt + DAY : modified;\n } catch {\n release.publishedAt += DAY;\n }\n }),\n );\n return releases;\n}\n\nasync function fetchImageTags(pin: ImagePin): Promise<{ pinned: HubTag | null; tags: HubTag[] } | null> {\n const shape = pin.tag.match(MINOR_TAG);\n if (!shape) return null;\n const base = `https://hub.docker.com/v2/repositories/${hubRepository(pin.image)}/tags`;\n const filter = shape[2] ?? `${shape[1].split('.')[0]}.`;\n const [list, pinned] = await Promise.all([\n fetchJson(`${base}?page_size=100&ordering=last_updated&name=${encodeURIComponent(filter)}`),\n fetchJson(`${base}/${encodeURIComponent(pin.tag)}`),\n ]);\n const results = (list as { results?: unknown[] } | null)?.results;\n if (!Array.isArray(results)) return null;\n return { pinned: hubTag(pinned), tags: results.flatMap((entry) => hubTag(entry) ?? []) };\n}\n\n/** The npm advisories against a pnpm version; null when the registry does not answer. */\nexport async function fetchPnpmAdvisories(version: string): Promise<BulkAdvisory[] | null> {\n const answer = await fetchJson('https://registry.npmjs.org/-/npm/v1/security/advisories/bulk', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ pnpm: [version] }),\n });\n return answer ? ((answer as { pnpm?: BulkAdvisory[] }).pnpm ?? []) : null;\n}\n\n/** Ask every feed the pins need, in parallel. Only pins whose tag names a minor reach Docker Hub. */\nexport async function fetchRuntimeFeeds(pins: RuntimePins, cwd: string, now: number): Promise<RuntimeFeeds> {\n const nodeMajor = pins.node ? parseComparableVersion(pins.node)?.major : undefined;\n const [node, published, advisories, images] = await Promise.all([\n nodeMajor === undefined ? null : fetchNodeReleases(nodeMajor, now),\n pins.pnpm ? fetchPublishTimes('pnpm', cwd) : null,\n pins.pnpm ? fetchPnpmAdvisories(pins.pnpm) : null,\n Promise.all(pins.images.map(fetchImageTags)),\n ]);\n return { node, pnpm: published && advisories ? { published, advisories } : null, images };\n}\n\nconst count = (n: number, noun: string, plural = `${noun}s`): string => `${n} ${n === 1 ? noun : plural}`;\n\nconst monthYear = (time: number): string =>\n new Date(time).toLocaleString('en', { month: 'short', year: 'numeric', timeZone: 'UTC' }).toLowerCase();\n\n/** The highest version above `pinned` in its major that is older than the release age. */\nexport function newestAged(pinned: string, versions: Array<{ version: string; publishedAt: number }>, cutoff: number) {\n const major = parseComparableVersion(pinned)?.major;\n return versions\n .filter(\n (entry) =>\n !isPrerelease(entry.version) &&\n parseComparableVersion(entry.version)?.major === major &&\n compareVersionStrings(entry.version, pinned) > 0 &&\n entry.publishedAt <= cutoff,\n )\n .sort((a, b) => compareVersionStrings(b.version, a.version))[0];\n}\n\n/**\n * The pins that can move: a newer version in the same major (a newer minor tag for an image), never\n * younger than the release age. `unchecked` names each runtime whose feed did not answer.\n */\nexport function planRuntimeUpdates(\n pins: RuntimePins,\n feeds: RuntimeFeeds,\n options: { releaseAgeMinutes: number; now: number },\n): { updates: RuntimeUpdate[]; unchecked: string[] } {\n const cutoff = options.now - options.releaseAgeMinutes * 60 * 1000;\n const updates: RuntimeUpdate[] = [];\n const unchecked: string[] = [];\n\n if (pins.node) {\n if (!feeds.node) unchecked.push('node');\n const target = feeds.node && newestAged(pins.node, feeds.node, cutoff);\n if (target) {\n const node = pins.node;\n const security = (feeds.node ?? []).some(\n (release) =>\n release.security &&\n compareVersionStrings(release.version, node) > 0 &&\n compareVersionStrings(release.version, target.version) <= 0,\n );\n updates.push({\n name: 'node',\n current: node,\n target: target.version,\n file: 'package.json',\n severity: security ? 'high' : null,\n note: security ? 'security release' : '',\n releasesUrl: `https://nodejs.org/en/blog/release/v${target.version}`,\n pin: { kind: 'node' },\n });\n }\n }\n\n if (pins.pnpm) {\n if (!feeds.pnpm) unchecked.push('pnpm');\n const published = Object.entries(feeds.pnpm?.published ?? {}).map(([version, time]) => ({\n version,\n publishedAt: Date.parse(time),\n }));\n const target = feeds.pnpm && newestAged(pins.pnpm, published, cutoff);\n if (target) {\n const pnpm = pins.pnpm;\n const fixed = (feeds.pnpm?.advisories ?? []).filter(\n (advisory) =>\n satisfiesComparators(pnpm, advisory.vulnerable_versions) &&\n !satisfiesComparators(target.version, advisory.vulnerable_versions),\n ).length;\n updates.push({\n name: 'pnpm',\n current: pnpm,\n target: target.version,\n file: 'package.json',\n severity: fixed > 0 ? 'high' : null,\n note: fixed > 0 ? count(fixed, 'advisory', 'advisories') : '',\n releasesUrl: `https://github.com/pnpm/pnpm/releases/tag/v${target.version}`,\n pin: { kind: 'pnpm' },\n });\n }\n }\n\n pins.images.forEach((pin, i) => {\n const shape = pin.tag.match(MINOR_TAG);\n if (!shape) return;\n const feed = feeds.images[i];\n if (!feed) {\n unchecked.push(pin.image);\n return;\n }\n const [, version, suffix = ''] = shape;\n const parts = version.split('.').length;\n const major = version.split('.')[0];\n const target = feed.tags\n .map((tag) => ({ tag, match: tag.name.match(MINOR_TAG) }))\n .filter(\n ({ match }) =>\n match &&\n (match[2] ?? '') === suffix &&\n match[1].split('.').length === parts &&\n match[1].split('.')[0] === major &&\n compareVersionStrings(match[1], version) > 0,\n )\n .sort((a, b) => compareVersionStrings(b.match?.[1] ?? '', a.match?.[1] ?? ''))[0];\n if (!target?.match) return;\n\n const frozen =\n !!feed.pinned &&\n options.now - feed.pinned.pushedAt > FROZEN_AFTER &&\n options.now - target.tag.pushedAt < RECENT_PUSH;\n const repository = hubRepository(pin.image);\n updates.push({\n name: pin.image,\n current: version,\n target: target.match[1],\n file: pin.file,\n severity: frozen ? 'moderate' : null,\n note: frozen && feed.pinned ? `tag frozen since ${monthYear(feed.pinned.pushedAt)}` : '',\n releasesUrl: repository.startsWith('library/')\n ? `https://hub.docker.com/_/${pin.image}/tags`\n : `https://hub.docker.com/r/${repository}/tags`,\n pin: { kind: 'image', line: pin.line, ref: `${pin.image}:${pin.tag}`, to: `${pin.image}:${target.tag.name}` },\n });\n });\n\n return { updates, unchecked };\n}\n\n/** The file content with the update's pin moved to its target. */\nexport function applyRuntimeUpdate(content: string, update: RuntimeUpdate): string {\n const { pin } = update;\n if (pin.kind === 'image') {\n const lines = content.split('\\n');\n lines[pin.line] = lines[pin.line].replace(pin.ref, pin.to);\n return lines.join('\\n');\n }\n return editJsonText(content, (json) => {\n if (pin.kind === 'node') (json.engines as Record<string, string>).node = update.target;\n // A `+sha` suffix names the old version's tarball, so it goes.\n else json.packageManager = `pnpm@${update.target}`;\n });\n}\n\n/** The `node:<version><suffix>` images a Node bump would build from that Docker Hub does not have (yet). */\nexport async function missingNodeImages(version: string, suffixes: string[]): Promise<string[]> {\n const missing = await Promise.all(\n suffixes.map(async (suffix) => {\n const tag = `${version}${suffix}`;\n const found = await fetchJson(`https://hub.docker.com/v2/repositories/library/node/tags/${tag}`);\n return found ? [] : [`node:${tag}`];\n }),\n );\n return missing.flat();\n}\n\n/** Where a pin lives, for the table: the file's directory, or the file itself at the root. */\nexport function pinLocation(file: string): string {\n const dir = dirname(file);\n return dir === '.' ? file : dir;\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/** Files the update step changed, written by the security pass together with its own settings. */\nexport interface WorkspaceEdits {\n /** Manifests whose dependencies changed, by path from the workspace root: staged before the resolve. */\n manifests: Record<string, string>;\n /** Other files, such as runtime pins: written as they are, with nothing to resolve. */\n files: Record<string, string>;\n}\n\nconst NO_EDITS: WorkspaceEdits = { manifests: {}, files: {} };\n\n/**\n * Run the security pass on the workspace at `forkPath`, with the update step's `edits` already in\n * place in the staging copy, so the plan judges the workspace as it will be. The workspace is\n * written once, at the end; with `apply` off nothing is written. Returns whether the edits landed:\n * false for a report, a failure or a cancelled prompt, which all leave the workspace as it was.\n */\nexport async function runSecurityPass(\n forkPath: string,\n options: { apply: boolean; releaseAgeMinutes: number; edits?: WorkspaceEdits },\n): Promise<boolean> {\n const { releaseAgeMinutes, edits = NO_EDITS } = options;\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 false;\n }\n const auditKeys = Object.keys(previous.overrides).filter(isAuditOverride);\n const lasting = Object.fromEntries(Object.entries(previous.overrides).filter(([key]) => !isAuditOverride(key)));\n const updatesManifests = Object.keys(edits.manifests).length > 0;\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 = ''): false => {\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 return false;\n };\n\n const staging = await createStaging(forkPath, workspaceYaml);\n try {\n for (const [file, content] of Object.entries(edits.manifests)) writeFileSync(join(staging, file), content);\n\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) {\n const without = updatesManifests ? 'with the selected updates' : 'without its audit overrides';\n return fail(`could not resolve the workspace ${without}`, bare.error);\n }\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 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 false;\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 false;\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 const settingsChanged = nextYaml !== workspaceYaml;\n\n const otherFiles = Object.keys(edits.files);\n const writeFiles = (): void => {\n for (const [file, content] of Object.entries(edits.files)) writeFileSync(join(forkPath, file), content);\n if (otherFiles.length > 0) console.info(`${checkMark} ${otherFiles.join(', ')} updated`);\n };\n\n if (!settingsChanged && !updatesManifests) {\n writeFiles();\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 true;\n }\n\n const summarize = (): void => {\n if (!settingsChanged) return;\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 (!updatesManifests && sameEntries(next.overrides, previous.overrides)) {\n writeFiles();\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 true;\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 const written = { ...edits.files, ...edits.manifests, [WORKSPACE_FILE]: nextYaml, [LOCK_FILE]: staged.lock };\n const before = Object.fromEntries(Object.keys(written).map((file) => [file, readOr(join(forkPath, file))]));\n before[WORKSPACE_FILE] = workspaceYaml;\n before[LOCK_FILE] = workspaceLock;\n for (const [file, content] of Object.entries(written)) writeFileSync(join(forkPath, file), content);\n const install = spawnSync('pnpm', ['install'], { cwd: forkPath, stdio: 'inherit' });\n console.info();\n if (install.status !== 0) {\n for (const [file, content] of Object.entries(before)) writeFileSync(join(forkPath, file), content);\n console.error(`${pc.red('✗')} pnpm install failed (exit code ${install.status})`);\n console.info(pc.dim(` ${Object.keys(before).join(', ')} are back as they were; run pnpm install to match`));\n console.info();\n return false;\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 return true;\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, openInBrowser, writeDiffPage } 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 const page = await writeDiffPage(\n [{ files: [{ path, patch: patch.toString() }] }],\n { title: path, note: `cella ← → ${forkName}` },\n cwd,\n path,\n );\n setStatusMsg(openInBrowser(page) ? `opened ${path} in browser` : `diff page: ${page}`);\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 * 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';\nimport { reportReviewPage } from './review-page';\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 await reportReviewPage(config.forkPath, result, 'sync');\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;AAGO,SAAS,gBAAgB,OAAuB,QAAoC;AACzF,SAAO,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC;AAC1E;AAKA,SAAS,eACP,OACA,QACA,aACA,SACM;AACN,QAAM,SAAS,aAAa,MAAM;AAClC,QAAM,QAAQ,SAAS,SAAS,GAAG,OAAO,IAAI,IAAI,OAAO,KAAK;AAC9D,mBAAiB,gBAAgB,OAAO,MAAM,GAAG,OAAO,aAAa,EAAE,GAAG,SAAS,MAAM,OAAO,KAAK,CAAC;AACxG;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;AAGA,SAAS,0BAA0B,MAA4B;AAC7D,QAAM,IAAI,KAAK,uBAAuB;AACtC,SAAO,IAAI,IAAI,eAAG,OAAO,SAAM,OAAO,GAAG,eAAe,CAAC,SAAS,IAAI;AACxE;AASO,SAAS,wBAAwB,OAAuB,aAAgC;AAC7F,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,EACR,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,UAAQ,KAAK,eAAG,IAAI,KAAK,qBAAqB,EAAE,CAAC;AACnD;AAGO,SAAS,OAAOC,QAAe,UAAkB,aAAa,GAAG,QAAQ,KAAa;AAC3F,SAAO,GAAGA,MAAK,IAAIA,WAAU,IAAI,WAAW,UAAU;AACxD;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;AAAA,EAClG;AACA,UAAQ,KAAK,eAAG,IAAI,+FAA+F,CAAC;AACtH;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;;;AEzkBA,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;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;;;AVvFA,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,OACkG;AAClG,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,IAC5F;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,aAAa;AAAA,IACxD,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,aAAa;AACpE,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;;;AKjsBA,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;;;AC1RA,SAAS,YAAAI,iBAAgB;AACzB,OAAOC,cAAa;AACpB,SAAS,qBAAqB;;;ACF9B,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,WAAW,qBAAqB;AACzC,SAAS,QAAAC,aAAY;AACrB,OAAOC,cAAa;AAQb,SAAS,YAAY,KAAa,OAAe,UAA0B;AAChF,MAAI;AACF,WAAOC,cAAa,OAAO,CAAC,QAAQ,cAAc,OAAO,MAAM,QAAQ,GAAG,EAAE,KAAK,WAAW,WAAW,CAAC;AAAA,EAC1G,SAAS,OAAO;AACd,UAAM,SAAU,MAA8B,QAAQ,SAAS,EAAE,KAAK;AACtE,UAAM,IAAI,MAAM,UAAU,kBAAkB,QAAQ,EAAE;AAAA,EACxD;AACF;AAwBA,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,UAA6B,MAAqC;AAGrG,QAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,mBAAmB;AAE7D,QAAM,aAAa,OAAO,SAAuB;AAC/C,UAAM,EAAE,gBAAgB,IAAI,MAAM,iBAAiB;AAAA,MACjD,OAAO,KAAK;AAAA,MACZ,SAAS;AAAA,QACP,WAAW;AAAA,QACX,WAAW;AAAA,QACX,cAAc;AAAA,QACd,gBAAgB;AAAA,QAChB,UAAU;AAAA,MACZ;AAAA,IACF,CAAC;AAGD,WAAO;AAAA,EAA6D,eAAe;AAAA;AAAA,EACrF;AAEA,QAAM,SAAmB,CAAC;AAC1B,aAAW,CAACC,QAAO,OAAO,KAAK,SAAS,QAAQ,GAAG;AACjD,UAAM,QAAkB,CAAC;AACzB,eAAW,QAAQ,QAAQ,MAAO,OAAM,KAAK,MAAM,WAAW,IAAI,CAAC;AACnE,UAAMC,SAAQ,QAAQ,MAAM,UAAU,QAAQ,SAAS,UAAU;AACjE,UAAM,QAAQ,QAAQ,QAClB,OAAO,WAAW,QAAQ,KAAK,CAAC,6BAA0BA,MAAK,IAAIA,WAAU,IAAI,SAAS,OAAO,iBACjG;AACJ,UAAM,OAAO,QAAQ,OAAO,mBAAmB,WAAW,QAAQ,IAAI,CAAC,SAAS;AAChF,UAAM,UAAU,QAAQ,SAAS,SAC7B,sGAAsG,QAAQ,QAC3G,IAAI,CAAC,SAAS,aAAa,WAAW,IAAI,CAAC,cAAc,EACzD,KAAK,EAAE,CAAC,UACX;AACJ,WAAO,KAAK,wBAAwBD,SAAQ,CAAC,KAAK,KAAK,GAAG,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC,GAAG,OAAO,YAAY;AAAA,EACzG;AAEA,QAAM,SAAS,SAAS,OAAO,CAAC,YAAY,QAAQ,KAAK;AACzD,QAAM,QACJ,OAAO,SAAS,IACZ,YAAY,SACT;AAAA,IAAI,CAAC,SAAS,MACb,QAAQ,QACJ,yBAAyB,IAAI,CAAC,KAAK,WAAW,QAAQ,KAAK,CAAC,iCAC1D,QAAQ,MAAM,UAAU,QAAQ,SAAS,UAAU,EACrD,iBACA;AAAA,EACN,EACC,KAAK,EAAE,CAAC,gBACX;AACN,QAAM,OAAO,KAAK,OAAO,sBAAsB,WAAW,KAAK,IAAI,CAAC,YAAY;AAEhF,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,SAKA,WAAW,KAAK,KAAK,CAAC;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAwCrB,WAAW,KAAK,KAAK,CAAC;AAAA,IAC5B,IAAI;AAAA;AAAA;AAAA,EAGN,KAAK;AAAA,EACL,OAAO,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAInB;AASA,eAAsB,cACpB,UACA,MACA,UACA,MACiB;AACjB,QAAM,OAAO,MAAM,eAAe,UAAU,IAAI;AAChD,QAAM,SAASD,cAAa,OAAO,CAAC,aAAa,oBAAoB,GAAG,EAAE,KAAK,UAAU,UAAU,OAAO,CAAC,EAAE,KAAK;AAClH,QAAM,MAAMG,MAAK,QAAQ,YAAY;AACrC,YAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,QAAM,UAAUA,MAAK,KAAK,GAAG,KAAK,QAAQ,aAAa,GAAG,CAAC,OAAO;AAClE,gBAAc,SAAS,IAAI;AAC3B,SAAO;AACT;AAMO,SAAS,cAAc,QAAyB;AACrD,MAAI;AACF,IAAAH,cAAaI,SAAQ,aAAa,WAAW,SAAS,YAAY,CAAC,MAAM,GAAG,EAAE,OAAO,SAAS,CAAC;AAC/F,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ADnLA,IAAM,iBAAiB;AAGvB,IAAM,kBAAkB,MAAM;AAiBvB,SAAS,eAAe,QAAqB,SAA8C;AAChG,QAAM,CAAC,MAAM,QAAQ,IAAI,OAAO,mBAAmB,MAAM,IAAI,KAAK,CAAC;AACnE,MAAI,CAAC,QAAQ,CAAC,SAAU,QAAO,CAAC;AAChC,QAAM,YAAY,GAAG,IAAI,KAAK,QAAQ;AAEtC,QAAM,UACJ,YAAY,SACR;AAAA,IACE,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,OAAO,sBAAsB,CAAC;AAAA,EACvC,IACA;AAAA,IACE,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,oBAAoB,OAAO,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,EAClE;AAEN,QAAM,WAA4B;AAAA,IAChC;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ,OAAO,0BAA0B,CAAC,GAAG,QAAQ,CAAC,UAAU,MAAM,KAAK;AAAA,IAC7E;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,gBAAgB,OAAO,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,IAC9D;AAAA,EACF;AAEA,MAAI,YAAY,WAAW;AACzB,aAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,MAAM;AAAA,QACN,OAAO,SAAS,QAAQ;AAAA,QACxB,OAAO,gBAAgB,OAAO,OAAO,OAAO,EACzC,OAAO,CAAC,UAAU,KAAK,uBAAuB,KAAK,CAAC,EACpD,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,MAC5B;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,MAAM;AAAA,QACN,OAAO,GAAG,IAAI;AAAA,QACd,OAAO,gBAAgB,OAAO,OAAO,SAAS,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AAEA,SAAO,SAAS,OAAO,CAAC,YAAY,QAAQ,MAAM,SAAS,CAAC;AAC9D;AAOA,eAAsB,gBACpB,UACA,UACA,MACsD;AACtD,QAAM,CAAC,MAAM,QAAQ,IAAI,KAAK,MAAM,MAAM,IAAI;AAC9C,MAAI,QAAQ;AACZ,QAAM,eAAkC,CAAC;AAEzC,aAAW,WAAW,UAAU;AAC9B,UAAM,cAA+B,EAAE,OAAO,QAAQ,OAAO,MAAM,QAAQ,MAAM,OAAO,CAAC,GAAG,SAAS,CAAC,EAAE;AACxG,eAAW,QAAQ,QAAQ,OAAO;AAChC,UAAI,SAAS,gBAAgB;AAC3B,oBAAY,SAAS,KAAK,IAAI;AAC9B;AAAA,MACF;AACA,YAAM,QAAQ,YAAY,UAAU,QAAQ,OAAO,IAAI;AACvD,UAAI,MAAM,WAAW,EAAG;AACxB,UAAI,MAAM,SAAS,mBAAmB,CAAC,MAAM,SAAS,OAAO,GAAG;AAC9D,oBAAY,SAAS,KAAK,IAAI;AAC9B;AAAA,MACF;AACA,kBAAY,MAAM,KAAK,EAAE,MAAM,OAAO,MAAM,SAAS,EAAE,CAAC;AACxD;AAAA,IACF;AACA,QAAI,YAAY,MAAM,SAAS,KAAK,YAAY,SAAS,OAAQ,cAAa,KAAK,WAAW;AAAA,EAChG;AAEA,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA,EAAE,OAAO,GAAG,KAAK,OAAO,WAAW,MAAM,GAAGC,UAAS,QAAQ,CAAC,mBAAgB,IAAI,oBAAe,QAAQ,GAAG;AAAA,IAC5G;AAAA,IACA,GAAG,KAAK,OAAO;AAAA,EACjB;AACA,SAAO,EAAE,MAAM,MAAM,MAAM;AAC7B;AAOA,eAAsB,iBACpB,UACA,QACA,SACe;AACf,QAAM,WAAW,eAAe,QAAQ,OAAO;AAC/C,MAAI,SAAS,WAAW,KAAK,CAAC,OAAO,kBAAmB;AAExD,gBAAc,wBAAwB;AACtC,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,gBAAgB,UAAU,UAAU,EAAE,SAAS,OAAO,OAAO,kBAAkB,CAAC;AAAA,EAC/F,QAAQ;AACN,WAAO;AAAA,EACT;AACA,iBAAe;AACf,MAAI,CAAC,KAAM;AAEX,QAAM,SAAS,YAAY,UAAUC,SAAQ,OAAO,UAAU,QAAQ,cAAc,KAAK,IAAI;AAC7F,UAAQ,KAAK;AACb,UAAQ;AAAA,IACN,GAAG,eAAG,KAAK,QAAG,CAAC,qBAAqB,OAAO,KAAK,OAAO,MAAM,CAAC,GAAG,SAAS,4BAA4B,EAAE;AAAA,EAC1G;AACA,UAAQ,KAAK,eAAG,IAAI,KAAK,UAAU,KAAK,MAAM,cAAc,KAAK,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;AACjF;;;AE1JA,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,WAAW;AAEjD,qBAAmB,QAAQ,kBAAkB;AAC7C,QAAM,iBAAiB,OAAO,UAAU,QAAQ,SAAS;AAEzD,QAAM,wBAAwB,QAAQ,MAAM;AAE5C,UAAQ,KAAK;AAEb,SAAO;AACT;;;AC3FA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,YAAAC,WAAU,QAAAC,QAAM,YAAAC,iBAAgB;AACzC,SAAS,UAAU,iBAAiB;;;ACPpC,SAAS,YAAAC,iBAAgB;AACzB,SAAS,aAAAC,kBAAiB;AAI1B,IAAMC,iBAAgBC,WAAUC,SAAQ;AAgBjC,SAAS,oBAAoB,KAAqB;AACvD,QAAM,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AAC7B,QAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAC9B,SAAO,OAAO,KAAK,OAAO,KAAK,MAAM,GAAG,EAAE;AAC5C;AA0CO,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;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,sBAAsB,KAA8B;AACxE,QAAM,UAAU,OAAO,UAAU,MAAM,QAAQ,CAAC,UAAU,OAAO,mBAAmB,GAAG,GAAG,GAAG,QAAQ,EAAE;AACvG,SAAO,OAAO,MAAM,OAAO,IAAI,IAAI;AACrC;AAGA,eAAsB,kBAAkB,MAAc,KAAqD;AACzG,QAAM,QAAQ,MAAM,YAAY,CAAC,QAAQ,MAAM,QAAQ,QAAQ,GAAG,GAAG;AAErE,SAAO,SAAS,OAAO,UAAU,YAAY,EAAE,WAAW,SAAU,QAAmC;AACzG;AAMO,SAAS,aAAa,SAAiB,QAAyD;AACrG,QAAM,OAAO,KAAK,MAAM,OAAO;AAC/B,SAAO,IAAI;AACX,QAAM,SAAS,QAAQ,MAAM,eAAe,IAAI,CAAC,KAAK;AACtD,SAAO,GAAG,KAAK,UAAU,MAAM,MAAM,MAAM,CAAC,GAAG,QAAQ,SAAS,IAAI,IAAI,OAAO,EAAE;AACnF;AAOO,SAAS,iBAAiB,MAAc,QAA+B;AAC5E,QAAM,QAAQ,KAAK,MAAM,iDAAiD;AAC1E,SAAO,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,KAAK;AAC1C;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;;;AC5MA,SAAS,YAAAC,iBAAgB;AACzB,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,cAAc;AACvB,SAAS,WAAW,WAAAC,UAAS,QAAAC,QAAM,OAAAC,YAAW;AAC9C,SAAS,aAAAC,kBAAiB;;;ACJ1B,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,YAAAC,WAAU,WAAAC,UAAS,QAAAC,cAAY;AAiExC,IAAM,MAAM,KAAK,KAAK,KAAK;AAG3B,IAAM,eAAe,MAAM;AAC3B,IAAM,cAAc,KAAK;AAEzB,IAAM,gBAAgB;AAEtB,IAAM,YAAY;AAGlB,IAAM,eAAe;AAGrB,IAAM,YAAY;AAElB,IAAM,eAAe,CAAC,SAA0B,mCAAmC,KAAKC,UAAS,IAAI,CAAC;AAG/F,SAAS,gBAAgB,MAAc,SAAsE;AAClH,QAAM,SAAqB,CAAC;AAC5B,QAAM,oBAA8B,CAAC;AACrC,QAAM,SAAS,oBAAI,IAAY;AAE/B,UAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC,MAAM,SAAS;AAC1C,UAAM,QAAQ,KAAK,MAAM,SAAS;AAClC,QAAI,CAAC,MAAO;AACZ,UAAM,CAAC,EAAE,KAAK,KAAK,IAAI;AACvB,UAAM,YAAY,OAAO,IAAI,IAAI,YAAY,CAAC;AAC9C,QAAI,MAAO,QAAO,IAAI,MAAM,YAAY,CAAC;AACzC,QAAI,aAAa,IAAI,SAAS,GAAG,EAAG;AAEpC,UAAM,UAAU,IAAI,MAAM,YAAY;AACtC,QAAI,SAAS;AACX,wBAAkB,KAAK,QAAQ,CAAC,CAAC;AACjC;AAAA,IACF;AACA,QAAI,IAAI,SAAS,GAAG,EAAG;AAEvB,UAAM,QAAQ,IAAI,YAAY,GAAG;AACjC,UAAM,QAAQ,IAAI,YAAY,GAAG;AACjC,QAAI,SAAS,MAAO;AACpB,QAAI,QAAQ,IAAI,MAAM,GAAG,KAAK;AAC9B,UAAM,MAAM,IAAI,MAAM,QAAQ,CAAC;AAC/B,UAAM,OAAO,MAAM,SAAS,GAAG,IAAI,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI;AACzD,QAAI,SAAS,YAAa,SAAQ,MAAM,MAAM,KAAK,SAAS,CAAC,EAAE,QAAQ,cAAc,EAAE;AAAA,aAC9E,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,GAAG,KAAK,SAAS,YAAa;AAC3E,QAAI,UAAU,UAAW;AACzB,WAAO,KAAK,EAAE,MAAM,MAAM,OAAO,IAAI,CAAC;AAAA,EACxC,CAAC;AAED,SAAO,EAAE,QAAQ,kBAAkB;AACrC;AAGA,eAAsB,gBAAgB,UAAwC;AAC5E,MAAI,WAAqE,CAAC;AAC1E,MAAI;AACF,eAAW,KAAK,MAAMC,cAAaC,OAAK,UAAU,cAAc,GAAG,MAAM,CAAC;AAAA,EAC5E,QAAQ;AAAA,EAER;AACA,QAAM,OAAO,SAAS,SAAS,MAAM,KAAK,KAAK;AAC/C,QAAM,OAAO,SAAS,gBAAgB,MAAM,iCAAiC,IAAI,CAAC,KAAK;AAEvF,QAAM,WAAW,MAAM,IAAI,CAAC,YAAY,IAAI,GAAG,UAAU,EAAE,cAAc,KAAK,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,YAAY;AACjH,QAAM,SAAqB,CAAC;AAC5B,QAAM,oBAAoB,oBAAI,IAAY;AAC1C,aAAW,QAAQ,SAAS;AAC1B,QAAI;AACJ,QAAI;AACF,gBAAUD,cAAaC,OAAK,UAAU,IAAI,GAAG,MAAM;AAAA,IACrD,QAAQ;AACN;AAAA,IACF;AACA,UAAM,SAAS,gBAAgB,MAAM,OAAO;AAC5C,WAAO,KAAK,GAAG,OAAO,MAAM;AAC5B,eAAW,UAAU,OAAO,kBAAmB,mBAAkB,IAAI,MAAM;AAAA,EAC7E;AAEA,SAAO;AAAA,IACL,MAAM,cAAc,KAAK,IAAI,IAAI,OAAO;AAAA,IACxC;AAAA,IACA;AAAA,IACA,mBAAmB,CAAC,GAAG,iBAAiB;AAAA,EAC1C;AACF;AAGA,eAAsB,UAAU,KAAa,MAAsC;AACjF,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,KAAK,EAAE,GAAG,MAAM,QAAQ,YAAY,QAAQ,GAAM,EAAE,CAAC;AAClF,WAAO,SAAS,KAAK,MAAM,SAAS,KAAK,IAAI;AAAA,EAC/C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAM,gBAAgB,CAAC,UAA2B,MAAM,SAAS,GAAG,IAAI,QAAQ,WAAW,KAAK;AAEhG,IAAM,SAAS,CAAC,UAAkC;AAChD,QAAM,EAAE,MAAM,aAAa,IAAK,SAAS,CAAC;AAC1C,QAAM,WAAW,KAAK,MAAM,gBAAgB,EAAE;AAC9C,SAAO,QAAQ,CAAC,OAAO,MAAM,QAAQ,IAAI,EAAE,MAAM,SAAS,IAAI;AAChE;AAOA,eAAsB,kBAAkB,OAAe,KAA4C;AACjG,QAAM,QAAQ,MAAM,UAAU,oCAAoC;AAClE,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,WAAW,MACd,IAAI,CAAC,UAAU,KAAgE,EAC/E,OAAO,CAAC,UAAU,MAAM,WAAW,uBAAuB,MAAM,OAAO,GAAG,UAAU,KAAK,EACzF,IAAI,CAAC,WAAW;AAAA,IACf,SAAS,OAAO,MAAM,OAAO,EAAE,QAAQ,MAAM,EAAE;AAAA,IAC/C,aAAa,KAAK,MAAM,MAAM,QAAQ,EAAE;AAAA,IACxC,UAAU,MAAM,aAAa;AAAA,EAC/B,EAAE,EACD,OAAO,CAAC,YAAY,CAAC,OAAO,MAAM,QAAQ,WAAW,CAAC;AAEzD,QAAM,QAAQ;AAAA,IACZ,SACG,OAAO,CAAC,YAAY,MAAM,QAAQ,cAAc,IAAI,GAAG,EACvD,IAAI,OAAO,YAAY;AACtB,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,4BAA4B,QAAQ,OAAO,mBAAmB;AAAA,UACzF,QAAQ;AAAA,UACR,QAAQ,YAAY,QAAQ,GAAM;AAAA,QACpC,CAAC;AACD,cAAM,WAAW,KAAK,MAAM,SAAS,QAAQ,IAAI,eAAe,KAAK,EAAE;AACvE,gBAAQ,cAAc,OAAO,MAAM,QAAQ,IAAI,QAAQ,cAAc,MAAM;AAAA,MAC7E,QAAQ;AACN,gBAAQ,eAAe;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACL;AACA,SAAO;AACT;AAEA,eAAe,eAAe,KAA0E;AACtG,QAAM,QAAQ,IAAI,IAAI,MAAM,SAAS;AACrC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,0CAA0C,cAAc,IAAI,KAAK,CAAC;AAC/E,QAAM,SAAS,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;AACpD,QAAM,CAAC,MAAM,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACvC,UAAU,GAAG,IAAI,6CAA6C,mBAAmB,MAAM,CAAC,EAAE;AAAA,IAC1F,UAAU,GAAG,IAAI,IAAI,mBAAmB,IAAI,GAAG,CAAC,EAAE;AAAA,EACpD,CAAC;AACD,QAAM,UAAW,MAAyC;AAC1D,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AACpC,SAAO,EAAE,QAAQ,OAAO,MAAM,GAAG,MAAM,QAAQ,QAAQ,CAAC,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC,EAAE;AACzF;AAGA,eAAsB,oBAAoB,SAAiD;AACzF,QAAM,SAAS,MAAM,UAAU,gEAAgE;AAAA,IAC7F,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;AAAA,EAC1C,CAAC;AACD,SAAO,SAAW,OAAqC,QAAQ,CAAC,IAAK;AACvE;AAGA,eAAsB,kBAAkB,MAAmB,KAAa,KAAoC;AAC1G,QAAM,YAAY,KAAK,OAAO,uBAAuB,KAAK,IAAI,GAAG,QAAQ;AACzE,QAAM,CAAC,MAAM,WAAW,YAAY,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC9D,cAAc,SAAY,OAAO,kBAAkB,WAAW,GAAG;AAAA,IACjE,KAAK,OAAO,kBAAkB,QAAQ,GAAG,IAAI;AAAA,IAC7C,KAAK,OAAO,oBAAoB,KAAK,IAAI,IAAI;AAAA,IAC7C,QAAQ,IAAI,KAAK,OAAO,IAAI,cAAc,CAAC;AAAA,EAC7C,CAAC;AACD,SAAO,EAAE,MAAM,MAAM,aAAa,aAAa,EAAE,WAAW,WAAW,IAAI,MAAM,OAAO;AAC1F;AAEA,IAAM,QAAQ,CAAC,GAAW,MAAcC,UAAS,GAAG,IAAI,QAAgB,GAAG,CAAC,IAAI,MAAM,IAAI,OAAOA,OAAM;AAEvG,IAAM,YAAY,CAAC,SACjB,IAAI,KAAK,IAAI,EAAE,eAAe,MAAM,EAAE,OAAO,SAAS,MAAM,WAAW,UAAU,MAAM,CAAC,EAAE,YAAY;AAGjG,SAAS,WAAW,QAAgB,UAA2D,QAAgB;AACpH,QAAM,QAAQ,uBAAuB,MAAM,GAAG;AAC9C,SAAO,SACJ;AAAA,IACC,CAAC,UACC,CAAC,aAAa,MAAM,OAAO,KAC3B,uBAAuB,MAAM,OAAO,GAAG,UAAU,SACjD,sBAAsB,MAAM,SAAS,MAAM,IAAI,KAC/C,MAAM,eAAe;AAAA,EACzB,EACC,KAAK,CAAC,GAAG,MAAM,sBAAsB,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;AAClE;AAMO,SAAS,mBACd,MACA,OACA,SACmD;AACnD,QAAM,SAAS,QAAQ,MAAM,QAAQ,oBAAoB,KAAK;AAC9D,QAAM,UAA2B,CAAC;AAClC,QAAM,YAAsB,CAAC;AAE7B,MAAI,KAAK,MAAM;AACb,QAAI,CAAC,MAAM,KAAM,WAAU,KAAK,MAAM;AACtC,UAAM,SAAS,MAAM,QAAQ,WAAW,KAAK,MAAM,MAAM,MAAM,MAAM;AACrE,QAAI,QAAQ;AACV,YAAM,OAAO,KAAK;AAClB,YAAM,YAAY,MAAM,QAAQ,CAAC,GAAG;AAAA,QAClC,CAAC,YACC,QAAQ,YACR,sBAAsB,QAAQ,SAAS,IAAI,IAAI,KAC/C,sBAAsB,QAAQ,SAAS,OAAO,OAAO,KAAK;AAAA,MAC9D;AACA,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ,OAAO;AAAA,QACf,MAAM;AAAA,QACN,UAAU,WAAW,SAAS;AAAA,QAC9B,MAAM,WAAW,qBAAqB;AAAA,QACtC,aAAa,uCAAuC,OAAO,OAAO;AAAA,QAClE,KAAK,EAAE,MAAM,OAAO;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,KAAK,MAAM;AACb,QAAI,CAAC,MAAM,KAAM,WAAU,KAAK,MAAM;AACtC,UAAM,YAAY,OAAO,QAAQ,MAAM,MAAM,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO;AAAA,MACtF;AAAA,MACA,aAAa,KAAK,MAAM,IAAI;AAAA,IAC9B,EAAE;AACF,UAAM,SAAS,MAAM,QAAQ,WAAW,KAAK,MAAM,WAAW,MAAM;AACpE,QAAI,QAAQ;AACV,YAAM,OAAO,KAAK;AAClB,YAAM,SAAS,MAAM,MAAM,cAAc,CAAC,GAAG;AAAA,QAC3C,CAAC,aACC,qBAAqB,MAAM,SAAS,mBAAmB,KACvD,CAAC,qBAAqB,OAAO,SAAS,SAAS,mBAAmB;AAAA,MACtE,EAAE;AACF,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ,OAAO;AAAA,QACf,MAAM;AAAA,QACN,UAAU,QAAQ,IAAI,SAAS;AAAA,QAC/B,MAAM,QAAQ,IAAI,MAAM,OAAO,YAAY,YAAY,IAAI;AAAA,QAC3D,aAAa,8CAA8C,OAAO,OAAO;AAAA,QACzE,KAAK,EAAE,MAAM,OAAO;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,OAAK,OAAO,QAAQ,CAAC,KAAK,MAAM;AAC9B,UAAM,QAAQ,IAAI,IAAI,MAAM,SAAS;AACrC,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,MAAM,OAAO,CAAC;AAC3B,QAAI,CAAC,MAAM;AACT,gBAAU,KAAK,IAAI,KAAK;AACxB;AAAA,IACF;AACA,UAAM,CAAC,EAAE,SAAS,SAAS,EAAE,IAAI;AACjC,UAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE;AACjC,UAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,CAAC;AAClC,UAAM,SAAS,KAAK,KACjB,IAAI,CAAC,SAAS,EAAE,KAAK,OAAO,IAAI,KAAK,MAAM,SAAS,EAAE,EAAE,EACxD;AAAA,MACC,CAAC,EAAE,MAAM,MACP,UACC,MAAM,CAAC,KAAK,QAAQ,UACrB,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,WAAW,SAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,MAAM,SAC3B,sBAAsB,MAAM,CAAC,GAAG,OAAO,IAAI;AAAA,IAC/C,EACC,KAAK,CAAC,GAAG,MAAM,sBAAsB,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;AAClF,QAAI,CAAC,QAAQ,MAAO;AAEpB,UAAM,SACJ,CAAC,CAAC,KAAK,UACP,QAAQ,MAAM,KAAK,OAAO,WAAW,gBACrC,QAAQ,MAAM,OAAO,IAAI,WAAW;AACtC,UAAM,aAAa,cAAc,IAAI,KAAK;AAC1C,YAAQ,KAAK;AAAA,MACX,MAAM,IAAI;AAAA,MACV,SAAS;AAAA,MACT,QAAQ,OAAO,MAAM,CAAC;AAAA,MACtB,MAAM,IAAI;AAAA,MACV,UAAU,SAAS,aAAa;AAAA,MAChC,MAAM,UAAU,KAAK,SAAS,oBAAoB,UAAU,KAAK,OAAO,QAAQ,CAAC,KAAK;AAAA,MACtF,aAAa,WAAW,WAAW,UAAU,IACzC,4BAA4B,IAAI,KAAK,UACrC,4BAA4B,UAAU;AAAA,MAC1C,KAAK,EAAE,MAAM,SAAS,MAAM,IAAI,MAAM,KAAK,GAAG,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,GAAG;AAAA,IAC9G,CAAC;AAAA,EACH,CAAC;AAED,SAAO,EAAE,SAAS,UAAU;AAC9B;AAGO,SAAS,mBAAmB,SAAiB,QAA+B;AACjF,QAAM,EAAE,IAAI,IAAI;AAChB,MAAI,IAAI,SAAS,SAAS;AACxB,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,UAAM,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,EAAE,QAAQ,IAAI,KAAK,IAAI,EAAE;AACzD,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACA,SAAO,aAAa,SAAS,CAAC,SAAS;AACrC,QAAI,IAAI,SAAS,OAAQ,CAAC,KAAK,QAAmC,OAAO,OAAO;AAAA,QAE3E,MAAK,iBAAiB,QAAQ,OAAO,MAAM;AAAA,EAClD,CAAC;AACH;AAGA,eAAsB,kBAAkB,SAAiB,UAAuC;AAC9F,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,SAAS,IAAI,OAAO,WAAW;AAC7B,YAAM,MAAM,GAAG,OAAO,GAAG,MAAM;AAC/B,YAAM,QAAQ,MAAM,UAAU,4DAA4D,GAAG,EAAE;AAC/F,aAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,GAAG,EAAE;AAAA,IACpC,CAAC;AAAA,EACH;AACA,SAAO,QAAQ,KAAK;AACtB;AAGO,SAAS,YAAY,MAAsB;AAChD,QAAM,MAAMC,SAAQ,IAAI;AACxB,SAAO,QAAQ,MAAM,OAAO;AAC9B;;;AClVO,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;;;AF1NA,IAAMC,iBAAgBC,WAAUC,SAAQ;AAoCxC,SAAS,WAAW,MAAc,OAAiB,CAAC,GAAkB;AACpE,aAAW,QAAQ,OAAO,MAAM,KAAK,IAAI,MAAM,SAAS,GAAG;AACzD,QAAI,CAAC,OAAO,KAAK,SAAS,GAAG,KAAK,IAAI,SAAS,eAAeC,IAAG,MAAM,EAAG;AAC1E,QAAIC,YAAWC,OAAK,KAAK,IAAI,CAAC,EAAG,QAAOA,OAAK,KAAK,IAAI;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,YAAY,MAAyB;AAC5C,MAAI,OAAO;AACX,MAAI;AACF,WAAOC,cAAa,IAAI;AAAA,EAC1B,QAAQ;AAAA,EAER;AACA,MAAI,KAAK,SAAS,GAAGH,IAAG,SAASA,IAAG,EAAE,EAAG,QAAO;AAChD,SAAO,wCAAwC,KAAK,IAAI,IAAI,SAAS;AACvE;AAGA,eAAe,UAAU,MAAc,KAAsC;AAC3E,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAMH,eAAc,MAAM,CAAC,WAAW,GAAG,EAAE,UAAU,QAAQ,SAAS,KAAQ,IAAI,CAAC;AACtG,WAAO,OAAO,MAAM,eAAe,IAAI,CAAC,KAAK;AAAA,EAC/C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,SAAS,KAA0C;AAChE,QAAM,UAAU,QAAQ,QAAQ,MAAM,CAAC;AACvC,QAAM,QAAQ,uBAAuB,OAAO,GAAG,SAAS;AACxD,SAAO,EAAE,SAAS,WAAW,YAAY,QAAQ,QAAQ,GAAG,UAAU,MAAM,kBAAkB,OAAO,GAAG,EAAE;AAC5G;AAMA,eAAe,SAAS,KAA0C;AAChE,QAAM,UAAU,OAAO,cAAc;AACrC,QAAM,OAAO,WAAW,QAAQ,UAAU,CAACO,SAAQ,OAAO,CAAC,IAAI,CAAC,CAAC;AACjE,QAAM,UAAU,QAAS,MAAM,UAAU,MAAM,OAAO,CAAC;AACvD,MAAI,CAAC,QAAQ,CAAC,QAAS,QAAO;AAC9B,QAAM,CAAC,WAAW,UAAU,IAAI,MAAM,QAAQ,IAAI,CAAC,kBAAkB,QAAQ,GAAG,GAAG,oBAAoB,OAAO,CAAC,CAAC;AAChH,SAAO,EAAE,SAAS,WAAW,YAAY,IAAI,GAAG,WAAW,WAAW;AACxE;AAOA,eAAe,mBAAmB,QAAgB,SAA0D;AAC1G,QAAM,SAAS,MAAM,UAAU,gCAAgC;AAAA,IAC7D,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,WAAW,KAAK,GAAG,QAAQ,CAAC;AAAA,EAC9E,CAAC;AACD,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,SAAS,oBAAI,IAAmC;AACtD,aAAW,QAAS,OAAiC,SAAS,CAAC,GAAG;AAChE,UAAM,KAAK,CAAC,KAAK,IAAI,GAAI,KAAK,WAAW,CAAC,CAAE,EAAE,KAAK,CAAC,UAAU,MAAM,WAAW,OAAO,CAAC,KAAK,KAAK;AACjG,UAAM,WAAW,WAAW,KAAK,CAAC,UAAU,UAAU,KAAK,mBAAmB,UAAU,YAAY,CAAC;AACrG,QAAI,YAAY,CAAC,OAAO,IAAI,EAAE,EAAG,QAAO,IAAI,IAAI,YAAY,UAAU;AAAA,EACxE;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;AAEA,eAAe,SAAoC;AACjD,QAAM,OAAO,WAAW,IAAI;AAC5B,QAAM,UAAU,QAAS,MAAM,UAAU,IAAI;AAC7C,MAAI,CAAC,QAAQ,CAAC,QAAS,QAAO;AAC9B,QAAM,CAAC,MAAM,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC3C,UAAU,2DAA2D;AAAA,IACrE,mBAAmB,yBAAyB,OAAO;AAAA,EACrD,CAAC;AACD,QAAM,WAAW,MAAM,QAAQ,IAAI,IAC/B,KAAK,QAAQ,CAAC,UAAU;AACtB,UAAM,EAAE,UAAU,aAAa,IAAI;AACnC,UAAM,cAAc,KAAK,MAAM,gBAAgB,EAAE;AACjD,WAAO,YAAY,CAAC,OAAO,MAAM,WAAW,IAAI,CAAC,EAAE,SAAS,SAAS,QAAQ,MAAM,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC;AAAA,EAC5G,CAAC,IACD;AACJ,SAAO,EAAE,SAAS,WAAW,YAAY,IAAI,GAAG,UAAU,WAAW;AACvE;AAGA,eAAsB,eAAe,KAAa,KAAkC;AAClF,QAAM,CAAC,MAAM,MAAM,EAAE,IAAI,MAAM,QAAQ,IAAI,CAAC,SAAS,GAAG,GAAG,SAAS,GAAG,GAAG,OAAO,CAAC,CAAC;AACnF,SAAO,EAAE,MAAM,MAAM,GAAG;AAC1B;AAGA,SAAS,eAAe,MAAc,WAAsB,QAAoC;AAC9F,MAAI,cAAc,OAAQ,QAAO,gBAAgB,IAAI;AACrD,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,cAAc,QAAS,QAAO,iBAAiB,IAAI,IAAI,MAAM;AACjE,SAAO,SAAS,SAAS,oBAAoB,MAAM,KAAK,aAAa,MAAM;AAC7E;AAGA,SAAS,QACP,MACA,MACA,QACA,QACA,MACgB;AAChB,MAAI,CAAC;AACH,WAAO,EAAE,MAAM,SAAS,KAAK,SAAS,UAAU,MAAM,MAAM,wCAAwC,KAAK,GAAG;AAC9G,MAAI,OAAO,WAAW,EAAG,QAAO,EAAE,MAAM,SAAS,KAAK,SAAS,UAAU,MAAM,MAAM,IAAI,KAAK,GAAG;AACjG,QAAM,OAAO,OAAO,OAAO,CAAC,aAAa,aAAa,cAAc,aAAa,MAAM,EAAE;AACzF,SAAO;AAAA,IACL;AAAA,IACA,SAAS,KAAK;AAAA,IACd,UAAU,WAAW,KAAK,CAAC,aAAa,OAAO,SAAS,QAAQ,CAAC,KAAK;AAAA,IACtE,MAAM,GAAG,OAAO,OAAO,QAAQ,GAAG,IAAI,CAAC,GAAG,OAAO,KAAK,OAAO,OAAO,SAAS,KAAK,IAAI,UAAU,EAAE;AAAA,IAClG,KAAK,eAAe,MAAM,KAAK,WAAW,MAAM;AAAA,EAClD;AACF;AAOO,SAAS,eACd,OACA,SACkB;AAClB,QAAM,SAAS,QAAQ,MAAM,QAAQ,oBAAoB,KAAK;AAC9D,QAAM,EAAE,MAAM,MAAM,GAAG,IAAI;AAE3B,QAAM,aAAa,KAAK,WAAW,WAAW,KAAK,SAAS,KAAK,UAAU,MAAM,IAAI;AACrF,QAAM,oBAAoB,KAAK,YAAY,CAAC,GAAG;AAAA,IAC7C,CAAC,YACC,QAAQ,YACR,cACA,sBAAsB,QAAQ,SAAS,KAAK,OAAO,IAAI,KACvD,sBAAsB,QAAQ,SAAS,WAAW,OAAO,KAAK;AAAA,EAClE;AACA,QAAM,SAAS;AAAA,IACb;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK,YAAY,iBAAiB,IAAI,MAA6B,MAAM;AAAA,MACzE,YAAY;AAAA,MACZ,CAAC,oBAAoB,mBAAmB;AAAA,IAC1C;AAAA,EACF;AAEA,MAAI,MAAM;AACR,UAAM,YAAY,CAAC,aAChB,KAAK,cAAc,CAAC,GAAG,OAAO,CAAC,aAAa,qBAAqB,SAAS,SAAS,mBAAmB,CAAC;AAC1G,UAAM,QAAQ,OAAO,QAAQ,KAAK,aAAa,CAAC,CAAC,EAC9C,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,EAAE,SAAS,aAAa,KAAK,MAAM,IAAI,EAAE,EAAE,EACrE;AAAA,MACC,CAAC,YACC,uBAAuB,QAAQ,OAAO,KACtC,CAAC,aAAa,QAAQ,OAAO,KAC7B,QAAQ,eAAe,UACvB,sBAAsB,QAAQ,SAAS,KAAK,OAAO,IAAI,KACvD,UAAU,QAAQ,OAAO,EAAE,WAAW;AAAA,IAC1C,EACC,KAAK,CAAC,GAAG,MAAM,sBAAsB,EAAE,SAAS,EAAE,OAAO,CAAC;AAC7D,UAAM,QAAQ,uBAAuB,KAAK,OAAO,GAAG;AACpD,UAAM,SAAS,MAAM,KAAK,CAAC,YAAY,uBAAuB,QAAQ,OAAO,GAAG,UAAU,KAAK,KAAK,MAAM,CAAC;AAC3G,UAAM,SAAS,KAAK,cAAc,KAAK,aAAa,UAAU,KAAK,OAAO,EAAE,IAAI,CAAC,aAAa,SAAS,QAAQ;AAC/G,WAAO,KAAK,QAAQ,QAAQ,MAAM,QAAQ,QAAQ,SAAS,CAAC,YAAY,YAAY,CAAC,CAAC;AAAA,EACxF;AAEA,MAAI,IAAI;AACN,UAAM,SAAS,GAAG,WAAW,WAAW,GAAG,SAAS,GAAG,UAAU,MAAM,IAAI;AAC3E,WAAO,KAAK,QAAQ,MAAM,IAAI,GAAG,YAAY,QAAQ,SAAS,CAAC,YAAY,YAAY,CAAC,CAAC;AAAA,EAC3F;AAEA,SAAO;AACT;;;AG1OA,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,aAAAC,YAAW,aAAa,gBAAAC,eAAc,QAAQ,iBAAAC,sBAAqB;AAChG,SAAS,UAAAC,eAAc;AACvB,SAAS,WAAAC,UAAS,QAAAC,QAAM,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,IAAMC,SAAQ,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,OAAKC,QAAO,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,YAAYD,OAAKE,UAAS,UAAU,QAAQ,IAAI,GAAG,cAAc,CAAC;AAAA,EACrF;AACA,aAAW,QAAQ,IAAI,IAAI,KAAK,GAAG;AACjC,QAAI,KAAK,WAAW,IAAI,KAAK,CAACN,YAAWI,OAAK,UAAU,IAAI,CAAC,EAAG;AAChE,IAAAG,WAAUC,SAAQJ,OAAK,SAAS,IAAI,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;AAC3D,WAAOA,OAAK,UAAU,IAAI,GAAGA,OAAK,SAAS,IAAI,CAAC;AAAA,EAClD;AACA,SAAO;AACT;AAGA,eAAe,eACb,SACA,eACA,UAC+C;AAC/C,EAAAK,eAAcL,OAAK,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,OAAK,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,MAAMM,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;AAUA,IAAM,WAA2B,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,EAAE;AAQ5D,eAAsB,gBACpB,UACA,SACkB;AAClB,QAAM,EAAE,mBAAmB,QAAQ,SAAS,IAAI;AAChD,QAAM,gBAAgB,OAAON,OAAK,UAAU,cAAc,CAAC;AAC3D,QAAM,gBAAgB,OAAOA,OAAK,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,WAAO;AAAA,EACT;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;AAC9G,QAAM,mBAAmB,OAAO,KAAK,MAAM,SAAS,EAAE,SAAS;AAE/D,QAAM,UAAU;AAAA,IACd,UAAU,SAAS,IACf,yBAAyBF,OAAM,UAAU,QAAQ,gBAAgB,CAAC,QAClE;AAAA,EACN;AACA,QAAM,OAAO,CAAC,SAAiB,SAAS,OAAc;AACpD,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;AACb,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,MAAM,cAAc,UAAU,aAAa;AAC3D,MAAI;AACF,eAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,MAAM,SAAS,EAAG,CAAAO,eAAcL,OAAK,SAAS,IAAI,GAAG,OAAO;AAGzG,UAAM,OAAO,MAAM,eAAe,SAAS,eAAe,EAAE,GAAG,UAAU,WAAW,SAAS,cAAc,CAAC,EAAE,CAAC;AAC/G,QAAI,WAAW,MAAM;AACnB,YAAM,UAAU,mBAAmB,8BAA8B;AACjE,aAAO,KAAK,mCAAmC,OAAO,IAAI,KAAK,KAAK;AAAA,IACtE;AAEA,gBAAY,iCAAiC;AAC7C,UAAM,QAAQ,MAAM,aAAa,OAAO;AACxC,QAAI,CAAC,MAAO,QAAO,KAAK,sDAAsD;AAC9E,UAAM,aAAa,oBAAoB,KAAK;AAE5C,gBAAY,YAAYF,OAAM,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,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,aAAO;AAAA,IACT;AAEA,QAAI;AACJ,QAAI;AACF,kBAAY,MAAM,OAAO,OAAO,eAAe;AAAA,IACjD,QAAQ;AACN,cAAQ,KAAK,eAAG,IAAI,yCAAyC,CAAC;AAC9D,aAAO;AAAA,IACT;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;AACvD,UAAM,kBAAkB,aAAa;AAErC,UAAM,aAAa,OAAO,KAAK,MAAM,KAAK;AAC1C,UAAM,aAAa,MAAY;AAC7B,iBAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,MAAM,KAAK,EAAG,CAAAO,eAAcL,OAAK,UAAU,IAAI,GAAG,OAAO;AACtG,UAAI,WAAW,SAAS,EAAG,SAAQ,KAAK,GAAG,SAAS,IAAI,WAAW,KAAK,IAAI,CAAC,UAAU;AAAA,IACzF;AAEA,QAAI,CAAC,mBAAmB,CAAC,kBAAkB;AACzC,iBAAW;AACX,YAAM,QAAQ,GAAGF,OAAM,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,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,MAAY;AAC5B,UAAI,CAAC,gBAAiB;AACtB,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,CAAC,oBAAoB,YAAY,KAAK,WAAW,SAAS,SAAS,GAAG;AACxE,iBAAW;AACX,MAAAO,eAAcL,OAAK,UAAU,cAAc,GAAG,QAAQ;AACtD,cAAQ,KAAK,GAAG,SAAS,IAAI,cAAc,YAAY,eAAG,IAAI,yBAAsB,CAAC,EAAE;AACvF,gBAAU,IAAI;AACd,gBAAU;AACV,aAAO;AAAA,IACT;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,UAAM,UAAU,EAAE,GAAG,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,cAAc,GAAG,UAAU,CAAC,SAAS,GAAG,OAAO,KAAK;AAC3G,UAAM,SAAS,OAAO,YAAY,OAAO,KAAK,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,OAAOA,OAAK,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1G,WAAO,cAAc,IAAI;AACzB,WAAO,SAAS,IAAI;AACpB,eAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,OAAO,EAAG,CAAAK,eAAcL,OAAK,UAAU,IAAI,GAAG,OAAO;AAClG,UAAM,UAAUO,WAAU,QAAQ,CAAC,SAAS,GAAG,EAAE,KAAK,UAAU,OAAO,UAAU,CAAC;AAClF,YAAQ,KAAK;AACb,QAAI,QAAQ,WAAW,GAAG;AACxB,iBAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,MAAM,EAAG,CAAAF,eAAcL,OAAK,UAAU,IAAI,GAAG,OAAO;AACjG,cAAQ,MAAM,GAAG,eAAG,IAAI,QAAG,CAAC,mCAAmC,QAAQ,MAAM,GAAG;AAChF,cAAQ,KAAK,eAAG,IAAI,KAAK,OAAO,KAAK,MAAM,EAAE,KAAK,IAAI,CAAC,mDAAmD,CAAC;AAC3G,cAAQ,KAAK;AACb,aAAO;AAAA,IACT;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;AACV,WAAO;AAAA,EACT,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,IAAIF,OAAM,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,GAAGA,OAAM,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;;;ANtaA,IAAM,sBAAsB,CAAC,gBAAgB,mBAAmB,sBAAsB;AAMtF,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,MAAMU,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;AACF,UAAM,OAAO,MAAM,gBAAgB,QAAQ;AAC3C,UAAM,MAAM,KAAK,IAAI;AAErB,UAAM,CAAC,UAAU,aAAa,mBAAmB,OAAO,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,MACnF,YAAY,CAAC,MAAM,YAAY,UAAU,QAAQ,GAAG,QAAQ;AAAA,MAC5D,aAAa,QAAQ;AAAA,MACrB,sBAAsB,QAAQ;AAAA,MAC9B,kBAAkB,MAAM,UAAU,GAAG;AAAA,MACrC,eAAe,UAAU,GAAG;AAAA,IAC9B,CAAC;AACD,QAAI,CAAC,UAAU;AACb,kBAAY,+DAA+D;AAC3E,cAAQ,KAAK,GAAG,WAAW,wDAAwD;AACnF;AAAA,IACF;AAEA,UAAM,WAAW,mBAAmB,MAAM,OAAO,EAAE,mBAAmB,IAAI,CAAC;AAC3E,UAAM,aAAa,eAAe,SAAS,EAAE,mBAAmB,IAAI,CAAC;AACrE,UAAM,OAAO;AAAA,MACX,GAAG,YAAY,UAA6C,cAAc,oBAAoB,WAAW,IAAI,CAAC,CAAC;AAAA,MAC/G,GAAG,SAAS,QAAQ,IAAI,UAAU;AAAA,IACpC;AAEA,QAAI,KAAK,WAAW,GAAG;AACrB,qBAAe,0CAA0C;AACzD,iBAAW,UAAU,SAAS,SAAS;AACvC,cAAQ,KAAK;AACb,sBAAgB,UAAU;AAC1B,YAAM,gBAAgB,UAAU,EAAE,OAAO,CAAC,OAAO,MAAM,kBAAkB,CAAC;AAC1E;AAAA,IACF;AAEA,YAAQ,KAAK;AACb,yBAAqB,MAAM,QAAQ;AACnC,eAAW,UAAU,SAAS,SAAS;AACvC,YAAQ,KAAK;AACb,oBAAgB,UAAU;AAG1B,QAAI,OAAO,MAAM;AACf,YAAM,gBAAgB,UAAU,EAAE,OAAO,OAAO,kBAAkB,CAAC;AACnE;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,iBAAiB,IAAI;AAC5C,QAAI,CAAC,SAAU;AACf,UAAM,EAAE,OAAO,OAAO,IAAI,MAAM,UAAU,UAAU,MAAM,UAAU,KAAK,iBAAiB;AAC1F,QAAI,MAAM,gBAAgB,UAAU,EAAE,OAAO,MAAM,mBAAmB,MAAM,CAAC,EAAG,WAAU,MAAM;AAAA,EAClG,UAAE;AACA,YAAQ,KAAK;AAAA,EACf;AACF;AAGA,SAAS,YAAY,UAA2C,YAAoD;AAClH,QAAM,aAAa,CAAC,SAClB,WAAW,KAAK,CAAC,aAAa,WAAW,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE,aAAa,QAAQ,CAAC,KAAK;AACzG,QAAM,mBAAmB,yBAAyB;AAElD,QAAM,OAA8B,OAAO,QAAQ,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM;AAC/E,UAAM,OAAO,oBAAoB,GAAG;AACpC,UAAM,UAAU,WAAW,IAAI,gBAAgB,YAAY,GAAG;AAE9D,UAAM,UAAU,IAAI,WAAW;AAG/B,UAAM,WAAqB,CAAC;AAC5B,eAAW,KAAK,IAAI,mBAAmB;AACrC,YAAM,OAAO,iBAAiB,EAAE,QAAQ,IAAI,IAAI,cAAc,IAAI,IAAI,KAAK;AAC3E,UAAI,QAAQ,CAAC,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,GAAG;AACnF,iBAAS,KAAK,EAAE,IAAI;AAAA,MACtB;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,IAAI;AAAA,MACZ,mBAAmB,IAAI;AAAA,MACvB,OAAO,IAAI,mBAAmB;AAAA,MAC9B,UAAU,eAAe,SAAS,IAAI,MAAM;AAAA,MAC5C;AAAA,MACA;AAAA,MACA,aAAa,eAAe,OAAO;AAAA,MACnC,UAAU,WAAW,IAAI;AAAA,IAC3B;AAAA,EACF,CAAC;AAED,SAAO,KAAK,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE,cAAc,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAC/F;AAEA,SAAS,WAAW,QAA4C;AAC9D,SAAO;AAAA,IACL,KAAK,WAAW,OAAO,IAAI,IAAI,OAAO,IAAI;AAAA,IAC1C,MAAM,OAAO;AAAA,IACb,SAAS,OAAO;AAAA,IAChB,QAAQ,OAAO;AAAA,IACf,mBAAmB,CAAC;AAAA,IACpB,OAAO;AAAA,IACP,UAAU,eAAe,OAAO,SAAS,OAAO,MAAM;AAAA,IACtD,UAAU,CAAC;AAAA,IACX,SAAS;AAAA,IACT,aAAa,OAAO;AAAA,IACpB,UAAU,OAAO;AAAA,IACjB,SAAS;AAAA,EACX;AACF;AAEA,IAAM,QAAQ,CAAC,QAAsC,IAAI,aAAa,cAAc,IAAI,aAAa;AAGrG,IAAM,SAAS,CAAC,QACd,IAAI,UAAU,YAAY,IAAI,QAAQ,IAAI,IAAI,iBAAiB,IAAI,kBAAkB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAEzG,SAAS,qBAAqB,MAA6B,UAAwB;AACjF,QAAM,UAAU;AAChB,QAAM,cAAc;AACpB,QAAM,eAAe;AACrB,QAAM,qBAAqB;AAC3B,QAAM,MAAM,CAAC,QAA8B,IAAI,UAAU,cAAc,IAAI,QAAQ,UAAU;AAC7F,QAAM,aAAa,KAAK,IAAI,cAAc,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,KAAK,SAAS,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;AACxG,QAAM,gBAAgB,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,QAAQ,MAAM,CAAC;AACtE,QAAM,eAAe,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,OAAO,MAAM,CAAC;AACpE,QAAM,mBAAmB,KAAK,IAAI,oBAAoB,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;AAGxG,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,MAAM;AACtB,UAAM,gBAAgB,IAAI,WAAW,YAAY,IAAI,QAAQ,IAAI;AAEjE,UAAM,cAAc,eAAe,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,UAAU;AACvE,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,WAAW,eAAG,KAAK,eAAG,MAAM,UAAU,CAAC,IAAI,eAAG,MAAM,UAAU;AAEjF,UAAM,aAAa,eAAG,IAAI,eAAe,OAAO,GAAG,GAAG,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;AAEhG,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,MAAM;AACtB,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,WAAW,UAAkB,WAA2B;AAC/D,MAAI,OAAiB,CAAC;AACtB,MAAI;AACF,UAAM,eAAe,aAAaH,cAAaC,OAAK,UAAU,qBAAqB,GAAG,MAAM,GAAG,cAAc;AAC7G,UAAM,UAAW,cAA+D;AAChF,WAAO,MAAM,QAAQ,OAAO,IAAI,QAAQ,IAAI,MAAM,IAAI,CAAC;AAAA,EACzD,QAAQ;AAAA,EAER;AACA,MAAI,KAAK,SAAS,EAAG,SAAQ,KAAK,KAAK,eAAG,IAAI,SAAS,KAAK,KAAK,IAAI,CAAC,wCAAqC,CAAC,EAAE;AAC9G,MAAI,UAAU,SAAS;AACrB,YAAQ,KAAK,KAAK,eAAG,IAAI,yCAAyC,UAAU,KAAK,IAAI,CAAC,EAAE,CAAC,EAAE;AAC/F;AAGA,SAAS,gBAAgB,QAAgC;AACvD,QAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI,KAAK,OAAO,GAAG,MAAM,CAAC;AACrF,UAAQ,KAAK,eAAG,KAAK,cAAc,CAAC;AACpC,aAAW,QAAQ,QAAQ;AACzB,UAAM,QAAQ,GAAG,KAAK,IAAI,IAAI,KAAK,OAAO,GAAG,OAAO,KAAK;AACzD,UAAM,SAAS,KAAK,WAChB,GAAG,KAAK,IAAI,IAAI,eAAG,IAAI,MAAG,CAAC,IAAI,KAAK,GAAG,KACvC,eAAG,IAAI,KAAK,QAAQ,2BAA2B;AACnD,YAAQ,KAAK,GAAG,KAAK,WAAW,YAAY,KAAK,QAAQ,IAAI,GAAG,IAAI,KAAK,KAAK,MAAM,EAAE;AAAA,EACxF;AACA,UAAQ,KAAK;AACf;AAGA,SAAS,mBACP,MACsE;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,QAAQ;AAAA,MACZ,IAAI,WAAW,eAAG,KAAK,UAAU,IAAI;AAAA,MACrC,IAAI,SAAS,OAAO,eAAG,IAAI,IAAI,QAAQ,IAAI,IAAI;AAAA,MAC/C,IAAI,SAAS,SAAS,IAAI,GAAG,WAAW,IAAI,eAAG,IAAI,aAAa,IAAI,SAAS,KAAK,IAAI,CAAC,EAAE,CAAC,KAAK;AAAA,IACjG,EAAE,OAAO,OAAO;AAChB,WAAO;AAAA,MACL,MAAM,GAAG,IAAI,IAAI,GAAG,MAAM,KAAK,OAAO,GAAG,MAAM,SAAS,IAAI,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE;AAAA,MACxF,OAAO,IAAI;AAAA,MACX,SAAS,MAAM,GAAG;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,WAAW,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO;AAC7C,QAAM,SAAS,KAAK,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,SAAS,CAAC;AACrE,QAAM,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,WAAW,CAAC;AAExE,QAAM,UAAgF,CAAC;AAEvF,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,KAAK,IAAI,UAAU,eAAG,OAAO,0BAAgB,SAAS,MAAM,gBAAM,CAAC,CAAC;AAC5E,YAAQ,KAAK,GAAG,SAAS,IAAI,UAAU,CAAC;AAAA,EAC1C;AACA,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,QAAQ,SAAS,EAAG,SAAQ,KAAK,IAAI,UAAU,eAAG,IAAI,0BAAgB,QAAQ,MAAM,gBAAM,CAAC,CAAC;AAChG,YAAQ,KAAK,GAAG,QAAQ,IAAI,UAAU,CAAC;AAAA,EACzC;AAEA,SAAO;AACT;AAGA,eAAe,iBAAiB,MAAuD;AACrF,MAAI;AACF,UAAM,WAAW,MAAM,SAAS;AAAA,MAC9B,SAAS,yBAAyB,eAAG,IAAI,sCAAmC,CAAC;AAAA,MAC7E,SAAS,mBAAmB,IAAI;AAAA,MAChC,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;AAAA,QAC/C;AAAA,MACF;AAAA,IACF,CAAC;AACD,YAAQ,KAAK;AACb,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,SAAS,QAA+B;AAC/C,MAAI,OAAO,IAAI,SAAS,OAAQ,QAAO,gBAAgB,OAAO,MAAM;AACpE,MAAI,OAAO,IAAI,SAAS,OAAQ,QAAO,uBAAuB,OAAO,MAAM;AAC3E,SAAO,OAAO,IAAI;AACpB;AAOA,eAAe,UACb,UACA,MACA,UACA,mBAC6D;AAC7D,QAAM,WAAW,oBAAI,IAAoD;AACzE,QAAM,UAAU,oBAAI,IAAsB;AAC1C,QAAM,SAA0B,CAAC;AACjC,QAAM,OAAO,CAAC,MAAc,OAAe,MAAc,UAAmB,WAAwC;AAClH,UAAM,QAAQ,SAAS,IAAI,IAAI,KAAK,EAAE,SAASD,cAAaC,OAAK,UAAU,IAAI,GAAG,MAAM,GAAG,UAAU,MAAM;AAC3G,UAAM,OAAO,OAAO,MAAM,OAAO;AACjC,QAAI,SAAS,MAAM,QAAS;AAC5B,aAAS,IAAI,MAAM,EAAE,SAAS,MAAM,UAAU,MAAM,YAAY,SAAS,CAAC;AAC1E,YAAQ,IAAI,OAAO,CAAC,GAAI,QAAQ,IAAI,KAAK,KAAK,CAAC,GAAI,IAAI,CAAC;AAAA,EAC1D;AAEA,QAAM,SAAS,KAAK,OAAO,CAAC,QAAQ,SAAS,SAAS,IAAI,GAAG,CAAC;AAC9D,aAAW,OAAO,QAAQ;AACxB,QAAI,IAAI,QAAS;AACjB,eAAW,EAAE,MAAM,WAAW,SAAS,KAAK,IAAI,mBAAmB;AACjE,YAAM,OAAOI,UAAS,UAAUJ,OAAK,UAAU,cAAc,CAAC;AAC9D;AAAA,QAAK;AAAA,QAAM,aAAa;AAAA,QAAM,IAAI;AAAA,QAAM;AAAA,QAAM,CAAC,YAC7C,aAAa,SAAS,CAAC,SAAS;AAC9B,qBAAW,WAAW,qBAAqB;AACzC,kBAAM,OAAO,KAAK,OAAO;AACzB,kBAAM,OAAO,OAAO,IAAI,IAAI;AAC5B,gBAAI,CAAC,QAAQ,SAAS,OAAW;AACjC,kBAAM,OAAO,iBAAiB,MAAM,IAAI,MAAM;AAC9C,gBAAI,KAAM,MAAK,IAAI,IAAI,IAAI;AAAA,gBACtB,SAAQ,KAAK,GAAG,WAAW,IAAI,IAAI,IAAI,OAAO,aAAa,IAAI,qBAAqB,IAAI,EAAE;AAAA,UACjG;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,aAAW,OAAO,QAAQ;AACxB,UAAM,SAAS,IAAI;AACnB,QAAI,CAAC,OAAQ;AACb,QAAI,OAAO,IAAI,SAAS,QAAQ;AAC9B,YAAM,UAAU,MAAM,kBAAkB,OAAO,QAAQ,iBAAiB;AACxE,UAAI,QAAQ,SAAS,GAAG;AACtB,gBAAQ,KAAK,GAAG,WAAW,SAAS,OAAO,MAAM,aAAa,QAAQ,KAAK,IAAI,CAAC,2BAA2B;AAC3G;AAAA,MACF;AAAA,IACF;AACA,SAAK,OAAO,MAAM,OAAO,MAAM,SAAS,MAAM,GAAG,OAAO,CAAC,YAAY,mBAAmB,SAAS,MAAM,CAAC;AACxG,WAAO,KAAK,MAAM;AAAA,EACpB;AAEA,aAAW,CAAC,OAAO,KAAK,KAAK,SAAS;AACpC,YAAQ,KAAK,GAAG,eAAG,KAAK,QAAG,CAAC,IAAI,eAAG,KAAK,KAAK,CAAC,KAAK,eAAG,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,EAAE;AAAA,EAC/E;AACA,MAAI,QAAQ,OAAO,EAAG,SAAQ,KAAK;AAEnC,QAAM,QAAwB,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,EAAE;AACzD,aAAW,CAAC,MAAM,EAAE,SAAS,SAAS,CAAC,KAAK,UAAU;AACpD,KAAC,WAAW,MAAM,YAAY,MAAM,OAAO,IAAI,IAAI;AAAA,EACrD;AACA,SAAO,EAAE,OAAO,OAAO;AACzB;AAGA,SAAS,UAAU,QAA+B;AAChD,QAAM,QAA+C,CAAC;AACtD,QAAM,OAAO,OAAO,KAAK,CAAC,WAAW,OAAO,IAAI,SAAS,MAAM;AAC/D,MAAI,QAAQ,QAAQ,YAAY,IAAI,KAAK,MAAM,IAAI;AACjD,UAAM,UAAU,OAAO,YAAY,IAAI,sBAAsB,KAAK,MAAM,KAAK,kBAAkB,KAAK,MAAM;AAC1G,UAAM,KAAK,CAAC,SAAS,qBAAqB,QAAQ,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,EACvE;AACA,aAAW,UAAU,QAAQ;AAC3B,QAAI,OAAO,IAAI,SAAS,QAAS,OAAM,KAAK,CAAC,mBAAmB,OAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA,EACjH;AACA,MAAI,MAAM,WAAW,EAAG;AAExB,QAAM,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC,OAAO,MAAM,QAAQ,MAAM,CAAC;AAClE,UAAQ,KAAK,eAAG,KAAK,MAAM,CAAC;AAC5B,aAAW,CAAC,SAAS,GAAG,KAAK,MAAO,SAAQ,KAAK,KAAK,eAAG,IAAI,QAAG,CAAC,IAAI,QAAQ,OAAO,KAAK,CAAC,MAAM,eAAG,IAAI,GAAG,CAAC,EAAE;AAC7G,UAAQ,KAAK;AACf;;;AO/bA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,UAAAK,eAAc;;;ACNvB,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;;;AFcA,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,cAAMC,QAAO,MAAM;AAAA,UACjB,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,OAAO,MAAM,SAAS,EAAE,CAAC,EAAE,CAAC;AAAA,UAC/C,EAAE,OAAO,MAAM,MAAM,uBAAa,QAAQ,GAAG;AAAA,UAC7C;AAAA,UACA;AAAA,QACF;AACA,qBAAa,cAAcA,KAAI,IAAI,UAAU,IAAI,gBAAgB,cAAcA,KAAI,EAAE;AAAA,MACvF,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;;;AGzbA,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,cAAY,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,aAAW,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;;;AFhbA,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;AAC1C,QAAM,iBAAiB,OAAO,UAAU,QAAQ,MAAM;AAEtD,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;;;AD7qBA,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;;;AzClUA,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","basename","process","execFileSync","join","process","execFileSync","index","count","join","process","basename","process","readFileSync","basename","join","relative","execFile","promisify","execFileAsync","promisify","execFile","str","execFile","existsSync","realpathSync","dirname","join","sep","promisify","readFileSync","basename","dirname","join","basename","readFileSync","join","plural","dirname","execFileAsync","promisify","execFile","sep","existsSync","join","realpathSync","dirname","spawnSync","existsSync","mkdirSync","readFileSync","writeFileSync","tmpdir","dirname","join","relative","select","existsSync","readFileSync","count","plural","join","tmpdir","relative","mkdirSync","dirname","writeFileSync","select","spawnSync","readFileSync","join","basename","count","packageJsonPath","relative","select","rmSync","dirname","join","resolve","dirname","resolve","join","rmSync","existsSync","dirname","resolve","dirname","resolve","existsSync","page","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"]}
|
|
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/git.ts","../src/utils/manifest.ts","../src/utils/layout.ts","../src/utils/overrides.ts","../src/utils/alignments.ts","../src/services/align.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/analyze-report.ts","../src/services/review-page.ts","../src/utils/diff.ts","../src/services/analyze.ts","../src/services/audit.ts","../src/utils/audit-utils.ts","../src/utils/local-tools.ts","../src/utils/runtimes.ts","../src/utils/security-plan.ts","../src/utils/workspace-yaml.ts","../src/services/audit-security.ts","../src/services/contributions.ts","../src/services/contrib-core.ts","../src/services/fork-utils.ts","../src/services/forks.ts","../src/services/upgrade.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 { runAlign } from './services/align';\nimport { runAnalyze } from './services/analyze';\nimport { runAudit } from './services/audit';\nimport { runContributions } from './services/contributions';\nimport { runForks } from './services/forks';\nimport { runStats } from './services/stats';\nimport { runBranchStats } from './services/stats-since';\nimport { runUpgradeCommand } from './services/upgrade';\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 upgrade 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 upgrade: runUpgradeCommand,\n align: runAlign,\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, renamedSettingWarnings, 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 /** The former service name the command line used, from {@link ServiceDefinition.aliases}. */\n renamedFrom?: string;\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 `align --run` hands to the codemod. */\n operands?: ServiceOption;\n /** Former names that still run the service, hidden from help, with a warning to use the current name. */\n aliases?: string[];\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 upgrade',\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 ['--all', 'list every file instead of collapsing large groups'],\n trackOption,\n refOption,\n unpinnedOption,\n ],\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'upgrade',\n description: 'merge upstream changes onto a fresh branch, merge package.json and open a squash-merge PR',\n aliases: ['sync'],\n options: [\n trackOption,\n refOption,\n ['--keep-config', 'merge with your CLI config as it stands when upstream changed its own'],\n unpinnedOption,\n ],\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'align',\n description: 'list the upstream alignments this app has not handled yet',\n options: [\n ['--all', 'list every upstream alignment, handled or not'],\n jsonOption,\n ['--show <id>', \"print one alignment's README and what git tells about it\"],\n ['--extract <id>', \"write one alignment's folder under node_modules/.cache to run its codemod\"],\n ['--run <id>', \"run one alignment's codemod; files identical to upstream stay as they are\"],\n ['--mark <ids...>', 'record alignments as handled'],\n ],\n operands: [\n '[codemodArgs...]',\n \"with --run, after `--`: arguments for the codemod (default: inventory and the alignment's roots)\",\n ],\n includeInMenu: (context) => !context.isUpstreamRepo,\n },\n {\n name: 'audit',\n description: 'update outdated packages and runtime pins, 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 the upgrade inside local fork repositories',\n options: [\n forkOption,\n ['--keep-config', \"merge with the fork's CLI 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 for (const name of [definition.name, ...(definition.aliases ?? [])]) {\n const renamedFrom = name === definition.name ? undefined : name;\n const command = program.command(name, { hidden: !!renamedFrom }).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 renamedFrom,\n options: readOptions(opts, operands),\n });\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 upgrade --track branch',\n ' $ cella upgrade --ref 4f7d87c',\n ' $ cella align --run 20261001T2116-tailwind-class-conventions -- rewrite frontend/src',\n ' $ cella align --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 = [\n ...renamedSettingWarnings(userConfig),\n ...(await validateOverrides(userConfig, forkPath, branchRef)),\n ];\n if (selection.renamedFrom) {\n warnings.unshift(`\\`cella ${selection.renamedFrom}\\` is renamed to \\`cella ${selection.service}\\``);\n }\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 the cella 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 PackageJsonKey, 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 upgrade` cuts per run\n * (e.g. `cella/upgrade/20260702-1430`).\n *\n * The three-segment shape (`cella/upgrade/<stamp>`) means it can never collide with a real branch\n * named `cella` or `cella/upgrade`.\n */\nexport const UPGRADE_BRANCH_PREFIX = 'cella/upgrade';\n\n/** Branch prefixes of a cycle in progress or an open PR: CLI 0.5 cut its branches under `cella/sync`. */\nexport const TEMPORARY_BRANCH_PREFIXES = [UPGRADE_BRANCH_PREFIX, 'cella/sync'];\n\n/** The package.json keys that merge when a config omits `packageJsonKeys`. */\nexport const DEFAULT_PACKAGE_JSON_KEYS: PackageJsonKey[] = ['dependencies', 'devDependencies'];\n\n/** Settings renamed in 0.6, by their old name: `loadConfig` reads them under the new one. */\nconst RENAMED_SETTINGS = { packageJsonSync: 'packageJsonKeys', syncWithPackages: 'mergePackageJson' } as const;\n\n/** A warning per renamed setting the config still uses. */\nexport function renamedSettingWarnings(config: CellaCliConfig): string[] {\n return Object.entries(RENAMED_SETTINGS)\n .filter(([old]) => old in config.settings)\n .map(([old, current]) => `settings.${old} is renamed to ${current}: rename it in ${CONFIG_FILE}`);\n}\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/** Whether `branch` is one of the temporary integration branches `cella upgrade` cuts. */\nexport function isTemporarySyncBranch(branch: string): boolean {\n return TEMPORARY_BRANCH_PREFIXES.some((prefix) => branch.startsWith(`${prefix}/`));\n}\n\n/**\n * Resolve the trunk branch `cella upgrade` 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 an upgrade cycle, e.g.\n * `cella/upgrade/20260702-1430`. Cutting a fresh branch per cycle keeps each PR\n * scoped to that upgrade'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 `${UPGRADE_BRANCH_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) upgrades 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 // Settings renamed in 0.6 keep working under their old names (see RENAMED_SETTINGS).\n config.settings.packageJsonKeys ??= config.settings.packageJsonSync;\n config.settings.mergePackageJson ??= config.settings.syncWithPackages;\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_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 merge from upstream */\nexport type PackageJsonKey = (typeof PACKAGE_JSON_KEYS)[number];\n\n/**\n * Settings: all configurable options for the cella 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): upgrade 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 upgrade` 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 merge from upstream (default: ['dependencies', 'devDependencies']). `type` always merges. */\n packageJsonKeys?: PackageJsonKey[];\n\n /** Merge the `packageJsonKeys` of every package.json after the upgrade merge (default: true). */\n mergePackageJson?: boolean;\n\n /** @deprecated Renamed to `packageJsonKeys`. */\n packageJsonSync?: PackageJsonKey[];\n\n /** @deprecated Renamed to `mergePackageJson`. */\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 upgrade 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 packageJsonKeys: z.array(z.enum(PACKAGE_JSON_KEYS)).optional(),\n mergePackageJson: z.boolean().optional(),\n packageJsonSync: z.array(z.enum(PACKAGE_JSON_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' | 'upgrade' | 'align' | '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/upgrade), 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/upgrade), 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 CLI config as it stands (upgrade service). Without it, a new merge stops\n * before anything changes when upstream changed its own `overrides` or `packageJsonKeys` 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 file instead of collapsing large groups (analyze), or every upstream alignment (align) */\n all?: boolean;\n\n /** Print one alignment's README (align service) */\n show?: string;\n\n /** Write one alignment's folder where its codemod can run (align service) */\n extract?: string;\n\n /** Run one alignment's codemod, keeping files identical to upstream as they are (align service) */\n run?: string;\n\n /** Arguments after `--`, passed to the codemod as given (align service, with `run`) */\n runArgs?: string[];\n\n /** Alignment ids to record as handled (align 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 /** Unix epoch seconds of the commit */\n timestamp?: number;\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` and `upstreamOnly` 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 /** Upstream commits since the last sync point */\n upstreamCommitCount?: number;\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 /** `<merge-base>..<upstream>` range of short SHAs: what upstream changed since the last sync, for the review page. */\n upstreamDiffRange?: string;\n /** How upstream's own CLI 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 alignments: how many the incoming ref holds, which ones upstream added since the\n * sync point, and the ones open in the fork after the run. A sync opens the arrivals; a dry run\n * leaves them out of `open`.\n */\n alignments?: { total: number; arrived: string[]; open: string[] };\n}\n\n/** Entries of one CLI config list (`pinned`, `ignored` or `packageJsonKeys`) 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 CLI config changes the fork should review. The CLI config is managed (never merged),\n * so new upstream `pinned`/`ignored` entries and `packageJsonKeys` 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 packageJsonKeys: OverrideListChanges;\n }\n | { kind: 'unreadable'; side: 'base' | 'incoming' };\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/** CLI 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 CLI 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 { splitPrNumber } from './git';\nimport { fitText, padVisible, shortAge, terminalColumns } from './layout';\nimport { CONFIG_FILE, isGeneratedFile, 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 commit the run analyzed: file links show the file as it is there */\n upstreamSha?: string;\n /** Base GitHub URL of the fork's `origin`, for links to the fork's own commits */\n forkGitHubUrl?: 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 listed in the sync PR body */\nexport const COMMIT_LIST_MAX = 50;\n\n/** Most recent upstream commits listed under the `upstream` step */\nexport const COMMIT_STEP_MAX = 10;\n\n/** Width of the label column of step lines (`✓ upstream …`) */\nconst STEP_LABEL_WIDTH = 9;\n\n/** Where the detail of a step line starts: the mark, the label column and two spaces */\nexport const STEP_INDENT = 2 + STEP_LABEL_WIDTH + 2;\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 version = ` · v${VERSION}`;\n const right = 'cellajs.com';\n // Padding counts the visible characters only, not the ANSI codes\n const padding = Math.max(1, DIVIDER.length - `${left}${version}${right}`.length);\n console.info();\n console.info(`${pc.cyan(left)}${pc.dim(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/**\n * Print a completed step of the merge engine on one line, `✓ label detail`; further lines of\n * `detail` line up under its first.\n */\nexport function printStep(label: string, detail?: string, mark = checkMark): void {\n stopSpinner();\n const [first = '', ...rest] = (detail ?? '').split('\\n');\n console.info(`${mark} ${pc.bold(label.padEnd(STEP_LABEL_WIDTH))} ${first}`.trimEnd());\n for (const line of rest) console.info(line ? `${' '.repeat(STEP_INDENT)}${line}` : '');\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/** A commit subject colored by kind: releases dim, breaking changes (`feat!:`) with a yellow type. */\nfunction styleSubject(subject: string): string {\n if (/^chore(\\([^)]*\\))?: release\\b/.test(subject)) return pc.dim(subject);\n const breaking = /^([a-z]+(\\([^)]*\\))?!:)/.exec(subject);\n return breaking ? `${pc.yellow(breaking[1])}${subject.slice(breaking[1].length)}` : subject;\n}\n\n/**\n * The `checkout` step: branch and commit, whether the tree is clean, and how the branch stands to\n * its remote when it is ahead or behind. The path shows when it is not the current directory, as\n * when `forks` syncs another repo.\n */\nexport function formatCheckoutStep(checkout: {\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 { forkPath, branch, headSha, changeCount, upstream } = checkout;\n const parts = [\n changeCount === 0 ? 'clean' : `${plural(changeCount, 'uncommitted change')}, not included in the analysis`,\n ];\n if (upstream.upstream && (upstream.ahead > 0 || upstream.behind > 0)) {\n parts.push(`${upstream.ahead} ahead, ${upstream.behind} behind ${upstream.upstream}`);\n }\n const line = `${branch} @ ${headSha}${pc.dim(` · ${parts.join(' · ')}`)}`;\n return resolve(forkPath) === resolve(process.cwd()) ? line : `${line}\\n${pc.dim(forkPath)}`;\n}\n\n/**\n * The `upstream` step: the branch or release upgraded to and how many commits it brings since the\n * last upgrade, then those commits (see {@link formatUpstreamCommits}).\n */\nexport function formatUpstreamStep(upstream: {\n label: string;\n sha: string;\n baseSha: string;\n pinned: boolean;\n commitCount: number;\n commits: CommitRangeEntry[];\n githubUrl?: string;\n}): string {\n const { label, sha, baseSha, pinned, commitCount, commits, githubUrl } = upstream;\n const since =\n commitCount === 0\n ? 'no new commits since the last upgrade'\n : `${plural(commitCount, 'new commit')} since the last upgrade at ${baseSha}`;\n return [\n `${label} @ ${sha}${pc.dim(`${pinned ? ' · --ref' : ''} · ${since}`)}`,\n ...formatUpstreamCommits(commitCount, commits, githubUrl),\n ].join('\\n');\n}\n\n/**\n * The upstream commits under the `upstream` step: newest first, one line each with the short hash,\n * the subject cut to the terminal width, the PR number and the age; hash and PR link to GitHub.\n * `commits` comes oldest first, as `listCommitsBetween` returns it.\n */\nexport function formatUpstreamCommits(\n commitCount: number,\n commits: CommitRangeEntry[],\n upstreamGitHubUrl?: string,\n options: { columns?: number; max?: number; nowMs?: number } = {},\n): string[] {\n const { columns = terminalColumns(), max = COMMIT_STEP_MAX, nowMs } = options;\n const shown = commits.slice(-max).reverse();\n const rows = shown.map((commit) => ({ commit, ...splitPrNumber(commit.message) }));\n const prWidth = Math.max(0, ...rows.map((row) => (row.pr ? `#${row.pr}`.length : 0)));\n const ages = rows.map((row) => (row.commit.timestamp ? shortAge(row.commit.timestamp, nowMs) : ''));\n const ageWidth = Math.max(0, ...ages.map((age) => age.length));\n const subjectWidth = Math.max(\n 20,\n columns - STEP_INDENT - 7 - 2 - (prWidth ? prWidth + 2 : 0) - (ageWidth ? ageWidth + 2 : 0),\n );\n\n const lines = rows.map((row, index) => {\n const hash = hyperlink(\n row.commit.hash.slice(0, 7),\n upstreamGitHubUrl && `${upstreamGitHubUrl}/commit/${row.commit.hash}`,\n );\n const subject = fitText(row.subject, subjectWidth);\n let line = `${pc.dim(hash)} ${padVisible(styleSubject(subject), subjectWidth)}`;\n if (prWidth) {\n const pr = row.pr ? hyperlink(`#${row.pr}`, upstreamGitHubUrl && `${upstreamGitHubUrl}/pull/${row.pr}`) : '';\n line += ` ${pc.dim(padVisible(pr, prWidth))}`;\n }\n if (ageWidth) line += ` ${pc.dim(ages[index].padStart(ageWidth))}`;\n return line.trimEnd();\n });\n if (commitCount > shown.length) lines.push(pc.dim(`+ ${commitCount - shown.length} earlier`));\n return lines;\n}\n\n/** One step of `next steps`: a label for what to do, the command or link, and lines under it. */\nexport interface NextStep {\n label: string;\n line: string;\n details?: string[];\n}\n\n/**\n * The `next steps` section that closes analyze and sync, numbered in the order to take them. The\n * line and details of each step start at the column the engine's step details do.\n */\nexport function printNextSteps(steps: NextStep[]): void {\n if (steps.length === 0) return;\n printSectionHeader(pc.cyan('next steps'));\n for (const [index, step] of steps.entries()) {\n const label = step.label.padEnd(STEP_INDENT - 5);\n console.info(` ${pc.dim(String(index + 1))} ${pc.bold(label)} ${step.line}`.trimEnd());\n for (const detail of step.details ?? []) console.info(`${' '.repeat(STEP_INDENT)}${detail}`);\n }\n}\n\n/** A section header: a blank line, the title, the divider under it, and a blank line. */\nexport function printSectionHeader(title: string): void {\n console.info();\n console.info(title);\n console.info(DIVIDER);\n console.info();\n}\n\nexport function formatMergeInProgressDetail(\n conflictCount: number,\n autoMergedFiles: string[],\n linkOptions: LinkOptions,\n maxFiles = 100,\n): string {\n const lines = [`${plural(conflictCount, 'conflict')} to resolve in your editor`];\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 update' },\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/** The grouped count of every status, under its own section header. */\nexport function 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/** Files with `status`, managed files left out: the list each analyze file group prints. */\nexport function filesWithStatus(files: AnalyzedFile[], status: FileStatus): AnalyzedFile[] {\n return files.filter((f) => f.status === status && !isManagedFile(f.path));\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 // Generated output is rebuilt from the fork's own sources, so upstream's copy has nothing to adopt.\n return files.filter((file) => file.upstreamChanged && !isManagedFile(file.path) && !isGeneratedFile(file.path));\n}\n\n/**\n * Every protected file upstream changed since the last sync that the sync leaves as the fork has\n * it: those both sides changed ({@link findProtectedBehind}) and the ignored files only upstream\n * changed, added or deleted (`MergeResult.ignoredUpstreamChanges`). Analyze lists them as one\n * section, on the terminal and on the review page.\n */\nexport function findProtectedBehindUpstream(\n result: Pick<MergeResult, 'files' | 'ignoredUpstreamChanges'>,\n): AnalyzedFile[] {\n const ignoredOnly = new Set((result.ignoredUpstreamChanges ?? []).flatMap((group) => group.paths));\n return [...findProtectedBehind(result.files), ...result.files.filter((file) => ignoredOnly.has(file.path))];\n}\n\n/** Hint under the protected files an upgrade kept the fork version of. */\nconst PROTECTED_BEHIND_HINT =\n 'pinned/ignored files where upstream also changed since the last upgrade; the fork side wins on conflict, ' +\n 'so review what upstream changed and adopt what you need.';\n\n/** Icon by protection kind (⨂ ignored, ⨀ pinned) for protected-but-behind lines. */\nexport function 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\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 const counts = `${plural(updated, 'file')} updated, ${merged} auto-merged, ${plural(conflicts, 'conflict')}`;\n console.info();\n if (options.stagedBranch) {\n console.info(`${checkMark} upgrade merge staged on '${options.stagedBranch}'`);\n console.info(pc.dim(` ${counts}. committing next...`));\n } else if (conflicts > 0) {\n console.info(`${warningMark} upgrade merge staged with conflicts`);\n console.info(pc.dim(` ${counts}`));\n } else {\n console.info(`${checkMark} upgrade merge complete`);\n console.info(pc.dim(` ${counts}`));\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 console.info(pc.dim(` ${PROTECTED_BEHIND_HINT}`));\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/**\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. 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 }\n console.info(\n pc.dim(' the fork left these untouched and ignored paths never merge: review and adopt what you need.'),\n );\n}\n\n/**\n * Upstream CLI config entries the fork config does not follow (`MergeResult.upstreamOverrides`):\n * `overrides` entries and `packageJsonKeys` upstream added that the fork lacks, and ones\n * upstream dropped that the fork still has. The CLI 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 upgrade' : 'the incoming ref';\n console.info(\n pc.dim(`upstream CLI 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', 'packageJsonKeys'] 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 CLI 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 merges: 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 CLI 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 */\nexport function 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 CLI 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.6.0\",\n \"private\": false,\n \"license\": \"MIT\",\n \"description\": \"CLI for managing your monorepo and upgrading it 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.28.7\",\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 * 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\n/** A trailing `(#1519)` that squash merges add to a commit subject: the PR number, and the subject without it. */\nexport function splitPrNumber(subject: string): { subject: string; pr?: number } {\n const match = /\\s*\\(#(\\d+)\\)\\s*$/.exec(subject);\n return match ? { subject: subject.slice(0, match.index), pr: Number(match[1]) } : { subject };\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%x1f%ct', '--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, timestamp] = line.split('\\x1f');\n if (!hash || !message || !date) continue;\n commits.push({ hash, message, date, timestamp: Number(timestamp) || undefined });\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/** The local ref holding the upstream commit of the last upgrade, and `<ref>-head` the fork HEAD then. */\nconst LAST_UPGRADE_REF = 'refs/cella/last-upgrade';\n\n/** Where CLI 0.5 kept the same two refs; read while a fork has not upgraded under 0.6. */\nconst LEGACY_LAST_UPGRADE_REF = 'refs/cella/last-sync';\n\n/**\n * Store the upstream commit hash after a successful upgrade merge.\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-upgrade-head`. The last-upgrade\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', LAST_UPGRADE_REF, upstreamHash], cwd);\n const head = await revParse(cwd, 'HEAD');\n if (head) await git(['update-ref', `${LAST_UPGRADE_REF}-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-upgrade ref and its HEAD, under the 0.5 names when the 0.6 ones are absent. */\nasync function readStoredSyncRefs(cwd: string): Promise<{ ref: string; head: string | null } | null> {\n for (const name of [LAST_UPGRADE_REF, LEGACY_LAST_UPGRADE_REF]) {\n const ref = await revParse(cwd, name);\n if (ref) return { ref, head: await revParse(cwd, `${name}-head`) };\n }\n return null;\n}\n\n/** The stored last-upgrade upstream ref, or null when no upgrade has been recorded. */\nexport async function getStoredSyncRef(cwd: string): Promise<string | null> {\n return (await readStoredSyncRefs(cwd))?.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 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 an upgrade 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 'An upgrade 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 the upgrade.${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 upgrade 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-upgrade` 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-upgrade`. 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 upgrade 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 the upgrade:\\n\\n' +\n ` git update-ref ${LAST_UPGRADE_REF} <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 upgrade ancestry\");\n\n await git(['replace', '-f', '--graft', root, baseSha], cwd);\n await git(['update-ref', LAST_UPGRADE_REF, 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 upgraded before the manifest was committed: the local\n * last-upgrade ref, discarded while HEAD still sits at the recorded HEAD (an aborted merge,\n * see {@link storeLastSyncRef}).\n */\nasync function getLegacySyncRef(cwd: string, headRef: string): Promise<string | null> {\n const stored = await readStoredSyncRefs(cwd);\n if (!stored) return null;\n\n if (stored.head) {\n const currentHead = await revParse(cwd, headRef);\n if (currentHead && currentHead === stored.head) return null;\n }\n\n return stored.ref;\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-upgrade ref is the fallback for forks whose last upgrade 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-upgrade`) 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 upgrade manifest: the committed record of the last upstream point the app upgraded to.\n * `upstream.commit` seeds the merge-base on a clone without `refs/cella/last-upgrade` (fresh clone,\n * CI), and the rest shows in each upgrade PR which upstream point the app moved to. The merge engine\n * stages it with every applied upgrade.\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 upgrade 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 upgrade (ISO 8601). */\n upgradedAt?: 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-upgrade` 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 its first upgrade).\n await mkdir(dirname(manifestPath), { recursive: true });\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\n}\n","/**\n * Terminal layout helpers: visible widths that ignore escape codes, column padding, cutting text\n * to the terminal width, and the short ages and counts the file rows print.\n */\n\nimport process from 'node:process';\nimport { stripVTControlCharacters } from 'node:util';\n\n/** Columns a line may use: the terminal's width, 80 when stdout is not a terminal. */\nexport function terminalColumns(): number {\n const columns = process.stdout.isTTY ? process.stdout.columns : undefined;\n return Math.max(60, columns || 80);\n}\n\n/** Width of `text` as a terminal shows it: colors and OSC 8 link targets take no columns. */\nexport function visibleWidth(text: string): number {\n return stripVTControlCharacters(text).length;\n}\n\n/** Pad `text` with spaces to `width` visible columns, on the right (`start`) or left (`end`). */\nexport function padVisible(text: string, width: number, align: 'start' | 'end' = 'start'): string {\n const padding = ' '.repeat(Math.max(0, width - visibleWidth(text)));\n return align === 'start' ? `${text}${padding}` : `${padding}${text}`;\n}\n\n/** Plain `text` cut to `width` columns, ending in `…` when cut. */\nexport function fitText(text: string, width: number): string {\n if (text.length <= width) return text;\n return `${text.slice(0, Math.max(0, width - 1)).trimEnd()}…`;\n}\n\n/** Steps git's relative dates use (`--date=relative`), in seconds, with the unit each prints in. */\nconst AGE_STEPS: Array<[below: number, unit: number, suffix: string]> = [\n [90 * 60, 60, 'm'],\n [36 * 3600, 3600, 'h'],\n [14 * 86400, 86400, 'd'],\n [70 * 86400, 7 * 86400, 'w'],\n [365 * 86400, 30 * 86400, 'mo'],\n];\n\n/** `4m`, `3h`, `2d`, `8w`, `3mo`, `2y` since `epochSeconds`; `now` under a minute. */\nexport function shortAge(epochSeconds: number, nowMs = Date.now()): string {\n const seconds = Math.max(0, Math.round(nowMs / 1000 - epochSeconds));\n if (seconds < 60) return 'now';\n for (const [below, unit, suffix] of AGE_STEPS) {\n if (seconds < below) return `${Math.max(1, Math.round(seconds / unit))}${suffix}`;\n }\n return `${Math.floor(seconds / (365 * 86400))}y`;\n}\n\n/** A line count that fits a narrow column: `909`, `9999`, `12.4k`, `311.8k`, `1.2M`. */\nexport function compactCount(count: number): string {\n if (count < 10_000) return String(count);\n if (count < 1_000_000) return `${(count / 1000).toFixed(1)}k`;\n return `${(count / 1_000_000).toFixed(1)}M`;\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 } from '../config/types';\nimport { isUpstreamOnly } from './alignments';\nimport { fileExistsAtRef, listChangedSinceRef, revParse } from './git';\nimport { isGeneratedFile, isManagedFile } from './managed-files';\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 (alignments),\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 * 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 * Upstream alignments, read from git.\n *\n * Upstream ships one alignment per breaking change in `cella/alignments/<id>/`: a README.md\n * that 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. Alignments are read from upstream commits the sync already fetched.\n *\n * The fork records only the alignments it has not handled yet, in `cella/cella.alignments.json` as\n * `{ \"pending\": [...] }`. The sync adds the ones that arrive with it; `cella align --mark` removes\n * them. A missing file means nothing is pending, so a new app needs no seed. Alignments are\n * information, never a gate: nothing blocks on a pending one.\n */\n\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { git, splitPrNumber } from './git';\n\n/** Upstream folder holding one subfolder per alignment. Upstream-only: never synced into a fork. */\nexport const ALIGNMENTS_DIR = 'cella/alignments';\n\n/**\n * Folders the sync keeps out of a fork: the alignments, and `cella/migrations`, the migration notes\n * upstream deleted when it started the alignments. Older syncs copied that folder into forks.\n */\nexport const UPSTREAM_ONLY_DIRS = [ALIGNMENTS_DIR, 'cella/migrations'];\n\n/** The fork's record of alignments still to handle. */\nexport const PENDING_FILE = 'cella/cella.alignments.json';\n\n/** An alignment folder name: `<YYYYMMDDThhmm>-<slug>`, UTC minute precision, so ids sort chronologically. */\nconst ALIGNMENT_ID = /^\\d{8}T\\d{4}-[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/** What catches app code the change leaves behind: the typecheck, the tests the app inherits, or nothing. */\nexport type CaughtBy = 'compiler' | 'tests' | 'nothing';\n\nconst CAUGHT_BY: CaughtBy[] = ['compiler', 'tests', 'nothing'];\n\n/** One alignment, as read at an upstream ref. */\nexport interface Alignment {\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 breaking: boolean;\n /** Bumped `clientCacheVersion` or shipped a lens module. */\n clientCacheBump: boolean;\n /** Null when the frontmatter names none, or a value outside {@link CaughtBy}. */\n caughtBy: CaughtBy | null;\n /** The change needs `pnpm generate`. */\n generate: boolean;\n /** Identifiers, wire fields or config keys app code may still use, matched as whole words. */\n grep: string[];\n /** Default scan roots for the codemod. */\n roots: string[];\n /** File name of the codemod inside the alignment folder, or null for a manual one. */\n codemod: string | null;\n}\n\n/** Where an alignment came from: the upstream commit that added its README. */\nexport interface AlignmentSource {\n commit: string;\n /** From a trailing `(#NNNN)` in the commit subject, as squash merges write it; null without one. */\n pr: number | null;\n /** Ids of the other alignments the same commit added. */\n sharedCommit: string[];\n /** Every path the commit changed. */\n changedFiles: string[];\n}\n\n/** Whether a file in an alignment 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/** A comma-separated frontmatter value as a list, empty items dropped. */\nfunction splitList(value: string | undefined): string[] {\n return (value ?? '')\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean);\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 UPSTREAM_ONLY_DIRS.some((dir) => filePath === dir || filePath.startsWith(`${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 an alignment README. Unreadable frontmatter values fall back to false, null or empty. */\nexport function parseAlignment(id: string, source: string, fileNames: string[]): Alignment {\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 const caughtBy = CAUGHT_BY.find((value) => value === meta.get('caughtBy')) ?? null;\n\n return {\n id,\n title: title || id,\n summary,\n // `syncBreaking` is the field's name in alignments up to cella 0.27\n breaking: (meta.get('breaking') ?? meta.get('syncBreaking')) === 'true',\n clientCacheBump: meta.get('clientCacheBump') === 'true',\n caughtBy,\n generate: meta.get('generate') === 'true',\n grep: splitList(meta.get('grep')),\n roots: splitList(meta.get('roots')),\n codemod: fileNames.find(isCodemodFile) ?? null,\n };\n}\n\n/** Ids of every alignment at `ref`, oldest first; empty when the ref has no alignments folder. */\nexport async function listAlignmentIds(cwd: string, ref: string): Promise<string[]> {\n const out = await git(['ls-tree', '--name-only', `${ref}:${ALIGNMENTS_DIR}`], cwd, { ignoreErrors: true });\n return out\n .split('\\n')\n .filter((name) => ALIGNMENT_ID.test(name))\n .sort();\n}\n\n/** One alignment at `ref`, or null when its README is not there. */\nexport async function readAlignment(cwd: string, ref: string, id: string): Promise<Alignment | null> {\n const source = await git(['show', `${ref}:${ALIGNMENTS_DIR}/${id}/README.md`], cwd, { ignoreErrors: true });\n if (!source) return null;\n const files = await git(['ls-tree', '--name-only', `${ref}:${ALIGNMENTS_DIR}/${id}`], cwd, { ignoreErrors: true });\n return parseAlignment(id, source, files.split('\\n').filter(Boolean));\n}\n\n/** Alignments upstream added between two commits: present at `to`, absent at `from`. */\nexport async function arrivedAlignmentIds(cwd: string, from: string, to: string): Promise<string[]> {\n const [before, after] = await Promise.all([listAlignmentIds(cwd, from), listAlignmentIds(cwd, to)]);\n const known = new Set(before);\n return after.filter((id) => !known.has(id));\n}\n\n/** The upstream commit at or before `ref` that added the alignment's README; null when git finds none. */\nexport async function readAlignmentSource(cwd: string, ref: string, id: string): Promise<AlignmentSource | null> {\n const out = await git(\n ['log', '-1', '--diff-filter=A', '--format=%H%x09%s', ref, '--', `${ALIGNMENTS_DIR}/${id}/README.md`],\n cwd,\n { ignoreErrors: true },\n );\n if (!out) return null;\n const [commit, subject = ''] = out.split('\\t');\n const { pr = null } = splitPrNumber(subject);\n\n const nulSeparated = (text: string) => text.split('\\0').filter(Boolean);\n const [changed, added] = await Promise.all([\n git(['diff-tree', '--root', '--no-commit-id', '--name-only', '--no-renames', '-r', '-z', commit], cwd),\n git(\n [\n 'diff-tree',\n '--root',\n '--no-commit-id',\n '--name-only',\n '--diff-filter=A',\n '-r',\n '-z',\n commit,\n '--',\n ALIGNMENTS_DIR,\n ],\n cwd,\n ),\n ]);\n const readmeId = new RegExp(`^${ALIGNMENTS_DIR}/([^/]+)/README\\\\.md$`);\n const sharedCommit = nulSeparated(added)\n .map((path) => readmeId.exec(path)?.[1])\n .filter((other): other is string => !!other && other !== id && ALIGNMENT_ID.test(other))\n .sort();\n\n return { commit, pr, sharedCommit, changedFiles: nulSeparated(changed) };\n}\n\n/**\n * Lines in the working tree where any of `terms` occurs as a whole word, limited to the files\n * `inFiles` accepts. Terms match as fixed strings; an empty list yields no hits.\n */\nexport async function grepAlignmentTerms(\n cwd: string,\n terms: string[],\n inFiles: (path: string) => boolean,\n): Promise<Array<{ file: string; line: number }>> {\n if (terms.length === 0) return [];\n const out = await git(['grep', '-n', '-I', '-w', '-F', '-z', ...terms.flatMap((term) => ['-e', term]), '--'], cwd, {\n ignoreErrors: true,\n });\n // With -z each match is `<path>\\0<line>\\0<text>`, one match per output line\n return out\n .split('\\n')\n .map((match) => match.split('\\0'))\n .filter(([file, line]) => file && line && inFiles(file))\n .map(([file, line]) => ({ file, line: Number(line) }));\n}\n\n/** The fork's pending alignment 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 an alignment's README at a commit, when upstream is on GitHub. */\nexport function alignmentUrl(upstreamGitHubUrl: string | undefined, commit: string, id: string): string | undefined {\n return upstreamGitHubUrl ? `${upstreamGitHubUrl}/blob/${commit}/${ALIGNMENTS_DIR}/${id}/README.md` : undefined;\n}\n\n/**\n * The info line `cella align` ends with, e.g. `alignments: 94 of 97 handled · 3 open: pnpm cella align`.\n * Analyze and sync list the alignments under their `next steps` instead.\n */\nexport function formatAlignmentsLine(total: number, open: number): string {\n const parts = [open === 0 ? `all ${total} handled` : `${Math.max(0, total - open)} of ${total} handled`];\n if (open > 0) parts.push(`${open} open: pnpm cella align`);\n return `alignments: ${parts.join(' · ')}`;\n}\n","/**\n * Align service: the upstream alignments this fork has not handled yet.\n *\n * Alignments live upstream only (see `utils/alignments`). 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 alignment also gets a GitHub permalink for readers\n * without the upstream remote. Nothing here blocks: the list is information to act on.\n *\n * Next to what the README says, each alignment shows what git can tell about it: the upstream\n * commit and PR that added it, the files of that commit the app owns or changed, and where app\n * code still uses the README's `grep` terms (see `describeAlignment`).\n *\n * `--run` runs an alignment's codemod from an extracted copy and puts back the files it changed\n * that were identical to upstream (see `runAlignment`).\n */\n\nimport { execFileSync, spawnSync } from 'node:child_process';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport process from 'node:process';\nimport type { RuntimeConfig } from '../config/types';\nimport {\n ALIGNMENTS_DIR,\n type Alignment,\n alignmentUrl,\n formatAlignmentsLine,\n grepAlignmentTerms,\n isUpstreamOnly,\n listAlignmentIds,\n readAlignment,\n readAlignmentSource,\n readPending,\n writePending,\n} from '../utils/alignments';\nimport pc from '../utils/colors';\nimport { DEFAULT_UPSTREAM_REMOTE } from '../utils/config';\nimport { checkMark, hyperlink, type NextStep, plural, 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 { isGeneratedFile, isManagedFile } from '../utils/managed-files';\nimport { readManifestBase } from '../utils/manifest';\nimport { isUnderAnyFolder } from '../utils/overrides';\nimport { getGitHubBaseUrl } from './merge-engine';\n\n/** Where `--extract` writes an alignment folder: inside the fork, so a codemod resolves the fork's packages. */\nconst EXTRACT_DIR = 'node_modules/.cache/cella/alignments';\n\n/** How many restored paths `--run` lists before it cuts the list short. */\nconst RESTORED_LIST_MAX = 20;\n\n/** How many paths or grep hits `--show` lists per block before it cuts the list short. */\nconst SHOW_LIST_MAX = 30;\n\n/** An alignment with what git tells about it, as `--json` writes it. */\ninterface DescribedAlignment extends Alignment {\n kind: 'codemod' | 'manual';\n open: boolean;\n url: string | null;\n /** The upstream commit that added the README, or null when git finds none. */\n commit: string | null;\n pr: number | null;\n prUrl: string | null;\n /** Ids of the other alignments that commit added. */\n sharedCommit: string[];\n /** Paths that commit changed which the app pins, ignores, or changed from upstream. */\n yourFiles: string[];\n /** Where app code uses a `grep` term: files that differ from upstream only. */\n grepHits: Array<{ file: string; line: number }>;\n}\n\n/** What the fork holds against the upstream commit it synced to, read once per run. */\ninterface ForkView {\n githubUrl: string | undefined;\n /** Whether the app pins or ignores a path (managed and generated files left out). */\n owns: (path: string) => boolean;\n /** Tracked paths whose working tree copy differs from the sync point, or that the sync point lacks. */\n changed: Set<string>;\n}\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 upgraded to, fetched if this clone lacks it; null before any upgrade. */\nasync function resolveAlignmentsRef(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 alignments at the fork's sync point, for a run without a merge result; null before any upgrade. */\nexport async function readOpenAlignments(config: RuntimeConfig): Promise<AlignmentsView | null> {\n try {\n const ref = await resolveAlignmentsRef(config);\n if (!ref) return null;\n return { ref, open: await readPending(config.forkPath) };\n } catch {\n return null;\n }\n}\n\n/** Alignments for the `align` step: the ref to read them at, and the ids by state. */\nexport interface AlignmentsView {\n ref: string;\n /** Open in the fork: listed by `pnpm cella align` */\n open: string[];\n /** Arriving with an upgrade a dry run previews: not open until the upgrade lands */\n arriving?: string[];\n /** Arrived with the upgrade this run made: open, and counted as such */\n arrived?: string[];\n}\n\n/** Alignment rows the `align` step lists before it points to `pnpm cella align`. */\nconst STEP_ROWS_MAX = 5;\n\n/** `manual · not breaking`, `codemod · breaking · caught by compiler`. */\nfunction alignmentTags(alignment: Alignment): string {\n return [\n alignment.codemod ? 'codemod' : 'manual',\n alignment.breaking ? 'breaking' : 'not breaking',\n alignment.caughtBy ? `caught by ${alignment.caughtBy}` : null,\n ]\n .filter(Boolean)\n .join(' · ');\n}\n\n/**\n * The `align` step that closes analyze and upgrade: the alignments arriving with the upgrade (in a dry\n * run) and the open ones, by title with their kind, then the command. Without a terminal each row\n * also gets its id, for `pnpm cella align --show <id>`. Undefined when there are none.\n */\nexport async function alignmentsStep(config: RuntimeConfig, view: AlignmentsView): Promise<NextStep | undefined> {\n const arriving = view.arriving ?? [];\n const open = view.open.filter((id) => !arriving.includes(id));\n const arrived = (view.arrived ?? []).filter((id) => open.includes(id));\n if (arriving.length === 0 && open.length === 0) return undefined;\n\n const line =\n arriving.length > 0\n ? `${plural(arriving.length, 'alignment')} ${arriving.length === 1 ? 'arrives' : 'arrive'} with this upgrade${open.length > 0 ? pc.dim(` · ${open.length} open`) : ''}`\n : `${plural(open.length, 'alignment')} open${arrived.length > 0 ? pc.dim(` · ${arrived.length} arrived with this upgrade`) : ''}`;\n\n const githubUrl = getGitHubBaseUrl(config.settings.upstreamUrl) ?? undefined;\n const ids = [...arriving, ...open];\n const details: string[] = [];\n for (const id of ids.slice(0, STEP_ROWS_MAX)) {\n const alignment = await readAlignment(config.forkPath, view.ref, id).catch(() => null);\n const title = hyperlink(alignment?.title ?? id, alignmentUrl(githubUrl, view.ref, id));\n details.push(`${pc.cyan('○')} ${title}${alignment ? pc.dim(` · ${alignmentTags(alignment)}`) : ''}`);\n if (!process.stdout.isTTY) details.push(pc.dim(` id ${id}`));\n }\n if (ids.length > STEP_ROWS_MAX) details.push(pc.dim(`+ ${ids.length - STEP_ROWS_MAX} more`));\n details.push(`${arriving.length > 0 ? pc.dim('after the upgrade: ') : ''}pnpm cella align`);\n return { label: 'align', line, details };\n}\n\n/** Read the fork's overrides and its differences from the sync point, for the derived fields. */\nasync function readForkView(config: RuntimeConfig, ref: string): Promise<ForkView> {\n const { pinned = [], ignored = [] } = config.overrides ?? {};\n const counts = (path: string) => !isManagedFile(path) && !isGeneratedFile(path) && !isUpstreamOnly(path);\n const out = await git(['diff', '--name-only', '--no-renames', '-z', ref, '--'], config.forkPath);\n return {\n githubUrl: getGitHubBaseUrl(config.settings.upstreamUrl) ?? undefined,\n owns: (path) => counts(path) && isUnderAnyFolder(path, [...pinned, ...ignored]),\n changed: new Set(out.split('\\0').filter((path) => path && counts(path))),\n };\n}\n\n/** An alignment plus its source commit, the app's files in it and the grep hits in app code. */\nasync function describeAlignment(\n config: RuntimeConfig,\n view: ForkView,\n ref: string,\n alignment: Alignment,\n open: boolean,\n): Promise<DescribedAlignment> {\n const { forkPath } = config;\n const [source, grepHits] = await Promise.all([\n readAlignmentSource(forkPath, ref, alignment.id),\n grepAlignmentTerms(forkPath, alignment.grep, (path) => view.changed.has(path)),\n ]);\n const pr = source?.pr ?? null;\n return {\n ...alignment,\n kind: alignment.codemod ? 'codemod' : 'manual',\n open,\n url: alignmentUrl(view.githubUrl, ref, alignment.id) ?? null,\n commit: source?.commit ?? null,\n pr,\n prUrl: pr !== null && view.githubUrl ? `${view.githubUrl}/pull/${pr}` : null,\n sharedCommit: source?.sharedCommit ?? [],\n yourFiles: (source?.changedFiles ?? []).filter((path) => view.owns(path) || view.changed.has(path)),\n grepHits,\n };\n}\n\n/** `grep: 3 hits in 2 app files`, `grep: no app hits`, or null for an alignment without grep terms. */\nfunction grepSummary(alignment: DescribedAlignment): string | null {\n if (alignment.grep.length === 0) return null;\n const hits = alignment.grepHits.length;\n if (hits === 0) return 'grep: no app hits';\n const files = new Set(alignment.grepHits.map((hit) => hit.file)).size;\n return `grep: ${hits} hit${hits === 1 ? '' : 's'} in ${files} app file${files === 1 ? '' : 's'}`;\n}\n\n/** Print one alignment in the human list. */\nfunction printAlignment(index: number, alignment: DescribedAlignment): void {\n const tags = [\n alignment.codemod ? 'codemod' : 'manual',\n alignment.breaking ? 'breaking' : null,\n alignment.clientCacheBump ? 'cache-bump' : null,\n alignment.caughtBy ? `caught by: ${alignment.caughtBy}` : null,\n alignment.generate ? 'generate' : null,\n ]\n .filter(Boolean)\n .join(', ');\n const grep = grepSummary(alignment);\n console.info(`${index}. ${alignment.title} ${pc.dim(`[${tags}]`)}`);\n console.info(pc.dim(` id: ${alignment.id}`));\n if (alignment.summary) console.info(` ${alignment.summary}`);\n if (alignment.pr !== null) {\n console.info(pc.dim(` added in #${alignment.pr}${alignment.prUrl ? ` ${alignment.prUrl}` : ''}`));\n }\n if (grep) console.info(pc.dim(` ${grep}`));\n console.info(pc.dim(` read: pnpm cella align --show ${alignment.id}`));\n if (alignment.url) console.info(pc.dim(` ${alignment.url}`));\n if (alignment.codemod) console.info(pc.dim(` codemod: pnpm cella align --run ${alignment.id}`));\n console.info();\n}\n\n/** Print a titled block of lines for `--show`, cut short after {@link SHOW_LIST_MAX}. */\nfunction printShowBlock(title: string, items: string[]): void {\n if (items.length === 0) return;\n console.info(pc.dim(`${title} (${items.length}):`));\n for (const item of items.slice(0, SHOW_LIST_MAX)) console.info(pc.dim(` ${item}`));\n if (items.length > SHOW_LIST_MAX) console.info(pc.dim(` ... + ${items.length - SHOW_LIST_MAX} more`));\n}\n\n/**\n * `--show <id>`: the README, then what git tells about it. Read at the sync point, or at the\n * fetched upstream branch when the sync point lacks it (an alignment read before its sync merges).\n */\nasync function showAlignment(config: RuntimeConfig, ref: string, pending: string[], id: string): Promise<void> {\n const { forkPath } = config;\n const upstreamBranch = `${DEFAULT_UPSTREAM_REMOTE}/${config.settings.upstreamBranch}`;\n let readRef = ref;\n let alignment = await readAlignment(forkPath, ref, id);\n if (!alignment && (await revParse(forkPath, upstreamBranch))) {\n alignment = await readAlignment(forkPath, upstreamBranch, id);\n readRef = upstreamBranch;\n }\n if (!alignment) throw new Error(`no alignment '${id}' at upstream ${ref.slice(0, 7)} or ${upstreamBranch}`);\n\n const source = await git(['show', `${readRef}:${ALIGNMENTS_DIR}/${id}/README.md`], forkPath);\n const described = await describeAlignment(\n config,\n await readForkView(config, ref),\n readRef,\n alignment,\n pending.includes(id),\n );\n\n if (readRef !== ref) console.info(pc.dim(`not at the last upgrade ${ref.slice(0, 7)}: read at ${upstreamBranch}`));\n if (described.url) console.info(pc.dim(described.url));\n console.info(source);\n console.info();\n if (described.commit) {\n const pr = described.pr !== null ? `#${described.pr} ` : '';\n console.info(\n pc.dim(`added in ${pr}(${described.commit.slice(0, 9)})${described.prUrl ? ` ${described.prUrl}` : ''}`),\n );\n }\n printShowBlock('added in the same commit', described.sharedCommit);\n printShowBlock('files of that commit the app pins, ignores or changed', described.yourFiles);\n const grep = grepSummary(described);\n if (grep) console.info(pc.dim(`${grep} (${described.grep.join(', ')})`));\n printShowBlock(\n 'grep hits',\n described.grepHits.map((hit) => `${hit.file}:${hit.line}`),\n );\n}\n\n/**\n * Write an alignment's folder under {@link EXTRACT_DIR}, byte for byte. Returns the alignment, the\n * folder (relative to the fork) and its files.\n */\nasync function writeAlignmentFolder(\n config: RuntimeConfig,\n ref: string,\n id: string,\n): Promise<{ alignment: Alignment; target: string; files: string[] }> {\n const { forkPath } = config;\n const alignment = await readAlignment(forkPath, ref, id);\n if (!alignment) throw new Error(`no alignment '${id}' at upstream ${ref.slice(0, 7)}`);\n\n const files = (await git(['ls-tree', '-r', '--name-only', `${ref}:${ALIGNMENTS_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}:${ALIGNMENTS_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 { alignment, target, files };\n}\n\n/** `--extract <id>`: write the alignment folder under {@link EXTRACT_DIR} and print how to run its codemod. */\nasync function extractAlignment(config: RuntimeConfig, ref: string, id: string): Promise<void> {\n const { alignment, target, files } = await writeAlignmentFolder(config, ref, id);\n\n console.info(`${checkMark} extracted ${files.length} file(s) to ${target}/`);\n console.info(pc.dim(` the README's ${ALIGNMENTS_DIR}/${id}/ paths are this folder.`));\n if (alignment.codemod) {\n console.info(pc.dim(` pnpm exec tsx ${target}/${alignment.codemod} inventory ${alignment.roots.join(' ')}`));\n console.info(pc.dim(` or, keeping files identical to upstream as they are: pnpm cella align --run ${id}`));\n }\n}\n\n/**\n * `--run <id>`: run the alignment's codemod with `tsx` from the fork root, then give each file that\n * was identical to the manifest's upstream commit before the run, and changed by it, its upstream\n * content back.\n */\nasync function runAlignment(config: RuntimeConfig, ref: string, id: string): Promise<void> {\n const { forkPath } = config;\n const { alignment, target } = await writeAlignmentFolder(config, ref, id);\n if (!alignment.codemod) {\n throw new Error(\n `alignment '${id}' ships no codemod script: its steps are manual, read them with \\`pnpm cella align --show ${id}\\`.`,\n );\n }\n const script = join(target, alignment.codemod);\n const args = config.runArgs?.length ? config.runArgs : ['inventory', ...alignment.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', ...alignment.roots].join(' ');\n console.info(pc.dim(`report only. to apply: pnpm cella align --run ${id} -- ${apply}`));\n }\n}\n\n/** `--mark <ids…>`: drop handled alignments from the pending list. */\nasync function markAlignments(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} alignment(s) as handled`);\n if (unknown.length > 0) console.info(pc.dim(`not pending, left as is: ${unknown.join(', ')}`));\n console.info(pc.dim(formatAlignmentsLine((await listAlignmentIds(config.forkPath, ref)).length, open.size)));\n}\n\n/** Run the align service. */\nexport async function runAlign(config: RuntimeConfig): Promise<void> {\n const { forkPath } = config;\n const ref = await resolveAlignmentsRef(config);\n if (!ref) {\n console.info(pc.dim('no upgrade recorded yet: alignments start with the first `pnpm cella upgrade`.'));\n return;\n }\n\n const pending = await readPending(forkPath);\n\n if (config.mark?.length) return markAlignments(config, ref, pending, config.mark);\n if (config.run) return runAlignment(config, ref, config.run);\n if (config.extract) return extractAlignment(config, ref, config.extract);\n if (config.show) return showAlignment(config, ref, pending, config.show);\n\n const ids = config.all ? await listAlignmentIds(forkPath, ref) : pending;\n const read = await Promise.all(ids.map((id) => readAlignment(forkPath, ref, id)));\n const alignments: Alignment[] = read.map(\n (alignment, i) =>\n alignment ?? {\n id: ids[i],\n title: `${ids[i]} (no longer upstream)`,\n summary: '',\n breaking: false,\n clientCacheBump: false,\n caughtBy: null,\n generate: false,\n grep: [],\n roots: [],\n codemod: null,\n },\n );\n const total = (await listAlignmentIds(forkPath, ref)).length;\n const open = new Set(pending);\n const view = await readForkView(config, ref);\n const described = await Promise.all(\n alignments.map((alignment) => describeAlignment(config, view, ref, alignment, open.has(alignment.id))),\n );\n\n if (config.json) {\n writeStdout(JSON.stringify({ upstreamCommit: ref, total, open: pending.length, alignments: described }, null, 2));\n return;\n }\n\n console.info(pc.dim(formatAlignmentsLine(total, pending.length)));\n if (described.length === 0) return;\n console.info();\n for (const [i, alignment] of described.entries()) printAlignment(i + 1, alignment);\n\n const schema = described.filter((alignment) => alignment.open && alignment.generate);\n if (schema.length > 1) {\n console.info(\n pc.dim(\n `${schema.length} open alignments change the schema: work their code steps first, then run pnpm generate once.`,\n ),\n );\n }\n if (pending.length > 0) {\n console.info(pc.dim(\"work each alignment's README, check with `pnpm check`, then record it:\"));\n console.info(pc.dim(` pnpm cella align --mark ${pending.join(' ')}`));\n }\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 {\n arrivedAlignmentIds,\n listAlignmentIds,\n PENDING_FILE,\n readPending,\n UPSTREAM_ONLY_DIRS,\n writePending,\n} from '../utils/alignments';\nimport { cliVersionMismatch, readUpstreamCliRange } from '../utils/cli-version';\nimport pc from '../utils/colors';\nimport { DEFAULT_UPSTREAM_REMOTE, resolveUpstream } from '../utils/config';\nimport {\n COMMIT_STEP_MAX,\n createSpinner,\n formatCheckoutStep,\n formatMergeInProgressDetail,\n formatUpstreamStep,\n plural,\n printStep,\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 { groupIgnoredUpstreamChanges, 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 upgrade` 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 CLI 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 CLI 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/** The fork's GitHub base URL from its `origin` remote; undefined without one on GitHub. */\nexport async function readOriginGitHubUrl(forkPath: string): Promise<string | undefined> {\n const origin = await git(['remote', 'get-url', 'origin'], forkPath, { ignoreErrors: true });\n return getGitHubBaseUrl(origin.trim()) ?? undefined;\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 /** Upstream commits since the last sync */\n commitCount: number;\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 'Upgrade 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?.('checkout', formatCheckoutStep({ forkPath, branch, headSha, changeCount, upstream: 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\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 upgrade until a release past ${syncShort}; to follow the tip instead, run with --track branch.`\n : `Nothing to upgrade until '${branchRef}' moves past ${syncShort}.`;\n throw new BehindSyncPointError(\n `upstream ${upstreamLabel} (${upstreamShort}) is behind the last upgrade at ${syncShort}: the fork already ` +\n `has it, and merging 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_STEP_MAX) : [];\n\n const [upstreamShort, baseShort] = await Promise.all([\n getShortSha(forkPath, upstreamCommit.hash),\n getShortSha(forkPath, mergeBase),\n ]);\n onStep?.(\n 'upstream',\n formatUpstreamStep({\n label: releaseTag ?? branchRef.replace(`${remoteName}/`, ''),\n sha: upstreamShort,\n baseSha: baseShort,\n pinned: !!config.ref,\n commitCount,\n commits: upstreamCommits,\n githubUrl: upstreamGitHubUrl,\n }),\n );\n\n return { upstreamRef, releaseTag, mergeBase, mergeRef, upstreamGitHubUrl, upstreamCommit, commitCount };\n}\n\n/**\n * Stop a new merge when upstream changed its CLI 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 upstreamCommitCount: ctx.commitCount,\n };\n}\n\n/**\n * Upstream changes the fork never receives, shared by both engine modes: the upstream config's\n * `overrides` entries and `packageJsonKeys` the fork config does not follow (the config itself\n * never merges), ignored files only upstream changed, and the range the review page diffs upstream's\n * changes over. Report only, read from refs (the merge state is irrelevant); a failure here yields\n * no report and never fails the run.\n */\nasync function upstreamOnlyReports(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n files: AnalyzedFile[],\n): Promise<Pick<MergeResult, 'upstreamDiffRange' | 'upstreamOverrides' | 'ignoredUpstreamChanges'>> {\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 };\n } catch {\n return {};\n }\n}\n\n/** Upstream alignments for this sync range, and the fork's pending list before the arrivals are added. */\ninterface AlignmentsInRange {\n total: number;\n arrived: string[];\n pending: string[];\n}\n\n/** The fork's pending list once a sync records the arrivals. */\nfunction pendingAfterSync(alignments: AlignmentsInRange): string[] {\n return [...new Set([...alignments.pending, ...alignments.arrived])];\n}\n\n/**\n * Read the alignments for this sync range: upstream's alignments at the incoming ref and the ones\n * added since the recorded sync point. Runs before the sync point moves. A failure yields no\n * alignments and never fails the run.\n */\nasync function readAlignmentsInRange(\n config: RuntimeConfig,\n ctx: UpstreamContext,\n): Promise<AlignmentsInRange | undefined> {\n const { forkPath } = config;\n try {\n const [total, arrived, pending] = await Promise.all([\n listAlignmentIds(forkPath, ctx.upstreamRef),\n arrivedAlignmentIds(forkPath, ctx.mergeBase, ctx.upstreamRef),\n readPending(forkPath),\n ]);\n return { total: total.length, arrived, pending };\n } catch {\n return undefined;\n }\n}\n\n/**\n * The {@link MergeResult} view of {@link AlignmentsInRange}. A sync records the arrivals as open; a\n * dry run leaves them arriving, since `pnpm cella align` only lists them once the sync lands.\n */\nfunction alignmentsResult(\n alignments: AlignmentsInRange | undefined,\n options: { dryRun: boolean },\n): Pick<MergeResult, 'alignments'> {\n if (!alignments) return {};\n const open = options.dryRun ? alignments.pending : pendingAfterSync(alignments);\n return { alignments: { total: alignments.total, arrived: alignments.arrived, open } };\n}\n\n/**\n * Remove the fork's copy of an upstream-only 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 for (const dir of UPSTREAM_ONLY_DIRS) {\n if (!existsSync(join(forkPath, dir))) continue;\n await git(['rm', '-r', '-q', '--ignore-unmatch', '--', dir], forkPath);\n await rm(join(forkPath, dir), { recursive: true, force: true });\n onStep?.('alignments', `removed ${dir}/: alignments stay upstream, list them with pnpm cella align`);\n }\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 alignments = await readAlignmentsInRange(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-upgrade` ref plus the manifest,\n // staged so it rides in the upgrade 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 upgradedAt: 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 // Alignments that arrived join the fork's pending list; an empty list deletes the file.\n if (alignments) {\n await writePending(forkPath, pendingAfterSync(alignments));\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?.('merged', formatMergeInProgressDetail(remainingConflicts.length, autoMergedFiles, { forkPath }, 100));\n } else if (totalResolved > 0) {\n const label = synced > 0 ? `${synced} files from upstream` : 'upstream changes';\n await recordSyncPoint();\n onStep?.('upgraded', `${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 merge');\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)),\n ...alignmentsResult(alignments, { dryRun: false }),\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 alignments = await readAlignmentsInRange(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);\n onStep?.('analyzed', `${plural(analyzedFiles.length, 'file')}${pc.dim(' · dry run, nothing changed')}`);\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 ...alignmentsResult(alignments, { dryRun: true }),\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 printStep(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 * An upgrade bumps the fork's `@cellajs/cli` along with its other packages, so each upgrade runs on the\n * CLI from before it. A fix to analyze or upgrade would reach a fork one upgrade 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 upgrade itself.`,\n ` update it, commit, then rerun: pnpm add -D -w '${CLI_PACKAGE}@${range}'`,\n ].join('\\n');\n}\n","/**\n * Upstream override changes: the upgrade never merges the fork's config, so this reads upstream's\n * `overrides` lists and `packageJsonKeys` 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_KEYS } 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 CLI config, as plain string entries. */\ninterface OverrideLists {\n pinned: string[];\n ignored: string[];\n /** `settings.packageJsonKeys`, the default when the config names none; null when it cannot be read statically. */\n packageJsonKeys: 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.packageJsonKeys` of a config object, or its 0.5 name `packageJsonSync` at an older commit:\n * the default keys when `settings` or the list is absent, null when either is present without a\n * statically readable value.\n */\nfunction readPackageJsonKeys(config: ObjectLiteralExpression, sourceFile: SourceFile): string[] | null {\n const settings = readProperty(config, 'settings', sourceFile);\n if (settings === undefined) return [...DEFAULT_PACKAGE_JSON_KEYS];\n if (!settings || !Node.isObjectLiteralExpression(settings)) return null;\n const current = readProperty(settings, 'packageJsonKeys', sourceFile);\n const keys = current === undefined ? readProperty(settings, 'packageJsonSync', sourceFile) : current;\n if (keys === undefined) return [...DEFAULT_PACKAGE_JSON_KEYS];\n return keys ? readStringEntries(keys) : null;\n}\n\n/**\n * Extract `overrides.pinned`, `overrides.ignored` and `settings.packageJsonKeys` 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; unreadable `packageJsonKeys` alone read 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 packageJsonKeys: readPackageJsonKeys(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 * `packageJsonKeys` 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] | 'packageJsonKeys', 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.packageJsonKeys, incoming.packageJsonKeys, fork.packageJsonKeys];\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'), packageJsonKeys: diffKeys() };\n}\n\n/**\n * Report how upstream's `overrides` and `packageJsonKeys` 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 packageJsonKeys: forkConfig.settings.packageJsonKeys ?? DEFAULT_PACKAGE_JSON_KEYS,\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 incoming changes the sync leaves out: one numstat call limited to the flagged paths.\n const flagged = analyzedFiles.filter(\n (file) => (file.upstreamChanged && !renamedProtected.has(file.path)) || file.upstreamOnly,\n );\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 || file.upstreamOnly) {\n // Diverged/pinned (and protected files incoming 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 * The file sections of the analyze report, in the order they need you: files that sync on their\n * own first, the upstream changes the sync leaves out last. Each file is a row with its path, a\n * count and an age in columns. Large groups collapse unless `--all` asks for every path.\n */\n\nimport { basename } from 'node:path';\nimport type { AnalyzedFile, MergeResult } from '../config/types';\nimport pc from '../utils/colors';\nimport {\n filesWithStatus,\n findProtectedBehindUpstream,\n hyperlink,\n type LinkOptions,\n plural,\n printSectionHeader,\n protectionIcon,\n warningMark,\n} from '../utils/display';\nimport { compactCount, padVisible, shortAge, terminalColumns, visibleWidth } from '../utils/layout';\nimport { isUnderAnyFolder, normalizeEntry } from '../utils/overrides';\n\n/** Behind files listed one per row up to this count; more collapse to one row per folder. */\nconst BEHIND_FLAT_MAX = 15;\n\n/** Pinned files listed in full up to this count; more list only the ones missing many upstream lines. */\nconst AHEAD_FLAT_MAX = 8;\n\n/** Upstream lines a pinned file must miss to keep its own row once the section is cut short. */\nconst ABSENT_SHOWN_MIN = 10;\n\n/** Rows of one kind under one override entry that collapse to a single row. */\nconst ENTRY_COLLAPSE_MIN = 5;\n\n/** Rows a section prints at most. */\nconst SECTION_ROWS_MAX = 100;\n\nexport interface AnalyzeReportOptions {\n links: LinkOptions;\n /** List every path instead of collapsing large groups (`--all`). */\n all?: boolean;\n /** The fork config's override entries: protected files collapse by the entry that holds them. */\n overrides?: { ignored?: string[]; pinned?: string[] };\n columns?: number;\n nowMs?: number;\n}\n\n/** One row of a section: a path or a collapsed group's label, with optional icon, count, tag and age. */\ninterface Row {\n label: string;\n /** Dim text after the label, inside the label column */\n note?: string;\n link?: string;\n icon?: string;\n count?: string;\n countColor?: (text: string) => string;\n tag?: string;\n tagColor?: (text: string) => string;\n age?: string;\n}\n\n/** Which change a section dates and links: the `changed*` or `upstream*` fields, and whose repo holds the commit. */\ninterface Side {\n fields: 'changed' | 'upstream';\n repo: 'upstream' | 'fork';\n}\n\nconst UPSTREAM_CHANGE: Side = { fields: 'changed', repo: 'upstream' };\nconst UPSTREAM_SIDE: Side = { fields: 'upstream', repo: 'upstream' };\nconst FORK_SIDE: Side = { fields: 'changed', repo: 'fork' };\n\n/** `value` padded to `width`, colored when it is not empty; plain spaces otherwise, so lines trim. */\nfunction cell(value: string | undefined, width: number, color?: (text: string) => string, align?: 'end'): string {\n if (!value) return ' '.repeat(width);\n return padVisible(color ? color(value) : value, width, align === 'end' ? 'end' : 'start');\n}\n\n/** Rows as aligned lines: label column as wide as the longest label, then count, tag and age columns. */\nfunction formatRows(rows: Row[], caption?: string): string[] {\n const iconWidth = rows.some((row) => row.icon) ? 2 : 0;\n const labelWidth = Math.max(...rows.map((row) => row.label.length + (row.note ? row.note.length + 1 : 0)));\n const countWidth = Math.max(0, ...rows.map((row) => row.count?.length ?? 0));\n const tagWidth = Math.max(0, ...rows.map((row) => row.tag?.length ?? 0));\n const ageWidth = Math.max(0, ...rows.map((row) => row.age?.length ?? 0));\n\n const lines: string[] = [];\n if (caption && countWidth > 0) lines.push(pc.dim(caption.padStart(2 + iconWidth + labelWidth + 2 + countWidth)));\n for (const row of rows) {\n const icon = iconWidth ? cell(row.icon, iconWidth) : '';\n const label = `${hyperlink(row.label, row.link)}${row.note ? ` ${pc.dim(row.note)}` : ''}`;\n const cells = [` ${icon}${padVisible(label, labelWidth)}`];\n if (countWidth) cells.push(cell(row.count, countWidth, row.countColor, 'end'));\n if (tagWidth) cells.push(cell(row.tag, tagWidth, row.tagColor));\n if (ageWidth) cells.push(cell(row.age, ageWidth, pc.dim, 'end'));\n lines.push(cells.join(' ').trimEnd());\n }\n return lines;\n}\n\n/** Rows as lines, cut at {@link SECTION_ROWS_MAX} with a count of the rest. */\nfunction formatCappedRows(rows: Row[], caption?: string): string[] {\n if (rows.length <= SECTION_ROWS_MAX) return formatRows(rows, caption);\n return [\n ...formatRows(rows.slice(0, SECTION_ROWS_MAX), caption),\n pc.dim(` + ${rows.length - SECTION_ROWS_MAX} more`),\n ];\n}\n\n/** A dim hint line, with a command in the plain color so it stands out. */\nfunction hint(text: string, command = ''): string {\n return ` ${pc.dim(text)}${command}`;\n}\n\nfunction printSection(title: string, count: number, body: string[], hints: string[] = []): void {\n printSectionHeader(`${title} ${pc.dim(`· ${plural(count, 'file')}`)}`);\n for (const line of body) console.info(line);\n if (hints.length === 0) return;\n console.info();\n for (const line of hints) console.info(line);\n}\n\nfunction byPath(a: AnalyzedFile, b: AnalyzedFile): number {\n return a.path.localeCompare(b.path);\n}\n\n/**\n * Where a row links, per `fileLinkMode`: the file as it is at the analyzed upstream commit, or the\n * commit that last changed it, in the repo that holds that commit (a fork commit 404s upstream).\n */\nfunction fileLink(file: AnalyzedFile, side: Side, links: LinkOptions): string | undefined {\n const { fileLinkMode = 'commit', upstreamGitHubUrl, upstreamSha, forkGitHubUrl } = links;\n if (fileLinkMode === 'file') {\n if (!upstreamGitHubUrl || !upstreamSha || !file.existsInUpstream) return undefined;\n return `${upstreamGitHubUrl}/blob/${upstreamSha}/${file.path}`;\n }\n const commit = side.fields === 'upstream' ? file.upstreamCommit : file.changedCommit;\n const repo = side.repo === 'upstream' ? upstreamGitHubUrl : forkGitHubUrl;\n return commit && repo ? `${repo}/commit/${commit}` : undefined;\n}\n\nfunction changeTimestamp(file: AnalyzedFile, side: Side): number | undefined {\n return side.fields === 'upstream' ? file.upstreamChangedTs : file.changedTs;\n}\n\n/** A file added or deleted upstream: `new` (the fork lacks it) or `deleted` (upstream lacks it). */\nfunction changeKind(file: AnalyzedFile): 'new' | 'deleted' | 'changed' {\n if (!file.existsInFork) return 'new';\n if (!file.existsInUpstream) return 'deleted';\n return 'changed';\n}\n\nconst KIND_TAG = { new: { tag: 'new', color: pc.green }, deleted: { tag: 'deleted', color: pc.red } } as const;\n\nfunction fileRow(file: AnalyzedFile, side: Side, options: AnalyzeReportOptions, extra: Partial<Row> = {}): Row {\n const timestamp = changeTimestamp(file, side);\n const kind = changeKind(file);\n return {\n label: file.path,\n link: fileLink(file, side, options.links),\n age: timestamp ? shortAge(timestamp, options.nowMs) : undefined,\n ...(kind === 'changed' ? {} : { tag: KIND_TAG[kind].tag, tagColor: KIND_TAG[kind].color }),\n ...extra,\n };\n}\n\n/** The deepest folder every path shares, '' when they share none. */\nfunction commonFolder(paths: string[]): string {\n const folders = paths.map((path) => path.split('/').slice(0, -1));\n const [first] = folders;\n let depth = 0;\n while (depth < first.length && folders.every((parts) => parts[depth] === first[depth])) depth++;\n return first.slice(0, depth).join('/');\n}\n\n/**\n * Behind files as one row per top-level folder: the deepest folder the group shares, its count,\n * and as many file names as fit, added (`+`) and deleted (`−`) first. A file alone in its group\n * keeps its whole path.\n */\nfunction formatFolderRows(files: AnalyzedFile[], columns: number): string[] {\n const groups = new Map<string, AnalyzedFile[]>();\n for (const file of files) {\n const top = file.path.includes('/') ? file.path.split('/')[0] : file.path;\n groups.set(top, [...(groups.get(top) ?? []), file]);\n }\n const rows = [...groups.values()]\n .map((group) => ({\n label: group.length === 1 ? group[0].path : `${commonFolder(group.map((file) => file.path))}/`,\n files: group,\n }))\n .sort((a, b) => b.files.length - a.files.length || a.label.localeCompare(b.label));\n\n const labelWidth = Math.max(...rows.map((row) => row.label.length));\n const countWidth = Math.max(...rows.map((row) => String(row.files.length).length));\n const order = { new: 0, deleted: 1, changed: 2 };\n return rows.map((row) => {\n let line = ` ${row.label.padEnd(labelWidth)} ${pc.cyan(String(row.files.length).padStart(countWidth))}`;\n if (row.files.length === 1) return line.trimEnd();\n // A name two files share (`SKILL.md`) is shown with its path inside the folder.\n const seen = new Map<string, number>();\n for (const file of row.files) seen.set(basename(file.path), (seen.get(basename(file.path)) ?? 0) + 1);\n const names = row.files\n .map((file) => ({\n kind: changeKind(file),\n name: (seen.get(basename(file.path)) ?? 0) > 1 ? file.path.slice(row.label.length) : basename(file.path),\n }))\n .sort((a, b) => order[a.kind] - order[b.kind] || a.name.localeCompare(b.name));\n let width = visibleWidth(line);\n for (const { kind, name } of names) {\n const text = kind === 'new' ? `+${name}` : kind === 'deleted' ? `−${name}` : name;\n if (width + 2 + text.length > columns - 2) {\n line += pc.dim(' …');\n break;\n }\n line += ` ${kind === 'new' ? pc.green(text) : kind === 'deleted' ? pc.red(text) : pc.dim(text)}`;\n width += 2 + text.length;\n }\n return line;\n });\n}\n\nfunction printBehind(files: AnalyzedFile[], options: AnalyzeReportOptions, columns: number): void {\n const behind = filesWithStatus(files, 'behind').sort(byPath);\n if (behind.length === 0) return;\n const title = pc.cyan('↓ behind on upstream');\n if (options.all || behind.length <= BEHIND_FLAT_MAX) {\n printSection(title, behind.length, formatCappedRows(behind.map((file) => fileRow(file, UPSTREAM_CHANGE, options))));\n return;\n }\n printSection(title, behind.length, formatFolderRows(behind, columns), [\n hint('every path: ', 'pnpm cella analyze --all'),\n ]);\n}\n\nfunction printFlat(files: AnalyzedFile[], title: string, side: Side, options: AnalyzeReportOptions): void {\n if (files.length === 0) return;\n const rows = [...files].sort(byPath).map((file) => fileRow(file, side, options));\n printSection(title, files.length, formatCappedRows(rows));\n}\n\nfunction absentLines(file: AnalyzedFile): number {\n return file.upstreamLinesAbsent ?? 0;\n}\n\n/** `11 with 1–2 lines absent, 1 with none` for the pinned files a cut-short section leaves out. */\nfunction describeAbsent(files: AnalyzedFile[]): string {\n const counts = files.map(absentLines);\n const missing = counts.filter((count) => count > 0);\n const parts: string[] = [];\n if (missing.length > 0) {\n const [low, high] = [Math.min(...missing), Math.max(...missing)];\n parts.push(`${missing.length} with ${low === high ? plural(low, 'line') : `${low}–${high} lines`} absent`);\n }\n if (missing.length < counts.length) parts.push(`${counts.length - missing.length} with none`);\n return parts.join(', ');\n}\n\n/**\n * Pinned files the fork changed. A count is upstream content the fork does not have, dropped by\n * an earlier sync or removed on purpose. A long list keeps the files missing the most.\n */\nfunction printAhead(files: AnalyzedFile[], options: AnalyzeReportOptions): void {\n const ahead = filesWithStatus(files, 'ahead').sort((a, b) => absentLines(b) - absentLines(a) || byPath(a, b));\n if (ahead.length === 0) return;\n\n let shown = ahead;\n if (!options.all && ahead.length > AHEAD_FLAT_MAX) {\n const many = ahead.filter((file) => absentLines(file) >= ABSENT_SHOWN_MIN);\n shown = many.length > 0 ? many : ahead.slice(0, 5);\n }\n const rest = ahead.slice(shown.length);\n const rows = shown.map((file) =>\n fileRow(file, FORK_SIDE, options, {\n count: absentLines(file) > 0 ? String(absentLines(file)) : undefined,\n countColor: pc.yellow,\n }),\n );\n const body = formatCappedRows(rows, 'upstream lines absent');\n if (rest.length > 0) body.push(pc.dim(` + ${rest.length} more: ${describeAbsent(rest)}`));\n const hints = ahead.some((file) => absentLines(file) > 0)\n ? [hint('what a merge would bring in: ', 'pnpm cella analyze --unpinned')]\n : [];\n printSection(pc.blue('↑ protected in fork'), ahead.length, body, hints);\n}\n\n/** A protected file upstream changed, with the override entry that protects it. */\ninterface ProtectedItem {\n file: AnalyzedFile;\n kind: 'new' | 'deleted' | 'changed';\n entry?: string;\n}\n\n/** The most specific `ignored` or `pinned` entry holding a path. */\nfunction entryFinder(overrides: AnalyzeReportOptions['overrides']): (path: string) => string | undefined {\n const entries = [...(overrides?.ignored ?? []), ...(overrides?.pinned ?? [])]\n .map(normalizeEntry)\n .filter(Boolean)\n .sort((a, b) => b.length - a.length);\n return (path) => entries.find((entry) => isUnderAnyFolder(path, [entry]));\n}\n\nconst KIND_ORDER = { new: 0, changed: 1, deleted: 2 };\n\nfunction protectedRow(items: ProtectedItem[], options: AnalyzeReportOptions): Row {\n const [{ file, kind, entry }] = items;\n const lines = items.map((item) => item.file.upstreamChangedLines);\n const total = lines.every((count) => count !== undefined)\n ? lines.reduce<number>((sum, count) => sum + (count ?? 0), 0)\n : undefined;\n const sign = kind === 'new' ? '+' : kind === 'deleted' ? '−' : '';\n const newest = Math.max(0, ...items.map((item) => changeTimestamp(item.file, UPSTREAM_SIDE) ?? 0));\n const row: Row = {\n label: file.path,\n link: fileLink(file, UPSTREAM_SIDE, options.links),\n icon: protectionIcon(file),\n count: total === undefined ? undefined : `${sign}${compactCount(total)}`,\n countColor: kind === 'new' ? pc.green : kind === 'deleted' ? pc.red : pc.yellow,\n ...(kind === 'changed' ? {} : { tag: KIND_TAG[kind].tag, tagColor: KIND_TAG[kind].color }),\n age: newest ? shortAge(newest, options.nowMs) : undefined,\n };\n if (items.length === 1 || !entry) return row;\n\n const names = new Set(items.map((item) => basename(item.file.path)));\n const { upstreamGitHubUrl, upstreamSha } = options.links;\n return {\n ...row,\n label: `${entry}/`,\n note: names.size === 1 ? `· ${items.length} × ${[...names][0]}` : `· ${items.length} files`,\n link: upstreamGitHubUrl && upstreamSha ? `${upstreamGitHubUrl}/tree/${upstreamSha}/${entry}` : undefined,\n };\n}\n\n/**\n * Protected files upstream changed since the last sync, which the sync leaves as the fork has\n * them: pinned or ignored files both sides changed, and ignored files only upstream changed,\n * added or deleted. New files first, then by the lines upstream changed. Five or more of one kind\n * under one override entry collapse to a row for the entry.\n */\nfunction printProtectedBehind(result: MergeResult, options: AnalyzeReportOptions): void {\n const findEntry = entryFinder(options.overrides);\n // Both sides changed reads as a change even where the fork deleted its copy; only upstream's own\n // additions and deletions get a tag.\n const items: ProtectedItem[] = findProtectedBehindUpstream(result).map((file) => ({\n file,\n kind: file.upstreamOnly ? changeKind(file) : 'changed',\n entry: findEntry(file.path),\n }));\n if (items.length === 0) return;\n\n const groups = new Map<string, ProtectedItem[]>();\n for (const item of items) {\n const key = options.all || !item.entry ? item.file.path : `${item.kind}\\0${item.entry}`;\n groups.set(key, [...(groups.get(key) ?? []), item]);\n }\n const single = (group: ProtectedItem[]) => group.length < ENTRY_COLLAPSE_MIN;\n const lines = (group: ProtectedItem[]) => group.reduce((sum, item) => sum + (item.file.upstreamChangedLines ?? 0), 0);\n const ordered = [...groups.values()]\n .flatMap((group) => (single(group) ? group.map((item) => [item]) : [group]))\n .sort(\n (a, b) =>\n Number(a.length > 1) - Number(b.length > 1) ||\n KIND_ORDER[a[0].kind] - KIND_ORDER[b[0].kind] ||\n lines(b) - lines(a) ||\n byPath(a[0].file, b[0].file),\n );\n\n printSection(\n `${warningMark} ${pc.yellow('protected but behind upstream')}`,\n items.length,\n formatCappedRows(\n ordered.map((group) => protectedRow(group, options)),\n 'lines changed upstream',\n ),\n [hint('the fork side wins: adopt what you need from the review page')],\n );\n}\n\n/**\n * Print the analyze file sections: behind, diverged, protected in fork, drifted, and protected but\n * behind upstream. Every `pinned`-status file is a protected-but-behind one, so there is no\n * separate `pinned` section.\n */\nexport function printAnalysisFileGroups(result: MergeResult, options: AnalyzeReportOptions): void {\n const columns = options.columns ?? terminalColumns();\n printBehind(result.files, options, columns);\n printFlat(filesWithStatus(result.files, 'diverged'), pc.magenta('⇅ diverged'), UPSTREAM_SIDE, options);\n printAhead(result.files, options);\n printFlat(\n filesWithStatus(result.files, 'drifted'),\n `${warningMark} ${pc.yellow('drifted from upstream')}`,\n FORK_SIDE,\n options,\n );\n printProtectedBehind(result, options);\n}\n","/**\n * Review page: one browser page per analyze or upgrade run, holding the diff of every file the run\n * asks you to review, under the same sections the terminal prints.\n */\n\nimport { existsSync, rmSync } from 'node:fs';\nimport { basename } from 'node:path';\nimport process from 'node:process';\nimport { pathToFileURL } from 'node:url';\nimport type { MergeResult } from '../config/types';\nimport pc from '../utils/colors';\nimport { type DiffPageSection, diffPagePath, gitDiffFile, openInBrowser, writeDiffPage } from '../utils/diff';\nimport {\n createSpinner,\n filesWithStatus,\n findMaskingPins,\n findProtectedBehindUpstream,\n hyperlink,\n type NextStep,\n plural,\n spinnerSuccess,\n} from '../utils/display';\n\n/**\n * What one page renders at most; the rest is listed by path. A rendered patch line costs about\n * 0.6 KB of page, so the line budget keeps a page near 9 MB: 42 drizzle snapshot diffs once made\n * a 164 MB page that browsers could not open.\n */\nexport interface ReviewPageLimits {\n /** Diffs on the page, each ~60 ms to render */\n files: number;\n /** Patch lines across the page */\n lines: number;\n /** Patch lines of one file: a larger patch would take a large share of the page */\n patchLines: number;\n}\n\nconst PAGE_LIMITS: ReviewPageLimits = { files: 50, lines: 15_000, patchLines: 2_000 };\n\n/** Larger patches are listed without counting their lines: highlighting them stalls the run. */\nconst MAX_PATCH_BYTES = 512 * 1024;\n\n/** What {@link writeReviewPage} wrote: the page, its diffs, and the files it lists without one. */\nexport interface ReviewPage {\n path: string;\n diffs: number;\n listed: number;\n sections: number;\n}\n\n/** The files of one terminal list, and the `from..to` refs their diffs run over. */\nexport interface ReviewSection {\n title: string;\n /** What the diffs show and why the files are listed */\n hint: string;\n range: string;\n paths: string[];\n}\n\n/**\n * The review page's sections for a run, from the same lists the terminal prints. Upgrade shows the\n * upstream changes it did not bring in; analyze adds pinned files missing upstream lines and the\n * fork's own changes to files that still merge. Analyze lists ignored files only upstream changed\n * under protected but behind upstream, as its terminal does. Empty sections are left out, and so is\n * every section when the engine could not resolve the upgrade range.\n */\nexport function reviewSections(result: MergeResult, command: 'analyze' | 'upgrade'): ReviewSection[] {\n const [base, upstream] = result.upstreamDiffRange?.split('..') ?? [];\n if (!base || !upstream) return [];\n const sinceSync = `${base}..${upstream}`;\n\n const sections: ReviewSection[] =\n command === 'upgrade'\n ? [\n {\n title: 'protected files kept the fork version',\n hint: 'What upstream changed in these files since the last upgrade. The fork kept its own version, so none of it arrived: adopt what you need.',\n range: sinceSync,\n paths: result.protectedConflicts ?? [],\n },\n {\n title: 'ignored paths changed upstream',\n hint: 'What upstream changed under ignored paths since the last upgrade. The fork left these files untouched, and ignored paths never merge.',\n range: sinceSync,\n paths: (result.ignoredUpstreamChanges ?? []).flatMap((group) => group.paths),\n },\n ]\n : [\n {\n title: 'protected but behind upstream',\n hint: 'What upstream changed in these files since the last upgrade. They are pinned or ignored, so the upgrade keeps the fork version and none of it arrives: adopt what you need.',\n range: sinceSync,\n paths: findProtectedBehindUpstream(result).map((file) => file.path),\n },\n ];\n\n sections.push({\n title: 'pinned files that match the previous upstream',\n hint: 'What upstream changed in these files since the last upgrade. The fork copy still equals the previous upstream, so the pin only drops these changes: unpin to take them.',\n range: sinceSync,\n paths: findMaskingPins(result.files).map((file) => file.path),\n });\n\n if (command === 'analyze') {\n sections.push(\n {\n title: 'protected in fork, upstream lines absent',\n hint: \"The fork's version against upstream's, both as they are now: added lines are upstream content the fork does not have, dropped by an earlier upgrade or removed on purpose.\",\n range: `HEAD..${upstream}`,\n paths: filesWithStatus(result.files, 'ahead')\n .filter((file) => (file.upstreamLinesAbsent ?? 0) > 0)\n .map((file) => file.path),\n },\n {\n title: 'drifted from upstream',\n hint: 'What the fork changed in these files since the last upgrade. They are not pinned or ignored, so upstream changes still merge into them.',\n range: `${base}..HEAD`,\n paths: filesWithStatus(result.files, 'drifted').map((file) => file.path),\n },\n );\n }\n\n return sections.filter((section) => section.paths.length > 0);\n}\n\n/** Lines in a patch, without decoding it. */\nfunction countLines(patch: Buffer): number {\n let count = 0;\n for (let at = patch.indexOf(10); at !== -1; at = patch.indexOf(10, at + 1)) count++;\n return count;\n}\n\n/**\n * Write the review page for `sections` and return its path, its diffs and the files it lists\n * without one. Sections take turns, one file each, so a section of large diffs cannot fill the\n * page before the next gets any. Files past the page limits, oversized patches and patches without\n * a text hunk (binary, mode only) are listed by path. Undefined when no file has a diff.\n */\nexport async function writeReviewPage(\n forkPath: string,\n sections: ReviewSection[],\n meta: { command: 'analyze' | 'upgrade'; range: string },\n limits: ReviewPageLimits = PAGE_LIMITS,\n): Promise<ReviewPage | undefined> {\n const [base, upstream] = meta.range.split('..');\n const pageSections: Array<Required<DiffPageSection>> = sections.map((section) => ({\n title: section.title,\n hint: section.hint,\n files: [],\n omitted: [],\n }));\n const queues = sections.map((section) => [...section.paths]);\n let diffs = 0;\n let lines = 0;\n\n while (queues.some((queue) => queue.length > 0)) {\n for (const [index, queue] of queues.entries()) {\n const path = queue.shift();\n if (path === undefined) continue;\n const pageSection = pageSections[index];\n if (diffs >= limits.files || lines >= limits.lines) {\n pageSection.omitted.push(path);\n continue;\n }\n const patch = gitDiffFile(forkPath, sections[index].range, path);\n if (patch.length === 0) continue;\n const patchLines = patch.length > MAX_PATCH_BYTES ? Number.POSITIVE_INFINITY : countLines(patch);\n if (patchLines > limits.patchLines || lines + patchLines > limits.lines || !patch.includes('\\n@@ ')) {\n pageSection.omitted.push(path);\n continue;\n }\n pageSection.files.push({ path, patch: patch.toString() });\n diffs++;\n lines += patchLines;\n }\n }\n\n if (diffs === 0) return undefined;\n const shown = pageSections.filter((section) => section.files.length > 0 || section.omitted.length > 0);\n const page = await writeDiffPage(\n shown,\n { title: `${meta.command} review`, note: `${basename(forkPath)} · last upgrade ${base} → upstream ${upstream}` },\n forkPath,\n `${meta.command}-review`,\n );\n const listed = shown.reduce((count, section) => count + section.omitted.length, 0);\n return { path: page, diffs, listed, sections: shown.length };\n}\n\n/** A written review page, and whether the run opened it in the browser. */\nexport interface ReviewPageReport extends ReviewPage {\n command: 'analyze' | 'upgrade';\n opened: boolean;\n}\n\n/**\n * After an analyze or upgrade report: write the review page. Upgrade opens it in the browser when\n * stdout is a terminal, since the upstream changes it lists did not arrive. Undefined when there\n * is nothing to review; a failure is undefined too and never fails the run. An upgrade with nothing to\n * review removes the page an earlier upgrade left, so a rerun that resumes this merge never lists it.\n */\nexport async function reportReviewPage(\n forkPath: string,\n result: MergeResult,\n command: 'analyze' | 'upgrade',\n): Promise<ReviewPageReport | undefined> {\n const sections = reviewSections(result, command);\n let page: ReviewPage | undefined;\n if (sections.length > 0 && result.upstreamDiffRange) {\n createSpinner('writing review page...');\n try {\n page = await writeReviewPage(forkPath, sections, { command, range: result.upstreamDiffRange });\n } catch {\n page = undefined;\n }\n spinnerSuccess();\n }\n if (!page) {\n if (command === 'upgrade') removeSyncReviewPage(forkPath);\n return undefined;\n }\n\n const opened = command === 'upgrade' && process.stdout.isTTY === true && openInBrowser(page.path);\n return { ...page, command, opened };\n}\n\nfunction removeSyncReviewPage(forkPath: string): void {\n try {\n rmSync(diffPagePath(forkPath, 'upgrade-review'), { force: true });\n } catch {\n // Not a git repo or no git: there is no page to remove either.\n }\n}\n\n/** The upgrade review page the merge run of this upgrade wrote, when it is still there. */\nexport function existingSyncReviewPage(forkPath: string): string | undefined {\n try {\n const path = diffPagePath(forkPath, 'upgrade-review');\n return existsSync(path) ? path : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The `review` step: the page as a `file://` URL in full, so a terminal without OSC 8 links still\n * makes it clickable, and what is on it. A page from an earlier run has no counts.\n */\nexport function reviewStep(page: ReviewPageReport | string): NextStep {\n const path = typeof page === 'string' ? page : page.path;\n const url = pathToFileURL(path).href;\n let detail = pc.dim('upstream changes the upgrade did not bring in, from the merge run');\n if (typeof page !== 'string') {\n const what =\n page.command === 'upgrade'\n ? `${plural(page.diffs, 'diff')} of upstream changes that did not arrive`\n : `${plural(page.diffs, 'diff')} in ${plural(page.sections, 'section')}`;\n const notes = [\n page.listed > 0 ? `${page.listed} listed without a diff` : '',\n page.opened ? 'opened in the browser' : '',\n ]\n .filter(Boolean)\n .map((note) => ` · ${note}`)\n .join('');\n detail = `${what}${notes ? pc.dim(notes) : ''}`;\n }\n return { label: 'review', line: hyperlink(pc.cyan(url), url), details: [detail] };\n}\n","/**\n * Diff helpers: a single-file `git diff`, and diffs rendered as a self-contained HTML page that\n * opens in the default browser. Used by the contributions service and the review page.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, 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 with standard a/ b/ prefixes, which the HTML renderer's patch\n * parser requires; empty when the file is identical.\n */\nexport function gitDiffFile(cwd: string, range: string, filePath: string): Buffer {\n try {\n return execFileSync('git', ['diff', '--no-color', range, '--', filePath], { 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/** One file on a diff page: its path and its unified diff, with standard a/ b/ prefixes. */\nexport interface DiffPageFile {\n path: string;\n patch: string;\n}\n\n/** A group of files on a diff page, under an optional title and a line saying what the diffs show. */\nexport interface DiffPageSection {\n title?: string;\n hint?: string;\n files: DiffPageFile[];\n /** Paths of files listed without a diff (binary, too large, or past the page limit) */\n omitted?: string[];\n}\n\n/** The page header: a title, plus dim context after it. */\ninterface DiffPageMeta {\n title: string;\n /** Extra context shown after the title (e.g. 'cella ← → myfork') */\n note?: string;\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\n/**\n * Render diffs as a complete, self-contained HTML document: one block per file, grouped in\n * sections, with a section index at the top when there is more than one.\n *\n * Highlighting and diff layout come from `@pierre/diffs` (Shiki-based), rendered server-side to\n * static HTML: no scripts, no external requests, adapts to the viewer's light/dark preference.\n * Patches must use standard a/ b/ prefixes, as `gitDiffFile` returns them.\n */\nexport async function renderDiffPage(sections: DiffPageSection[], 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 renderFile = async (file: DiffPageFile) => {\n const { prerenderedHTML } = await preloadPatchDiff({\n patch: file.patch,\n options: {\n diffStyle: 'split',\n themeType: 'system',\n lineDiffType: 'word-alt',\n hunkSeparators: 'line-info',\n overflow: 'wrap',\n },\n });\n // Declarative shadow DOM: the library's CSS targets :host, which only matches inside a\n // shadow root (its browser component renders into one).\n return `<div class=\"diff-shell\"><template shadowrootmode=\"open\">\\n${prerenderedHTML}\\n</template></div>`;\n };\n\n const blocks: string[] = [];\n for (const [index, section] of sections.entries()) {\n const files: string[] = [];\n for (const file of section.files) files.push(await renderFile(file));\n const count = section.files.length + (section.omitted?.length ?? 0);\n const title = section.title\n ? `<h2>${escapeHtml(section.title)} <span class=\"count\">· ${count} ${count === 1 ? 'file' : 'files'}</span></h2>`\n : '';\n const hint = section.hint ? `<p class=\"hint\">${escapeHtml(section.hint)}</p>` : '';\n const omitted = section.omitted?.length\n ? `<p class=\"hint\">Not shown here (binary, too large, or past the page limit):</p><ul class=\"omitted\">${section.omitted\n .map((path) => `<li><code>${escapeHtml(path)}</code></li>`)\n .join('')}</ul>`\n : '';\n blocks.push(`<section id=\"section-${index + 1}\">${title}${hint}${files.join('\\n')}${omitted}</section>`);\n }\n\n const titled = sections.filter((section) => section.title);\n const index =\n titled.length > 1\n ? `<nav><ol>${sections\n .map((section, i) =>\n section.title\n ? `<li><a href=\"#section-${i + 1}\">${escapeHtml(section.title)}</a> <span class=\"count\">· ${\n section.files.length + (section.omitted?.length ?? 0)\n }</span></li>`\n : '',\n )\n .join('')}</ol></nav>`\n : '';\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>${escapeHtml(meta.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; z-index: 1;\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 .note { margin-left: auto; font-size: 0.8rem; opacity: 0.7; }\n main { max-width: 1400px; margin: 1rem auto; padding: 0 1rem 2rem; }\n nav ol { margin: 0 0 1.5rem; padding-left: 1.25rem; line-height: 1.7; }\n nav a { color: inherit; }\n section { scroll-margin-top: 4rem; }\n h2 { font-size: 1.05rem; margin: 2rem 0 0.25rem; }\n .count { font-weight: normal; opacity: 0.6; }\n .hint { margin: 0 0 1rem; font-size: 0.9rem; opacity: 0.75; max-width: 80ch; }\n .diff-shell {\n border: 1px solid light-dark(#e2e2e2, #2a2a2a);\n border-radius: 8px; overflow: hidden;\n background: light-dark(#fff, #161616);\n margin-bottom: 1rem;\n }\n .omitted { font-size: 0.85rem; opacity: 0.8; }\n .omitted code { font-family: ui-monospace, monospace; }\n</style>\n</head>\n<body>\n<header>\n <span class=\"brand\">⧈ cella diff</span>\n <code>${escapeHtml(meta.title)}</code>\n ${note}\n</header>\n<main>\n${index}\n${blocks.join('\\n')}\n</main>\n</body>\n</html>`;\n}\n\n/**\n * Render a diff page and write it to `<git dir>/cella-diff/<name>.html`. Inside the git dir the\n * page never reaches a commit and goes with the checkout; the path is stable per name, so a\n * rerun overwrites it and a browser refresh shows the latest render.\n *\n * @returns Absolute path of the written HTML file.\n */\nexport async function writeDiffPage(\n sections: DiffPageSection[],\n meta: DiffPageMeta,\n repoPath: string,\n name: string,\n): Promise<string> {\n const html = await renderDiffPage(sections, meta);\n const outPath = diffPagePath(repoPath, name);\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, html);\n return outPath;\n}\n\n/** Where {@link writeDiffPage} writes the page called `name`: `<git dir>/cella-diff/<name>.html`. */\nexport function diffPagePath(repoPath: string, name: string): string {\n const gitDir = execFileSync('git', ['rev-parse', '--absolute-git-dir'], { cwd: repoPath, encoding: 'utf8' }).trim();\n return join(gitDir, 'cella-diff', `${name.replace(/[^\\w.-]+/g, '-')}.html`);\n}\n\n/**\n * Open a file or URL with `open` (macOS) or `xdg-open`. Best-effort: a missing or failing opener\n * is not fatal, it returns false (e.g. a headless environment without a browser).\n */\nexport function openInBrowser(target: string): boolean {\n try {\n execFileSync(process.platform === 'darwin' ? 'open' : 'xdg-open', [target], { stdio: 'ignore' });\n return true;\n } catch {\n return false;\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 pc from '../utils/colors';\nimport {\n createSpinner,\n type NextStep,\n printMaskingPinWarning,\n printNextSteps,\n printSummary,\n printUpstreamOverrideChanges,\n spinnerSuccess,\n writeStdout,\n} from '../utils/display';\nimport { CONFIG_FILE } from '../utils/managed-files';\nimport { alignmentsStep } from './align';\nimport { printAnalysisFileGroups } from './analyze-report';\nimport { readOriginGitHubUrl, runEngineWithSpinner } from './merge-engine';\nimport { reportReviewPage, reviewStep } from './review-page';\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 CLI 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 CLI config: upstream override entries and packageJsonKeys the fork config does not follow\n upstreamOverrides:\n overrides && f.path === CONFIG_FILE\n ? { pinned: overrides.pinned, ignored: overrides.ignored, packageJsonKeys: overrides.packageJsonKeys }\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 // File sections first, ordered by how much they need you; the summary and the next steps close the output.\n printAnalysisFileGroups(result, {\n links: {\n upstreamGitHubUrl: result.upstreamGitHubUrl,\n upstreamSha: result.upstreamCommit?.hash,\n forkGitHubUrl: await readOriginGitHubUrl(config.forkPath),\n fileLinkMode: config.settings.fileLinkMode,\n forkPath: config.forkPath,\n },\n all: config.all,\n overrides: config.overrides,\n });\n printUpstreamOverrideChanges(result);\n printMaskingPinWarning(result.files);\n printSummary(result.summary, 'analysis summary');\n\n const steps: NextStep[] = [];\n const review = await reportReviewPage(config.forkPath, result, 'analyze');\n if (review) steps.push(reviewStep(review));\n const sync = syncStep(result);\n if (sync) steps.push(sync);\n const align =\n result.alignments && result.upstreamCommit\n ? await alignmentsStep(config, {\n ref: result.upstreamCommit.hash,\n open: result.alignments.open,\n arriving: result.alignments.arrived,\n })\n : undefined;\n if (align) steps.push(align);\n printNextSteps(steps);\n\n return result;\n}\n\n/** The `upgrade` step: what the upgrade would change, left out when upstream has nothing new. */\nfunction syncStep(result: MergeResult): NextStep | undefined {\n if (!result.upstreamCommitCount) return undefined;\n const { behind, diverged, renamed } = result.summary;\n const changes = [\n behind > 0 ? `${behind} update` : '',\n diverged > 0 ? `${diverged} merge` : '',\n renamed > 0 ? `${renamed} rename` : '',\n ].filter(Boolean);\n return {\n label: 'upgrade',\n line: 'pnpm cella upgrade',\n details: [\n pc.dim(\n `commits on a fresh branch, a rerun opens the PR · ${changes.length > 0 ? changes.join(', ') : 'no file changes'}`,\n ),\n ],\n };\n}\n","/**\n * Audit service for the Cella CLI.\n *\n * One table and one checkbox for outdated packages and runtime pins (Node, pnpm, image tags). The\n * picked updates become file edits that the security pass (see audit-security.ts) stages, checks\n * and writes, so the workspace changes once and only with a single install. Below the table, the\n * security fixes this machine's own Node, pnpm and gh miss (see local-tools.ts).\n */\n\nimport { readFileSync } from 'node:fs';\nimport { basename, join, relative } from 'node:path';\nimport { checkbox, Separator } from '@inquirer/prompts';\nimport type { RuntimeConfig } from '../config/types';\nimport {\n type EnhancedPackageInfo,\n editJsonText,\n formatDependents,\n getReleasesUrl,\n getRepoUrl,\n getVulnIcon,\n middleTruncate,\n type OutdatedPackage,\n outdatedPackageName,\n readReleaseAgeMinutes,\n rewriteSpecifier,\n runPnpmAudit,\n runPnpmJson,\n} from '../utils/audit-utils';\nimport pc from '../utils/colors';\nimport { createSpinner, hyperlink, spinnerFail, spinnerSuccess, warningMark } from '../utils/display';\nimport { getEnv } from '../utils/env';\nimport { type LocalToolCheck, planLocalTools, readLocalTools } from '../utils/local-tools';\nimport {\n applyRuntimeUpdate,\n fetchRuntimeFeeds,\n missingNodeImages,\n pinLocation,\n planRuntimeUpdates,\n type RuntimeUpdate,\n readRuntimePins,\n} from '../utils/runtimes';\nimport { advisoriesFromAudit, SEVERITIES } from '../utils/security-plan';\nimport { isBreakingJump } from '../utils/versions';\nimport { readTopLevel } from '../utils/workspace-yaml';\nimport { runSecurityPass, type WorkspaceEdits } from './audit-security';\n\n/** The manifest sections an update rewrites, as `pnpm up --latest` does. */\nconst DEPENDENCY_SECTIONS = ['dependencies', 'devDependencies', 'optionalDependencies'] as const;\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 packages and runtimes...');\n try {\n const pins = await readRuntimePins(forkPath);\n const now = Date.now();\n // --long adds each package's latest manifest, which holds its repository URL.\n const [outdated, auditResult, releaseAgeMinutes, feeds, machine] = await Promise.all([\n runPnpmJson(['-r', 'outdated', '--json', '--long'], forkPath),\n runPnpmAudit(forkPath),\n readReleaseAgeMinutes(forkPath),\n fetchRuntimeFeeds(pins, forkPath, now),\n readLocalTools(forkPath, now),\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\n const runtimes = planRuntimeUpdates(pins, feeds, { releaseAgeMinutes, now });\n const localTools = planLocalTools(machine, { releaseAgeMinutes, now });\n const rows = [\n ...packageRows(outdated as Record<string, OutdatedPackage>, auditResult ? advisoriesFromAudit(auditResult) : []),\n ...runtimes.updates.map(runtimeRow),\n ];\n\n if (rows.length === 0) {\n spinnerSuccess('all packages and runtimes are up to date');\n printNotes(forkPath, runtimes.unchecked);\n console.info();\n printLocalTools(localTools);\n await runSecurityPass(forkPath, { apply: !config.list, releaseAgeMinutes });\n return;\n }\n\n spinner.stop();\n printOutdatedResults(rows, forkPath);\n printNotes(forkPath, runtimes.unchecked);\n console.info();\n printLocalTools(localTools);\n\n // --list is the non-interactive mode: report only, no prompts and no writes.\n if (config.list) {\n await runSecurityPass(forkPath, { apply: false, releaseAgeMinutes });\n return;\n }\n\n const selected = await promptForUpdates(rows);\n if (!selected) return;\n const { edits, bumped } = await planEdits(forkPath, rows, selected, pins.nodeImageSuffixes);\n if (await runSecurityPass(forkPath, { apply: true, releaseAgeMinutes, edits })) printNext(bumped);\n } finally {\n spinner.stop();\n }\n}\n\n/** The outdated packages as table rows, sorted by the workspaces that depend on them. */\nfunction packageRows(outdated: Record<string, OutdatedPackage>, advisories: ReturnType<typeof advisoriesFromAudit>) {\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 rows: EnhancedPackageInfo[] = Object.entries(outdated).map(([key, pkg]) => {\n const name = outdatedPackageName(key);\n const repoUrl = getRepoUrl(pkg.latestManifest?.repository?.url);\n // pnpm leaves `current` out for a dependency that is not installed.\n const current = pkg.current ?? 'missing';\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 key,\n name,\n current,\n latest: pkg.latest,\n dependentPackages: pkg.dependentPackages,\n isDev: pkg.dependencyType === 'devDependencies',\n breaking: isBreakingJump(current, pkg.latest),\n pinnedIn,\n repoUrl,\n releasesUrl: getReleasesUrl(repoUrl),\n severity: severityOf(name),\n };\n });\n\n return rows.sort((a, b) => inText(a).localeCompare(inText(b)) || a.name.localeCompare(b.name));\n}\n\nfunction runtimeRow(update: RuntimeUpdate): EnhancedPackageInfo {\n return {\n key: `runtime:${update.file}:${update.name}`,\n name: update.name,\n current: update.current,\n latest: update.target,\n dependentPackages: [],\n isDev: false,\n breaking: isBreakingJump(update.current, update.target),\n pinnedIn: [],\n repoUrl: null,\n releasesUrl: update.releasesUrl,\n severity: update.severity,\n runtime: update,\n };\n}\n\nconst isRed = (row: EnhancedPackageInfo): boolean => row.severity === 'critical' || row.severity === 'high';\n\n/** The \"in\" column: where a runtime is pinned, or the workspaces that depend on the package, as \"first +N\". */\nconst inText = (row: EnhancedPackageInfo): string =>\n row.runtime ? pinLocation(row.runtime.file) : formatDependents(row.dependentPackages.map((d) => d.name));\n\nfunction printOutdatedResults(rows: EnhancedPackageInfo[], forkPath: string): void {\n const DEV_TAG = ' (dev)';\n const RUNTIME_TAG = ' (runtime)';\n const MAX_NAME_LEN = 35;\n const MAX_DEPENDENTS_LEN = 15;\n const tag = (row: EnhancedPackageInfo) => (row.runtime ? RUNTIME_TAG : row.isDev ? DEV_TAG : '');\n const maxNameLen = Math.min(MAX_NAME_LEN, Math.max(7, ...rows.map((p) => p.name.length + tag(p).length)));\n const maxCurrentLen = Math.max(7, ...rows.map((p) => p.current.length));\n const maxLatestLen = Math.max(6, ...rows.map((p) => p.latest.length));\n const maxDependentsLen = Math.min(MAX_DEPENDENTS_LEN, Math.max(10, ...rows.map((p) => inText(p).length)));\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 rows) {\n const vulnIndicator = pkg.severity ? getVulnIcon(pkg.severity) : ' ';\n\n const displayName = middleTruncate(`${pkg.name}${tag(pkg)}`, 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.breaking ? pc.bold(pc.green(latestText)) : pc.green(latestText);\n\n const dependents = pc.dim(middleTruncate(inText(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 rows) {\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 packages pnpm holds back (`updateConfig.ignoreDependencies`), and the runtimes whose feed did not answer. */\nfunction printNotes(forkPath: string, unchecked: string[]): void {\n let held: string[] = [];\n try {\n const updateConfig = readTopLevel(readFileSync(join(forkPath, 'pnpm-workspace.yaml'), 'utf8'), 'updateConfig');\n const ignored = (updateConfig as { ignoreDependencies?: unknown } | undefined)?.ignoreDependencies;\n held = Array.isArray(ignored) ? ignored.map(String) : [];\n } catch {\n // No workspace file: nothing is held.\n }\n if (held.length > 0) console.info(` ${pc.dim(`held: ${held.join(', ')} · pnpm-workspace.yaml updateConfig`)}`);\n if (unchecked.length > 0)\n console.info(` ${pc.dim(`not checked, no answer from the feed: ${unchecked.join(', ')}`)}`);\n}\n\n/** The tools this machine works with, each with the security fixes it misses and how to get them. */\nfunction printLocalTools(checks: LocalToolCheck[]): void {\n const width = Math.max(...checks.map((tool) => `${tool.name} ${tool.version}`.length));\n console.info(pc.bold('this machine'));\n for (const tool of checks) {\n const label = `${tool.name} ${tool.version}`.padEnd(width);\n const detail = tool.severity\n ? `${tool.note} ${pc.dim('·')} ${tool.fix}`\n : pc.dim(tool.note || 'no missing security fixes');\n console.info(`${tool.severity ? getVulnIcon(tool.severity) : ' '} ${label} ${detail}`);\n }\n console.info();\n}\n\n/** The grouped checkbox choices: runtimes, pinned packages, then the regular ones. A red dot starts ticked. */\nfunction buildUpdateChoices(\n rows: EnhancedPackageInfo[],\n): Array<{ name: string; value: string; checked: boolean } | Separator> {\n const makeChoice = (row: EnhancedPackageInfo) => {\n const devTag = row.isDev ? pc.dim(' (dev)') : '';\n const version = `${pc.red(row.current)} → ${pc.green(row.latest)}`;\n const notes = [\n row.breaking ? pc.bold('breaking') : '',\n row.runtime?.note ? pc.dim(row.runtime.note) : '',\n row.pinnedIn.length > 0 ? `${warningMark} ${pc.dim(`pinned in ${row.pinnedIn.join(', ')}`)}` : '',\n ].filter(Boolean);\n return {\n name: `${row.name}${devTag} ${version}${notes.length > 0 ? ` ${notes.join(' ')}` : ''}`,\n value: row.key,\n checked: isRed(row),\n };\n };\n\n const runtimes = rows.filter((p) => p.runtime);\n const pinned = rows.filter((p) => !p.runtime && p.pinnedIn.length > 0);\n const regular = rows.filter((p) => !p.runtime && p.pinnedIn.length === 0);\n\n const choices: Array<{ name: string; value: string; checked: boolean } | Separator> = [];\n\n if (runtimes.length > 0) {\n choices.push(new Separator(pc.yellow(`── runtimes (${runtimes.length}) ──`)));\n choices.push(...runtimes.map(makeChoice));\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 (choices.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/** The one prompt of the update step; null when it was cancelled. Submitting with nothing ticked skips the updates. */\nasync function promptForUpdates(rows: EnhancedPackageInfo[]): Promise<string[] | null> {\n try {\n const selected = await checkbox({\n message: `toggle what to update ${pc.dim('· enter with nothing ticked skips')}`,\n choices: buildUpdateChoices(rows),\n required: false,\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} selected`),\n },\n },\n });\n console.info();\n return selected;\n } catch {\n return null;\n }\n}\n\n/** The text of a runtime bump in the summary, e.g. `engines.node 26.12.1`. */\nfunction bumpText(update: RuntimeUpdate): string {\n if (update.pin.kind === 'node') return `engines.node ${update.target}`;\n if (update.pin.kind === 'pnpm') return `packageManager pnpm@${update.target}`;\n return update.pin.to;\n}\n\n/**\n * The selected updates as file contents, printed as one line per changed file. A dependency's\n * specifier keeps its prefix; one the audit cannot rewrite is left as written with a warning. A\n * Node bump waits until Docker Hub has every `node:<version><suffix>` image the Dockerfiles build from.\n */\nasync function planEdits(\n forkPath: string,\n rows: EnhancedPackageInfo[],\n selected: string[],\n nodeImageSuffixes: string[],\n): Promise<{ edits: WorkspaceEdits; bumped: RuntimeUpdate[] }> {\n const contents = new Map<string, { content: string; resolves: boolean }>();\n const summary = new Map<string, string[]>();\n const bumped: RuntimeUpdate[] = [];\n const edit = (file: string, label: string, item: string, resolves: boolean, change: (content: string) => string) => {\n const entry = contents.get(file) ?? { content: readFileSync(join(forkPath, file), 'utf8'), resolves: false };\n const next = change(entry.content);\n if (next === entry.content) return;\n contents.set(file, { content: next, resolves: entry.resolves || resolves });\n summary.set(label, [...(summary.get(label) ?? []), item]);\n };\n\n const chosen = rows.filter((row) => selected.includes(row.key));\n for (const row of chosen) {\n if (row.runtime) continue;\n for (const { name: dependent, location } of row.dependentPackages) {\n const file = relative(forkPath, join(location, 'package.json'));\n edit(file, dependent || file, row.name, true, (content) =>\n editJsonText(content, (json) => {\n for (const section of DEPENDENCY_SECTIONS) {\n const deps = json[section] as Record<string, string> | undefined;\n const spec = deps?.[row.name];\n if (!deps || spec === undefined) continue;\n const next = rewriteSpecifier(spec, row.latest);\n if (next) deps[row.name] = next;\n else console.info(`${warningMark} ${row.name} in ${dependent || file} left as written: ${spec}`);\n }\n }),\n );\n }\n }\n\n for (const row of chosen) {\n const update = row.runtime;\n if (!update) continue;\n if (update.pin.kind === 'node') {\n const missing = await missingNodeImages(update.target, nodeImageSuffixes);\n if (missing.length > 0) {\n console.info(`${warningMark} node ${update.target} skipped: ${missing.join(', ')} is not on docker hub yet`);\n continue;\n }\n }\n edit(update.file, update.file, bumpText(update), false, (content) => applyRuntimeUpdate(content, update));\n bumped.push(update);\n }\n\n for (const [label, items] of summary) {\n console.info(`${pc.cyan('↑')} ${pc.bold(label)}: ${pc.dim(items.join(', '))}`);\n }\n if (summary.size > 0) console.info();\n\n const edits: WorkspaceEdits = { manifests: {}, files: {} };\n for (const [file, { content, resolves }] of contents) {\n (resolves ? edits.manifests : edits.files)[file] = content;\n }\n return { edits, bumped };\n}\n\n/** The steps a runtime bump leaves to the developer: this machine's Node, and a local build of each changed image. */\nfunction printNext(bumped: RuntimeUpdate[]): void {\n const steps: Array<[command: string, why: string]> = [];\n const node = bumped.find((update) => update.pin.kind === 'node');\n if (node && process.version !== `v${node.target}`) {\n const command = getEnv('VOLTA_HOME') ? `volta install node@${node.target}` : `switch to node ${node.target}`;\n steps.push([command, `this machine runs ${process.version.slice(1)}`]);\n }\n for (const update of bumped) {\n if (update.pin.kind === 'image') steps.push([`docker build -f ${update.file} .`, 'check that the image builds']);\n }\n if (steps.length === 0) return;\n\n const width = Math.max(...steps.map(([command]) => command.length));\n console.info(pc.bold('next'));\n for (const [command, why] of steps) console.info(` ${pc.dim('•')} ${command.padEnd(width)} ${pc.dim(why)}`);\n console.info();\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 type { RuntimeUpdate } from './runtimes';\n\nconst execFileAsync = promisify(execFile);\n\n/** One package in `pnpm -r outdated --json --long`. */\nexport interface OutdatedPackage {\n /** Missing for a dependency that is not installed. */\n current?: string;\n latest: string;\n dependencyType: 'dependencies' | 'devDependencies';\n dependentPackages: Array<{ name: string; location: string }>;\n latestManifest?: { repository?: { url?: string } };\n}\n\n/**\n * The package name of a `pnpm -r outdated --json` key. pnpm keys a name that has several entries\n * (another installed version or dependency type) as `name@current (dev)`.\n */\nexport function outdatedPackageName(key: string): string {\n const name = key.split(' ')[0];\n const at = name.indexOf('@', 1);\n return at === -1 ? name : name.slice(0, at);\n}\n\nexport interface EnhancedPackageInfo {\n /** The checkbox value: pnpm's outdated key for a package, `runtime:<file>:<name>` for a runtime pin. */\n key: string;\n /** The package name as a manifest lists it, or the runtime's name. */\n name: string;\n current: string;\n latest: string;\n dependentPackages: OutdatedPackage['dependentPackages'];\n isDev: boolean;\n /** The update leaves the range a caret allows: another major, or another minor below 1.0. */\n breaking: 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 /** Set for a runtime pin (Node, pnpm, an image tag) shown among the packages. */\n runtime?: RuntimeUpdate;\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/** 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/** pnpm's `minimumReleaseAge` in minutes; 0 when it is unset or unreadable. */\nexport async function readReleaseAgeMinutes(cwd: string): Promise<number> {\n const minutes = Number.parseInt((await runPnpm(['config', 'get', 'minimumReleaseAge'], cwd)).stdout, 10);\n return Number.isNaN(minutes) ? 0 : minutes;\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 // A failed lookup still prints JSON, as `{ \"error\": … }`.\n return times && typeof times === 'object' && !('error' in times) ? (times as Record<string, string>) : null;\n}\n\n/**\n * JSON text after `change` ran on its parsed value, written back with the file's own indent and\n * final newline, the way pnpm writes a manifest.\n */\nexport function editJsonText(content: string, change: (json: Record<string, unknown>) => void): string {\n const json = JSON.parse(content) as Record<string, unknown>;\n change(json);\n const indent = content.match(/^[ \\t]+(?=\")/m)?.[0] ?? ' ';\n return `${JSON.stringify(json, null, indent)}${content.endsWith('\\n') ? '\\n' : ''}`;\n}\n\n/**\n * The specifier that moves a dependency to `latest` and keeps its prefix (`^`, `~` or exact), as\n * `pnpm up --latest` writes it; null for one the audit leaves as written (`workspace:`, `catalog:`,\n * `npm:` aliases, operator ranges, tags).\n */\nexport function rewriteSpecifier(spec: string, latest: string): string | null {\n const match = spec.match(/^([\\^~]?)\\d+(?:\\.\\d+){0,2}(?:-[0-9A-Za-z.-]+)?$/);\n return match ? `${match[1]}${latest}` : 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 tools this machine works on the workspace with: the Node that runs it, the pnpm a terminal\n * starts, and gh. Each is checked for the security fixes it misses. The audit only reports them,\n * with the upgrade command that fits how the tool was installed.\n */\n\nimport { execFile } from 'node:child_process';\nimport { existsSync, realpathSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { delimiter, dirname, join, sep } from 'node:path';\nimport { promisify } from 'node:util';\nimport { fetchPublishTimes, type VulnerabilitySeverity } from './audit-utils';\nimport { plural } from './display';\nimport { getEnv } from './env';\nimport {\n type BulkAdvisory,\n fetchJson,\n fetchNodeReleases,\n fetchPnpmAdvisories,\n type NodeRelease,\n newestAged,\n} from './runtimes';\nimport { SEVERITIES } from './security-plan';\nimport { compareVersionStrings, isPrerelease, parseComparableVersion, satisfiesComparators } from './versions';\n\nconst execFileAsync = promisify(execFile);\n\n/** How a tool was installed, read from the path its binary resolves to. */\ntype Installer = 'volta' | 'brew' | null;\n\ninterface InstalledTool {\n version: string;\n installer: Installer;\n}\n\n/** The tools found on this machine, null when not installed, with their feeds; a feed that did not answer is null. */\nexport interface LocalTools {\n node: InstalledTool & { releases: NodeRelease[] | null };\n pnpm: (InstalledTool & { published: Record<string, string> | null; advisories: BulkAdvisory[] | null }) | null;\n /** `advisories` holds the severity of each advisory OSV lists against the installed version. */\n gh:\n | (InstalledTool & {\n releases: Array<{ version: string; publishedAt: number }> | null;\n advisories: VulnerabilitySeverity[] | null;\n })\n | null;\n}\n\n/** One tool as the audit shows it. */\nexport interface LocalToolCheck {\n name: string;\n version: string;\n /** The highest severity among the fixes the version misses; null when it misses none or was not checked. */\n severity: VulnerabilitySeverity | null;\n /** What it misses (`5 advisories, 1 high`), why it was not checked, or empty. */\n note: string;\n /** The command that gets the fixes (`update to <version>` for an install the audit cannot tell); empty when nothing is missed. */\n fix: string;\n}\n\n/** The first `name` binary on PATH outside `node_modules/.bin` folders and the folders in `skip`. */\nfunction findOnPath(name: string, skip: string[] = []): string | null {\n for (const dir of (getEnv('PATH') ?? '').split(delimiter)) {\n if (!dir || skip.includes(dir) || dir.endsWith(`node_modules${sep}.bin`)) continue;\n if (existsSync(join(dir, name))) return join(dir, name);\n }\n return null;\n}\n\nfunction installerOf(file: string): Installer {\n let real = file;\n try {\n real = realpathSync(file);\n } catch {\n // A broken link: read the path as found.\n }\n if (real.includes(`${sep}.volta${sep}`)) return 'volta';\n return /[\\\\/](Cellar|homebrew|linuxbrew)[\\\\/]/.test(real) ? 'brew' : null;\n}\n\n/** The first x.y.z in a binary's `--version` output; null when it does not run. */\nasync function versionOf(file: string, cwd?: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(file, ['--version'], { encoding: 'utf8', timeout: 10_000, cwd });\n return stdout.match(/\\d+\\.\\d+\\.\\d+/)?.[0] ?? null;\n } catch {\n return null;\n }\n}\n\nasync function readNode(now: number): Promise<LocalTools['node']> {\n const version = process.version.slice(1);\n const major = parseComparableVersion(version)?.major ?? 0;\n return { version, installer: installerOf(process.execPath), releases: await fetchNodeReleases(major, now) };\n}\n\n/**\n * The pnpm a terminal starts, asked outside any project. A pnpm that switched to the workspace's\n * `packageManager` puts its own folder first on PATH, so the folder of the running pnpm is skipped.\n */\nasync function readPnpm(cwd: string): Promise<LocalTools['pnpm']> {\n const running = getEnv('npm_execpath');\n const file = findOnPath('pnpm', running ? [dirname(running)] : []);\n const version = file && (await versionOf(file, tmpdir()));\n if (!file || !version) return null;\n const [published, advisories] = await Promise.all([fetchPublishTimes('pnpm', cwd), fetchPnpmAdvisories(version)]);\n return { version, installer: installerOf(file), published, advisories };\n}\n\n/**\n * The severity of each advisory OSV lists against a Go module version; null when OSV does not\n * answer. OSV lists an advisory under its GHSA id and its GO id, and only the GHSA entry carries a\n * severity; one without a GHSA entry counts as moderate.\n */\nasync function fetchOsvSeverities(module: string, version: string): Promise<VulnerabilitySeverity[] | null> {\n const answer = await fetchJson('https://api.osv.dev/v1/query', {\n method: 'POST',\n body: JSON.stringify({ package: { name: module, ecosystem: 'Go' }, version }),\n });\n if (!answer) return null;\n type OsvVuln = { id: string; aliases?: string[]; database_specific?: { severity?: string } };\n const byGhsa = new Map<string, VulnerabilitySeverity>();\n for (const vuln of (answer as { vulns?: OsvVuln[] }).vulns ?? []) {\n const id = [vuln.id, ...(vuln.aliases ?? [])].find((alias) => alias.startsWith('GHSA-')) ?? vuln.id;\n const severity = SEVERITIES.find((level) => level === vuln.database_specific?.severity?.toLowerCase());\n if (severity || !byGhsa.has(id)) byGhsa.set(id, severity ?? 'moderate');\n }\n return [...byGhsa.values()];\n}\n\nasync function readGh(): Promise<LocalTools['gh']> {\n const file = findOnPath('gh');\n const version = file && (await versionOf(file));\n if (!file || !version) return null;\n const [list, advisories] = await Promise.all([\n fetchJson('https://api.github.com/repos/cli/cli/releases?per_page=30'),\n fetchOsvSeverities('github.com/cli/cli/v2', version),\n ]);\n const releases = Array.isArray(list)\n ? list.flatMap((entry) => {\n const { tag_name, published_at } = entry as { tag_name?: string; published_at?: string };\n const publishedAt = Date.parse(published_at ?? '');\n return tag_name && !Number.isNaN(publishedAt) ? [{ version: tag_name.replace(/^v/, ''), publishedAt }] : [];\n })\n : null;\n return { version, installer: installerOf(file), releases, advisories };\n}\n\n/** Node, pnpm and gh as installed on this machine, with their release and advisory feeds, in parallel. */\nexport async function readLocalTools(cwd: string, now: number): Promise<LocalTools> {\n const [node, pnpm, gh] = await Promise.all([readNode(now), readPnpm(cwd), readGh()]);\n return { node, pnpm, gh };\n}\n\n/** The command that moves a tool to `target`; Homebrew picks its own version. */\nfunction upgradeCommand(name: string, installer: Installer, target: string | undefined): string {\n if (installer === 'brew') return `brew upgrade ${name}`;\n if (!target) return 'no fixed release older than the release age yet';\n if (installer === 'volta') return `volta install ${name}@${target}`;\n return name === 'pnpm' ? `pnpm self-update ${target}` : `update to ${target}`;\n}\n\n/** The line for one tool; `missed` is null when its feed did not answer. */\nfunction toCheck(\n name: 'node' | 'pnpm' | 'gh',\n tool: InstalledTool,\n missed: VulnerabilitySeverity[] | null,\n target: string | undefined,\n noun: [singular: string, plural: string],\n): LocalToolCheck {\n if (!missed)\n return { name, version: tool.version, severity: null, note: 'not checked, no answer from the feed', fix: '' };\n if (missed.length === 0) return { name, version: tool.version, severity: null, note: '', fix: '' };\n const high = missed.filter((severity) => severity === 'critical' || severity === 'high').length;\n return {\n name,\n version: tool.version,\n severity: SEVERITIES.find((severity) => missed.includes(severity)) ?? null,\n note: `${plural(missed.length, ...noun)}${high > 0 && high < missed.length ? `, ${high} high` : ''}`,\n fix: upgradeCommand(name, tool.installer, target),\n };\n}\n\n/**\n * The security fixes each tool misses, and the version that has them: the newest one in its major\n * older than the release age. For pnpm that is the newest version no advisory affects, in its\n * major when one there has every fix.\n */\nexport function planLocalTools(\n tools: LocalTools,\n options: { releaseAgeMinutes: number; now: number },\n): LocalToolCheck[] {\n const cutoff = options.now - options.releaseAgeMinutes * 60 * 1000;\n const { node, pnpm, gh } = tools;\n\n const nodeTarget = node.releases ? newestAged(node.version, node.releases, cutoff) : undefined;\n const securityReleases = (node.releases ?? []).filter(\n (release) =>\n release.security &&\n nodeTarget &&\n compareVersionStrings(release.version, node.version) > 0 &&\n compareVersionStrings(release.version, nodeTarget.version) <= 0,\n );\n const checks = [\n toCheck(\n 'node',\n node,\n node.releases && securityReleases.map((): VulnerabilitySeverity => 'high'),\n nodeTarget?.version,\n ['security release', 'security releases'],\n ),\n ];\n\n if (pnpm) {\n const affecting = (version: string) =>\n (pnpm.advisories ?? []).filter((advisory) => satisfiesComparators(version, advisory.vulnerable_versions));\n const fixed = Object.entries(pnpm.published ?? {})\n .map(([version, time]) => ({ version, publishedAt: Date.parse(time) }))\n .filter(\n (release) =>\n parseComparableVersion(release.version) &&\n !isPrerelease(release.version) &&\n release.publishedAt <= cutoff &&\n compareVersionStrings(release.version, pnpm.version) > 0 &&\n affecting(release.version).length === 0,\n )\n .sort((a, b) => compareVersionStrings(b.version, a.version));\n const major = parseComparableVersion(pnpm.version)?.major;\n const target = fixed.find((release) => parseComparableVersion(release.version)?.major === major) ?? fixed[0];\n const missed = pnpm.advisories && pnpm.published && affecting(pnpm.version).map((advisory) => advisory.severity);\n checks.push(toCheck('pnpm', pnpm, missed, target?.version, ['advisory', 'advisories']));\n }\n\n if (gh) {\n const target = gh.releases ? newestAged(gh.version, gh.releases, cutoff) : undefined;\n checks.push(toCheck('gh', gh, gh.advisories, target?.version, ['advisory', 'advisories']));\n }\n\n return checks;\n}\n","/**\n * Runtime pins for the audit: the Node and pnpm versions the root package.json pins, and the image\n * tags of the Dockerfiles, checked against their release feeds. Reading, planning and rewriting\n * are pure; the fetches never throw, so a feed that does not answer only leaves its runtime out.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { basename, dirname, join } from 'node:path';\nimport { editJsonText, fetchPublishTimes, type VulnerabilitySeverity } from './audit-utils';\nimport { git } from './git';\nimport { compareVersionStrings, isPrerelease, parseComparableVersion, satisfiesComparators } from './versions';\n\n/** An image tag in a Dockerfile `FROM` line. */\nexport interface ImagePin {\n file: string;\n /** Zero-based line of the `FROM`. */\n line: number;\n /** The image as written, e.g. `caddy` or `bitnami/redis`. */\n image: string;\n tag: string;\n}\n\n/** What the workspace pins: exact versions only, since a range already follows its line. */\nexport interface RuntimePins {\n node: string | null;\n pnpm: string | null;\n images: ImagePin[];\n /** Suffixes of `FROM node:${…}<suffix>` lines (`-alpine`): the images a Node bump needs to exist. */\n nodeImageSuffixes: string[];\n}\n\n/** A Node release from nodejs.org, with the time it was published. */\nexport interface NodeRelease {\n version: string;\n publishedAt: number;\n security: boolean;\n}\n\n/** An image tag on Docker Hub and when it was last pushed. */\nexport interface HubTag {\n name: string;\n pushedAt: number;\n}\n\n/** An npm advisory, reduced to its vulnerable range and severity. */\nexport interface BulkAdvisory {\n vulnerable_versions: string;\n severity: VulnerabilitySeverity;\n}\n\n/** What the feeds answered; null where a feed did not answer. */\nexport interface RuntimeFeeds {\n node: NodeRelease[] | null;\n pnpm: { published: Record<string, string>; advisories: BulkAdvisory[] } | null;\n /** Per image pin, in the order of {@link RuntimePins.images}. */\n images: Array<{ pinned: HubTag | null; tags: HubTag[] } | null>;\n}\n\n/** How a pin moves, and what the audit shows about it. */\nexport interface RuntimeUpdate {\n name: string;\n current: string;\n target: string;\n /** Where it is pinned, relative to the workspace root. */\n file: string;\n /** A red dot for a security fix, a yellow dot for a tag that stopped getting pushes. */\n severity: 'high' | 'moderate' | null;\n note: string;\n releasesUrl: string;\n pin: { kind: 'node' } | { kind: 'pnpm' } | { kind: 'image'; line: number; ref: string; to: string };\n}\n\nconst DAY = 24 * 60 * 60 * 1000;\n\n/** A tag without a push for this long, while a newer line got one, gets no more fixes. */\nconst FROZEN_AFTER = 180 * DAY;\nconst RECENT_PUSH = 30 * DAY;\n\nconst EXACT_VERSION = /^\\d+\\.\\d+\\.\\d+$/;\n\nconst FROM_LINE = /^\\s*FROM\\s+(?:--platform=\\S+\\s+)?(\\S+)(?:\\s+AS\\s+(\\S+))?\\s*$/i;\n\n/** `FROM node:${NODE_VERSION}-alpine`: the version comes from a build argument. */\nconst NODE_ARG_TAG = /^(?:docker\\.io\\/)?(?:library\\/)?node:\\$\\{?\\w+\\}?([\\w.-]*)$/;\n\n/** A tag naming at least a minor (`2.8`, `2.8.4`), with an optional suffix (`-alpine`). */\nconst MINOR_TAG = /^(\\d+(?:\\.\\d+){1,2})(-[\\w.-]+)?$/;\n\nconst isDockerfile = (path: string): boolean => /(^|\\.)Dockerfile$|^Dockerfile\\./i.test(basename(path));\n\n/** The image pins and Node build-argument suffixes in one Dockerfile. */\nexport function parseDockerfile(file: string, content: string): { images: ImagePin[]; nodeImageSuffixes: string[] } {\n const images: ImagePin[] = [];\n const nodeImageSuffixes: string[] = [];\n const stages = new Set<string>();\n\n content.split('\\n').forEach((text, line) => {\n const match = text.match(FROM_LINE);\n if (!match) return;\n const [, ref, stage] = match;\n const fromStage = stages.has(ref.toLowerCase());\n if (stage) stages.add(stage.toLowerCase());\n if (fromStage || ref.includes('@')) return;\n\n const nodeArg = ref.match(NODE_ARG_TAG);\n if (nodeArg) {\n nodeImageSuffixes.push(nodeArg[1]);\n return;\n }\n if (ref.includes('$')) return;\n\n const slash = ref.lastIndexOf('/');\n const colon = ref.lastIndexOf(':');\n if (colon <= slash) return;\n let image = ref.slice(0, colon);\n const tag = ref.slice(colon + 1);\n const host = image.includes('/') ? image.split('/')[0] : '';\n if (host === 'docker.io') image = image.slice(host.length + 1).replace(/^library\\//, '');\n else if (host.includes('.') || host.includes(':') || host === 'localhost') return;\n if (image === 'scratch') return;\n images.push({ file, line, image, tag });\n });\n\n return { images, nodeImageSuffixes };\n}\n\n/** The exact Node and pnpm pins of the root package.json, and the image tags of every tracked Dockerfile. */\nexport async function readRuntimePins(forkPath: string): Promise<RuntimePins> {\n let manifest: { engines?: { node?: string }; packageManager?: string } = {};\n try {\n manifest = JSON.parse(readFileSync(join(forkPath, 'package.json'), 'utf8'));\n } catch {\n // No root manifest: nothing pinned there.\n }\n const node = manifest.engines?.node?.trim() ?? '';\n const pnpm = manifest.packageManager?.match(/^pnpm@(\\d+\\.\\d+\\.\\d+)(?:\\+.*)?$/)?.[1] ?? null;\n\n const tracked = (await git(['ls-files', '-z'], forkPath, { ignoreErrors: true })).split('\\0').filter(isDockerfile);\n const images: ImagePin[] = [];\n const nodeImageSuffixes = new Set<string>();\n for (const file of tracked) {\n let content: string;\n try {\n content = readFileSync(join(forkPath, file), 'utf8');\n } catch {\n continue;\n }\n const parsed = parseDockerfile(file, content);\n images.push(...parsed.images);\n for (const suffix of parsed.nodeImageSuffixes) nodeImageSuffixes.add(suffix);\n }\n\n return {\n node: EXACT_VERSION.test(node) ? node : null,\n pnpm,\n images,\n nodeImageSuffixes: [...nodeImageSuffixes],\n };\n}\n\n/** The parsed JSON answer of a URL; null for an error status, a timeout or unparsable output. */\nexport async function fetchJson(url: string, init?: RequestInit): Promise<unknown> {\n try {\n const response = await fetch(url, { ...init, signal: AbortSignal.timeout(10_000) });\n return response.ok ? await response.json() : null;\n } catch {\n return null;\n }\n}\n\nconst hubRepository = (image: string): string => (image.includes('/') ? image : `library/${image}`);\n\nconst hubTag = (entry: unknown): HubTag | null => {\n const { name, last_updated } = (entry ?? {}) as { name?: string; last_updated?: string };\n const pushedAt = Date.parse(last_updated ?? '');\n return name && !Number.isNaN(pushedAt) ? { name, pushedAt } : null;\n};\n\n/**\n * Node releases from nodejs.org. The index gives a release day only, so a release from the last\n * two days, where the day alone cannot settle the release age, gets its exact time from the\n * Last-Modified header of its checksum file (the end of its day when that does not answer).\n */\nexport async function fetchNodeReleases(major: number, now: number): Promise<NodeRelease[] | null> {\n const index = await fetchJson('https://nodejs.org/dist/index.json');\n if (!Array.isArray(index)) return null;\n const releases = index\n .map((entry) => entry as { version?: string; date?: string; security?: boolean })\n .filter((entry) => entry.version && parseComparableVersion(entry.version)?.major === major)\n .map((entry) => ({\n version: String(entry.version).replace(/^v/, ''),\n publishedAt: Date.parse(entry.date ?? ''),\n security: entry.security === true,\n }))\n .filter((release) => !Number.isNaN(release.publishedAt));\n\n await Promise.all(\n releases\n .filter((release) => now - release.publishedAt < 2 * DAY)\n .map(async (release) => {\n try {\n const response = await fetch(`https://nodejs.org/dist/v${release.version}/SHASUMS256.txt`, {\n method: 'HEAD',\n signal: AbortSignal.timeout(10_000),\n });\n const modified = Date.parse(response.headers.get('last-modified') ?? '');\n release.publishedAt = Number.isNaN(modified) ? release.publishedAt + DAY : modified;\n } catch {\n release.publishedAt += DAY;\n }\n }),\n );\n return releases;\n}\n\nasync function fetchImageTags(pin: ImagePin): Promise<{ pinned: HubTag | null; tags: HubTag[] } | null> {\n const shape = pin.tag.match(MINOR_TAG);\n if (!shape) return null;\n const base = `https://hub.docker.com/v2/repositories/${hubRepository(pin.image)}/tags`;\n const filter = shape[2] ?? `${shape[1].split('.')[0]}.`;\n const [list, pinned] = await Promise.all([\n fetchJson(`${base}?page_size=100&ordering=last_updated&name=${encodeURIComponent(filter)}`),\n fetchJson(`${base}/${encodeURIComponent(pin.tag)}`),\n ]);\n const results = (list as { results?: unknown[] } | null)?.results;\n if (!Array.isArray(results)) return null;\n return { pinned: hubTag(pinned), tags: results.flatMap((entry) => hubTag(entry) ?? []) };\n}\n\n/** The npm advisories against a pnpm version; null when the registry does not answer. */\nexport async function fetchPnpmAdvisories(version: string): Promise<BulkAdvisory[] | null> {\n const answer = await fetchJson('https://registry.npmjs.org/-/npm/v1/security/advisories/bulk', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ pnpm: [version] }),\n });\n return answer ? ((answer as { pnpm?: BulkAdvisory[] }).pnpm ?? []) : null;\n}\n\n/** Ask every feed the pins need, in parallel. Only pins whose tag names a minor reach Docker Hub. */\nexport async function fetchRuntimeFeeds(pins: RuntimePins, cwd: string, now: number): Promise<RuntimeFeeds> {\n const nodeMajor = pins.node ? parseComparableVersion(pins.node)?.major : undefined;\n const [node, published, advisories, images] = await Promise.all([\n nodeMajor === undefined ? null : fetchNodeReleases(nodeMajor, now),\n pins.pnpm ? fetchPublishTimes('pnpm', cwd) : null,\n pins.pnpm ? fetchPnpmAdvisories(pins.pnpm) : null,\n Promise.all(pins.images.map(fetchImageTags)),\n ]);\n return { node, pnpm: published && advisories ? { published, advisories } : null, images };\n}\n\nconst count = (n: number, noun: string, plural = `${noun}s`): string => `${n} ${n === 1 ? noun : plural}`;\n\nconst monthYear = (time: number): string =>\n new Date(time).toLocaleString('en', { month: 'short', year: 'numeric', timeZone: 'UTC' }).toLowerCase();\n\n/** The highest version above `pinned` in its major that is older than the release age. */\nexport function newestAged(pinned: string, versions: Array<{ version: string; publishedAt: number }>, cutoff: number) {\n const major = parseComparableVersion(pinned)?.major;\n return versions\n .filter(\n (entry) =>\n !isPrerelease(entry.version) &&\n parseComparableVersion(entry.version)?.major === major &&\n compareVersionStrings(entry.version, pinned) > 0 &&\n entry.publishedAt <= cutoff,\n )\n .sort((a, b) => compareVersionStrings(b.version, a.version))[0];\n}\n\n/**\n * The pins that can move: a newer version in the same major (a newer minor tag for an image), never\n * younger than the release age. `unchecked` names each runtime whose feed did not answer.\n */\nexport function planRuntimeUpdates(\n pins: RuntimePins,\n feeds: RuntimeFeeds,\n options: { releaseAgeMinutes: number; now: number },\n): { updates: RuntimeUpdate[]; unchecked: string[] } {\n const cutoff = options.now - options.releaseAgeMinutes * 60 * 1000;\n const updates: RuntimeUpdate[] = [];\n const unchecked: string[] = [];\n\n if (pins.node) {\n if (!feeds.node) unchecked.push('node');\n const target = feeds.node && newestAged(pins.node, feeds.node, cutoff);\n if (target) {\n const node = pins.node;\n const security = (feeds.node ?? []).some(\n (release) =>\n release.security &&\n compareVersionStrings(release.version, node) > 0 &&\n compareVersionStrings(release.version, target.version) <= 0,\n );\n updates.push({\n name: 'node',\n current: node,\n target: target.version,\n file: 'package.json',\n severity: security ? 'high' : null,\n note: security ? 'security release' : '',\n releasesUrl: `https://nodejs.org/en/blog/release/v${target.version}`,\n pin: { kind: 'node' },\n });\n }\n }\n\n if (pins.pnpm) {\n if (!feeds.pnpm) unchecked.push('pnpm');\n const published = Object.entries(feeds.pnpm?.published ?? {}).map(([version, time]) => ({\n version,\n publishedAt: Date.parse(time),\n }));\n const target = feeds.pnpm && newestAged(pins.pnpm, published, cutoff);\n if (target) {\n const pnpm = pins.pnpm;\n const fixed = (feeds.pnpm?.advisories ?? []).filter(\n (advisory) =>\n satisfiesComparators(pnpm, advisory.vulnerable_versions) &&\n !satisfiesComparators(target.version, advisory.vulnerable_versions),\n ).length;\n updates.push({\n name: 'pnpm',\n current: pnpm,\n target: target.version,\n file: 'package.json',\n severity: fixed > 0 ? 'high' : null,\n note: fixed > 0 ? count(fixed, 'advisory', 'advisories') : '',\n releasesUrl: `https://github.com/pnpm/pnpm/releases/tag/v${target.version}`,\n pin: { kind: 'pnpm' },\n });\n }\n }\n\n pins.images.forEach((pin, i) => {\n const shape = pin.tag.match(MINOR_TAG);\n if (!shape) return;\n const feed = feeds.images[i];\n if (!feed) {\n unchecked.push(pin.image);\n return;\n }\n const [, version, suffix = ''] = shape;\n const parts = version.split('.').length;\n const major = version.split('.')[0];\n const target = feed.tags\n .map((tag) => ({ tag, match: tag.name.match(MINOR_TAG) }))\n .filter(\n ({ match }) =>\n match &&\n (match[2] ?? '') === suffix &&\n match[1].split('.').length === parts &&\n match[1].split('.')[0] === major &&\n compareVersionStrings(match[1], version) > 0,\n )\n .sort((a, b) => compareVersionStrings(b.match?.[1] ?? '', a.match?.[1] ?? ''))[0];\n if (!target?.match) return;\n\n const frozen =\n !!feed.pinned &&\n options.now - feed.pinned.pushedAt > FROZEN_AFTER &&\n options.now - target.tag.pushedAt < RECENT_PUSH;\n const repository = hubRepository(pin.image);\n updates.push({\n name: pin.image,\n current: version,\n target: target.match[1],\n file: pin.file,\n severity: frozen ? 'moderate' : null,\n note: frozen && feed.pinned ? `tag frozen since ${monthYear(feed.pinned.pushedAt)}` : '',\n releasesUrl: repository.startsWith('library/')\n ? `https://hub.docker.com/_/${pin.image}/tags`\n : `https://hub.docker.com/r/${repository}/tags`,\n pin: { kind: 'image', line: pin.line, ref: `${pin.image}:${pin.tag}`, to: `${pin.image}:${target.tag.name}` },\n });\n });\n\n return { updates, unchecked };\n}\n\n/** The file content with the update's pin moved to its target. */\nexport function applyRuntimeUpdate(content: string, update: RuntimeUpdate): string {\n const { pin } = update;\n if (pin.kind === 'image') {\n const lines = content.split('\\n');\n lines[pin.line] = lines[pin.line].replace(pin.ref, pin.to);\n return lines.join('\\n');\n }\n return editJsonText(content, (json) => {\n if (pin.kind === 'node') (json.engines as Record<string, string>).node = update.target;\n // A `+sha` suffix names the old version's tarball, so it goes.\n else json.packageManager = `pnpm@${update.target}`;\n });\n}\n\n/** The `node:<version><suffix>` images a Node bump would build from that Docker Hub does not have (yet). */\nexport async function missingNodeImages(version: string, suffixes: string[]): Promise<string[]> {\n const missing = await Promise.all(\n suffixes.map(async (suffix) => {\n const tag = `${version}${suffix}`;\n const found = await fetchJson(`https://hub.docker.com/v2/repositories/library/node/tags/${tag}`);\n return found ? [] : [`node:${tag}`];\n }),\n );\n return missing.flat();\n}\n\n/** Where a pin lives, for the table: the file's directory, or the file itself at the root. */\nexport function pinLocation(file: string): string {\n const dir = dirname(file);\n return dir === '.' ? file : dir;\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/** Files the update step changed, written by the security pass together with its own settings. */\nexport interface WorkspaceEdits {\n /** Manifests whose dependencies changed, by path from the workspace root: staged before the resolve. */\n manifests: Record<string, string>;\n /** Other files, such as runtime pins: written as they are, with nothing to resolve. */\n files: Record<string, string>;\n}\n\nconst NO_EDITS: WorkspaceEdits = { manifests: {}, files: {} };\n\n/**\n * Run the security pass on the workspace at `forkPath`, with the update step's `edits` already in\n * place in the staging copy, so the plan judges the workspace as it will be. The workspace is\n * written once, at the end; with `apply` off nothing is written. Returns whether the edits landed:\n * false for a report, a failure or a cancelled prompt, which all leave the workspace as it was.\n */\nexport async function runSecurityPass(\n forkPath: string,\n options: { apply: boolean; releaseAgeMinutes: number; edits?: WorkspaceEdits },\n): Promise<boolean> {\n const { releaseAgeMinutes, edits = NO_EDITS } = options;\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 false;\n }\n const auditKeys = Object.keys(previous.overrides).filter(isAuditOverride);\n const lasting = Object.fromEntries(Object.entries(previous.overrides).filter(([key]) => !isAuditOverride(key)));\n const updatesManifests = Object.keys(edits.manifests).length > 0;\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 = ''): false => {\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 return false;\n };\n\n const staging = await createStaging(forkPath, workspaceYaml);\n try {\n for (const [file, content] of Object.entries(edits.manifests)) writeFileSync(join(staging, file), content);\n\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) {\n const without = updatesManifests ? 'with the selected updates' : 'without its audit overrides';\n return fail(`could not resolve the workspace ${without}`, bare.error);\n }\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 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 false;\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 false;\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 const settingsChanged = nextYaml !== workspaceYaml;\n\n const otherFiles = Object.keys(edits.files);\n const writeFiles = (): void => {\n for (const [file, content] of Object.entries(edits.files)) writeFileSync(join(forkPath, file), content);\n if (otherFiles.length > 0) console.info(`${checkMark} ${otherFiles.join(', ')} updated`);\n };\n\n if (!settingsChanged && !updatesManifests) {\n writeFiles();\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 true;\n }\n\n const summarize = (): void => {\n if (!settingsChanged) return;\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 (!updatesManifests && sameEntries(next.overrides, previous.overrides)) {\n writeFiles();\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 true;\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 const written = { ...edits.files, ...edits.manifests, [WORKSPACE_FILE]: nextYaml, [LOCK_FILE]: staged.lock };\n const before = Object.fromEntries(Object.keys(written).map((file) => [file, readOr(join(forkPath, file))]));\n before[WORKSPACE_FILE] = workspaceYaml;\n before[LOCK_FILE] = workspaceLock;\n for (const [file, content] of Object.entries(written)) writeFileSync(join(forkPath, file), content);\n const install = spawnSync('pnpm', ['install'], { cwd: forkPath, stdio: 'inherit' });\n console.info();\n if (install.status !== 0) {\n for (const [file, content] of Object.entries(before)) writeFileSync(join(forkPath, file), content);\n console.error(`${pc.red('✗')} pnpm install failed (exit code ${install.status})`);\n console.info(pc.dim(` ${Object.keys(before).join(', ')} are back as they were; run pnpm install to match`));\n console.info();\n return false;\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 return true;\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 the cella 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, openInBrowser, writeDiffPage } 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 const page = await writeDiffPage(\n [{ files: [{ path, patch: patch.toString() }] }],\n { title: path, note: `cella ← → ${forkName}` },\n cwd,\n path,\n );\n setStatusMsg(openInBrowser(page) ? `opened ${path} in browser` : `diff page: ${page}`);\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 * 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 { runUpgradeCommand } from './upgrade';\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 // Last upgrade: 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 upgraded');\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/** Upgrade 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(`upgrading ${fork.name}...`));\n console.info(pc.dim(`path: ${forkPath}`));\n console.info();\n\n const forkConfig = await loadConfig(forkPath);\n await runUpgradeCommand({\n ...forkConfig,\n forkPath,\n upstreamRef: resolveUpstream(forkConfig.settings).branchRef,\n service: 'upgrade',\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 upgrade:',\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 * Upgrade 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 upgrade` 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 { alignmentUrl, listAlignmentIds, readAlignment, readPending } from '../utils/alignments';\nimport pc from '../utils/colors';\nimport {\n buildTemporarySyncBranch,\n isTemporarySyncBranch,\n resolveReleaseBase,\n TEMPORARY_BRANCH_PREFIXES,\n} from '../utils/config';\nimport {\n COMMIT_LIST_MAX,\n checkMark,\n createSpinner,\n hyperlink,\n type NextStep,\n plural,\n printEngineReports,\n printNextSteps,\n printStep,\n printSyncComplete,\n printUpstreamOverrideChanges,\n spinnerFail,\n spinnerSuccess,\n warningMark,\n} from '../utils/display';\nimport { errorMessage } from '../utils/errors';\nimport { closePr, createPr, 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 { alignmentsStep, readOpenAlignments } from './align';\nimport {\n BehindSyncPointError,\n readOriginGitHubUrl,\n runEngineWithSpinner,\n UpstreamConfigChangedError,\n} from './merge-engine';\nimport { runPackages } from './packages';\nimport { existingSyncReviewPage, type ReviewPageReport, reportReviewPage, reviewStep } from './review-page';\n\n/** Context for the temporary branch a sync cycle runs on. */\ninterface TemporarySyncBranch {\n /** The freshly cut temporary branch, e.g. `cella/upgrade/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 the upgrade.`,\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/upgrade/<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 upgrade 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/** A sync's merge result, with the review page the run wrote. */\nexport interface SyncRunResult extends MergeResult {\n reviewPage?: ReviewPageReport;\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<SyncRunResult> {\n createSpinner('starting upgrade...');\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 CLI 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('upgrade merge completed with conflicts');\n }\n\n // Print summary (no file lists for an upgrade) 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 const reviewPage = await reportReviewPage(config.forkPath, result, 'upgrade');\n\n return { ...result, reviewPage };\n}\n\n/** Conflicted files the `resolve` step lists before it counts the rest. */\nconst CONFLICTS_LISTED = 10;\n\n/**\n * The `align` step after a sync run: from the merge result when this run merged, otherwise from\n * the fork's sync point and pending list.\n */\nasync function syncAlignmentsStep(config: RuntimeConfig, run?: MergeResult): Promise<NextStep | undefined> {\n if (run?.alignments && run.upstreamCommit) {\n const { open, arrived } = run.alignments;\n return alignmentsStep(config, { ref: run.upstreamCommit.hash, open, arrived });\n }\n const view = await readOpenAlignments(config);\n return view ? alignmentsStep(config, view) : undefined;\n}\n\n/** The review page of this sync: the one this run wrote, or on a rerun the one the merge run left. */\nfunction syncReviewStep(config: RuntimeConfig, run?: SyncRunResult): NextStep | undefined {\n const page = run ? run.reviewPage : existingSyncReviewPage(config.forkPath);\n return page ? reviewStep(page) : undefined;\n}\n\n/** Next steps while a sync branch holds conflicts: resolve, let a rerun commit, review, align. */\nasync function conflictSteps(config: RuntimeConfig, conflicts: string[], run?: SyncRunResult): Promise<NextStep[]> {\n const listed = conflicts.slice(0, CONFLICTS_LISTED).map((file) => pc.dim(file));\n if (conflicts.length > CONFLICTS_LISTED) listed.push(pc.dim(`+ ${conflicts.length - CONFLICTS_LISTED} more`));\n const steps: Array<NextStep | undefined> = [\n {\n label: 'resolve',\n line: `${plural(conflicts.length, 'conflict')} in your editor, then stage them`,\n details: listed,\n },\n {\n label: 'finish',\n line: 'pnpm cella upgrade',\n details: [\n pc.dim('commits the upgrade and stops for drift triage'),\n pc.dim('let the rerun commit: a manual `git commit` records a merge commit that bloats the PR'),\n ],\n },\n syncReviewStep(config, run),\n await syncAlignmentsStep(config, run),\n ];\n return steps.filter((step): step is NextStep => !!step);\n}\n\n/** Conventional PR title prefix required by release-please. */\nconst UPGRADE_PR_TITLE = 'chore: upgrade cella';\n\n/**\n * Build the upgrade commit subject, e.g. `chore: upgrade cella to 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 UPGRADE_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\n ? `${UPGRADE_PR_TITLE} to v${version.replace(/^v/, '')} (${shortSha})`\n : `${UPGRADE_PR_TITLE} to ${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 alignments at the sync point: the total, and the ones the app has not handled yet. */\n alignments?: { 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, alignments } = 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 = [`Upgrades ${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(\n '',\n `**${totalCount} upstream commit${totalCount === 1 ? '' : 's'} since the last upgrade**${compare}:`,\n '',\n );\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 (alignments && alignments.total > 0) {\n const { total, open } = alignments;\n if (open.length === 0) lines.push('', `**Alignments**: all ${total} handled.`);\n else {\n lines.push(\n '',\n `**Alignments**: ${Math.max(0, total - open.length)} of ${total} handled, open (\\`pnpm cella align\\`):`,\n '',\n );\n for (const alignment of open)\n lines.push(\n `- ${alignment.url ? `[${alignment.title}](${alignment.url})` : alignment.title} (\\`${alignment.id}\\`)`,\n );\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-upgrade` 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 alignments = await readPrBodyAlignments(forkPath, toSha, manifest.upstream.repo).catch(() => undefined);\n return buildSyncPrBody({\n repoSlug: manifest.upstream.repo,\n version,\n fromSha,\n toSha,\n commits,\n totalCount,\n alignments,\n });\n}\n\n/** Alignments for the PR body: the total at the sync point and the app's open ones, with permalinks. */\nasync function readPrBodyAlignments(\n forkPath: string,\n toSha: string,\n repoSlug?: string,\n): Promise<SyncPrBodyInput['alignments']> {\n const githubUrl = repoSlug ? `https://github.com/${repoSlug}` : undefined;\n const [ids, pending] = await Promise.all([listAlignmentIds(forkPath, toSha), readPending(forkPath)]);\n const open = await Promise.all(\n pending.map(async (id) => ({\n id,\n title: (await readAlignment(forkPath, toSha, id))?.title ?? id,\n url: alignmentUrl(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 = UPGRADE_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) : UPGRADE_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 repoSlug = (await readOriginGitHubUrl(forkPath))?.replace('https://github.com/', '') ?? null;\n const pr = createPr(forkPath, repoSlug, { base, head: branch, title: prTitle, body: prBody });\n prUrl = pr.url;\n prOpened = pr.ok;\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} upgrade pull request ${prOpened ? 'opened' : 'ready'}`);\n console.info(pc.dim(` ${prUrl} · branch pushed, ${position}`));\n } else {\n console.info(`${checkMark} upgrade branch pushed`);\n console.info(pc.dim(` '${branch}' is on origin, ${position}`));\n }\n const steps: Array<NextStep | undefined> = [\n prUrl\n ? {\n label: 'merge',\n line: hyperlink(pc.cyan(prUrl), prUrl),\n details: [pc.dim(`squash-merge it into '${base}'; the next upgrade offers to while it is open`)],\n }\n : undefined,\n await syncAlignmentsStep(config),\n ];\n printNextSteps(steps.filter((step): step is NextStep => !!step));\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, with its merge result when it merged. */\ntype SyncCycleOutcome =\n | { status: 'conflicts'; branch: TemporarySyncBranch; result: SyncRunResult }\n | { status: 'staged'; branch: TemporarySyncBranch; result: SyncRunResult }\n | { status: 'noop'; behind?: string; result?: SyncRunResult };\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: SyncRunResult;\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 upgrade went past is nothing to upgrade, 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.mergePackageJson !== false) {\n // Merge package.json keys even when the merge left conflicts: package.json files that are\n // themselves conflicted are skipped and reported; all others still merge.\n await runPackages(config, { conflictedFiles: result.conflicts });\n }\n\n if (result.conflicts.length > 0) return { status: 'conflicts', branch, result };\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', result };\n }\n\n return { status: 'staged', branch, result };\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 * `run` is the merge this run made, absent when it resumes an earlier run's merge.\n */\nasync function commitSyncMerge(config: RuntimeConfig, branch: string, run?: SyncRunResult): Promise<void> {\n const { forkPath } = config;\n const conflicts = await getConflictedFiles(forkPath);\n\n console.info();\n if (conflicts.length > 0) {\n printStep('conflicts', `${plural(conflicts.length, 'file')} still conflict on '${branch}'`, warningMark);\n printNextSteps(await conflictSteps(config, conflicts, run));\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 printStep('checks', '`pnpm install` or `pnpm check` failed', warningMark);\n printNextSteps([\n { label: 'fix', line: 'what failed above', details: [pc.dim(`the merge stays staged on '${branch}'`)] },\n {\n label: 'finish',\n line: 'pnpm cella upgrade',\n details: [pc.dim('commits the upgrade and stops for drift triage')],\n },\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 printStep('committed', `${message}\\n${pc.dim(`on '${branch}', not pushed`)}`);\n const steps: Array<NextStep | undefined> = [\n syncReviewStep(config, run),\n {\n label: 'triage',\n line: 'pnpm cella analyze',\n details: [pc.dim('drift triage: commit any follow-ups on this branch')],\n },\n await syncAlignmentsStep(config, run),\n { label: 'ship', line: 'pnpm cella upgrade', details: [pc.dim('pushes the branch and opens the squash-merge PR')] },\n ];\n printNextSteps(steps.filter((step): step is NextStep => !!step));\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 upgrade\\`:`));\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, TEMPORARY_BRANCH_PREFIXES);\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 upgrade PRs are` : 'an earlier upgrade 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(\n pc.dim(` starting a new upgrade now produces a PR that re-includes ${many ? 'these' : 'those'} changes.`),\n );\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 upgrade ${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 upgrade` command. Idempotent: each run advances the upgrade one stage\n * (cut and merge, commit, ship) and never commits and ships in the same run.\n */\nexport async function runUpgradeCommand(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 `upgrade 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 upgrading.');\n }\n if ((await guardAgainstOpenSyncPr(config)) === 'cancel') return;\n\n const outcome = await runSyncCycle(config);\n\n if (outcome.status === 'noop') {\n console.info();\n if (outcome.behind) {\n console.info(pc.green('nothing to upgrade: the last upgrade 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 upgrade.'));\n }\n const align = await syncAlignmentsStep(config, outcome.result);\n if (align) printNextSteps([align]);\n return;\n }\n\n const { temporaryBranch } = outcome.branch;\n if (outcome.status === 'conflicts') {\n const conflicts = await getConflictedFiles(forkPath);\n printStep('conflicts', `${plural(conflicts.length, 'file')} on '${temporaryBranch}'`, warningMark);\n printNextSteps(await conflictSteps(config, conflicts, outcome.result));\n return;\n }\n\n await commitSyncMerge(config, temporaryBranch, outcome.result);\n}\n","/**\n * GitHub CLI (`gh`) helpers for the cella CLI.\n *\n * Thin wrappers around `gh` used by the sync service to open, 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 upgrade PRs (head branch under one of `prefixes`, e.g. `cella/upgrade/`), 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, prefixes: 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\n .filter((pr) => prefixes.some((prefix) => pr.headRefName.startsWith(`${prefix}/`)))\n .sort((a, b) => b.number - a.number);\n}\n\n/**\n * Open a PR through the GitHub REST API. `gh pr create` goes through GraphQL, which a Claude\n * cloud session's GitHub proxy refuses. `repoSlug` is `owner/repo`; without it `gh` resolves\n * `{owner}/{repo}` from the current repository. When the create fails, `url` is the open PR for\n * the same head branch, if there is one (a PR that already exists gets a 422).\n */\nexport function createPr(\n cwd: string,\n repoSlug: string | null,\n pr: { base: string; head: string; title: string; body: string },\n): GhResult & { url?: string } {\n const repo = repoSlug ?? '{owner}/{repo}';\n const fields = ['title', 'head', 'base', 'body'] as const;\n const created = runGh(cwd, [\n 'api',\n `repos/${repo}/pulls`,\n '-X',\n 'POST',\n ...fields.flatMap((field) => ['-f', `${field}=${pr[field]}`]),\n '--jq',\n '.html_url',\n ]);\n if (created.ok) return { ...created, url: created.output || undefined };\n\n const owner = repoSlug ? repoSlug.split('/')[0] : '{owner}';\n const existing = runGh(cwd, [\n 'api',\n `repos/${repo}/pulls?state=open&head=${owner}:${pr.head}`,\n '--jq',\n '.[0].html_url // empty',\n ]);\n return { ...created, url: existing.ok && existing.output ? existing.output : undefined };\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 merged from upstream into the fork, three-way against the merge-base\n * package.json (upstream as of the previous upgrade):\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 merges, whatever `packageJsonKeys` lists (see mergeModuleType)\n * - A workspace package.json upstream added since the base arrives verbatim\n * Without a base (first upgrade, 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 { PackageJsonKey, RuntimeConfig } from '../config/types';\nimport pc from '../utils/colors';\nimport { DEFAULT_PACKAGE_JSON_KEYS } 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 PackageJsonKey[] = [\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 `packageJsonKeys` 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: PackageJsonKey[],\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 an upgrade merge that left conflicts),\n * any package.json that is itself unmerged is skipped to avoid clobbering\n * conflict markers; all other package.json files still merge.\n */\nexport async function runPackages(config: RuntimeConfig, options: { conflictedFiles?: string[] } = {}): Promise<void> {\n createSpinner('merging package.json files...');\n\n const keysToSync = config.settings.packageJsonKeys || DEFAULT_PACKAGE_JSON_KEYS;\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(`merging ${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.json merge complete',\n `${plural(changedCount, 'package.json was', 'package.jsons 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 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 upgrade\\`:`,\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":"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","names":["existsSync","statSync","join","resolve","process","process","process","process","process","existsSync","join","z","join","pad","existsSync","z","resolve","process","existsSync","mkdir","dirname","join","resolve","join","existsSync","resolve","dirname","join","mkdir","process","count","process","resolve","byPath","count","existsSync","join","existsSync","mkdir","readFile","writeFile","dirname","join","join","existsSync","readFile","mkdir","dirname","writeFile","existsSync","join","process","mkdir","writeFile","dirname","join","process","existsSync","rm","join","Project","SyntaxKind","SyntaxKind","Project","count","status","upstreamChanged","upstreamOnly","upstreamShort","hint","existsSync","join","rm","process","join","mkdir","dirname","writeFile","basename","count","basename","existsSync","basename","process","execFileSync","dirname","join","process","execFileSync","index","count","hint","dirname","join","process","count","basename","process","existsSync","readFileSync","basename","join","relative","execFile","promisify","execFileAsync","promisify","execFile","str","execFile","existsSync","realpathSync","dirname","join","sep","promisify","readFileSync","basename","dirname","join","basename","readFileSync","join","plural","dirname","execFileAsync","promisify","execFile","sep","existsSync","join","realpathSync","dirname","spawnSync","existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","tmpdir","dirname","join","relative","select","existsSync","readFileSync","count","plural","join","tmpdir","relative","mkdirSync","dirname","writeFileSync","select","spawnSync","rmSync","readFileSync","join","basename","count","packageJsonPath","relative","select","rmSync","dirname","join","resolve","dirname","resolve","join","rmSync","existsSync","dirname","resolve","dirname","resolve","existsSync","page","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"]}
|