@cellajs/cli 0.6.2 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cella-cli.ts","../src/cli.ts","../src/utils/colors.ts","../src/utils/env.ts","../src/utils/config.ts","../src/config/types.ts","../src/utils/errors.ts","../src/utils/managed-files.ts","../src/utils/module-territory.ts","../src/utils/display.ts","../package.json","../src/utils/git.ts","../src/utils/manifest.ts","../src/utils/layout.ts","../src/utils/overrides.ts","../src/utils/alignments.ts","../src/utils/upstream-overrides.ts","../src/services/align.ts","../src/services/merge-engine.ts","../src/utils/versions.ts","../src/utils/cli-version.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.2\",\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, git, listChangedSinceRef, revParse } from './git';\nimport { CONFIG_FILE, isGeneratedFile, isManagedFile } from './managed-files';\nimport { parseOverrideLists } from './upstream-overrides';\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 // A pin upstream's own config lists is a file the template leaves to the app: identical until the app fills it in.\n const upstreamSource = await git(['show', `${upstream}:${CONFIG_FILE}`], forkPath, { ignoreErrors: true });\n const upstreamPins = (upstreamSource && parseOverrideLists(upstreamSource)?.pinned.map(normalizeEntry)) || [];\n for (const entry of pinsUpstreamHas) {\n if (differs.some((changed) => isUnderAnyFolder(changed, [entry]))) continue;\n if (upstreamPins.includes(normalizeEntry(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 * 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 * 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 * 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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\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), and what pnpm audit\n * reports before the prompt that the security pass waits for.\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 { checkMark, 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 { type Advisory, 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 advisories = auditResult ? advisoriesFromAudit(auditResult) : null;\n const rows = [\n ...packageRows(outdated as Record<string, OutdatedPackage>, advisories ?? []),\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 printReported(advisories);\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 most severe advisory on a package; null when it has none. */\nconst worstSeverity = (advisories: Advisory[], name: string) =>\n SEVERITIES.find((severity) => advisories.some((a) => a.module === name && a.severity === severity)) ?? null;\n\n/** The outdated packages as table rows, sorted by the workspaces that depend on them. */\nfunction packageRows(outdated: Record<string, OutdatedPackage>, advisories: Advisory[]) {\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: worstSeverity(advisories, 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/**\n * What pnpm audit reports on the workspace as it stands, most severe first. A transitive package has\n * no row in the table, and a cancelled prompt never reaches the security pass.\n */\nfunction printReported(advisories: Advisory[] | null): void {\n if (!advisories) {\n console.info(`${warningMark} pnpm audit gave no answer: a row in the table can lack its dot`);\n console.info();\n return;\n }\n if (advisories.length === 0) {\n console.info(`${checkMark} pnpm audit reports nothing ${pc.dim('· with the current overrides and ignores')}`);\n console.info();\n return;\n }\n\n const modules = [...new Set(advisories.map((a) => a.module))].map((name) => {\n const own = advisories.filter((a) => a.module === name);\n return {\n name,\n severity: worstSeverity(own, name) ?? own[0].severity,\n installed: [...new Set(own.flatMap((a) => a.installed))].join(', '),\n via: formatDependents([...new Set(own.flatMap((a) => a.via))]),\n direct: own.some((a) => a.direct),\n };\n });\n modules.sort((a, b) => SEVERITIES.indexOf(a.severity) - SEVERITIES.indexOf(b.severity));\n const nameWidth = Math.min(30, Math.max(...modules.map((m) => m.name.length)));\n const versionWidth = Math.max(...modules.map((m) => m.installed.length));\n\n console.info(`${pc.bold('pnpm audit')} ${pc.dim('· with the current overrides and ignores')}`);\n for (const m of modules) {\n const name = pc.white(middleTruncate(m.name, nameWidth).padEnd(nameWidth));\n const source = `${m.via}${m.direct ? ' (direct)' : ''}`;\n console.info(\n `${getVulnIcon(m.severity)} ${name} ${m.severity.padEnd(8)} ${m.installed.padEnd(versionWidth)} ${pc.dim(source)}`,\n );\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","Project","SyntaxKind","SyntaxKind","Project","count","existsSync","join","process","mkdir","writeFile","dirname","join","process","existsSync","rm","join","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"]}
1
+ {"version":3,"sources":["../src/cella-cli.ts","../src/cli.ts","../src/utils/app-facts.ts","../src/utils/env.ts","../src/tools/drive.ts","../src/tools/testbed.ts","../src/utils/colors.ts","../src/utils/display.ts","../package.json","../src/utils/git.ts","../src/utils/manifest.ts","../src/utils/layout.ts","../src/utils/managed-files.ts","../src/utils/signals.ts","../src/tools/a11y/audit.ts","../src/tools/a11y/axe-scan.ts","../src/tools/a11y/criteria.ts","../src/tools/a11y/session.ts","../src/tools/adapters.ts","../src/tools/a11y/define.ts","../src/tools/a11y/scope.ts","../src/tools/a11y/code-checks.ts","../src/tools/a11y/findings.ts","../src/tools/a11y/ledger.ts","../src/tools/a11y/probes/page-structure.ts","../src/tools/a11y/probes/contrast.ts","../src/tools/a11y/probes/forms.ts","../src/tools/a11y/review-packet.ts","../src/tools/a11y/probes/keyboard.ts","../src/tools/a11y/probes/layout.ts","../src/tools/a11y/visit.ts","../src/tools/a11y/decide.ts","../src/tools/a11y/report.ts","../src/tools/a11y/index.ts","../src/tools/bench/command.ts","../src/tools/bench/request.ts","../src/tools/i18n/index.ts","../src/tools/i18n/rename.ts","../src/tools/i18n/locales.ts","../src/tools/i18n/scan.ts","../src/tools/i18n/parity.ts","../src/tools/i18n/status.ts","../src/tools/i18n/unused.ts","../src/services/fork-utils.ts","../src/utils/config.ts","../src/config/types.ts","../src/utils/errors.ts","../src/utils/module-territory.ts","../src/tools/pentest/index.ts","../src/tools/pentest/adapter.ts","../src/tools/pentest/probe.ts","../src/tools/pentest/report.ts","../src/tools/pentest/scanners.ts","../src/tools/pentest/sessions.ts","../src/tools/screenshots/shoot.ts","../src/tools/screenshots/define.ts","../src/tools/screenshots/index.ts","../src/tools/style/index.ts","../src/utils/alignments.ts","../src/tools/style/repo.ts","../src/tools/style/alignment-rules.ts","../src/tools/style/comment-rules.ts","../src/tools/style/prose-rules.ts","../src/tools/style/source-comments.ts","../src/tools/style/doc-rules.ts","../src/tools/style/frontend-rules.ts","../src/tools/style/stamp-rules.ts","../src/tools/style/tailwind-class-rules.ts","../src/tools/style/class-tokens.ts","../src/tools/style/text-color-rules.ts","../src/tools/style/token-contrast-rules.ts","../src/tools/style/vocabulary-rules.ts","../src/tools/index.ts","../src/utils/overrides.ts","../src/utils/upstream-overrides.ts","../src/services/align.ts","../src/services/merge-engine.ts","../src/utils/versions.ts","../src/utils/cli-version.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/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, runs a tool command without the\n * upgrade config, or loads the config and routes to the selected upstream service.\n */\n\nimport { existsSync, statSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport process from 'node:process';\nimport { parseCli, parseToolCommand, type ToolSelection } 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 { printHeader } from './utils/display';\nimport { getEnv } from './utils/env';\nimport { errorMessage } from './utils/errors';\nimport { installSignalHandlers } from './utils/signals';\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 runTool({ tool, options }: ToolSelection, forkPath: string): Promise<void> {\n preflight(forkPath);\n process.exitCode = await tool.run(forkPath, options);\n}\n\nasync function main(): Promise<void> {\n installSignalHandlers();\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 tool = parseToolCommand(process.argv);\n if (tool) {\n // A gate prints its verdict alone: CI logs and agents read it\n const gate = tool.tool.group === 'gate';\n if (!gate) printHeader();\n await runTool(tool, forkPath);\n if (!gate) console.info();\n return;\n }\n\n const userConfig = await loadConfig(forkPath);\n\n const config = await parseCli(userConfig, forkPath);\n if ('tool' in config) {\n await runTool(config, forkPath);\n console.info();\n return;\n }\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 command definitions, commander wiring, and the\n * interactive menu, resolved into a RuntimeConfig or a tool command to run.\n */\n\nimport process from 'node:process';\nimport { select } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport type {\n AnalyzeScope,\n CellaCliConfig,\n CommandGroup,\n CommandOption,\n RuntimeConfig,\n SyncService,\n ToolCommand,\n} from './config/types';\nimport { toolCommands } from './tools';\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\n/** A tool command and the options it parsed for itself. */\nexport type ToolSelection = { tool: ToolCommand; options: unknown };\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 ServiceDefinition = {\n name: SyncService;\n /** Upstream unless set. */\n group?: CommandGroup;\n description: string;\n options?: CommandOption[];\n /** Arguments the service takes after its options, e.g. the ones `align --run` hands to the codemod. */\n operands?: CommandOption;\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: CommandOption = ['--json', 'machine-readable output for tooling/agents'];\nconst trackOption: CommandOption = ['--track <mode>', 'override upstream tracking for this run: release|branch'];\nconst refOption: CommandOption = ['--ref <ref>', 'pin the upstream commit for this run: sha, release tag or branch'];\nconst unpinnedOption: CommandOption = [\n '--unpinned',\n 'lift every pinned entry for this run (managed files stay pinned) and merge from the full upstream history',\n];\nconst forkOption: CommandOption = ['--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 group: 'security',\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\nconst groupOrder: CommandGroup[] = ['develop', 'security', 'upstream', 'gate'];\n\nconst groupHeadings: Record<CommandGroup, string> = {\n develop: 'Develop commands:',\n security: 'Security commands:',\n upstream: 'Upstream commands:',\n gate: 'Gate commands:',\n};\n\nconst serviceGroup = (definition: ServiceDefinition): CommandGroup => definition.group ?? 'upstream';\n\nfunction buildMenuChoices(context: MenuContext) {\n // Pad labels to align descriptions (longest label is 'contributions').\n const label = (name: string) => name.padEnd(14);\n const entries: { name: string; group: CommandGroup; description: string }[] = [\n ...serviceDefinitions\n .filter((service) => service.includeInMenu?.(context) ?? true)\n .map((service) => ({ name: service.name, group: serviceGroup(service), description: service.description })),\n ...toolCommands.filter((tool) => tool.group !== 'gate'),\n ];\n\n return [\n ...groupOrder.flatMap((group) => {\n const inGroup = entries.filter((entry) => entry.group === group);\n if (inGroup.length === 0) return [];\n return [\n { type: 'separator' as const, separator: pc.dim(group) },\n ...inGroup.map((entry) => ({ value: entry.name, name: `${label(entry.name)}${pc.dim(entry.description)}` })),\n ];\n }),\n { type: 'separator' as const, separator: MENU_DIVIDER },\n { value: 'exit', 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\n .command(name, { hidden: !!renamedFrom })\n .description(definition.description)\n .helpGroup(groupHeadings[serviceGroup(definition)]);\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\n/** The words of `argv` after the `--` that follows the command name. */\nfunction wordsAfterDash(argv: string[], commandName: string): string[] {\n const dash = argv.indexOf('--', argv.indexOf(commandName));\n return dash === -1 ? [] : argv.slice(dash + 1);\n}\n\nfunction addToolCommand(\n program: Command,\n tool: ToolCommand,\n argv: string[],\n setSelection: (selection: ToolSelection) => void,\n) {\n const jobs = tool.jobs.map(([name]) => name);\n const command = program.command(tool.name).description(tool.description).helpGroup(groupHeadings[tool.group]);\n if (jobs.length > 0) command.argument('[job]', `${jobs.join('|')} (default: ${jobs[0]})`);\n // Commander takes one variadic argument, the last: the command's own words, else the words after `--`\n if (tool.operands) command.argument(...tool.operands);\n else if (tool.passthrough) command.argument(`[${tool.passthrough[0]}...]`, tool.passthrough[1]);\n for (const option of tool.options ?? []) command.option(...option);\n\n command.action((...args: unknown[]) => {\n const declared = command.registeredArguments.length;\n const words = args\n .slice(0, declared)\n .flat()\n .filter((word) => typeof word === 'string');\n const opts = args[declared] as Record<string, unknown>;\n // Commander puts the words after `--` among the operands; the job and operands are what comes before them\n const passthrough = wordsAfterDash(argv, tool.name);\n const before = words.slice(0, words.length - passthrough.length);\n const job = jobs.length > 0 ? before[0] : undefined;\n const operands = jobs.length > 0 ? before.slice(1) : before;\n if (!tool.operands && operands.length > 0) {\n const hint = tool.passthrough ? '. a command to run goes after --' : '';\n throw new Error(`unexpected argument '${operands[0]}'${hint}`);\n }\n setSelection({ tool, options: tool.parse({ job, operands, opts, passthrough }) });\n });\n}\n\nfunction buildProgram(\n argv: string[],\n setSelection: (selection: CliServiceSelection) => void,\n setToolSelection: (selection: ToolSelection) => void,\n): Command {\n const program = new Command('cella')\n .version(VERSION, '-v, --version', 'output the current version')\n .usage('[command] [options]')\n .helpOption('-h, --help', 'display help for a command')\n .showHelpAfterError()\n .addHelpText(\n 'after',\n [\n '',\n 'Examples:',\n ' $ cella testbed',\n ' $ cella testbed -- node cella/skills/verify/smoke-driver.mjs',\n ' $ cella bench get-me --short --isolated',\n ' $ cella a11y --states sign-in,home',\n ' $ cella a11y decide --file decisions.json',\n ' $ cella screenshots settings',\n ' $ cella i18n unused --json',\n ' $ cella i18n rename c:old_key c:new_key',\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 ' $ cella style frontend/src',\n ].join('\\n'),\n );\n\n // Commander lists the help groups in the order their first command was added\n for (const group of groupOrder) {\n for (const definition of serviceDefinitions.filter((service) => serviceGroup(service) === group)) {\n addServiceCommand(program, definition, setSelection);\n }\n for (const tool of toolCommands.filter((command) => command.group === group)) {\n addToolCommand(program, tool, argv, setToolSelection);\n }\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(\n argv,\n (nextSelection) => {\n selection = nextSelection;\n },\n () => {},\n );\n\n program.parse(argv);\n return selection;\n}\n\n/** The tool command `argv` names, parsed; undefined when it names none. Tool commands load no upgrade config. */\nexport function parseToolCommand(argv: string[]): ToolSelection | undefined {\n if (!toolCommands.some((tool) => tool.name === argv[2])) return undefined;\n\n let selection: ToolSelection | undefined;\n const program = buildProgram(\n argv,\n () => {},\n (nextSelection) => {\n selection = nextSelection;\n },\n );\n program.parse(argv);\n return selection;\n}\n\nasync function promptForCommand(userConfig: CellaCliConfig, forkPath: string): Promise<SyncService | ToolSelection> {\n const selected = await select<string>({\n message: 'choose a command:',\n choices: buildMenuChoices(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 const tool = toolCommands.find((command) => command.name === selected);\n if (tool) {\n const job =\n tool.jobs.length > 1\n ? await select<string>({\n message: `${tool.name}:`,\n choices: tool.jobs.map(([name, description]) => ({\n value: name,\n name: `${name.padEnd(14)}${pc.dim(description)}`,\n })),\n loop: false,\n })\n : undefined;\n console.info();\n return { tool, options: tool.parse({ job, operands: [], opts: {}, passthrough: [] }) };\n }\n\n console.info();\n const service = serviceDefinitions.find((definition) => definition.name === selected);\n if (!service) throw new Error(`unknown command '${selected}'`);\n return service.name;\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\n/** The upstream command to run with its config, or the tool command picked from the menu. */\nexport async function parseCli(userConfig: CellaCliConfig, forkPath: string): Promise<RuntimeConfig | ToolSelection> {\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 const picked = await promptForCommand(userConfig, forkPath);\n if (typeof picked !== 'string') return picked;\n selection.service = picked;\n }\n\n return buildRuntimeConfig(userConfig, forkPath, selection, branchRef);\n}\n","import { execFileSync, spawnSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { z } from 'zod';\nimport { setEnv } from './env';\n\nconst appConfigSchema = z.object({\n frontendUrl: z.string(),\n backendUrl: z.string(),\n devPortOffset: z.number(),\n services: z.record(\n z.string(),\n z.object({ enabled: z.boolean(), port: z.number(), internalPort: z.number().optional() }),\n ),\n});\n\n/** The part of the app's development config the develop commands read. */\nexport type AppFacts = z.infer<typeof appConfigSchema>;\n\n/** The app's local database helpers (`shared/src/local-database.ts`), as the develop commands call them. */\nexport interface LocalDatabases {\n port: (database: string) => number;\n url: (database: string, role: 'postgres' | 'runtime_role' | 'admin_role') => string;\n /** The env `backend/compose.yaml` reads: the project name and each database's host port. */\n composeEnv: () => Record<string, string>;\n}\n\n/** Node strips the types of a file outside node_modules, so the app's own TS loads without a build or tsx. */\nexport async function importFromApp(forkPath: string, file: string): Promise<Record<string, unknown>> {\n const path = join(forkPath, file);\n if (!existsSync(path)) throw new Error(`not an app built from cella: ${path} is missing`);\n // The app's config reads the mode once, at its first import, and the dev port offset applies in development mode only\n setEnv('NODE_ENV', 'development');\n return import(pathToFileURL(path).href);\n}\n\n/**\n * The app's config in development mode, from its own `shared` package. In a linked worktree the import claims that\n * worktree's port slot, as `pnpm dev` would.\n */\nexport async function loadAppFacts(forkPath: string): Promise<AppFacts> {\n const parsed = appConfigSchema.safeParse((await importFromApp(forkPath, 'shared/index.ts')).appConfig);\n if (!parsed.success)\n throw new Error(`shared/index.ts exports no appConfig this CLI can read: ${parsed.error.message}`);\n return parsed.data;\n}\n\n/** The app's local database helpers. */\nexport async function loadLocalDatabases(forkPath: string): Promise<LocalDatabases> {\n const module = await importFromApp(forkPath, 'shared/src/local-database.ts');\n const { localDatabasePort, localDatabaseUrl, composeEnv } = module;\n if (\n typeof localDatabasePort !== 'function' ||\n typeof localDatabaseUrl !== 'function' ||\n typeof composeEnv !== 'function'\n ) {\n throw new Error('shared/src/local-database.ts lacks localDatabasePort, localDatabaseUrl or composeEnv');\n }\n return {\n port: (database) => localDatabasePort(database),\n url: (database, role) => localDatabaseUrl(database, role),\n composeEnv: () => composeEnv(),\n };\n}\n\n/**\n * A package as the app's `workspace` installed it, so a tool drives the app's own Playwright, TypeScript or Tailwind and\n * the CLI ships none. The package's ESM entry when it has one, else its CommonJS exports.\n * @throws when the workspace does not have the package installed\n */\nexport async function importFromWorkspace<T>(forkPath: string, workspace: string, name: string): Promise<T> {\n const require = createRequire(join(forkPath, workspace, 'package.json'));\n let manifestPath: string | undefined;\n try {\n manifestPath = require.resolve(`${name}/package.json`);\n } catch {\n // A package whose exports leave out package.json resolves by its main entry below\n }\n const root = manifestPath ? JSON.parse(readFileSync(manifestPath, 'utf8')).exports?.['.'] : undefined;\n const esm = typeof root?.import === 'string' ? root.import : root?.import?.default;\n if (manifestPath && typeof esm === 'string') return import(pathToFileURL(join(dirname(manifestPath), esm)).href);\n try {\n return require(name);\n } catch {\n throw new Error(`${name} is not installed in ${workspace}: run \\`pnpm --filter ${workspace} add -D ${name}\\``);\n }\n}\n\n/**\n * A Docker image as a tool runs it, pinned by digest (`name[:tag]@sha256:…`) so every run scans with the same code.\n * Pulls it on first use; the pull shows Docker's own progress.\n * @throws when the reference has no digest, Docker does not answer, or the pull fails\n */\nexport function resolveImage(reference: string): string {\n if (!/@sha256:[0-9a-f]{64}$/.test(reference)) throw new Error(`${reference} is not pinned by digest`);\n if (spawnSync('docker', ['info'], { stdio: 'ignore' }).status !== 0) {\n throw new Error('Docker does not answer: start Docker (or OrbStack) first');\n }\n if (spawnSync('docker', ['image', 'inspect', reference], { stdio: 'ignore' }).status === 0) return reference;\n if (spawnSync('docker', ['pull', reference], { stdio: ['ignore', 'inherit', 'inherit'] }).status !== 0) {\n throw new Error(`could not pull ${reference}`);\n }\n return reference;\n}\n\n/**\n * Where a tool keeps its results and state: `<git dir>/cella-<tool>/` of this checkout, or of the git directory every\n * worktree shares. Inside the git directory nothing shows in `git status`.\n */\nexport function toolDir(forkPath: string, tool: string, scope: 'checkout' | 'repository' = 'checkout'): string {\n const flag = scope === 'checkout' ? '--absolute-git-dir' : '--git-common-dir';\n const gitDir = execFileSync('git', ['rev-parse', flag], { cwd: forkPath, encoding: 'utf8' }).trim();\n return join(resolve(forkPath, gitDir), `cella-${tool}`);\n}\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/** Set a variable for this process and the children it spawns from here on. */\nexport function setEnv(name: string, value: string): void {\n // biome-ignore lint/style/noProcessEnv: This module centralizes intentional CLI environment access.\n process.env[name] = value;\n}\n","import { spawnSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport process from 'node:process';\nimport type { Browser, BrowserContext, BrowserContextOptions, Page } from 'playwright';\nimport { importFromWorkspace } from '../utils/app-facts';\n\nexport type { Browser, BrowserContext, BrowserContextOptions, Page } from 'playwright';\n\nexport type Playwright = typeof import('playwright');\n\n/** A signed-in user of the app: where it answers and the cookie that signs a browser or a request in. */\nexport interface Session {\n email: string;\n frontendUrl: string;\n /** The API, a path under the frontend's origin. */\n backendUrl: string;\n /** The app's slug, read off the cookie name; the persisted UI store's key starts with it. */\n slug: string;\n /** In the shape `context.addCookies` takes. */\n cookie: { name: string; value: string; url: string; httpOnly: true; sameSite: 'Strict' };\n /** `name=value`, for a request's cookie header. */\n header: string;\n}\n\nexport interface MintOptions {\n /** The app's root; default the current directory. */\n forkPath?: string;\n /** The environment the mint script runs in: a testbed's names its database. Default this process's. */\n env?: NodeJS.ProcessEnv;\n /** Session lifetime; default 2. */\n hours?: number;\n}\n\n/** Playwright as the app's frontend installed it, so the CLI ships none. */\nexport function loadPlaywright(forkPath = process.cwd()): Promise<Playwright> {\n return importFromWorkspace<Playwright>(forkPath, 'frontend', 'playwright');\n}\n\n/**\n * Checks that Playwright has its Chromium, before anything slow starts.\n * @throws with the install command when it has none\n */\nexport async function requireChromium(forkPath = process.cwd()): Promise<void> {\n const { chromium } = await loadPlaywright(forkPath);\n if (!existsSync(chromium.executablePath())) {\n throw new Error('Playwright has no Chromium yet: run `pnpm --filter frontend exec playwright install chromium`');\n }\n}\n\n/**\n * Signs `email` in through the backend's `session:mint` script, which refuses outside development and test. The script\n * prints `<cookie name>=<signed value>` and a curl line with the API URL, both from the config of the environment it runs\n * in, so a testbed's shifted ports and a linked worktree's are written down nowhere.\n * @throws when the script prints no session, as for an email with no user\n */\nexport function mintSession(email: string, { forkPath = process.cwd(), env, hours = 2 }: MintOptions = {}): Session {\n const minted = spawnSync('pnpm', ['--silent', '--filter', 'backend', 'session:mint', email, String(hours)], {\n cwd: forkPath,\n env,\n encoding: 'utf8',\n });\n const cookie = /^((?:__Host-)?([\\w-]+)-session-v\\d+)=(\\S+)$/m.exec(minted.stdout);\n const api = /^curl (\\S+)\\/me /m.exec(minted.stdout);\n if (!cookie || !api) throw new Error(`could not mint a session for ${email}:\\n${minted.stdout}\\n${minted.stderr}`);\n const frontendUrl = new URL(api[1]).origin;\n return {\n email,\n frontendUrl,\n backendUrl: api[1],\n slug: cookie[2],\n cookie: { name: cookie[1], value: cookie[3], url: frontendUrl, httpOnly: true, sameSite: 'Strict' },\n header: `${cookie[1]}=${cookie[3]}`,\n };\n}\n\n/**\n * Signs a minted session out, so a finished run leaves no live session in the user's sessions list. A JSON content type\n * passes the CSRF check without an Origin header; a stack that is already down leaves the session to expire.\n */\nexport async function signOut(session: Session | null | undefined): Promise<void> {\n if (!session) return;\n const headers = { cookie: session.header, 'content-type': 'application/json' };\n await fetch(`${session.backendUrl}/auth/sign-out`, { method: 'POST', headers }).catch(() => {});\n}\n\nexport interface ContextOptions extends BrowserContextOptions {\n /** Signs the context in. */\n session?: Session;\n /**\n * Fields written into the app's persisted UI store (`<slug>-ui`) before any page script runs, so the first paint is\n * already in the mode they set. Merged into what the store holds: a list joins the stored one, any other value wins.\n */\n uiStore?: { slug: string; state: Record<string, unknown> };\n}\n\n/** A browser context, signed in and with its UI store seeded when asked. */\nexport async function newContext(\n browser: Browser,\n { session, uiStore, ...options }: ContextOptions = {},\n): Promise<BrowserContext> {\n const context = await browser.newContext(options);\n // tsx and esbuild's keepNames wrap named functions in an `__name` helper that a page script does not have\n await context.addInitScript({ content: 'window.__name = (fn) => fn;' });\n if (session) await context.addCookies([session.cookie]);\n if (uiStore) {\n await context.addInitScript(\n ([key, fields]) => {\n const stored = JSON.parse(localStorage.getItem(key) ?? '{}');\n const state = { ...stored.state };\n for (const [name, value] of Object.entries(fields)) {\n const before = state[name];\n state[name] = Array.isArray(value) && Array.isArray(before) ? [...new Set([...before, ...value])] : value;\n }\n // A fresh entry needs the store's own version, or zustand drops it as written by an older build\n localStorage.setItem(key, JSON.stringify({ version: 1, ...stored, state }));\n },\n [`${uiStore.slug}-ui`, uiStore.state] as const,\n );\n }\n return context;\n}\n\n/**\n * Resolves once the page has stopped adding or changing content for `quiet` ms, or after `cap` ms. Lazy sections, query\n * results and opening overlays all show up as DOM changes; the network never goes idle in development.\n */\nexport async function settle(page: Page, { quiet = 400, cap = 3000 } = {}): Promise<void> {\n const waited = page.evaluate(\n ([quietMs, capMs]) =>\n new Promise<void>((resolve) => {\n const done = () => {\n observer.disconnect();\n clearTimeout(timer);\n clearTimeout(limit);\n resolve();\n };\n let timer = setTimeout(done, quietMs);\n const limit = setTimeout(done, capMs);\n const observer = new MutationObserver(() => {\n clearTimeout(timer);\n timer = setTimeout(done, quietMs);\n });\n observer.observe(document, { subtree: true, childList: true, characterData: true });\n }),\n [quiet, cap] as const,\n );\n // A navigation during the wait tears down the page's script context\n await waited.catch(() => page.waitForTimeout(quiet));\n}\n\n/**\n * Opens `url` in a new page and settles once the route has rendered its content.\n * @throws when the route redirects: a check or a shot would judge another page under this one's name\n */\nexport async function openPage(context: BrowserContext, url: string, { timeout = 30_000 } = {}): Promise<Page> {\n const page = await context.newPage();\n await page.goto(url, { waitUntil: 'domcontentloaded', timeout });\n await page.locator('main, [role=\"main\"], #accessibility-content, form, h1, footer').first().waitFor({ timeout });\n await settle(page);\n const landed = new URL(page.url()).pathname;\n const asked = new URL(url).pathname;\n if (landed !== asked) throw new Error(`${asked} redirected to ${landed}`);\n return page;\n}\n","import { type ChildProcess, spawn, spawnSync } from 'node:child_process';\nimport { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { constants } from 'node:os';\nimport { join } from 'node:path';\nimport process from 'node:process';\nimport { parseEnv } from 'node:util';\nimport type { ToolCommand } from '../config/types';\nimport { loadAppFacts, loadLocalDatabases, toolDir } from '../utils/app-facts';\nimport pc from '../utils/colors';\nimport { createSpinner, printStep, spinnerFail } from '../utils/display';\nimport { getEnvSnapshot } from '../utils/env';\nimport { onShutdown } from '../utils/signals';\n\n/** Above the checkout's own ports, clear of `pnpm dev` and of a second stack at offset 50 or 60. */\nconst PORT_SHIFT = 70;\n/** How long the servers get to answer, the frontend build included. */\nconst STARTUP_TIMEOUT_MS = 5 * 60_000;\n/** How long the servers get to exit before they are killed. */\nconst STOP_TIMEOUT_MS = 10_000;\n/** The database's name in `shared/src/local-database.ts` and its service in `backend/compose.yaml`. */\nconst DATABASE = 'testbed';\nconst DATABASE_SERVICE = 'db_testbed';\n\n/**\n * What a testbed's database holds: the app's own seed (`pnpm seed`), or the curated `json/showcase.json` its marketing\n * screenshots show (`pnpm seed showcase`). A start that asks for the other one seeds a new database, and every showcase\n * start does.\n */\nexport type TestbedData = 'seed' | 'showcase';\n\nconst showcasePath = (forkPath: string) => join(forkPath, 'json/showcase.json');\n\n/** Whether the app keeps a showcase for its screenshots. */\nexport const hasShowcase = (forkPath: string) => existsSync(showcasePath(forkPath));\n\n/** The user the showcase seed creates as its admin, and the one a command signs in as. */\nfunction showcaseAdmin(forkPath: string): string {\n const { admin } = JSON.parse(readFileSync(showcasePath(forkPath), 'utf8'));\n if (typeof admin?.email !== 'string') throw new Error('json/showcase.json names no admin email');\n return admin.email;\n}\n\nexport interface TestbedOptions {\n job: 'start' | 'stop';\n /** Start from an empty database. */\n fresh: boolean;\n /** Hold the showcase, for a screenshot review loop. */\n showcase: boolean;\n /** What to run against the testbed: the words after `--`. */\n command: string[];\n}\n\n/** A testbed a tool runs against: where it answers, and the env that points a process at it. */\nexport interface TestbedHandle {\n frontendUrl: string;\n backendUrl: string;\n /** `DEV_PORT_OFFSET` of the testbed's servers. */\n portOffset: number;\n /** Ports, database URLs and the seeded admin, over this process's own env. */\n env: NodeJS.ProcessEnv;\n /** The database's container, for `docker exec`. */\n container: string;\n data: TestbedData;\n}\n\ninterface Testbed extends TestbedHandle {\n forkPath: string;\n databasePort: number;\n /** Every port its servers listen on. */\n ports: number[];\n yjs: boolean;\n /** `<git common dir>/cella-testbed/`: the lock and the servers' log. One per repository, as the database is. */\n stateDir: string;\n}\n\n/** The process that holds a running testbed, written to `lock.json` while it runs. */\ninterface Lock {\n pid: number;\n forkPath: string;\n frontendUrl: string;\n /** Absent in a lock an older version wrote: those held the seed. */\n data?: TestbedData;\n}\n\nconst shiftPort = (url: string) => {\n const next = new URL(url);\n next.port = String(Number(next.port) + PORT_SHIFT);\n return next.toString().replace(/\\/$/, '');\n};\n\nasync function resolveTestbed(forkPath: string, data: TestbedData = 'seed'): Promise<Testbed> {\n const [facts, databases] = await Promise.all([loadAppFacts(forkPath), loadLocalDatabases(forkPath)]);\n const databasePort = databases.port(DATABASE);\n if (!Number.isInteger(databasePort)) {\n throw new Error('shared/src/local-database.ts names no testbed database: upgrade the app from cella first');\n }\n const composeEnv = databases.composeEnv();\n const envFile = join(forkPath, 'backend/.env');\n const fileEnv = existsSync(envFile) ? parseEnv(readFileSync(envFile, 'utf8')) : {};\n const portOffset = facts.devPortOffset + PORT_SHIFT;\n\n return {\n forkPath,\n frontendUrl: shiftPort(facts.frontendUrl),\n backendUrl: shiftPort(facts.backendUrl),\n databasePort,\n portOffset,\n env: {\n // The seed creates the admin that backend/.env names, and a command signs in as that user\n ...(fileEnv.ADMIN_EMAIL ? { ADMIN_EMAIL: fileEnv.ADMIN_EMAIL } : {}),\n ...getEnvSnapshot(),\n ...(data === 'showcase' ? { ADMIN_EMAIL: showcaseAdmin(forkPath) } : {}),\n ...composeEnv,\n NODE_ENV: 'development',\n DATABASE_URL: databases.url(DATABASE, 'runtime_role'),\n DATABASE_ADMIN_URL: databases.url(DATABASE, 'postgres'),\n DATABASE_CDC_URL: databases.url(DATABASE, 'admin_role'),\n DEV_PORT_OFFSET: String(portOffset),\n // The system pages need system admin access from this machine\n SYSTEM_ADMIN_IP_ALLOWLIST: '*',\n },\n ports: Object.values(facts.services).flatMap(({ port, internalPort }) =>\n (internalPort === undefined ? [port] : [port, internalPort]).map((value) => value + PORT_SHIFT),\n ),\n container: `${composeEnv.PROJECT_SLUG}_${DATABASE_SERVICE}`,\n data,\n yjs: facts.services.yjs?.enabled ?? false,\n stateDir: toolDir(forkPath, 'testbed', 'repository'),\n };\n}\n\nconst lockPath = (testbed: Testbed) => join(testbed.stateDir, 'lock.json');\nconst logPath = (testbed: Testbed) => join(testbed.stateDir, 'testbed.log');\nconst dataPath = (testbed: Testbed) => join(testbed.stateDir, 'data.json');\n\n/** What the kept database was seeded with: the seed when no start recorded it, as before the showcase. */\nfunction heldData(testbed: Testbed): TestbedData {\n try {\n return JSON.parse(readFileSync(dataPath(testbed), 'utf8')).data === 'showcase' ? 'showcase' : 'seed';\n } catch {\n return 'seed';\n }\n}\n\nconst describeData = (data: TestbedData) => (data === 'showcase' ? 'the showcase' : 'the seed data');\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\n/** The lock of a testbed whose process still runs. */\nfunction readLock(testbed: Testbed): Lock | undefined {\n try {\n const lock: Lock = JSON.parse(readFileSync(lockPath(testbed), 'utf8'));\n return isAlive(lock.pid) ? lock : undefined;\n } catch {\n return undefined;\n }\n}\n\nconst reachable = (url: string) =>\n fetch(url, { signal: AbortSignal.timeout(2000) }).then(\n (response) => response.status < 500,\n () => false,\n );\n\nconst sleep = (ms: number) => new Promise((done) => setTimeout(done, ms));\n\nfunction compose(testbed: Testbed, args: string[], stdio: 'inherit' | 'ignore' = 'ignore'): boolean {\n const composeArgs = ['compose', '-f', 'backend/compose.yaml', '--profile', DATABASE, ...args];\n return spawnSync('docker', composeArgs, { cwd: testbed.forkPath, env: testbed.env, stdio }).status === 0;\n}\n\n/** The database container and its volume go, so the next start migrates and seeds from nothing. */\nfunction removeDatabase(testbed: Testbed): void {\n const inspect = spawnSync('docker', ['inspect', '-f', '{{range .Mounts}}{{.Name}} {{end}}', testbed.container], {\n encoding: 'utf8',\n });\n if (inspect.status !== 0) return;\n spawnSync('docker', ['rm', '-f', testbed.container], { stdio: 'ignore' });\n for (const volume of inspect.stdout.trim().split(' ').filter(Boolean)) {\n spawnSync('docker', ['volume', 'rm', volume], { stdio: 'ignore' });\n }\n}\n\nfunction isSeeded(testbed: Testbed): boolean {\n const users = spawnSync(\n 'docker',\n ['exec', testbed.container, 'psql', '-U', 'postgres', '-tAc', 'select count(*) from users'],\n { encoding: 'utf8' },\n );\n return users.status === 0 && Number(users.stdout.trim()) > 0;\n}\n\n/** Process groups of whatever listens on the testbed's ports: what a testbed left behind still runs. */\nfunction listenerGroups(testbed: Testbed): Set<number> {\n const groups = new Set<number>();\n for (const port of testbed.ports) {\n const pids = spawnSync('lsof', ['-ti', `tcp:${port}`, '-sTCP:LISTEN'], { encoding: 'utf8' }).stdout;\n for (const pid of pids.split('\\n').filter(Boolean)) {\n const group = Number(spawnSync('ps', ['-o', 'pgid=', '-p', pid], { encoding: 'utf8' }).stdout.trim());\n if (group > 1) groups.add(group);\n }\n }\n return groups;\n}\n\nfunction killGroup(group: number, signal: NodeJS.Signals): void {\n try {\n process.kill(-group, signal);\n } catch {\n // It already exited\n }\n}\n\nfunction logTail(testbed: Testbed, lines = 30): string {\n if (!existsSync(logPath(testbed))) return '';\n return readFileSync(logPath(testbed), 'utf8').trimEnd().split('\\n').slice(-lines).join('\\n');\n}\n\n/** Waits until the frontend and the API answer; ends early with `failure()` once `alive()` turns false. */\nasync function untilAnswering(testbed: Testbed, alive: () => boolean, failure: () => string): Promise<void> {\n const deadline = Date.now() + STARTUP_TIMEOUT_MS;\n while (!((await reachable(testbed.frontendUrl)) && (await reachable(`${testbed.backendUrl}/health`)))) {\n if (!alive()) throw new Error(failure());\n if (Date.now() > deadline) throw new Error(`nothing answered at ${testbed.frontendUrl} within five minutes`);\n await sleep(2000);\n }\n}\n\n/** A started testbed: `exited` settles when its servers exit by themselves. */\ninterface Started {\n stop: () => Promise<void>;\n exited: Promise<void>;\n}\n\n/** Starts the database and the servers, and resolves once both answer; `drop` removes the database on stop. */\nasync function startTestbed(testbed: Testbed, fresh: boolean, drop = false): Promise<Started> {\n if (await reachable(testbed.frontendUrl)) {\n throw new Error(\n `something already answers at ${testbed.frontendUrl}: \\`pnpm cella testbed stop\\` ends a testbed left behind`,\n );\n }\n mkdirSync(testbed.stateDir, { recursive: true });\n // Written before the database starts, so a second start during the seed finds it\n writeFileSync(\n lockPath(testbed),\n JSON.stringify({\n pid: process.pid,\n forkPath: testbed.forkPath,\n frontendUrl: testbed.frontendUrl,\n data: testbed.data,\n } satisfies Lock),\n );\n const log = openSync(logPath(testbed), 'w');\n let stack: ChildProcess | undefined;\n let stopped = false;\n\n const stop = async () => {\n if (stopped) return;\n stopped = true;\n const spinner = createSpinner('stopping the testbed');\n const pid = stack?.pid;\n if (pid !== undefined && stack?.exitCode === null) {\n const exited = new Promise((done) => stack?.once('exit', done));\n killGroup(pid, 'SIGTERM');\n if (!(await Promise.race([exited.then(() => true), sleep(STOP_TIMEOUT_MS).then(() => false)]))) {\n killGroup(pid, 'SIGKILL');\n }\n }\n if (drop) removeDatabase(testbed);\n else compose(testbed, ['stop', DATABASE_SERVICE]);\n rmSync(lockPath(testbed), { force: true });\n closeSync(log);\n spinner.stop();\n const database = drop ? 'removed, the next start seeds a new one' : 'kept for the next start';\n printStep('stopped', pc.dim(`database container ${testbed.container} ${database}`));\n };\n const forget = onShutdown(stop);\n\n try {\n // The showcase's times are relative to its seed, so it never starts from a kept database, which would show them aged\n if (fresh || testbed.data === 'showcase' || heldData(testbed) !== testbed.data) removeDatabase(testbed);\n const spinner = createSpinner(`starting the database on port ${testbed.databasePort}`);\n if (!compose(testbed, ['up', '-d', '--wait', DATABASE_SERVICE])) {\n throw new Error('the testbed database did not start: is Docker running?');\n }\n\n // A new volume gets the schema and the seed data; a kept one gets the migrations added since\n const seeded = isSeeded(testbed);\n spinner.text = seeded\n ? 'migrating the database'\n : `migrating the database and seeding ${describeData(testbed.data)}`;\n const seed = testbed.data === 'showcase' ? ['seed', 'showcase'] : ['seed'];\n const prepare = seeded ? ['--filter', 'backend', 'migrate'] : seed;\n const prepared = spawnSync('pnpm', prepare, {\n cwd: testbed.forkPath,\n env: testbed.env,\n stdio: ['ignore', log, log],\n });\n if (prepared.status !== 0) throw new Error(`\\`pnpm ${prepare.join(' ')}\\` failed:\\n${logTail(testbed)}`);\n writeFileSync(dataPath(testbed), JSON.stringify({ data: testbed.data }));\n printStep(\n 'database',\n `${seeded ? 'migrated' : `seeded with ${describeData(testbed.data)}`}, port ${testbed.databasePort}`,\n );\n\n // `pnpm offline` starts no Yjs relay; with one the editors show their usual sync status\n const relay = testbed.yjs ? 'pnpm --filter yjs-worker dev & ' : '';\n stack = spawn('sh', ['-c', `${relay}pnpm offline`], {\n cwd: testbed.forkPath,\n env: testbed.env,\n // Its own process group, so one signal stops the servers, the workers and the frontend preview together\n detached: true,\n stdio: ['ignore', log, log],\n });\n\n createSpinner('building the frontend and starting the servers');\n const servers = stack;\n await untilAnswering(\n testbed,\n () => servers.exitCode === null,\n () => `the servers stopped while starting:\\n${logTail(testbed)}`,\n );\n printStep('servers', `${testbed.frontendUrl}, ports shifted by ${testbed.portOffset}`);\n } catch (error) {\n await stop();\n forget();\n throw error;\n }\n\n const running = stack;\n return {\n stop: async () => {\n await stop();\n forget();\n },\n // A stop ends the servers too; only an exit nobody asked for settles this\n exited: new Promise((done) => running.once('exit', () => !stopped && done())),\n };\n}\n\n/** Runs `command` in the app's root with `env`, in the foreground; resolves to its exit code. */\nexport function runCommand(forkPath: string, env: NodeJS.ProcessEnv, command: string[]): Promise<number> {\n const [program, ...args] = command;\n const child = spawn(program, args, { cwd: forkPath, env, stdio: 'inherit' });\n return new Promise((done) => {\n child.once('error', (error) => {\n spinnerFail(`${program}: ${error.message}`);\n done(127);\n });\n // A shell reports a process a signal ended as 128 plus the signal's number\n child.once('exit', (code, signal) => done(code ?? 128 + (signal ? constants.signals[signal] : 0)));\n });\n}\n\nasync function stopTestbed(testbed: Testbed): Promise<number> {\n const lock = readLock(testbed);\n if (lock) {\n // The process that holds it stops its servers and the database on SIGTERM\n process.kill(lock.pid, 'SIGTERM');\n const deadline = Date.now() + STOP_TIMEOUT_MS + 5000;\n while (isAlive(lock.pid) && Date.now() < deadline) await sleep(250);\n }\n const groups = listenerGroups(testbed);\n for (const group of groups) killGroup(group, 'SIGTERM');\n compose(testbed, ['stop', DATABASE_SERVICE]);\n rmSync(lockPath(testbed), { force: true });\n printStep(\n 'stopped',\n lock || groups.size > 0 ? (lock?.frontendUrl ?? testbed.frontendUrl) : pc.dim('no testbed was running'),\n );\n return 0;\n}\n\n/** The lock of a running testbed this checkout may use; refuses one another checkout holds. */\nfunction ownLock(testbed: Testbed): Lock | undefined {\n const lock = readLock(testbed);\n if (lock && lock.forkPath !== testbed.forkPath) {\n throw new Error(`a testbed of ${lock.forkPath} uses the database: \\`pnpm cella testbed stop\\` ends it`);\n }\n return lock;\n}\n\n/**\n * Runs `use` against a testbed: the one this checkout holds, once it answers, else one started for it and stopped after,\n * ctrl-c included. A `destructive` command writes and deletes rows, so it gets a testbed of its own on a new database,\n * removed after the run.\n * @throws for a destructive command while any testbed runs\n */\nexport async function withTestbed<T>(\n forkPath: string,\n use: (testbed: TestbedHandle) => Promise<T>,\n { fresh = false, destructive = false, data = 'seed' as TestbedData } = {},\n): Promise<T> {\n const testbed = await resolveTestbed(forkPath, data);\n const lock = ownLock(testbed);\n if (lock && destructive) {\n throw new Error(\n `a testbed runs at ${lock.frontendUrl}: this command needs one of its own, so stop that one first (\\`pnpm cella testbed stop\\`)`,\n );\n }\n if (lock && (lock.data ?? 'seed') !== data) {\n throw new Error(\n `a testbed with ${describeData(lock.data ?? 'seed')} runs at ${lock.frontendUrl}: this command needs ${describeData(data)}, so stop that one first (\\`pnpm cella testbed stop\\`)`,\n );\n }\n if (lock) {\n await untilAnswering(\n testbed,\n () => isAlive(lock.pid),\n () => 'the testbed stopped while starting',\n );\n return use(testbed);\n }\n const started = await startTestbed(testbed, fresh || destructive, destructive);\n try {\n return await use(testbed);\n } finally {\n await started.stop();\n }\n}\n\nasync function runTestbed(forkPath: string, options: TestbedOptions): Promise<number> {\n if (options.job === 'stop') return stopTestbed(await resolveTestbed(forkPath));\n if (options.showcase && !hasShowcase(forkPath)) throw new Error('this app keeps no json/showcase.json');\n const data: TestbedData = options.showcase ? 'showcase' : 'seed';\n if (options.command.length > 0) {\n return withTestbed(forkPath, (testbed) => runCommand(forkPath, testbed.env, options.command), { ...options, data });\n }\n\n const testbed = await resolveTestbed(forkPath, data);\n const lock = ownLock(testbed);\n if (lock) {\n throw new Error(\n `a testbed already runs at ${lock.frontendUrl}: \\`pnpm cella testbed -- <command>\\` runs against it`,\n );\n }\n const started = await startTestbed(testbed, options.fresh);\n console.info();\n console.info(` ${pc.bold(testbed.frontendUrl)}`);\n console.info(` ${pc.dim('run a command against it:')} pnpm cella testbed -- <command>`);\n console.info(` ${pc.dim('servers log:')} ${logPath(testbed)}`);\n console.info(` ${pc.dim('ctrl-c stops it')}`);\n console.info();\n // Ctrl-C stops it through the shutdown handler; reaching the next line means the servers exited by themselves\n await started.exited;\n spinnerFail(`the servers stopped by themselves:\\n${logTail(testbed)}`);\n await started.stop();\n return 1;\n}\n\nexport const testbedCommand: ToolCommand<TestbedOptions> = {\n name: 'testbed',\n group: 'develop',\n description: 'a throwaway copy of the app on its own seeded database and ports, beside pnpm dev',\n jobs: [\n ['start', 'start it and hold it until ctrl-c'],\n ['stop', 'stop the testbed that runs, or one left behind'],\n ],\n options: [\n ['--fresh', 'start from an empty database: migrate and seed it again'],\n ['--showcase', 'hold the showcase of json/showcase.json, which the screenshots shoot, for a review loop'],\n ],\n passthrough: [\n 'command',\n \"after `--`: run it against the testbed (this checkout's running one, else one started for it and stopped after)\",\n ],\n parse: ({ job = 'start', opts, passthrough }) => {\n if (job !== 'start' && job !== 'stop') throw new Error(`unknown job '${job}'. expected one of: start, stop`);\n if (job === 'stop' && passthrough.length > 0) throw new Error('stop takes no command');\n return { job, fresh: opts.fresh === true, showcase: opts.showcase === true, command: passthrough };\n },\n run: runTestbed,\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","/**\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 // One line holds one spinner: a new one replaces the one still running\n stopSpinner();\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.5\",\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 \"./bench\": {\n \"types\": \"./dist/bench.d.ts\",\n \"import\": \"./dist/bench.js\"\n },\n \"./style\": {\n \"types\": \"./dist/style.d.ts\",\n \"import\": \"./dist/style.js\"\n },\n \"./drive\": {\n \"types\": \"./dist/drive.d.ts\",\n \"import\": \"./dist/drive.js\"\n },\n \"./a11y\": {\n \"types\": \"./dist/a11y.d.ts\",\n \"import\": \"./dist/a11y.js\"\n },\n \"./screenshots\": {\n \"types\": \"./dist/screenshots.d.ts\",\n \"import\": \"./dist/screenshots.js\"\n },\n \"./pentest\": {\n \"types\": \"./dist/pentest.d.ts\",\n \"import\": \"./dist/pentest.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 \"axe-core\": \"^4.14.0\",\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 \"@tailwindcss/node\": \"^4.3.3\",\n \"@types/node\": \"26.6.3\",\n \"@typescript/native-preview\": \"7.0.0-dev.20260707.2\",\n \"playwright\": \"^1.64.1\",\n \"rimraf\": \"^6.1.3\",\n \"tailwindcss\": \"^4.3.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 * 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","import process from 'node:process';\n\ntype Cleanup = () => void | Promise<void>;\n\nconst cleanups = new Set<Cleanup>();\n\n/** Run `cleanup` when ctrl-c or a kill ends the CLI; the returned function takes it back once its work is done. */\nexport function onShutdown(cleanup: Cleanup): () => void {\n cleanups.add(cleanup);\n return () => cleanups.delete(cleanup);\n}\n\n/**\n * SIGINT exits 130 and SIGTERM 143, as a shell reports a process the signal ended, after the registered cleanups ran,\n * newest first. A second signal during cleanup ends the CLI at once.\n */\nexport function installSignalHandlers(): void {\n const handle = (code: number) => async () => {\n for (const cleanup of [...cleanups].reverse()) {\n try {\n await cleanup();\n } catch {\n // The exit goes ahead: a cleanup that failed has nothing left to protect\n }\n }\n process.exit(code);\n };\n process.once('SIGINT', handle(130));\n process.once('SIGTERM', handle(143));\n}\n","import { mkdirSync, statSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport pc from '../../utils/colors';\nimport { printStep, warningMark } from '../../utils/display';\nimport { onShutdown } from '../../utils/signals';\nimport type { TestbedHandle } from '../testbed';\nimport { type AxeScan, summarizeAxe } from './axe-scan';\nimport { runCodeChecks } from './code-checks';\nimport { type AuditRun, EvidenceSet, type Finding } from './findings';\nimport { ledgerFile, writeLedger } from './ledger';\nimport { acrossStates } from './probes/page-structure';\nimport type { Scope } from './scope';\nimport { endAudit, startAudit } from './session';\nimport { visitState } from './visit';\n\nexport interface AuditOptions {\n /** State ids to audit; all when empty. */\n states: string[];\n workers: number;\n /** The audit user; default the testbed's `ADMIN_EMAIL`. */\n email?: string;\n}\n\nconst seconds = (since: number) => `${((Date.now() - since) / 1000).toFixed(1)}s`;\n\n/**\n * Audits the testbed against WCAG 2.2 A and AA and writes the conformance ledger, or `ledger-partial.json` in the\n * results folder when the run covered part of the scope or skipped a visit: an incomplete run never replaces the\n * ledger. Resolves to the exit code: 1 when a visit was skipped.\n */\nexport async function runAudit(run: AuditRun, scope: Scope, testbed: TestbedHandle, options: AuditOptions) {\n const startedAt = Date.now();\n const email = options.email ?? testbed.env.ADMIN_EMAIL;\n if (!email) throw new Error('no audit user: pass --email, or set ADMIN_EMAIL in backend/.env');\n\n // A build is as old as its last `vite build`: say so, since a stale one audits old code without a sign\n const builtAt = statSync(join(run.forkPath, 'frontend/dist/index.html'), { throwIfNoEntry: false })?.mtime;\n printStep('auditing', `${testbed.frontendUrl}, frontend build of ${builtAt?.toLocaleString() ?? 'unknown date'}`);\n\n const states =\n options.states.length > 0 ? scope.states.filter((state) => options.states.includes(state.id)) : scope.states;\n const session = await startAudit(run.forkPath, scope, { email, env: testbed.env });\n const forget = onShutdown(() => endAudit(session));\n\n const findings: Finding[] = [];\n const scans: AxeScan[] = [];\n const errors: Record<string, string> = {};\n\n /** One visit: a state in a color mode. Dark visits measure contrast only. */\n const visits = (['light', 'dark'] as const).flatMap((mode) => states.map((state) => ({ state, mode })));\n\n /** Takes visits from the shared queue until it is empty. */\n const worker = async () => {\n for (let visit = visits.shift(); visit; visit = visits.shift()) {\n const { state, mode } = visit;\n const visitStartedAt = Date.now();\n const label = `${state.id} (${mode})`;\n try {\n const result = await visitState(run, session, state, mode);\n findings.push(...result.findings);\n scans.push(result.scan);\n console.info(` ${label} ${pc.dim(seconds(visitStartedAt))}`);\n } catch (error) {\n errors[label] = error instanceof Error ? error.message.split('\\n')[0] : String(error);\n console.info(` ${warningMark} ${label} skipped: ${errors[label]}`);\n }\n }\n };\n\n try {\n await Promise.all(Array.from({ length: options.workers }, worker));\n } finally {\n await endAudit(session);\n forget();\n }\n\n // Visits finish in any order; scope order keeps the ledger stable between runs\n const position = (label: string) =>\n scope.states.findIndex((state) => label === state.id || label.startsWith(`${state.id} (`));\n findings.sort((a, b) => position(a.state) - position(b.state));\n scans.sort(\n (a, b) =>\n Number(a.where.endsWith('(dark)')) - Number(b.where.endsWith('(dark)')) || position(a.where) - position(b.where),\n );\n\n const evidence = new EvidenceSet();\n mkdirSync(run.resultsDir, { recursive: true });\n const axe = summarizeAxe(scans);\n for (const [id, items] of axe.evidence) for (const item of items) evidence.add([id], item);\n writeFileSync(join(run.resultsDir, 'axe.json'), `${JSON.stringify({ ...axe.report, errors }, null, 2)}\\n`);\n evidence.addFindings(acrossStates(findings));\n runCodeChecks(evidence, run, scope.sources);\n\n // The ledger describes the whole scope, so a run that covered only part of it writes a separate file\n const skipped = Object.keys(errors).length;\n const target =\n options.states.length > 0 || skipped ? join(run.resultsDir, 'ledger-partial.json') : join(run.forkPath, ledgerFile);\n const ledger = writeLedger(\n run.forkPath,\n evidence.byCriterion,\n states.map((state) => state.id),\n target,\n );\n\n const count = (status: string | null) => ledger.criteria.filter((row) => row.status === status).length;\n console.info();\n console.info(\n ` ${ledger.criteria.length} criteria: ${count('supports')} supports, ${count('partially-supports')} partially ` +\n `supports, ${count('not-applicable')} not applicable, ${count(null)} open`,\n );\n for (const row of ledger.criteria.filter((r) => r.status === 'partially-supports')) {\n const failures = row.evidence.filter((e) => e.result === 'fail').map((e) => e.summary);\n console.info(` ${row.id} ${row.name}: ${pc.dim(failures.join(' '))}`);\n }\n console.info();\n printStep('ledger', target);\n printStep('results', run.resultsDir);\n printStep('done', `in ${seconds(startedAt)}${skipped ? `, ${skipped} visits skipped` : ''}`);\n return skipped ? 1 : 0;\n}\n","import axe from 'axe-core';\nimport type { Page } from 'playwright';\nimport { criterionFromAxeTag } from './criteria';\nimport type { Evidence } from './ledger';\nimport { devOnlySelectors } from './session';\n\nconst wcagTags = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22a', 'wcag22aa'];\nconst contrastRule = 'color-contrast';\n\ninterface AxeNode {\n target: string;\n html: string;\n summary: string;\n}\n\ninterface AxeRule {\n id: string;\n help: string;\n helpUrl: string;\n /** Criteria the rule maps to; empty for a best-practice rule. */\n criteria: string[];\n}\n\n/** What axe found on one state in one color mode. */\nexport interface AxeScan {\n where: string;\n failed: (AxeRule & { nodes: AxeNode[] })[];\n review: AxeRule[];\n passed: AxeRule[];\n /** Selectors of the text whose contrast axe could not decide; the text-contrast probe measures them. */\n undecidedContrast: string[];\n}\n\n/**\n * Runs axe on the open page. `contrastOnly` limits it to the one rule whose result depends on the color mode, for the\n * dark-mode visit.\n */\nexport async function axeScan(page: Page, where: string, contrastOnly = false): Promise<AxeScan> {\n // Injected once per page; a second injection would replace the `axe` a running scan holds\n if (!(await page.evaluate(() => 'axe' in window))) await page.evaluate(axe.source);\n const runOnly: axe.RunOnly = contrastOnly\n ? { type: 'rule', values: [contrastRule] }\n : { type: 'tag', values: [...wcagTags, 'best-practice'] };\n const result = await page.evaluate(\n ({ exclude, only }) => {\n const scanner: typeof axe = Reflect.get(window, 'axe');\n return scanner.run({ exclude }, { runOnly: only });\n },\n { exclude: devOnlySelectors.map((selector) => [selector]), only: runOnly },\n );\n\n const rule = ({ id, help, helpUrl, tags }: axe.Result): AxeRule => ({\n id,\n help,\n helpUrl,\n criteria: tags.map(criterionFromAxeTag).filter((criterion) => criterion !== null),\n });\n return {\n where,\n failed: result.violations.map((violation) => ({\n ...rule(violation),\n nodes: violation.nodes.map((node) => ({\n target: node.target.join(' '),\n html: node.html.slice(0, 200),\n summary: node.failureSummary ?? '',\n })),\n })),\n review: result.incomplete.map(rule),\n passed: result.passes.map(rule),\n undecidedContrast: result.incomplete\n .filter(({ id }) => id === contrastRule)\n .flatMap(({ nodes }) => nodes.map((node) => node.target.join(' '))),\n };\n}\n\n/**\n * Evidence per criterion from all scans, plus the raw report for fixing: every failing element per rule and state.\n * What axe could not decide about contrast is the text-contrast probe's to judge, so it leaves no review note here.\n */\nexport function summarizeAxe(scans: AxeScan[]) {\n const rules = new Map<string, AxeRule & { failed: Map<string, AxeNode[]>; review: string[]; passed: number }>();\n const advisories = new Map<string, { help: string; where: string[] }>();\n const tally = (rule: AxeRule) => {\n const entry = rules.get(rule.id) ?? {\n ...rule,\n failed: new Map<string, AxeNode[]>(),\n review: [] as string[],\n passed: 0,\n };\n rules.set(rule.id, entry);\n return entry;\n };\n\n for (const scan of scans) {\n for (const rule of scan.failed) {\n if (rule.criteria.length) tally(rule).failed.set(scan.where, rule.nodes);\n else advisories.set(rule.id, { help: rule.help, where: [...(advisories.get(rule.id)?.where ?? []), scan.where] });\n }\n for (const rule of scan.review) if (rule.criteria.length) tally(rule).review.push(scan.where);\n for (const rule of scan.passed) if (rule.criteria.length) tally(rule).passed += 1;\n }\n\n const evidence = new Map<string, Evidence[]>();\n for (const rule of rules.values()) {\n const failedWhere = [...rule.failed.keys()];\n const elements = [...rule.failed.values()].reduce((sum, nodes) => sum + nodes.length, 0);\n const item: Evidence = failedWhere.length\n ? {\n check: 'axe',\n result: 'fail',\n summary: `axe ${rule.id}: ${rule.help} (${elements} elements).`,\n where: failedWhere,\n }\n : rule.review.length && rule.id !== contrastRule\n ? {\n check: 'axe',\n result: 'review',\n summary: `axe ${rule.id} needs a person to check ${rule.review.length} states: ${rule.help}.`,\n where: rule.review,\n }\n : rule.review.length\n ? {\n check: 'axe',\n result: 'pass',\n summary: `axe ${rule.id} found no failing element; what it left undecided on ${rule.review.length} visits is measured by a probe.`,\n where: [],\n }\n : { check: 'axe', result: 'pass', summary: `axe ${rule.id} passed on ${rule.passed} states.`, where: [] };\n for (const id of rule.criteria) evidence.set(id, [...(evidence.get(id) ?? []), item]);\n }\n\n const report = {\n rules: Object.fromEntries(\n [...rules].map(([id, rule]) => [\n id,\n {\n help: rule.help,\n helpUrl: rule.helpUrl,\n criteria: rule.criteria,\n failed: Object.fromEntries(rule.failed),\n review: rule.review,\n },\n ]),\n ),\n advisories: Object.fromEntries(advisories),\n };\n return { evidence, report };\n}\n","/**\n * How a criterion gets its evidence: `axe` rules tagged with it, a named browser `probe`, a `code` check over the\n * repository, or a `manual` pass by a person. The audit decides a row only when none of its checks is `manual`.\n */\ntype CheckName = 'axe' | `probe:${string}` | `code:${string}` | 'manual';\n\nexport interface Criterion {\n id: string;\n name: string;\n level: 'A' | 'AA';\n /** EN 301 549 V3.2.1 web clause; null for criteria new in WCAG 2.2, which that version predates. */\n en301549: string | null;\n checks: CheckName[];\n}\n\nconst c = (id: string, name: string, level: 'A' | 'AA', checks: CheckName[], newIn22 = false): Criterion => ({\n id,\n name,\n level,\n en301549: newIn22 ? null : `9.${id}`,\n checks,\n});\n\n/** WCAG 2.2 Level A and AA success criteria (4.1.1 Parsing is obsolete and left out). */\nexport const criteria: Criterion[] = [\n c('1.1.1', 'Non-text Content', 'A', ['axe', 'manual']),\n c('1.2.1', 'Audio-only and Video-only (Prerecorded)', 'A', ['code:media']),\n c('1.2.2', 'Captions (Prerecorded)', 'A', ['code:media']),\n c('1.2.3', 'Audio Description or Media Alternative (Prerecorded)', 'A', ['code:media']),\n c('1.2.4', 'Captions (Live)', 'AA', ['code:media']),\n c('1.2.5', 'Audio Description (Prerecorded)', 'AA', ['code:media']),\n c('1.3.1', 'Info and Relationships', 'A', ['axe', 'manual']),\n c('1.3.2', 'Meaningful Sequence', 'A', ['manual']),\n c('1.3.3', 'Sensory Characteristics', 'A', ['manual']),\n c('1.3.4', 'Orientation', 'AA', ['probe:orientation']),\n c('1.3.5', 'Identify Input Purpose', 'AA', ['axe', 'probe:autocomplete']),\n c('1.4.1', 'Use of Color', 'A', ['axe', 'manual']),\n c('1.4.2', 'Audio Control', 'A', ['code:autoplay']),\n c('1.4.3', 'Contrast (Minimum)', 'AA', ['axe', 'probe:text-contrast']),\n c('1.4.4', 'Resize Text', 'AA', ['probe:resize']),\n c('1.4.5', 'Images of Text', 'AA', ['manual']),\n c('1.4.10', 'Reflow', 'AA', ['probe:reflow']),\n c('1.4.11', 'Non-text Contrast', 'AA', ['probe:control-contrast', 'manual']),\n c('1.4.12', 'Text Spacing', 'AA', ['probe:text-spacing']),\n c('1.4.13', 'Content on Hover or Focus', 'AA', ['manual']),\n c('2.1.1', 'Keyboard', 'A', ['axe', 'probe:keyboard', 'manual']),\n c('2.1.2', 'No Keyboard Trap', 'A', ['probe:keyboard']),\n c('2.1.4', 'Character Key Shortcuts', 'A', ['code:shortcuts']),\n c('2.2.1', 'Timing Adjustable', 'A', ['manual']),\n c('2.2.2', 'Pause, Stop, Hide', 'A', ['code:motion', 'manual']),\n c('2.3.1', 'Three Flashes or Below Threshold', 'A', ['code:motion']),\n c('2.4.1', 'Bypass Blocks', 'A', ['axe', 'probe:landmarks']),\n c('2.4.2', 'Page Titled', 'A', ['axe', 'probe:titles']),\n c('2.4.3', 'Focus Order', 'A', ['probe:keyboard', 'manual']),\n c('2.4.4', 'Link Purpose (In Context)', 'A', ['axe', 'manual']),\n c('2.4.5', 'Multiple Ways', 'AA', ['manual']),\n c('2.4.6', 'Headings and Labels', 'AA', ['manual']),\n c('2.4.7', 'Focus Visible', 'AA', ['probe:keyboard']),\n c('2.4.11', 'Focus Not Obscured (Minimum)', 'AA', ['probe:keyboard'], true),\n c('2.5.1', 'Pointer Gestures', 'A', ['code:gestures']),\n c('2.5.2', 'Pointer Cancellation', 'A', ['manual']),\n c('2.5.3', 'Label in Name', 'A', ['axe', 'manual']),\n c('2.5.4', 'Motion Actuation', 'A', ['code:motion-actuation']),\n c('2.5.7', 'Dragging Movements', 'AA', ['code:dragging', 'manual'], true),\n c('2.5.8', 'Target Size (Minimum)', 'AA', ['axe'], true),\n c('3.1.1', 'Language of Page', 'A', ['axe', 'probe:language']),\n c('3.1.2', 'Language of Parts', 'AA', ['manual']),\n c('3.2.1', 'On Focus', 'A', ['probe:keyboard']),\n c('3.2.2', 'On Input', 'A', ['manual']),\n c('3.2.3', 'Consistent Navigation', 'AA', ['manual']),\n c('3.2.4', 'Consistent Identification', 'AA', ['manual']),\n c('3.2.6', 'Consistent Help', 'A', ['manual'], true),\n c('3.3.1', 'Error Identification', 'A', ['probe:form-errors']),\n c('3.3.2', 'Labels or Instructions', 'A', ['axe', 'manual']),\n c('3.3.3', 'Error Suggestion', 'AA', ['manual']),\n c('3.3.4', 'Error Prevention (Legal, Financial, Data)', 'AA', ['manual']),\n c('3.3.7', 'Redundant Entry', 'A', ['manual'], true),\n c('3.3.8', 'Accessible Authentication (Minimum)', 'AA', ['code:authentication', 'probe:autocomplete'], true),\n c('4.1.2', 'Name, Role, Value', 'A', ['axe', 'manual']),\n c('4.1.3', 'Status Messages', 'AA', ['manual']),\n];\n\n/** What the person doing the manual pass checks, for each criterion a tool cannot decide alone. */\nexport const manualSteps: Record<string, string> = {\n '1.1.1':\n 'Every meaningful image, icon button and chart has a text alternative with the same purpose; decorative images are hidden from screen readers.',\n '1.2.1': 'Decide whether the app publishes media of its own, or only plays files users upload.',\n '1.3.1':\n 'With a screen reader, headings, lists, tables, form labels and groups are announced as what they look like.',\n '1.3.2': 'Reading each page top to bottom with a screen reader gives a sensible order that matches the visual one.',\n '1.3.3':\n 'No instruction relies only on shape, color, size, position or sound (\"press the round button on the right\").',\n '1.4.1':\n 'Color is never the only signal: links in text, required fields, errors, status badges and charts also differ in text or shape.',\n '1.4.2': 'Nothing plays sound by itself.',\n '1.4.3':\n 'Where the audit measured nothing, such as field values and placeholders, check contrast by eye: 4.5:1, or 3:1 for large text.',\n '1.4.5': 'No text is shown as an image, except logos.',\n '1.4.11':\n 'The audit measures form control edges. By hand: icons that carry meaning, focus indicators and chart parts reach 3:1 in both modes.',\n '1.4.13':\n 'Tooltips, menus and popovers that appear on hover or focus can be dismissed with Escape, hovered, and stay until dismissed.',\n '2.1.1':\n 'Every function works with the keyboard alone: menus, dialogs, the data grid, the editor, uploads, drag and drop, date pickers.',\n '2.2.1':\n 'No time limit makes a user lose work or information they need: the session lifetime, sign-in challenges (passkey, email link, step-up) and toasts that close by themselves.',\n '2.2.2':\n 'Animations that start by themselves and run longer than 5 seconds beside other content can be paused, or stop with reduced motion.',\n '2.4.3':\n 'The Tab order follows the visual and logical order; focus moves into a dialog when it opens and back to its trigger when it closes.',\n '2.4.4': 'Each link says where it goes, from its text or its sentence, list item or table cell.',\n '2.4.5': 'Each page can be reached in at least two ways: navigation, search, links.',\n '2.4.6': 'Headings and labels describe their topic or purpose.',\n '2.5.1': 'Every gesture (swipe, pinch) has a single-pointer alternative such as a button.',\n '2.5.2': 'Actions fire when the pointer is released and can be cancelled by moving away before release.',\n '2.5.3': 'The visible label of each control is part of its accessible name, so voice control can use it.',\n '2.5.7': 'Every drag action has a single-pointer alternative, such as a menu item or move buttons.',\n '2.5.8': 'Where axe could not decide, targets are at least 24 by 24 pixels or have enough space around them.',\n '3.1.2': 'Passages in another language than the page are marked with their language.',\n '3.2.2': 'Changing a field (select, checkbox, input) never navigates or submits without warning.',\n '3.2.3': 'Navigation repeated across pages appears in the same order.',\n '3.2.4': 'Components with the same function have the same label and icon everywhere.',\n '3.2.6': 'Help (contact, docs, chat) appears in the same relative place on every page that offers it.',\n '3.3.2': 'Every input has a visible label or instruction, including required markers and expected formats.',\n '3.3.3': 'Error messages say how to fix the input when that is known.',\n '3.3.4': 'Irreversible actions (delete, leave, remove members) can be confirmed, undone or reviewed first.',\n '3.3.7': 'Multi-step flows never ask again for information given earlier in the same process.',\n '4.1.2':\n 'With a screen reader, custom controls (menus, tabs, toggles, the grid, the editor) announce their name, role, state and value.',\n '4.1.3':\n 'With a screen reader, status messages (toasts, result counts, saving states) are announced without moving focus.',\n};\n\n/**\n * What to listen for in the screen reader pass that decides 4.1.2 and 4.1.3: no tool hears what is announced. One line\n * per kind of control; go through it on each page type and overlay of the scope.\n */\nexport const screenReaderSteps: string[] = [\n 'Page load: the title is read, then the main heading; the rotor or elements list shows headings in order and the landmarks (navigation, main).',\n 'Buttons and links: each is read with a name that says what it does, and as a button or a link; an icon-only one has a name too.',\n 'Toggles, switches, checkboxes and radio groups: the state is read (on, off, selected, pressed) and again after changing it; a group is read with its name.',\n 'Selects, comboboxes and menus: the current value is read with the label; opening one is announced, each option is read as you arrow through, the choice is confirmed.',\n 'Form fields: the label, required and the description are read on focus; after a failed submit the error is read and tied to its field.',\n 'Dialogs, sheets and drawers: opening one reads its title and moves focus inside; nothing behind it is reachable; closing returns to the trigger.',\n 'Data grids: moving by arrow keys reads the column header and the cell; sorting and selecting a row are announced; row and column counts are read on entry.',\n 'The text editor: typing is echoed, block type and formatting changes are read, a mention or slash menu reads its options.',\n 'Status messages (4.1.3): toasts, search result counts, saving and syncing states, and the reorder message are read without focus moving to them.',\n 'Tabs and side navigation: the current tab or section is read as current or selected.',\n];\n\n/** Maps an axe tag such as `wcag1410` to its criterion id (`1.4.10`), or null for non-criterion tags. */\nexport function criterionFromAxeTag(tag: string) {\n const match = /^wcag(\\d)(\\d)(\\d{1,2})$/.exec(tag);\n if (!match) return null;\n const id = `${match[1]}.${match[2]}.${match[3]}`;\n return criteria.some((criterion) => criterion.id === id) ? id : null;\n}\n","import process from 'node:process';\nimport type { Browser, BrowserContext, BrowserContextOptions, Page } from 'playwright';\nimport { getEnv } from '../../utils/env';\nimport { fillPath, signedIn } from '../adapters';\nimport { loadPlaywright, mintSession, newContext, openPage, type Session, settle, signOut } from '../drive';\nimport { type A11yState, auditContrast } from './define';\nimport { loadScope, type Scope } from './scope';\n\nexport type Mode = 'light' | 'dark';\n\ntype StorageState = Awaited<ReturnType<BrowserContext['storageState']>>;\n\n/** A signed-in audit: one browser for every visit, and what each visit starts from. */\nexport interface AuditSession {\n browser: Browser;\n user: Session;\n /** Cookies and local storage of a browser that has loaded the app once, as after a real sign-in. */\n storage: StorageState;\n /** Resolved `{name}` placeholders of the scope paths. */\n values: Record<string, string | null>;\n}\n\n/** Elements that exist only in development builds; scans and probes ignore them. */\nexport const devOnlySelectors = [\n '.TanStackRouterDevtools',\n '.tsqd-parent-container',\n '[aria-label=\"toggle debug toolbar\"]',\n];\n\nexport const defaultViewport = { width: 1280, height: 900 };\n\n/**\n * Signs the audit user in, runs the scope's `prepare` steps, resolves its placeholders and starts the browser.\n * `env` points the session mint at the database the app runs on.\n */\nexport async function startAudit(\n forkPath: string,\n scope: Scope,\n { email, env }: { email: string; env?: NodeJS.ProcessEnv },\n): Promise<AuditSession> {\n const user = mintSession(email, { forkPath, env, hours: 4 });\n try {\n for (const prepare of scope.prepare) await prepare(signedIn(user));\n const values: AuditSession['values'] = {};\n for (const [name, resolve] of Object.entries(scope.placeholders)) values[name] = await resolve(signedIn(user));\n\n const { chromium } = await loadPlaywright(forkPath);\n const browser = await chromium.launch();\n // Route guards read the user store, which a real sign-in fills before any deep link is opened\n const context = await newContext(browser, { session: user });\n const page = await context.newPage();\n await page.goto(`${user.frontendUrl}/home`, { waitUntil: 'domcontentloaded' });\n await page.locator('main').first().waitFor({ timeout: 60_000 });\n await settle(page);\n const storage = await context.storageState();\n await context.close();\n return { browser, user, storage, values };\n } catch (error) {\n await signOut(user);\n throw error;\n }\n}\n\n/** Closes the browser and signs the audit user out, so a finished audit leaves no live session behind. */\nexport async function endAudit(session: AuditSession): Promise<void> {\n await session.browser.close();\n await signOut(session.user);\n}\n\n/**\n * A fresh context for one visit: color mode, more contrast, reduced motion, the dev banner dismissed, and signed in\n * when the state needs it. `overrides` change the browser settings, such as the viewport or the motion preference.\n */\nexport function auditContext(\n session: AuditSession,\n { auth, mode }: { auth: boolean; mode: Mode },\n overrides: BrowserContextOptions = {},\n): Promise<BrowserContext> {\n return newContext(session.browser, {\n viewport: defaultViewport,\n colorScheme: mode,\n // Emulates `prefers-contrast`, which tailwind.css answers on its own, so public pages are covered like signed-in ones\n contrast: 'more',\n reducedMotion: 'reduce',\n serviceWorkers: 'block',\n storageState: auth ? session.storage : undefined,\n // `contrast` here is what the app's own `data-contrast` path reads; the context option above covers the media query\n uiStore: {\n slug: session.user.slug,\n state: { mode, theme: 'none', contrast: auditContrast, publicAlertsSeen: ['test-credentials'] },\n },\n ...overrides,\n });\n}\n\n/** Opens a state's path in `context`; its `open` step is the caller's. */\nexport function openStatePath(session: AuditSession, context: BrowserContext, state: A11yState): Promise<Page> {\n const path = fillPath(state.path, session.values, 'the a11y adapter');\n return openPage(context, `${session.user.frontendUrl}${path}`);\n}\n\ninterface OpenStateOptions {\n mode?: Mode;\n /** Over the state's own browser settings, such as a phone or `{ reducedMotion: 'no-preference' }`. */\n context?: BrowserContextOptions;\n /** Default `ADMIN_EMAIL`, which a testbed hands the command it runs. */\n email?: string;\n}\n\n/**\n * Opens a state of the app's audit scope by id, signed in: the start of a short script that checks a fix in the\n * running app. Run the script from the app's root through `pnpm cella testbed -- node <script>`; `close` ends it.\n * @throws when the scope has no state of that id, or no email is given and `ADMIN_EMAIL` is unset\n */\nexport async function openState(\n id: string,\n { mode = 'light', context: overrides, email = getEnv('ADMIN_EMAIL') }: OpenStateOptions = {},\n): Promise<{ page: Page; context: BrowserContext; close: () => Promise<void> }> {\n if (!email) throw new Error('no email: pass one, or run through `pnpm cella testbed --`, which sets ADMIN_EMAIL');\n const forkPath = process.cwd();\n const scope = await loadScope(forkPath);\n const state = scope.states.find((candidate) => candidate.id === id);\n if (!state) throw new Error(`no state \"${id}\" in the a11y scope`);\n const session = await startAudit(forkPath, scope, { email });\n try {\n const context = await auditContext(session, { auth: state.auth, mode }, { ...state.context, ...overrides });\n const page = await openStatePath(session, context, state);\n await state.open?.(page);\n return { page, context, close: () => endAudit(session) };\n } catch (error) {\n await endAudit(session);\n throw error;\n }\n}\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { z } from 'zod';\nimport { importFromWorkspace } from '../utils/app-facts';\nimport type { Session } from './drive';\n\n/** What `prepare` and a placeholder resolver get: the signed-in tool user, to call the API as. */\nexport type SignedIn = Pick<Session, 'email' | 'frontendUrl' | 'backendUrl'> & {\n /** `name=value`: the cookie header that signs a request in. */\n cookie: string;\n};\n\nexport const signedIn = ({ email, frontendUrl, backendUrl, header }: Session): SignedIn => ({\n email,\n frontendUrl,\n backendUrl,\n cookie: header,\n});\n\n/** Brings the tool user into the state the pages expect, before the first visit. */\nexport type Prepare = (user: SignedIn) => Promise<void>;\n\n/**\n * Values for the `{name}` placeholders of the paths, by name. A resolver that finds nothing returns null, and a path\n * that needs its value then fails with a message naming it.\n */\nexport type Placeholders = Record<string, (user: SignedIn) => Promise<string | null>>;\n\n/** A zod schema that accepts any function; the adapter's types say which. */\nexport const fn = <T>() => z.custom<T>((value) => typeof value === 'function', 'expected a function');\n\nexport const placeholdersSchema = z.record(z.string(), fn<Placeholders[string]>());\n\n/** Fills the `{name}` placeholders of `path`. */\nexport function fillPath(path: string, values: Record<string, string | null>, file: string): string {\n return path.replace(/\\{(\\w+)\\}/g, (_, name: string) => {\n const value = values[name];\n if (!value) throw new Error(`no value for {${name}}: its resolver in ${file} found nothing for the signed-in user`);\n return value;\n });\n}\n\ninterface TsxApi {\n tsImport: (specifier: string, parentURL: string) => Promise<Record<string, unknown>>;\n}\n\n/**\n * Imports an adapter file under the app's own tsx. An adapter imports the app's SDK, whose generated files import each\n * other without an extension, and Node's own type stripping resolves no such import.\n */\nasync function importAdapter(forkPath: string, file: string): Promise<unknown> {\n const { tsImport } = await importFromWorkspace<TsxApi>(forkPath, '.', 'tsx/esm/api');\n const module = await tsImport(pathToFileURL(join(forkPath, file)).href, import.meta.url);\n return module.default;\n}\n\nfunction parsed<T>(file: string, schema: z.ZodType<T>, value: unknown): T {\n const result = schema.safeParse(value);\n if (result.success) return result.data;\n throw new Error(`${file} does not fit this version of the CLI:\\n${z.prettifyError(result.error)}`);\n}\n\n/**\n * A tool's adapter in the app's `cella/` folder: the base `<tool>.ts`, synced from the template, and the optional delta\n * `<tool>.app.ts`, pinned to the app, each checked against its schema. A missing delta means the base alone.\n * @throws when the base is missing or a file does not fit its schema\n */\nexport async function loadAdapter<Base, App>(\n forkPath: string,\n tool: string,\n baseSchema: z.ZodType<Base>,\n appSchema: z.ZodType<App>,\n): Promise<{ base: Base; app: App | undefined }> {\n const baseFile = `cella/${tool}.ts`;\n const appFile = `cella/${tool}.app.ts`;\n if (!existsSync(join(forkPath, baseFile))) {\n throw new Error(`${baseFile} is missing: upgrade the app from cella to get the ${tool} adapter`);\n }\n const base = parsed(baseFile, baseSchema, await importAdapter(forkPath, baseFile));\n const app = existsSync(join(forkPath, appFile))\n ? parsed(appFile, appSchema, await importAdapter(forkPath, appFile))\n : undefined;\n return { base, app };\n}\n\n/**\n * The base's entries with the delta applied: `remove` drops ids, and an added entry replaces the base entry of its id in\n * place or else comes last.\n * @throws when `remove` names an id the base lacks, so a renamed base entry is noticed\n */\nexport function applyDelta<T extends { id: string }>(\n base: T[],\n { remove = [], add = [] }: { remove?: string[]; add?: T[] },\n file: string,\n): T[] {\n const unknown = remove.filter((id) => !base.some((entry) => entry.id === id));\n if (unknown.length > 0) throw new Error(`${file} removes ${unknown.join(', ')}, which the base does not have`);\n const replaced = base\n .filter((entry) => !remove.includes(entry.id))\n .map((entry) => add.find((added) => added.id === entry.id) ?? entry);\n return [...replaced, ...add.filter((added) => !base.some((entry) => entry.id === added.id))];\n}\n","import { z } from 'zod';\nimport { fn, type Placeholders, type Prepare, placeholdersSchema } from '../adapters';\nimport type { BrowserContextOptions, Page } from '../drive';\n\ntype Opener = (page: Page) => Promise<void>;\n\n/** A form probe a state runs on its page. */\nexport type FormCheck =\n /** Submitting the form empty identifies each error in text (3.3.1). */\n | 'required'\n /** Inputs for the user's own details declare their purpose (1.3.5). */\n | 'personal'\n /** Sign-in fields accept autofill and pasted text (3.3.8). */\n | 'sign-in';\n\n/** A page or state of the audit scope. */\nexport interface A11yState {\n id: string;\n /** Path on the frontend; a `{name}` placeholder takes the value its resolver returns. */\n path: string;\n auth: boolean;\n /** Brings the page into the state to audit, such as an open dialog. Runs after the page has loaded. */\n open?: Opener;\n /** `open` leaves an overlay (dialog, sheet, menu) open that holds focus until it closes. */\n overlay?: true;\n /** Browser settings of this state's visits, such as a viewport the state only exists at. */\n context?: BrowserContextOptions;\n forms?: FormCheck[];\n}\n\n/** `cella/a11y.ts`: the template's scope, synced with the UI it describes. */\nexport interface A11yBase {\n /** Brings the audit user into the state the pages expect, before the first visit. */\n prepare?: Prepare;\n /** Values for the `{name}` placeholders of the paths, read as the audit user before the first visit. */\n placeholders?: Placeholders;\n /** What the code checks search, as `git grep` pathspecs from the app's root. */\n sources: string[];\n /** The sample of pages and states the audit covers (WCAG-EM steps 2 and 3), in report order. */\n scope: A11yState[];\n}\n\n/** `cella/a11y.app.ts`, optional: what an app adds to the base, removes from it or overrides. */\nexport interface A11yApp {\n /** Runs after the base's. */\n prepare?: Prepare;\n /** Joins the base's; a name in both takes this one. */\n placeholders?: Placeholders;\n /** Base state ids the app does not have. */\n remove?: string[];\n /** States of the app's own; one with a base state's id replaces it in place. */\n add?: A11yState[];\n}\n\nconst stateSchema = z.strictObject({\n id: z.string().min(1),\n path: z.string().startsWith('/').or(z.string().startsWith('{')),\n auth: z.boolean(),\n open: fn<Opener>().optional(),\n overlay: z.literal(true).optional(),\n context: z.custom<BrowserContextOptions>((value) => typeof value === 'object' && value !== null).optional(),\n forms: z.array(z.enum(['required', 'personal', 'sign-in'])).optional(),\n}) satisfies z.ZodType<A11yState>;\n\nexport const baseSchema = z.strictObject({\n prepare: fn<Prepare>().optional(),\n placeholders: placeholdersSchema.optional(),\n sources: z.array(z.string()).min(1),\n scope: z.array(stateSchema).min(1),\n}) satisfies z.ZodType<A11yBase>;\n\nexport const appSchema = z.strictObject({\n prepare: fn<Prepare>().optional(),\n placeholders: placeholdersSchema.optional(),\n remove: z.array(z.string()).optional(),\n add: z.array(stateSchema).optional(),\n}) satisfies z.ZodType<A11yApp>;\n\n/**\n * The audit measures the app with increased contrast turned on, which is what raises the edge tokens to 3:1. It is a\n * user setting, not the default, so every report built from a run says so: the ledger records it and the report prints\n * it. `prepare` stores it for the audit user, since `/me` overwrites the seeded UI store on every authenticated page.\n */\nexport const auditContrast = 'more' as const;\n\nexport const defineA11yBase = (base: A11yBase): A11yBase => base;\n\nexport const defineA11yApp = (app: A11yApp): A11yApp => app;\n","import type { Page } from 'playwright';\nimport { z } from 'zod';\nimport { importFromApp } from '../../utils/app-facts';\nimport { setEnv } from '../../utils/env';\nimport { applyDelta, loadAdapter, type Placeholders, type Prepare } from '../adapters';\nimport { type A11yState, appSchema, baseSchema } from './define';\n\n/** The audit scope with the app's delta applied. */\nexport interface Scope {\n /** The base's, then the delta's. */\n prepare: Prepare[];\n placeholders: Placeholders;\n sources: string[];\n states: A11yState[];\n}\n\nexport async function loadScope(forkPath: string): Promise<Scope> {\n // The adapters read the app config, which takes the development ports and URLs in development mode only\n setEnv('NODE_ENV', 'development');\n const { base, app } = await loadAdapter(forkPath, 'a11y', baseSchema, appSchema);\n return {\n prepare: [base.prepare, app?.prepare].filter((step) => step !== undefined),\n placeholders: { ...base.placeholders, ...app?.placeholders },\n sources: base.sources,\n states: app ? applyDelta(base.scope, app, 'cella/a11y.app.ts') : base.scope,\n };\n}\n\nconst appConfigSchema = z.object({\n name: z.string(),\n slug: z.string(),\n description: z.string(),\n supportEmail: z.string(),\n frontendUrl: z.string(),\n company: z.object({ name: z.string() }),\n languages: z.array(z.string()).min(1),\n defaultLanguage: z.string(),\n enabledAuthStrategies: z.array(z.string()),\n});\n\n/** The part of the app's config the audit and the report read. */\nexport type AppConfig = z.infer<typeof appConfigSchema>;\n\n/** The app's config in `mode`: the report describes the production app, the audit runs against development builds. */\nexport async function loadAppConfig(forkPath: string, mode: 'development' | 'production'): Promise<AppConfig> {\n setEnv('NODE_ENV', mode);\n const parsed = appConfigSchema.safeParse((await importFromApp(forkPath, 'shared/index.ts')).appConfig);\n if (!parsed.success)\n throw new Error(`shared/index.ts exports no appConfig the audit can read: ${parsed.error.message}`);\n return parsed.data;\n}\n\n/** Overlays that hold focus while open. Toasts render as dialogs but never take focus. */\nexport const overlaySelector =\n '[role=\"dialog\"]:not([data-slot^=\"toast\"]), [role=\"alertdialog\"]:not([data-slot^=\"toast\"]), [role=\"menu\"], [role=\"listbox\"]';\n\n/** Opens the state's overlay again when a check (a resize, an Escape) closed it. */\nexport async function ensureOpen(page: Page, state: A11yState): Promise<void> {\n if (!state.overlay || !state.open || (await page.locator(overlaySelector).count())) return;\n await state.open(page);\n}\n","import { spawnSync } from 'node:child_process';\nimport type { AuditRun, EvidenceSet } from './findings';\n\nconst files = (lines: string[]) => [...new Set(lines.map((line) => line.split(':')[0]))];\n\n/** Keyboard shortcuts made of a printable character alone or with Shift only. */\nfunction characterShortcuts(search: (pattern: string) => string[]) {\n const found: { combo: string; file: string }[] = [];\n for (const line of search(String.raw`\\['[^']+'[[:space:]]*,[[:space:]]*\\(`)) {\n const combo = /\\['([^']+)'/.exec(line)?.[1];\n if (!combo) continue;\n const keys = combo.split('+').map((key) => key.trim().toLowerCase());\n const modifiers = keys.filter((key) => ['meta', 'ctrl', 'control', 'alt', 'mod'].includes(key));\n const printable = keys.filter((key) => key !== 'shift').every((key) => key.length === 1);\n if (!modifiers.length && printable) found.push({ combo, file: line.split(':')[0] });\n }\n return found;\n}\n\n/**\n * Repository checks for criteria a browser cannot see: media, motion, shortcuts, gestures, dragging and sign-in methods.\n * `sources` are the `git grep` pathspecs the adapter base names.\n */\nexport function runCodeChecks(evidence: EvidenceSet, { forkPath, app }: AuditRun, sources: string[]) {\n /** Matching lines (`file:line: text`). Patterns are POSIX ERE: no `\\s`, `\\w` or `\\b`. */\n const search = (pattern: string) =>\n spawnSync('git', ['grep', '-nIE', pattern, '--', ...sources], { cwd: forkPath, encoding: 'utf8' })\n .stdout.split('\\n')\n .filter(Boolean);\n\n const media = search('<(video|audio)[[:space:]>]|MediaPlayer|react-player');\n evidence.add(\n ['1.2.1', '1.2.2', '1.2.3', '1.2.4', '1.2.5'],\n media.length\n ? {\n check: 'code:media',\n result: 'review',\n summary: `The app plays media in ${files(media).join(', ')}. A person decides whether it publishes media of its own or only plays files users upload.`,\n where: files(media),\n }\n : { check: 'code:media', result: 'not-applicable', summary: 'The app contains no video or audio.', where: [] },\n );\n\n const autoplay = search('autoPlay|autoplay');\n evidence.add(\n ['1.4.2'],\n autoplay.length\n ? {\n check: 'code:autoplay',\n result: 'review',\n summary: `Autoplay is set in ${files(autoplay).join(', ')}; check that none of it plays sound.`,\n where: files(autoplay),\n }\n : {\n check: 'code:autoplay',\n result: 'not-applicable',\n summary: 'No audio or video plays automatically.',\n where: [],\n },\n );\n\n // A shortcut a person can turn off would pass too, but the app has no such switch: each shortcut needs a modifier\n const shortcuts = characterShortcuts(search);\n evidence.add(\n ['2.1.4'],\n shortcuts.length\n ? {\n check: 'code:shortcuts',\n result: 'fail',\n summary: `Shortcuts of a character alone or with Shift, which speech input fires by accident: ${shortcuts.map(({ combo, file }) => `${combo} (${file})`).join(', ')}. Give each Ctrl, Alt or Meta.`,\n where: [...new Set(shortcuts.map(({ file }) => file))],\n }\n : {\n check: 'code:shortcuts',\n result: 'pass',\n summary: 'Every keyboard shortcut needs Ctrl, Alt or Meta.',\n where: [],\n },\n );\n\n const looping = search('animate-(ping|pulse|bounce)|animation:[^;]*infinite|repeat: Infinity|carousel-autoplay');\n evidence.add(['2.2.2'], {\n check: 'code:motion',\n result: looping.length ? 'review' : 'pass',\n summary: looping.length\n ? `Looping animations in ${files(looping).slice(0, 8).join(', ')}; check that any that runs longer than 5 seconds beside other content can be paused or stops with reduced motion.`\n : 'No animation loops longer than 5 seconds.',\n where: files(looping),\n });\n\n const flashing = search('(blink|strobe|flash)[a-zA-Z]*[[:space:]]*[:{(]');\n evidence.add(\n ['2.3.1'],\n flashing.length\n ? {\n check: 'code:motion',\n result: 'review',\n summary: `Possible flashing effects in ${files(flashing).join(', ')}.`,\n where: files(flashing),\n }\n : { check: 'code:motion', result: 'pass', summary: 'Nothing in the interface flashes or blinks.', where: [] },\n );\n\n const gestures = search(String.raw`touches\\.length|pinch|onSwipe|useGesture|swipeDirection`);\n evidence.add(\n ['2.5.1'],\n gestures.length\n ? {\n check: 'code:gestures',\n result: 'review',\n summary: `Gesture handlers in ${files(gestures).join(', ')}; check each has a single-pointer alternative such as a button.`,\n where: files(gestures),\n }\n : { check: 'code:gestures', result: 'pass', summary: 'No multipoint or path-based gestures.', where: [] },\n );\n\n const deviceMotion = search('devicemotion|deviceorientation|DeviceMotionEvent|DeviceOrientationEvent');\n evidence.add(\n ['2.5.4'],\n deviceMotion.length\n ? {\n check: 'code:motion-actuation',\n result: 'review',\n summary: `Device motion is read in ${files(deviceMotion).join(', ')}.`,\n where: files(deviceMotion),\n }\n : {\n check: 'code:motion-actuation',\n result: 'not-applicable',\n summary: 'No function responds to shaking or tilting the device.',\n where: [],\n },\n );\n\n const dragging = search(\n String.raw`draggable\\(|dropTargetForElements|monitorForElements|onDragStart|useDrag[^a-zA-Z]`,\n );\n evidence.add(['2.5.7'], {\n check: 'code:dragging',\n result: 'review',\n summary: dragging.length\n ? `Drag and drop in ${files(dragging).join(', ')}; check each has a single-pointer alternative.`\n : 'No drag and drop.',\n where: files(dragging),\n });\n\n const strategies = app.enabledAuthStrategies;\n const oneTimeCode = search('one-time-code');\n const memoryFree = strategies.some((strategy) => ['passkey', 'magic', 'oauth'].includes(strategy));\n evidence.add(['3.3.8'], {\n check: 'code:authentication',\n result: memoryFree && (!strategies.includes('totp') || oneTimeCode.length) ? 'pass' : 'fail',\n summary: `Sign-in uses ${strategies.join(', ')}: no password to remember, and one-time codes support autofill (autocomplete=\"one-time-code\").`,\n where: [],\n });\n}\n","import type { Page } from 'playwright';\nimport type { A11yState } from './define';\nimport type { Evidence } from './ledger';\nimport type { AppConfig } from './scope';\n\n/** What one check found on one state. Empty `problems` and no `review` means the state passes. */\nexport interface Finding {\n /** The state it was found on; a check may narrow it, such as `sign-in (nl)`. */\n state: string;\n criteria: string[];\n check: string;\n /** What the check asserts, as it reads in the report. */\n what: string;\n problems: string[];\n /** A note for the person who has to judge; such a finding is neither pass nor fail. */\n review?: string;\n /** Raw value for checks that compare states with each other, such as the page title. */\n value?: string;\n /** Lowest ratio a contrast check measured on this state; the evidence quotes the lowest of all states. */\n lowest?: number;\n}\n\n/** What every check of one run shares: the app, its config and where the run writes its results. */\nexport interface AuditRun {\n forkPath: string;\n app: AppConfig;\n /** `<git dir>/cella-a11y/` of the checkout. */\n resultsDir: string;\n}\n\n/** A check inspects one open page. It returns nothing where it does not apply. */\nexport type Check = (page: Page, state: A11yState, run: AuditRun) => Promise<Omit<Finding, 'state'>[]>;\n\n/** Collects evidence per criterion. */\nexport class EvidenceSet {\n readonly byCriterion = new Map<string, Evidence[]>();\n\n add(criterionIds: string[], evidence: Evidence) {\n for (const id of criterionIds) this.byCriterion.set(id, [...(this.byCriterion.get(id) ?? []), evidence]);\n }\n\n /** Turns findings into one evidence entry per check and criterion: failing states fail it, review notes leave it open. */\n addFindings(findings: Finding[]) {\n const groups = new Map<string, Finding[]>();\n for (const finding of findings) {\n const key = [finding.check, finding.criteria.join(','), finding.what].join('|');\n groups.set(key, [...(groups.get(key) ?? []), finding]);\n }\n\n for (const group of groups.values()) {\n const { criteria, check, what } = group[0];\n const failing = group.filter((finding) => finding.problems.length);\n const notes = group.filter((finding) => finding.review);\n if (failing.length) {\n const detail = failing\n .map((finding) => `${finding.state}: ${finding.problems.slice(0, 3).join('; ')}`)\n .join(' | ');\n this.add(criteria, {\n check,\n result: 'fail',\n summary: `${what} failed on ${failing.length} of ${group.length} states. ${detail}`,\n where: failing.map((finding) => finding.state),\n });\n } else if (notes.length) {\n const sample = notes\n .slice(0, 3)\n .map((finding) => `${finding.state}: ${finding.review}`)\n .join(' | ');\n this.add(criteria, {\n check,\n result: 'review',\n summary: `${what} ${sample}`,\n where: notes.map((finding) => finding.state),\n });\n } else {\n const ratios = group.flatMap((finding) => (finding.lowest === undefined ? [] : [finding.lowest]));\n const lowest = ratios.length ? ` The lowest measured is ${Math.min(...ratios)}:1.` : '';\n this.add(criteria, {\n check,\n result: 'pass',\n summary: `${what} passed on all ${group.length} states.${lowest}`,\n where: [],\n });\n }\n }\n }\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Criterion, criteria } from './criteria';\nimport { auditContrast } from './define';\n\n/** What a reviewer may record: a row's status, or `open` for a finding that leaves the row undecided. */\nconst decisionStatuses = ['supports', 'partially-supports', 'does-not-support', 'not-applicable', 'open'] as const;\n\nexport type Status = Exclude<(typeof decisionStatuses)[number], 'open'>;\n\n/** Who may decide a row that the audit leaves open. An agent's decision stands until a person confirms or changes it. */\ntype Reviewer = 'agent' | 'human';\n\n/** One finding for one criterion. `review` means a tool could not decide and a reviewer has to look. */\nexport interface Evidence {\n /** `axe`, `probe:<name>`, `code:<name>`, or `review:agent` / `review:human` for a reviewer's own finding. */\n check: string;\n result: 'pass' | 'fail' | 'review' | 'not-applicable';\n /** What was checked or found, in a sentence. */\n summary: string;\n /** Scope states (or files) that failed or need review; empty for a pass, whose summary gives the count. */\n where: string[];\n /** Day a reviewer made the finding; the audit's own evidence is as fresh as the ledger's `auditedAt`. */\n date?: string;\n}\n\n/** A decided row names who decided it; an undecided row has neither a status nor a decider. */\ntype Verdict = { status: Status; decidedBy: 'audit' | Reviewer } | { status: null; decidedBy: null };\n\nexport type LedgerRow = Verdict & {\n id: string;\n name: string;\n level: 'A' | 'AA';\n en301549: string | null;\n /** Reader-facing text for the VPAT's \"Remarks and Explanations\" column. */\n remarks: string;\n /** Checks the audit could not complete, such as `manual`. */\n open: string[];\n evidence: Evidence[];\n};\n\ninterface Ledger {\n /** Name of the app the results are about. A ledger of another app (a fresh scaffold carries the template's) is never read. */\n product: string;\n edition: string;\n standard: string;\n auditedAt: string;\n /** Contrast setting the run measured. `more` means the evidence describes the opted-in state, not the default. */\n contrast: 'system' | 'more';\n scope: string[];\n criteria: LedgerRow[];\n}\n\n/** Committed, and `ignored` for upgrades: each app keeps its own. */\nexport const ledgerFile = 'cella/a11y-ledger.json';\n\n/** The root package's name and version. The name is the same in every mode, where the config slug is not. */\nexport function rootPackage(forkPath: string): { name: string; version: string } {\n return JSON.parse(readFileSync(join(forkPath, 'package.json'), 'utf8'));\n}\n\n/**\n * Decides a row from its evidence. Any failure makes it Partially Supports; only rows whose checks all ran and passed\n * become Supports. Everything else stays undecided with the open checks listed.\n */\nfunction decideByAudit(criterion: Criterion, evidence: Evidence[]): Verdict & Pick<LedgerRow, 'remarks' | 'open'> {\n const ran = new Set(evidence.map((e) => e.check));\n const open: string[] = criterion.checks.filter((check) => check === 'manual' || !ran.has(check));\n if (evidence.some((e) => e.result === 'review')) open.push('review');\n\n const failures = evidence.filter((e) => e.result === 'fail');\n if (failures.length) {\n const where = [...new Set(failures.flatMap((e) => e.where))];\n return {\n status: 'partially-supports',\n remarks: `Automated checks found failures on ${where.length} of the reviewed pages and states.`,\n decidedBy: 'audit',\n open,\n };\n }\n if (open.length) return { status: null, remarks: '', decidedBy: null, open };\n if (evidence.length && evidence.every((e) => e.result === 'not-applicable')) {\n return { status: 'not-applicable', remarks: evidence.map((e) => e.summary).join(' '), decidedBy: 'audit', open };\n }\n return { status: 'supports', remarks: evidence.map((e) => e.summary).join(' '), decidedBy: 'audit', open };\n}\n\n/** This app's ledger, or null when there is none yet or the file holds another app's results. */\nexport function readLedger(forkPath: string): Ledger | null {\n const path = join(forkPath, ledgerFile);\n if (!existsSync(path)) return null;\n const ledger: Ledger = JSON.parse(readFileSync(path, 'utf8'));\n return ledger.product === rootPackage(forkPath).name ? ledger : null;\n}\n\n/** The family a check belongs to: `axe`, `probe`, `code` or `review`. */\nconst family = (check: string) => check.split(':')[0];\n\n/** Evidence the audit produced itself; a reviewer's findings are left out. */\nexport const automated = (evidence: Evidence[]) => evidence.filter((item) => family(item.check) !== 'review');\n\n/**\n * Builds the ledger from the run's evidence; a reviewer's findings carry over from the previous ledger. A row a reviewer\n * decided keeps that decision, unless the audit now finds a failure on a row the reviewer called Supports or Not\n * Applicable.\n */\nexport function writeLedger(forkPath: string, evidenceById: Map<string, Evidence[]>, scope: string[], target: string) {\n const previous = new Map((readLedger(forkPath)?.criteria ?? []).map((row) => [row.id, row]));\n\n const rows = criteria.map((criterion): LedgerRow => {\n const before = previous.get(criterion.id);\n const kept = (before?.evidence ?? []).filter((item) => family(item.check) === 'review');\n const evidence = [...kept, ...(evidenceById.get(criterion.id) ?? [])];\n const byAudit = decideByAudit(criterion, automated(evidence));\n const reviewed = before?.decidedBy === 'agent' || before?.decidedBy === 'human';\n const contradicted =\n byAudit.status === 'partially-supports' && (before?.status === 'supports' || before?.status === 'not-applicable');\n const decision =\n before && reviewed && !contradicted\n ? { status: before.status, remarks: before.remarks, decidedBy: before.decidedBy, open: [] }\n : byAudit;\n return {\n id: criterion.id,\n name: criterion.name,\n level: criterion.level,\n en301549: criterion.en301549,\n ...decision,\n evidence,\n };\n });\n\n const ledger: Ledger = {\n product: rootPackage(forkPath).name,\n edition: 'VPAT® 2.5Rev WCAG',\n standard: 'WCAG 2.2 Level AA',\n auditedAt: new Date().toISOString().slice(0, 10),\n contrast: auditContrast,\n scope,\n criteria: rows,\n };\n writeFileSync(target, `${JSON.stringify(ledger, null, 2)}\\n`);\n return ledger;\n}\n\n/** A reviewer's decision on one criterion. `open` records a finding and leaves the row undecided. */\nexport interface Decision {\n id: string;\n status: Status | 'open';\n by: Reviewer;\n /** Reader-facing text for the report; required unless the criterion is supported. */\n remarks?: string;\n /** What the reviewer looked at and found, for whoever checks the decision. */\n evidence: string;\n /** States (or files) the finding is about. */\n where?: string[];\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;\nconst isStringList = (value: unknown): value is string[] =>\n Array.isArray(value) && value.every((item) => typeof item === 'string');\n\n/** Reads one decision from a decisions file or the command line; refuses one that lacks a field or carries one of the wrong type. */\nexport function parseDecision(raw: unknown): Decision {\n const { id, status, by, remarks, evidence, where }: Record<string, unknown> = isRecord(raw) ? raw : {};\n const known = decisionStatuses.find((candidate) => candidate === status);\n if (typeof id !== 'string' || !id || !known) {\n throw new Error(\n `${typeof id === 'string' && id ? id : 'A decision'} needs --id and --status (${decisionStatuses.join(', ')}).`,\n );\n }\n if (by !== 'agent' && by !== 'human') throw new Error(`${id} needs --by agent or --by human.`);\n if (typeof evidence !== 'string' || !evidence) throw new Error(`${id} needs --evidence.`);\n if (remarks !== undefined && typeof remarks !== 'string') throw new Error(`${id}: remarks must be text.`);\n if (where !== undefined && !isStringList(where)) throw new Error(`${id}: where must be a list of states or files.`);\n return { id, status: known, by, remarks, evidence, where };\n}\n\n/** Records reviewers' decisions in the ledger. Refuses what the evidence cannot carry; nothing is written unless all are valid. */\nexport function recordDecisions(forkPath: string, decisions: Decision[]) {\n const ledger = readLedger(forkPath);\n if (!ledger) throw new Error(`no ledger for ${rootPackage(forkPath).name} yet: run \\`pnpm cella a11y\\` first`);\n\n for (const { id, status, by, remarks = '', evidence, where = [] } of decisions) {\n const row = ledger.criteria.find((candidate) => candidate.id === id);\n if (!row) throw new Error(`${id} is not a WCAG 2.2 A/AA criterion.`);\n if (!evidence.trim()) throw new Error(`${id}: a decision needs its evidence.`);\n if (by === 'agent' && row.decidedBy === 'human')\n throw new Error(`${id} was decided by a person; only a person changes it.`);\n const passes = status === 'supports' || status === 'not-applicable';\n if (passes && automated(row.evidence).some((item) => item.result === 'fail')) {\n throw new Error(`${id}: the audit found failures, so it cannot be ${status}. Fix them or record what fails.`);\n }\n if (status !== 'supports' && status !== 'open' && !remarks.trim())\n throw new Error(`${id}: ${status} needs remarks for the reader.`);\n\n const result =\n status === 'open'\n ? 'review'\n : status === 'supports'\n ? 'pass'\n : status === 'not-applicable'\n ? 'not-applicable'\n : 'fail';\n const finding: Evidence = {\n check: `review:${by}`,\n result,\n summary: evidence.trim(),\n where,\n date: new Date().toISOString().slice(0, 10),\n };\n row.evidence = [...row.evidence.filter((item) => item.check !== finding.check), finding];\n\n if (status !== 'open') Object.assign(row, { status, remarks: remarks.trim(), decidedBy: by, open: [] });\n else if (row.decidedBy === 'agent' || row.decidedBy === 'human')\n Object.assign(row, { status: null, remarks: '', decidedBy: null, open: ['manual'] });\n }\n\n writeFileSync(join(forkPath, ledgerFile), `${JSON.stringify(ledger, null, 2)}\\n`);\n return ledger;\n}\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { settle } from '../../drive';\nimport type { Check, Finding } from '../findings';\n\nconst titles = { criteria: ['2.4.2'], check: 'probe:titles', what: 'A distinct, descriptive page title' };\nconst language = {\n criteria: ['3.1.1'],\n check: 'probe:language',\n what: 'The page language follows the language the user picks',\n};\n\n/** Title (2.4.2), a main landmark or skip link (2.4.1) and the declared language (3.1.1) of a page. */\nexport const pageStructure: Check = async (page, state, { app }) => {\n if (state.open) return [];\n const title = await page.title();\n const lang = await page.evaluate(() => document.documentElement.lang);\n const bypass = await page.evaluate(() => {\n if (document.querySelector('main, [role=\"main\"]')) return true;\n const first = document.querySelector<HTMLAnchorElement>('a[href^=\"#\"]');\n return !!(first?.hash && document.getElementById(first.hash.slice(1)));\n });\n\n return [\n {\n ...titles,\n value: title,\n problems: !title.trim() || title === app.name ? [`title is \"${title}\", which names no page`] : [],\n },\n {\n criteria: ['2.4.1'],\n check: 'probe:landmarks',\n what: 'A main landmark or skip link to bypass repeated navigation',\n problems: bypass ? [] : ['no main landmark and no skip link'],\n },\n { ...language, problems: lang === app.defaultLanguage ? [] : [`lang=\"${lang}\" on an ${app.defaultLanguage} page`] },\n ];\n};\n\n/**\n * Picks every other language with the app's own switcher and reads the declared page language. It changes the stored\n * language, so it runs last in a visit. Pages without a switcher return nothing.\n */\nexport const languageSwitch: Check = async (page, state, { app, forkPath }) => {\n if (state.open) return [];\n const names: Record<string, string> = JSON.parse(\n readFileSync(join(forkPath, 'locales', app.defaultLanguage, 'common.json'), 'utf8'),\n );\n const findings: Awaited<ReturnType<Check>> = [];\n\n for (const other of app.languages.filter((lng) => lng !== app.defaultLanguage)) {\n const button = page.getByRole('button', { name: /change language/i }).first();\n if (!(await button.count())) break;\n const label = names[other] ?? other;\n await button.click();\n await page\n .getByRole('menuitem', { name: label })\n .or(page.getByRole('menuitemradio', { name: label }))\n .first()\n .click();\n await settle(page);\n const lang = await page.evaluate(() => document.documentElement.lang);\n findings.push({\n ...language,\n value: other,\n problems: lang === other ? [] : [`after choosing ${label}, <html lang=\"${lang}\">`],\n });\n }\n return findings;\n};\n\n/** Checks that compare states with each other: a title shared by two pages, and whether any page offered a language switch. */\nexport function acrossStates(findings: Finding[]): Finding[] {\n const titled = findings.filter((finding) => finding.check === titles.check);\n for (const finding of titled) {\n const twins = titled\n .filter((other) => other !== finding && other.value === finding.value)\n .map((other) => other.state);\n if (twins.length) finding.problems.push(`\"${finding.value}\" is also the title of ${twins.join(', ')}`);\n }\n\n // A language finding with a value is one made after switching; label it so it reads apart from the default-language one\n const switched = findings.filter((finding) => finding.check === language.check && finding.value);\n for (const finding of switched) finding.state = `${finding.state} (${finding.value})`;\n const checkedDefault = findings.some((finding) => finding.check === language.check);\n if (checkedDefault && !switched.length) {\n return [\n ...findings,\n {\n ...language,\n state: 'all pages',\n problems: [],\n review: 'No page offers a language switcher, so no other language was checked.',\n },\n ];\n }\n return findings;\n}\n","import type { Page } from 'playwright';\nimport type { Check } from '../findings';\n\n/** Text nodes measured per visit; nodes that share tag and classes share their colours, so one of each kind is measured. */\nconst maxTextNodes = 60;\n\ninterface Measured {\n text: string;\n ratio: number;\n needed: number;\n}\n\n/**\n * Contrast of the text axe leaves undecided (over a gradient, an image or a pseudo-element, or too short to judge),\n * measured from rendered pixels: the element is captured with its text and with the text made transparent, and the\n * text colour is compared with what lies behind each text pixel.\n */\nexport const textContrast =\n (targets: string[]): Check =>\n async (page) => {\n if (!targets.length) return [];\n const measured: Measured[] = [];\n const kinds = new Set<string>();\n\n for (const target of targets) {\n if (kinds.size >= maxTextNodes) break;\n const locator = page.locator(target).first();\n const info = await locator\n .evaluate((el) => {\n const style = getComputedStyle(el);\n const size = Number.parseFloat(style.fontSize);\n const ownText = [...el.childNodes]\n .filter((node) => node.nodeType === Node.TEXT_NODE)\n .map((node) => node.textContent?.trim())\n .join(' ')\n .trim();\n return {\n kind: `${el.tagName}|${el.getAttribute('class') ?? ''}|${style.color}|${style.opacity}`,\n text: (ownText || el.textContent || '').trim().replace(/\\s+/g, ' ').slice(0, 40),\n // Decoration, and controls that cannot be used, are outside the criterion\n exempt:\n !!el.closest('[aria-hidden=\"true\"], :disabled, [aria-disabled=\"true\"]') || !el.getClientRects().length,\n large: size >= 24 || (size >= 18.66 && Number(style.fontWeight) >= 700),\n clipped: style.backgroundClip.includes('text') || style.webkitBackgroundClip?.includes('text'),\n };\n })\n .catch(() => null);\n if (!info || info.exempt || !info.text || kinds.has(info.kind)) continue;\n kinds.add(info.kind);\n\n try {\n await locator.scrollIntoViewIfNeeded({ timeout: 2000 });\n const shot = () => locator.screenshot({ animations: 'disabled', caret: 'hide', timeout: 4000 });\n const withText = await shot();\n // Text painted through a clipped background disappears with the element; any other text by losing its colour\n await locator.evaluate((el, clipped) => {\n const node = el as HTMLElement;\n node.dataset.a11yStyle = node.getAttribute('style') ?? '';\n if (clipped) node.style.setProperty('opacity', '0', 'important');\n else {\n node.style.setProperty('color', 'transparent', 'important');\n node.style.setProperty('-webkit-text-fill-color', 'transparent', 'important');\n node.style.setProperty('text-shadow', 'none', 'important');\n }\n }, info.clipped);\n const withoutText = await shot().finally(() =>\n locator.evaluate((el) => {\n const node = el as HTMLElement;\n node.setAttribute('style', node.dataset.a11yStyle ?? '');\n delete node.dataset.a11yStyle;\n }),\n );\n\n const ratio = await page.evaluate(\n async ([a, b]) => {\n const pixels = async (base64: string) => {\n const image = new Image();\n image.src = `data:image/png;base64,${base64}`;\n await image.decode();\n const canvas = document.createElement('canvas');\n canvas.width = image.width;\n canvas.height = image.height;\n const context = canvas.getContext('2d', { willReadFrequently: true });\n if (!context) return null;\n context.drawImage(image, 0, 0);\n return context.getImageData(0, 0, canvas.width, canvas.height).data;\n };\n const [text, behind] = [await pixels(a), await pixels(b)];\n if (!text || !behind || text.length !== behind.length) return null;\n const luminance = (data: Uint8ClampedArray, i: number) => {\n const channel = (value: number) => {\n const s = value / 255;\n return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n };\n return 0.2126 * channel(data[i]) + 0.7152 * channel(data[i + 1]) + 0.0722 * channel(data[i + 2]);\n };\n // The pixel that changed most is fully covered by a glyph: it carries the text colour\n let strongest = 0;\n let at = -1;\n const covered: number[] = [];\n for (let i = 0; i < text.length; i += 4) {\n const change = Math.max(\n Math.abs(text[i] - behind[i]),\n Math.abs(text[i + 1] - behind[i + 1]),\n Math.abs(text[i + 2] - behind[i + 2]),\n );\n if (change > 6) covered.push(i);\n if (change > strongest) {\n strongest = change;\n at = i;\n }\n }\n if (at < 0 || strongest < 12 || covered.length < 8) return null;\n const textLuminance = luminance(text, at);\n // Against what lies behind each glyph pixel; the low end counts, so a gradient is judged where it is weakest\n const ratios = covered\n .map((i) => {\n const background = luminance(behind, i);\n return (Math.max(textLuminance, background) + 0.05) / (Math.min(textLuminance, background) + 0.05);\n })\n .sort((x, y) => x - y);\n return Math.round(ratios[Math.floor(ratios.length * 0.05)] * 100) / 100;\n },\n [withText.toString('base64'), withoutText.toString('base64')] as const,\n );\n // No measurable text: a field's value or placeholder, which this capture does not hide\n if (ratio !== null) measured.push({ text: info.text, ratio, needed: info.large ? 3 : 4.5 });\n } catch {\n // An element that left the page between the scan and the capture is not measured\n }\n }\n\n if (!measured.length) return [];\n const problems = measured\n .filter(({ ratio, needed }) => ratio < needed)\n .map(({ text, ratio, needed }) => `\"${text}\" is ${ratio}:1, needs ${needed}:1`);\n const lowest = Math.min(...measured.map(({ ratio }) => ratio));\n return [\n {\n criteria: ['1.4.3'],\n check: 'probe:text-contrast',\n what: 'Text the scanner cannot decide (over gradients and images, or too short) reaches its contrast, measured from rendered pixels',\n problems,\n lowest,\n },\n ];\n };\n\nconst controls =\n 'input:not([type=\"hidden\"]):not([type=\"file\"]), textarea, select, [role=\"checkbox\"], [role=\"radio\"], [role=\"switch\"], [role=\"combobox\"], [data-slot=\"select-trigger\"]';\n\ninterface Edge {\n x: number;\n y: number;\n height: number;\n borderWidth: number;\n borderColor: string;\n}\n\n/**\n * Contrast of a box's left edge against what lies outside it. The colours outside and inside the edge come from a\n * capture, so a gradient or an image behind the control counts as it shows; the border colour comes from the styles\n * and is laid over the inside colour, since a captured one-pixel border is blurred by anti-aliasing.\n */\nasync function edgeContrast(page: Page, edge: Edge) {\n const viewport = page.viewportSize();\n const x = Math.floor(edge.x) - 3;\n const y = Math.round(edge.y + edge.height / 2);\n const width = Math.ceil(edge.borderWidth) + 8;\n if (!viewport || x < 0 || y < 0 || y >= viewport.height || x + width > viewport.width) return null;\n const strip = await page.screenshot({ clip: { x, y, width, height: 1 }, animations: 'disabled', caret: 'hide' });\n return page.evaluate(\n async ([base64, borderColor, borderWidth]) => {\n const image = new Image();\n image.src = `data:image/png;base64,${base64}`;\n await image.decode();\n const canvas = document.createElement('canvas');\n canvas.width = image.width;\n canvas.height = 1;\n const context = canvas.getContext('2d', { willReadFrequently: true });\n if (!context) return null;\n context.drawImage(image, 0, 0);\n const data = context.getImageData(0, 0, canvas.width, 1).data;\n const outside = [data[0], data[1], data[2]];\n const last = data.length - 4;\n const inside = [data[last], data[last + 1], data[last + 2]];\n\n context.clearRect(0, 0, 1, 1);\n context.fillStyle = borderColor;\n context.fillRect(0, 0, 1, 1);\n const [r, g, b, a] = context.getImageData(0, 0, 1, 1).data;\n const alpha = borderWidth > 0 ? a / 255 : 0;\n const border = [r, g, b].map((value, i) => value * alpha + inside[i] * (1 - alpha));\n\n const luminance = (rgb: number[]) => {\n const [x1, x2, x3] = rgb.map((value) => {\n const s = value / 255;\n return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * x1 + 0.7152 * x2 + 0.0722 * x3;\n };\n const ratio = (one: number[], other: number[]) => {\n const [l1, l2] = [luminance(one), luminance(other)];\n return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);\n };\n return Math.max(ratio(border, outside), ratio(inside, outside));\n },\n [strip.toString('base64'), edge.borderColor, edge.borderWidth] as const,\n );\n}\n\n/**\n * The edge of form controls against what surrounds them (1.4.11), from rendered pixels, so a gradient or an image\n * behind the control counts as it shows: a border, or a fill that sets the control apart, at 3:1. A control inside a\n * wrapper that draws the edge (an input group) is judged by the wrapper; one with no edge drawn at all is left out,\n * since the criterion asks for contrast of the edge that is there, not for an edge.\n */\nexport const controlContrast: Check = async (page) => {\n const kinds = new Set<string>();\n const problems: string[] = [];\n let lowest = Number.POSITIVE_INFINITY;\n\n for (const handle of await page.locator(controls).elementHandles()) {\n const info = await handle.evaluate((node) => {\n const el = node as HTMLElement;\n // A read-only field shows a value; a disabled or hidden one cannot be used\n const usable =\n !!el.offsetParent &&\n !el.closest(':disabled, [readonly], [aria-disabled=\"true\"], [aria-hidden=\"true\"]') &&\n el.clientWidth > 1 &&\n el.clientHeight > 1;\n return {\n usable,\n kind: `${el.tagName}|${el.getAttribute('role') ?? ''}|${el.getAttribute('type') ?? ''}|${el.getAttribute('class') ?? ''}`,\n name: (\n el.getAttribute('aria-label') ||\n el.getAttribute('name') ||\n el.getAttribute('placeholder') ||\n el.getAttribute('role') ||\n el.tagName.toLowerCase()\n ).slice(0, 30),\n };\n });\n if (!info.usable || kinds.has(info.kind)) continue;\n kinds.add(info.kind);\n await handle.scrollIntoViewIfNeeded({ timeout: 2000 }).catch(() => null);\n\n // The control itself, then up to two wrappers that may draw its edge\n let best = 1;\n for (let depth = 0; depth < 3 && best < 3; depth++) {\n const edge = await handle.evaluate((node, levels): Edge | null => {\n let el: Element | null = node as Element;\n for (let i = 0; i < levels; i++) el = el?.parentElement ?? null;\n if (!el) return null;\n const rect = el.getBoundingClientRect();\n const style = getComputedStyle(el);\n return {\n x: rect.x,\n y: rect.y,\n height: rect.height,\n borderWidth: Number.parseFloat(style.borderLeftWidth) || 0,\n borderColor: style.borderLeftColor,\n };\n }, depth);\n const measured = edge ? await edgeContrast(page, edge) : null;\n if (measured !== null) best = Math.max(best, measured);\n }\n if (best < 1.05) continue;\n best = Math.round(best * 100) / 100;\n lowest = Math.min(lowest, best);\n if (best < 3) problems.push(`${info.name}: ${best}:1`);\n }\n\n if (lowest === Number.POSITIVE_INFINITY) return [];\n return [\n {\n criteria: ['1.4.11'],\n check: 'probe:control-contrast',\n what: 'The edge of form controls (fields, selects, checkboxes, radios, switches) reaches 3:1 against what surrounds it',\n problems,\n lowest,\n },\n ];\n};\n","import type { Page } from 'playwright';\nimport type { Check } from '../findings';\n\n/** Submits the first form empty; every invalid field must be marked and described by visible error text. */\nfunction submitEmpty(page: Page) {\n return page.evaluate(async () => {\n const form = document.querySelector('[role=\"dialog\"] form') ?? document.querySelector('main form, form');\n if (!form) return ['no form found'];\n const submit =\n form.querySelector<HTMLButtonElement>('button[type=\"submit\"]') ??\n form.querySelector<HTMLButtonElement>('button:not([type=\"button\"])');\n if (!submit) return ['no submit button found'];\n submit.click();\n await new Promise((resolve) => setTimeout(resolve, 800));\n\n const problems: string[] = [];\n const invalid = [...form.querySelectorAll('[aria-invalid=\"true\"]')];\n const alerts = [\n ...document.querySelectorAll('[role=\"alert\"], [data-slot=\"form-message\"], [data-slot=\"field-error\"]'),\n ].filter((el) => el.textContent?.trim());\n if (!invalid.length && !alerts.length) problems.push('submitting empty shows no identified error');\n for (const field of invalid) {\n const ids = (field.getAttribute('aria-describedby') ?? '').split(/\\s+/).filter(Boolean);\n const described = ids.some((id) => document.getElementById(id)?.textContent?.trim());\n const label = field.getAttribute('aria-label') ?? field.getAttribute('name') ?? field.tagName.toLowerCase();\n if (!described) problems.push(`${label} is marked invalid but no error text is linked to it`);\n }\n return problems;\n });\n}\n\n/** Personal-data inputs without an autocomplete token (1.3.5), and inputs that refuse pasted text (3.3.8). */\nfunction inputPurpose(page: Page) {\n return page.evaluate(() => {\n const purpose: string[] = [];\n const paste: string[] = [];\n const personal = /e-?mail|first|last|full.?name|^name$|phone|tel|username/i;\n for (const input of document.querySelectorAll<HTMLInputElement>(\n 'input:not([type=\"hidden\"]):not([type=\"checkbox\"]):not([type=\"radio\"])',\n )) {\n // A disabled or read-only field collects nothing, so 1.3.5 does not apply\n if (input.disabled || input.readOnly) continue;\n const label = (input.labels?.[0]?.textContent ?? input.getAttribute('aria-label') ?? '').trim();\n const isPersonal =\n input.type === 'email' || input.type === 'tel' || personal.test(input.name) || personal.test(label);\n const token = input.getAttribute('autocomplete');\n if (isPersonal && (!token || token === 'off' || token === 'on'))\n purpose.push(`\"${label || input.name || input.type}\" has no autocomplete purpose`);\n\n const event = new ClipboardEvent('paste', { bubbles: true, cancelable: true, clipboardData: new DataTransfer() });\n input.dispatchEvent(event);\n if (event.defaultPrevented) paste.push(`\"${label || input.name || input.type}\" blocks paste`);\n }\n return { purpose, paste };\n });\n}\n\n/** Error identification (3.3.1). Submitting changes the page, so this runs late in a visit. */\nexport const formErrors: Check = async (page, state) => {\n if (!state.forms?.includes('required')) return [];\n const problems = await submitEmpty(page);\n // A failed submit may raise a toast, which would lie over other controls during the next check\n await page\n .waitForFunction(() => !document.querySelector('[data-slot=\"toast\"]'), null, { timeout: 8000 })\n .catch(() => undefined);\n return [\n {\n criteria: ['3.3.1'],\n check: 'probe:form-errors',\n what: 'Submitting required fields empty identifies each error in text',\n problems,\n },\n ];\n};\n\n/** Input purpose (1.3.5), and autofill and paste into the sign-in fields (3.3.8). */\nexport const inputs: Check = async (page, state) => {\n const personal = state.forms?.includes('personal');\n const signIn = state.forms?.includes('sign-in');\n if (!personal && !signIn) return [];\n const { purpose, paste } = await inputPurpose(page);\n const findings: Awaited<ReturnType<Check>> = [];\n if (personal) {\n findings.push({\n criteria: ['1.3.5'],\n check: 'probe:autocomplete',\n what: 'Inputs for personal data declare their purpose',\n problems: purpose,\n });\n }\n if (signIn) {\n findings.push({\n criteria: ['3.3.8'],\n check: 'probe:autocomplete',\n what: 'Sign-in fields accept autofill and pasted text',\n problems: [...purpose, ...paste],\n });\n }\n return findings;\n};\n","import { mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { AuditRun, Check } from './findings';\nimport { devOnlySelectors } from './session';\n\n/** Where the audit leaves, per state, what a reviewer (a person or an agent) needs to judge the criteria no tool decides. */\nexport const packetDir = (run: AuditRun, stateId: string) => join(run.resultsDir, 'review', stateId);\n\n/** Adds a file to a state's review packet. */\nexport function writePacketFile(run: AuditRun, stateId: string, name: string, content: string | Buffer) {\n mkdirSync(packetDir(run, stateId), { recursive: true });\n writeFileSync(join(packetDir(run, stateId), name), content);\n}\n\n/** Removes a file from a state's review packet; a missing one is fine. */\nexport function removePacketFile(run: AuditRun, stateId: string, name: string) {\n rmSync(join(packetDir(run, stateId), name), { force: true });\n}\n\n/** What the page states about itself, for the criteria that compare it with what is visible. */\nfunction pageFacts() {\n const text = (el: Element | null) => (el?.textContent ?? '').trim().replace(/\\s+/g, ' ');\n const visible = (el: Element) => {\n const rect = el.getBoundingClientRect();\n return rect.width > 1 && rect.height > 1 && getComputedStyle(el).visibility !== 'hidden';\n };\n const labelOf = (el: Element) =>\n el.getAttribute('aria-label') ??\n (el.getAttribute('aria-labelledby') ?? '')\n .split(/\\s+/)\n .map((id) => text(document.getElementById(id)))\n .join(' ')\n .trim();\n\n const controls = [\n ...document.querySelectorAll('button, a[href], [role=\"button\"], [role=\"link\"], [role=\"tab\"], [role=\"menuitem\"]'),\n ].filter(visible);\n return {\n title: document.title,\n lang: document.documentElement.lang,\n headings: [...document.querySelectorAll('h1, h2, h3, h4, h5, h6, [role=\"heading\"]')].filter(visible).map((el) => ({\n level: Number(el.getAttribute('aria-level') ?? el.tagName.slice(1)),\n text: text(el).slice(0, 80),\n })),\n landmarks: [\n ...document.querySelectorAll(\n 'main, nav, header, footer, aside, form[aria-label], [role=\"main\"], [role=\"navigation\"], [role=\"search\"]',\n ),\n ]\n .filter(visible)\n .map((el) => `${el.getAttribute('role') ?? el.tagName.toLowerCase()}${labelOf(el) ? ` \"${labelOf(el)}\"` : ''}`),\n images: [...document.querySelectorAll('img, svg[role=\"img\"], [role=\"img\"]')].filter(visible).map((el) => ({\n name: el.getAttribute('alt') ?? labelOf(el),\n decorative: el.getAttribute('alt') === '' || el.getAttribute('aria-hidden') === 'true',\n source: (el.getAttribute('src') ?? el.tagName.toLowerCase()).split('/').pop()?.slice(0, 60),\n within: text(el.closest('a, button, figure')).slice(0, 60),\n })),\n // 2.5.3: a control whose accessible name does not contain its visible text cannot be called by voice\n labelNotInName: controls\n .filter((el) => labelOf(el) && text(el) && !labelOf(el).toLowerCase().includes(text(el).toLowerCase()))\n .map((el) => ({ visible: text(el).slice(0, 60), name: labelOf(el).slice(0, 60) })),\n fields: [\n ...document.querySelectorAll<HTMLInputElement>(\n 'input:not([type=\"hidden\"]), textarea, select, [role=\"combobox\"], [role=\"switch\"], [role=\"checkbox\"]',\n ),\n ]\n .filter(visible)\n .map((el) => ({\n label: (el.labels?.[0] ? text(el.labels[0]) : '') || labelOf(el),\n type: el.getAttribute('type') ?? el.getAttribute('role') ?? el.tagName.toLowerCase(),\n required: el.required || el.getAttribute('aria-required') === 'true',\n placeholder: el.getAttribute('placeholder') ?? '',\n description: (el.getAttribute('aria-describedby') ?? '')\n .split(/\\s+/)\n .map((id) => text(document.getElementById(id)))\n .join(' ')\n .trim(),\n })),\n otherLanguages: [...document.querySelectorAll('[lang]')]\n .filter((el) => el !== document.documentElement && visible(el))\n .map((el) => ({ lang: el.getAttribute('lang'), text: text(el).slice(0, 60) })),\n liveRegions: [...document.querySelectorAll('[aria-live], [role=\"status\"], [role=\"alert\"], [role=\"log\"]')].map(\n (el) =>\n `${el.getAttribute('role') ?? 'aria-live'}=${el.getAttribute('aria-live') ?? 'implicit'}: ${text(el).slice(0, 60)}`,\n ),\n };\n}\n\n/**\n * Saves the state's review packet: a screenshot, the accessibility tree a screen reader works from, and facts about\n * the page. It decides nothing; the `a11y-review` skill describes how a reviewer uses it.\n */\nexport const reviewPacket: Check = async (page, state, run) => {\n // Development-only tools are not part of the product\n const hidden = await page.addStyleTag({ content: `${devOnlySelectors.join(', ')} { display: none !important; }` });\n writePacketFile(\n run,\n state.id,\n 'screenshot.png',\n await page.screenshot({ fullPage: !state.open, animations: 'disabled' }),\n );\n writePacketFile(run, state.id, 'tree.yml', await page.locator('body').ariaSnapshot());\n writePacketFile(run, state.id, 'facts.json', `${JSON.stringify(await page.evaluate(pageFacts), null, 2)}\\n`);\n await hidden.evaluate((element) => (element as Element).remove());\n return [];\n};\n","import type { ElementHandle, Page } from 'playwright';\nimport type { Check } from '../findings';\nimport { writePacketFile } from '../review-packet';\nimport { overlaySelector } from '../scope';\nimport { devOnlySelectors } from '../session';\n\nconst maxSteps = 60;\n\nconst withoutHash = (url: string) => url.split('#')[0];\n\ninterface Stop {\n key: string;\n name: string;\n /** Top-left corner on the page, to compare the Tab order with the visual order. */\n x: number;\n y: number;\n obscured: boolean;\n coveredBy: string;\n /** Inside the overlay that was open when the walk started; null when no overlay was open. */\n inOverlay: boolean | null;\n editable: boolean;\n /** Tag, role and classes: elements of one kind share their focus styling, so one of them is checked for it. */\n kind: string;\n}\n\n/** Two animation frames: enough for the browser to move focus and paint its styles. */\nconst painted = (page: Page) =>\n page.evaluate(() => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve))));\n\n/** Describes the focused element, and whether other content covers all of it. */\nfunction readFocus(page: Page, devOnly: string[]) {\n return page.evaluate(\n ([skip, overlays]): Stop | null => {\n const el = document.activeElement;\n if (!el || el === document.body || skip.some((selector) => el.closest(selector))) return null;\n const parts: string[] = [];\n for (let node: Element | null = el; node && node !== document.body; node = node.parentElement) {\n parts.unshift(\n `${node.tagName.toLowerCase()}:${node.parentElement ? [...node.parentElement.children].indexOf(node) : 0}`,\n );\n }\n const name = (el.getAttribute('aria-label') || el.textContent || el.getAttribute('placeholder') || el.tagName)\n .trim()\n .replace(/\\s+/g, ' ')\n .slice(0, 40);\n const rect = el.getBoundingClientRect();\n let obscured = false;\n let coveredBy = 'nothing at its position';\n if (rect.width > 2 && rect.height > 2) {\n const inset = 2;\n const points = [\n [rect.left + rect.width / 2, rect.top + rect.height / 2],\n [rect.left + inset, rect.top + inset],\n [rect.right - inset, rect.top + inset],\n [rect.left + inset, rect.bottom - inset],\n [rect.right - inset, rect.bottom - inset],\n ];\n const cover = points.map(([x, y]) => document.elementFromPoint(x, y));\n obscured = cover.every((hit) => !hit || !(el.contains(hit) || hit.contains(el)));\n // Name what lies on top, so the finding points at the element to fix\n const top = cover[0];\n if (obscured && top)\n coveredBy = `${top.tagName.toLowerCase()}${top.id ? `#${top.id}` : ''}.${[...top.classList].slice(0, 3).join('.')}`;\n }\n const open = document.querySelectorAll(overlays);\n const inOverlay = open.length ? [...open].some((overlay) => overlay.contains(el)) : null;\n const editable = el.matches(\n 'input:not([type=\"checkbox\"]):not([type=\"radio\"]):not([type=\"button\"]):not([type=\"submit\"]), textarea, [contenteditable=\"true\"]',\n );\n const kind = `${el.tagName}|${el.getAttribute('role') ?? ''}|${el.getAttribute('class') ?? ''}`;\n const [x, y] = [Math.round(rect.left + window.scrollX), Math.round(rect.top + window.scrollY)];\n return {\n key: parts.join('>'),\n name: `${el.tagName.toLowerCase()} \"${name}\"`,\n x,\n y,\n obscured,\n coveredBy,\n inOverlay,\n editable,\n kind,\n };\n },\n [devOnly, overlaySelector] as const,\n );\n}\n\n/** The area a focus indicator can occupy: the element, or the grid cell or row that styles focus for it. */\nasync function focusBox(page: Page, handle: ElementHandle) {\n const box = await handle.evaluate((node) => {\n const el = node as Element;\n const host =\n el.closest(\n '[role=\"gridcell\"], [role=\"columnheader\"], [role=\"rowheader\"], [role=\"cell\"], [role=\"row\"], [role=\"option\"], [role=\"menuitem\"], [role=\"tab\"], [role=\"treeitem\"]',\n ) ?? el;\n const a = el.getBoundingClientRect();\n const b = host.getBoundingClientRect();\n const left = Math.min(a.left, b.left);\n const top = Math.min(a.top, b.top);\n return { x: left, y: top, width: Math.max(a.right, b.right) - left, height: Math.max(a.bottom, b.bottom) - top };\n });\n const viewport = page.viewportSize();\n if (!viewport || box.width < 2 || box.height < 2) return null;\n const pad = 4;\n const x = Math.max(0, box.x - pad);\n const y = Math.max(0, box.y - pad);\n const width = Math.min(viewport.width, box.x + box.width + pad) - x;\n const height = Math.min(viewport.height, box.y + box.height + pad) - y;\n return width >= 2 && height >= 2 ? { x, y, width, height } : null;\n}\n\nconst shot = (page: Page, clip: { x: number; y: number; width: number; height: number }) =>\n page.screenshot({ clip, animations: 'disabled', caret: 'hide' });\n\n/**\n * Tabs through the page: focus must show (2.4.7), never be entirely covered (2.4.11), never change the page by itself\n * (3.2.1), never get stuck and close overlays with Escape (2.1.2), and stay inside an open overlay (2.4.3). Escape\n * closes the state's overlay, so this runs last among the checks that need it open.\n */\nexport const keyboardWalk: Check = async (page, state, run) => {\n const startUrl = page.url();\n const invisible: string[] = [];\n const obscured: string[] = [];\n const contextChanges: string[] = [];\n const traps: string[] = [];\n const escapes: string[] = [];\n const seen = new Set<string>();\n const shotKinds = new Set<string>();\n const order: string[] = [];\n const stops: { name: string; x: number; y: number }[] = [];\n const overlayOpen = (await page.locator(overlaySelector).count()) > 0;\n\n // The element focus just left, to compare its focused look with how it looks now. Blurring it would not do: a grid\n // keeps its selected-cell ring until another cell takes over, and a blur can close an overlay.\n let previous: { handle: ElementHandle; width: number; height: number; image: Buffer; name: string } | null = null;\n let repeats = 0;\n let lastKey = '';\n\n for (let step = 0; step < maxSteps; step++) {\n await page.keyboard.press('Tab');\n await painted(page);\n\n if (previous) {\n // Measured again: moving focus may have scrolled the page. A box cut differently by the viewport cannot be compared.\n const clip = await focusBox(page, previous.handle).catch(() => null);\n if (clip && clip.width === previous.width && clip.height === previous.height) {\n const after = await shot(page, clip).catch(() => null);\n if (after?.equals(previous.image)) invisible.push(previous.name);\n }\n previous = null;\n }\n\n // Scroll spies update the hash as focus scrolls the page, which is not a change of context\n if (withoutHash(page.url()) !== withoutHash(startUrl)) {\n contextChanges.push(`focus moved the page to ${new URL(page.url()).pathname}`);\n break;\n }\n\n const stop = await readFocus(page, devOnlySelectors);\n if (!stop) {\n if (overlayOpen) escapes.push('focus falls back to the page body');\n continue;\n }\n if (overlayOpen && stop.inOverlay === false) escapes.push(`focus reaches ${stop.name} behind the open overlay`);\n repeats = stop.key === lastKey ? repeats + 1 : 0;\n lastKey = stop.key;\n if (repeats >= 3) {\n traps.push(`focus stays on ${stop.name}`);\n break;\n }\n if (seen.has(stop.key)) break; // Wrapped around: every stop has been visited\n seen.add(stop.key);\n order.push(stop.name);\n stops.push({ name: stop.name, x: stop.x, y: stop.y });\n if (stop.obscured) obscured.push(`${stop.name} is covered by ${stop.coveredBy}`);\n // A text field shows focus with its caret, which screenshots hide\n if (stop.editable || shotKinds.has(stop.kind)) continue;\n shotKinds.add(stop.kind);\n\n const handle = (await page.evaluateHandle(() => document.activeElement)).asElement();\n const clip = handle && (await focusBox(page, handle).catch(() => null));\n if (!handle || !clip) continue;\n const focused = await shot(page, clip).catch(() => null);\n if (focused) previous = { handle, width: clip.width, height: clip.height, image: focused, name: stop.name };\n }\n\n // When focus already left the overlay, that is the finding; Escape would go to the page behind it\n if (overlayOpen && state.overlay && !escapes.length) {\n // Escape goes to the focused element, so put focus back inside the overlay first\n await page\n .locator(overlaySelector)\n .last()\n .evaluate((overlay) => {\n const target =\n overlay.querySelector<HTMLElement>('button, [href], input, [tabindex]:not([tabindex=\"-1\"])') ??\n (overlay as HTMLElement);\n target.focus();\n })\n .catch(() => undefined);\n const open = await page.locator(overlaySelector).count();\n await page.keyboard.press('Escape');\n // Closing animations keep the overlay in the DOM for a moment\n const closed = await page\n .waitForFunction(\n ([selector, count]) => document.querySelectorAll(selector).length < count,\n [overlaySelector, open] as const,\n { timeout: 2000 },\n )\n .then(\n () => true,\n () => false,\n );\n if (!closed) traps.push('Escape does not close the open overlay');\n }\n\n writePacketFile(run, state.id, 'tab-order.json', `${JSON.stringify(stops, null, 2)}\\n`);\n\n const probe = { check: 'probe:keyboard' };\n const unique = (list: string[]) => [...new Set(list)];\n const findings: Awaited<ReturnType<Check>> = [\n {\n ...probe,\n criteria: ['2.4.7'],\n what: 'A visible change on every element that receives keyboard focus',\n problems: unique(invisible),\n },\n {\n ...probe,\n criteria: ['2.4.11'],\n what: 'Focused elements are never entirely covered by other content',\n problems: unique(obscured),\n },\n {\n ...probe,\n criteria: ['3.2.1'],\n what: 'Moving focus never navigates or opens anything',\n problems: unique(contextChanges),\n },\n {\n ...probe,\n criteria: ['2.1.2'],\n what: 'Focus never gets stuck, and Escape closes overlays',\n problems: unique(traps),\n },\n // The focus order needs a person, so record it as material to review\n {\n ...probe,\n criteria: ['2.4.3', '2.1.1'],\n what: 'Tab order recorded for a person to compare with the visual order.',\n problems: [],\n review: order.slice(0, 12).join(' → '),\n },\n ];\n if (state.overlay) {\n findings.push({\n ...probe,\n criteria: ['2.4.3'],\n what: 'Focus stays inside an open overlay',\n problems: unique(escapes),\n });\n }\n return findings;\n};\n","import type { Page } from 'playwright';\nimport { settle } from '../../drive';\nimport type { Check } from '../findings';\nimport { ensureOpen } from '../scope';\nimport { defaultViewport } from '../session';\n\n/** Content that may scroll in two dimensions under 1.4.10: data grids, tables, code. */\nconst twoDimensional = '[role=\"grid\"], table, pre, code, [data-slot=\"table-container\"]';\n\n/** Text, images and controls cut off by the viewport edge with no scroll to reach them, plus sideways page scroll. */\nfunction horizontalOverflow(page: Page) {\n return page.evaluate((exempt) => {\n const width = document.documentElement.clientWidth;\n const problems: string[] = [];\n const pageScroll = document.documentElement.scrollWidth - width;\n if (pageScroll > 1) problems.push(`page scrolls ${pageScroll}px sideways`);\n\n const reachable = (el: Element) => {\n if (el.closest(exempt) || el.closest('[aria-hidden=\"true\"], [inert]')) return true;\n for (let node: Element | null = el; node && node !== document.body; node = node.parentElement) {\n const style = getComputedStyle(node);\n if (style.position === 'fixed' || style.visibility === 'hidden') return true;\n if (node !== el && (style.overflowX === 'auto' || style.overflowX === 'scroll')) return true;\n }\n return false;\n };\n const outside = (rect: DOMRect) => rect.width > 0 && rect.height > 0 && (rect.left < -1 || rect.right > width + 1);\n const cut = new Set<string>();\n\n // Text: a container may be wider than the screen while its text still fits, so measure the text itself\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);\n for (let node = walker.nextNode(); node && cut.size < 4; node = walker.nextNode()) {\n const text = node.textContent?.trim();\n const parent = node.parentElement;\n if (!text || !parent || reachable(parent)) continue;\n // A 1px box is text for screen readers only; where its text would lie says nothing about the layout\n const box = parent.getBoundingClientRect();\n if (box.width <= 1 && box.height <= 1) continue;\n const range = document.createRange();\n range.selectNodeContents(node);\n if ([...range.getClientRects()].some(outside)) cut.add(`text \"${text.slice(0, 40)}\"`);\n }\n for (const el of document.querySelectorAll('img, svg, video, canvas, button, a[href], input, select, textarea')) {\n if (cut.size >= 4) break;\n if (el.tagName.toLowerCase() === 'svg' && el.parentElement?.closest('svg')) continue;\n if (outside(el.getBoundingClientRect()) && !reachable(el)) {\n const name =\n el.getAttribute('aria-label') ?? el.getAttribute('alt') ?? el.textContent?.trim().slice(0, 30) ?? '';\n cut.add(`${el.tagName.toLowerCase()}${name ? ` \"${name}\"` : ''}`);\n }\n }\n for (const item of cut) problems.push(`${item} is cut off at the edge`);\n return problems;\n }, twoDimensional);\n}\n\nconst spacingCss = `* { line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important; }\np { margin-bottom: 2em !important; }`;\n\n/** Text-bearing elements whose content no longer fits their clipping box, each as `grid|path|text` or `page|path|text`. */\nfunction clippedText(page: Page) {\n return page.evaluate((grids) => {\n const clipped: string[] = [];\n const path = (el: Element) => {\n const parts: string[] = [];\n for (let node: Element | null = el; node && node !== document.body; node = node.parentElement) {\n const index = node.parentElement ? [...node.parentElement.children].indexOf(node) : 0;\n parts.unshift(`${node.tagName.toLowerCase()}:${index}`);\n }\n return parts.join('>');\n };\n for (const el of document.body.querySelectorAll('*')) {\n const ownText = [...el.childNodes].some((n) => n.nodeType === Node.TEXT_NODE && n.textContent?.trim());\n if (!ownText || !(el instanceof HTMLElement) || !el.offsetParent) continue;\n // A 1px box is text for screen readers only; it is clipped on purpose\n if (el.clientWidth <= 1 || el.clientHeight <= 1) continue;\n const style = getComputedStyle(el);\n const clips = ['hidden', 'clip'].includes(style.overflowX) || ['hidden', 'clip'].includes(style.overflowY);\n if (!clips) continue;\n if (el.scrollHeight > el.clientHeight + 2 || el.scrollWidth > el.clientWidth + 2) {\n const where = el.closest(grids) ? 'grid' : 'page';\n clipped.push(`${where}|${path(el)}|${(el.textContent ?? '').trim().slice(0, 40)}`);\n }\n }\n return clipped;\n }, twoDimensional);\n}\n\nconst textLength = (page: Page) =>\n page\n .locator('body')\n // The rendered text, not textContent: text that zoom or reflow hides counts as lost\n .innerText()\n .then((text) => text.length);\n\n/**\n * 200% zoom as a 640px viewport (1.4.4), reflow at 320px (1.4.10), both orientations (1.3.4) and text spacing (1.4.12).\n * The open page is resized, as it is for a user who zooms, and left at the state's own viewport with no extra styles.\n */\nexport const layout: Check = async (page, state) => {\n const ownViewport = page.viewportSize() ?? defaultViewport;\n const findings: Awaited<ReturnType<Check>> = [];\n const resize = async (viewport: { width: number; height: number }) => {\n await page.setViewportSize(viewport);\n await settle(page);\n // A breakpoint change may close an overlay or swap it for a drawer\n await ensureOpen(page, state);\n };\n\n await resize({ width: 640, height: 450 });\n findings.push({\n criteria: ['1.4.4'],\n check: 'probe:resize',\n what: 'Content fits at 200% zoom (a 640px viewport) without loss',\n problems: await horizontalOverflow(page),\n });\n\n await resize({ width: 320, height: 640 });\n findings.push({\n criteria: ['1.4.10'],\n check: 'probe:reflow',\n what: 'Content fits a 320px-wide viewport without sideways scrolling',\n problems: await horizontalOverflow(page),\n });\n\n if (!state.open) {\n await resize({ width: 390, height: 844 });\n const portrait = await textLength(page);\n await resize({ width: 844, height: 390 });\n const landscape = await textLength(page);\n // Narrow layouts show fewer grid rows and columns; only content that disappears counts\n const lost = Math.min(portrait, landscape) < Math.max(portrait, landscape) * 0.2;\n findings.push({\n criteria: ['1.3.4'],\n check: 'probe:orientation',\n what: 'The same content shows in portrait and landscape',\n problems: lost ? [`portrait shows ${portrait} characters, landscape ${landscape}`] : [],\n });\n }\n await resize(ownViewport);\n\n const before = new Set(await clippedText(page));\n const style = await page.addStyleTag({ content: spacingCss });\n await page.waitForTimeout(300);\n const after = await clippedText(page);\n await style.evaluate((element) => (element as Element).remove());\n const cut = after.filter((entry) => !before.has(entry)).map((entry) => entry.split('|'));\n findings.push({\n criteria: ['1.4.12'],\n check: 'probe:text-spacing',\n what: 'Text stays fully visible with WCAG text spacing applied',\n problems: cut.filter(([where]) => where === 'page').map(([, , text]) => `\"${text}\" is cut off`),\n });\n // A grid cell truncates by design and its column can be resized, so whether the value stays reachable is for a person\n const cells = cut.filter(([where]) => where === 'grid');\n if (cells.length) {\n findings.push({\n criteria: ['1.4.12'],\n check: 'probe:text-spacing',\n what: 'Grid and table cells truncate more with text spacing: check that the full value stays reachable.',\n problems: [],\n review: `${cells.length} cells, such as \"${cells[0][2]}\"`,\n });\n }\n\n return findings;\n};\n","import type { Page } from 'playwright';\nimport { type AxeScan, axeScan } from './axe-scan';\nimport type { A11yState } from './define';\nimport type { AuditRun, Check, Finding } from './findings';\nimport { controlContrast, textContrast } from './probes/contrast';\nimport { formErrors, inputs } from './probes/forms';\nimport { keyboardWalk } from './probes/keyboard';\nimport { layout } from './probes/layout';\nimport { languageSwitch, pageStructure } from './probes/page-structure';\nimport { packetDir, removePacketFile, reviewPacket, writePacketFile } from './review-packet';\nimport { type AuditSession, auditContext, type Mode, openStatePath } from './session';\n\ninterface Visit {\n findings: Finding[];\n scan: AxeScan;\n}\n\n/**\n * Opens one state once and runs every check on that page.\n *\n * The light visit runs them in an order that keeps each check's page intact: checks that only read come first, then the\n * ones that restore what they change, and last the keyboard walk, whose Escape closes the state's overlay, and the\n * language switch, which changes the stored language.\n *\n * The dark visit runs what depends on the color mode: axe's contrast rule and the two contrast probes.\n *\n * A step that throws fails the visit, so a state with findings missing never reaches the ledger. The visit then leaves\n * `failure-<mode>.png` and `failure-<mode>.json` in the state's review packet: what the page showed, its console\n * errors, and the steps that ran on it before, since a failing step often meets what an earlier one left behind.\n */\nexport async function visitState(run: AuditRun, session: AuditSession, state: A11yState, mode: Mode): Promise<Visit> {\n const context = await auditContext(session, { auth: state.auth, mode }, state.context);\n const consoleErrors: string[] = [];\n context.on('console', (message) => {\n if (message.type() === 'error') consoleErrors.push(message.text());\n });\n context.on('weberror', (webError) => consoleErrors.push(webError.error().message));\n\n const record = `failure-${mode}`;\n for (const extension of ['png', 'json']) removePacketFile(run, state.id, `${record}.${extension}`);\n\n /** Steps that finished on this page, in order. */\n const done: string[] = [];\n let step = 'open';\n let page: Page | undefined;\n try {\n page = await openStatePath(session, context, state);\n await state.open?.(page);\n done.push(step);\n const opened = page;\n const where = `${state.id} (${mode})`;\n\n const findings: Finding[] = [];\n // `name` for a check built by a call, which has no name of its own\n const runCheck = async (check: Check, name = check.name) => {\n step = name;\n for (const finding of await check(opened, state, run)) {\n findings.push({ ...finding, state: mode === 'dark' ? where : state.id });\n }\n done.push(step);\n };\n const scanPage = async (contrastOnly?: boolean) => {\n step = 'axe';\n const scan = await axeScan(opened, where, contrastOnly);\n done.push(step);\n return scan;\n };\n\n if (mode === 'dark') {\n const scan = await scanPage(true);\n await runCheck(textContrast(scan.undecidedContrast), 'textContrast');\n await runCheck(controlContrast);\n return { findings, scan };\n }\n\n for (const check of [pageStructure, inputs]) await runCheck(check);\n const scan = await scanPage();\n await runCheck(textContrast(scan.undecidedContrast), 'textContrast');\n for (const check of [controlContrast, reviewPacket, layout, formErrors, keyboardWalk, languageSwitch])\n await runCheck(check);\n return { findings, scan };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n // The page may be gone, as after a crash; the record is worth having without its picture\n const screenshot = await page\n ?.screenshot({ fullPage: true, animations: 'disabled', timeout: 5000 })\n .catch(() => null);\n if (screenshot) writePacketFile(run, state.id, `${record}.png`, screenshot);\n const failure = { step, error: message, after: done, url: page?.url() ?? null, consoleErrors };\n writePacketFile(run, state.id, `${record}.json`, `${JSON.stringify(failure, null, 2)}\\n`);\n\n const previous = done.at(-1);\n const hint = `${previous ? `after ${previous}; ` : ''}see ${packetDir(run, state.id)}/${record}.json`;\n throw new Error(`${step}: ${message.split('\\n')[0]} (${hint})`);\n } finally {\n await context.close();\n }\n}\n","import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { printStep } from '../../utils/display';\nimport { parseDecision, recordDecisions } from './ledger';\n\n/** One decision from flags, or a file that holds a list of `{ id, status, by, remarks?, evidence, where? }`. */\nexport interface DecideOptions {\n file?: string;\n decision: Record<string, unknown>;\n}\n\n/**\n * Records reviewers' decisions on criteria the audit leaves open. Nothing is written unless every decision is valid.\n * @throws when the file holds no list, or a decision is incomplete or contradicts the audit's evidence\n */\nexport function runDecide(forkPath: string, { file, decision }: DecideOptions): number {\n const input: unknown = file ? JSON.parse(readFileSync(resolve(file), 'utf8')) : [decision];\n if (!Array.isArray(input)) throw new Error(`${file} holds no list of decisions`);\n const decisions = input.map(parseDecision);\n const ledger = recordDecisions(forkPath, decisions);\n const count = (by: string) => ledger.criteria.filter((row) => row.decidedBy === by).length;\n printStep(\n 'recorded',\n `${decisions.length}; decided by the audit ${count('audit')}, by an agent ${count('agent')}, by a person ${count('human')}`,\n );\n return 0;\n}\n","import { spawnSync } from 'node:child_process';\nimport { copyFileSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { printStep } from '../../utils/display';\nimport { loadPlaywright } from '../drive';\nimport { manualSteps, screenReaderSteps } from './criteria';\nimport { automated, type LedgerRow, readLedger, rootPackage, type Status } from './ledger';\nimport { loadAppConfig } from './scope';\n\nconst statusLabel: Record<Status, string> = {\n supports: 'Supports',\n 'partially-supports': 'Partially Supports',\n 'does-not-support': 'Does Not Support',\n 'not-applicable': 'Not Applicable',\n};\n\n/** Text made safe for a Markdown table cell; backslashes first, so the escapes added after them stay intact. */\nconst cell = (text: string) =>\n text.replace(/\\\\/g, '\\\\\\\\').replace(/\\|/g, '\\\\|').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\\n/g, ' ');\n\n/** A row's remarks for the reader; a failing row also names what the audit found. */\nfunction remarksOf(r: LedgerRow) {\n const failures = automated(r.evidence)\n .filter((e) => e.result === 'fail')\n .map((e) => e.summary);\n return r.status === 'partially-supports' && failures.length ? `${r.remarks} ${failures.join(' ')}` : r.remarks;\n}\n\nfunction row(r: LedgerRow) {\n // An agent's decision is provisional until a person confirms it; the draft says so on the row\n const provisional = r.decidedBy === 'agent' ? ' *(agent review, to confirm)*' : '';\n const conformance = r.status ? `Web: ${statusLabel[r.status]}${provisional}` : '**Not evaluated yet**';\n const en = r.en301549 ? `<br>EN 301 549: ${r.en301549}` : '';\n return `| ${r.id} ${r.name} (Level ${r.level})${en} | ${conformance} | ${cell(remarksOf(r))} |`;\n}\n\n/** The report's Markdown as an HTML document: headings, paragraphs, a quote, lists and tables with header cells. */\nfunction toHtml(markdown: string, title: string) {\n const inline = (text: string) =>\n text\n .replace(/&(?!lt;|gt;|amp;)/g, '&amp;')\n .replace(/<(?!br>)/g, '&lt;')\n .replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>')\n .replace(/\\*\\((.+?)\\)\\*/g, '<em>($1)</em>')\n .replace(/`(.+?)`/g, '<code>$1</code>');\n const cells = (line: string) =>\n line\n .slice(1, -1)\n .split(/(?<!\\\\)\\|/)\n .map((value) => inline(value.trim().replace(/\\\\\\|/g, '|').replace(/\\\\\\\\/g, '\\\\')));\n const body: string[] = [];\n const lines = markdown.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const heading = /^(#{1,3}) (.+)$/.exec(line);\n if (heading) body.push(`<h${heading[1].length}>${inline(heading[2])}</h${heading[1].length}>`);\n else if (line.startsWith('| ')) {\n const head = cells(line);\n const rows: string[] = [];\n for (i += 2; i < lines.length && lines[i].startsWith('| '); i++) {\n const [first, ...rest] = cells(lines[i]);\n rows.push(`<tr><th scope=\"row\">${first}</th>${rest.map((value) => `<td>${value}</td>`).join('')}</tr>`);\n }\n i -= 1;\n body.push(\n `<table><thead><tr>${head.map((value) => `<th scope=\"col\">${value}</th>`).join('')}</tr></thead><tbody>${rows.join('')}</tbody></table>`,\n );\n } else if (line.startsWith('- ')) {\n const items: string[] = [];\n for (; i < lines.length && lines[i].startsWith('- '); i++) items.push(`<li>${inline(lines[i].slice(2))}</li>`);\n i -= 1;\n body.push(`<ul>${items.join('')}</ul>`);\n } else if (line.startsWith('> ')) body.push(`<p class=\"note\">${inline(line.slice(2))}</p>`);\n else if (line.trim()) body.push(`<p>${inline(line)}</p>`);\n }\n const style =\n 'body{font:11pt/1.45 system-ui,sans-serif;color:#111;margin:0}h1{font-size:20pt}h2{font-size:14pt;margin-top:1.6em}h3{font-size:12pt}' +\n 'table{border-collapse:collapse;width:100%;margin:.6em 0}th,td{border:1px solid #777;padding:5px 7px;text-align:left;vertical-align:top;font-size:9.5pt}' +\n 'thead th{background:#eee}tbody th{font-weight:600;width:27%}td:nth-child(2){width:19%}.note{border-left:4px solid #b45309;padding-left:10px}tr{break-inside:avoid}';\n return `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><title>${title}</title><style>${style}</style></head><body>${body.join('\\n')}</body></html>`;\n}\n\n/**\n * Renders the ledger as a VPAT® 2.5Rev WCAG report (Markdown, HTML and a tagged PDF), plus the checklist for the manual\n * pass, in the results folder. While rows are open or decided by an agent only, the report is a draft and says so.\n * `publish` puts the PDF where the app serves it and prints what the accessibility statement needs; it refuses a draft\n * unless `draft` is set, and the statement then calls the results provisional.\n * @throws when the app has no ledger yet, or `publish` meets a draft without `draft`\n */\nexport async function runReport(\n forkPath: string,\n resultsDir: string,\n { publish, draft }: { publish: boolean; draft: boolean },\n): Promise<number> {\n const ledger = readLedger(forkPath);\n const { name: product, version } = rootPackage(forkPath);\n if (!ledger) throw new Error(`no ledger for ${product} yet: run \\`pnpm cella a11y\\` first`);\n // The report describes the production app\n const app = await loadAppConfig(forkPath, 'production');\n\n const table = (level: 'A' | 'AA') =>\n [\n '| Criteria | Conformance Level | Remarks and Explanations |',\n '| --- | --- | --- |',\n ...ledger.criteria.filter((r) => r.level === level).map(row),\n ].join('\\n');\n\n const open = ledger.criteria.filter((r) => !r.status);\n const byAgent = ledger.criteria.flatMap((r) => (r.decidedBy === 'agent' ? [r] : []));\n const byPerson = ledger.criteria.filter((r) => r.decidedBy === 'human');\n const unconfirmed = open.length + byAgent.length;\n\n /** What keeps the report a draft, for its reader. */\n const draftNote = [\n open.length ? `${open.length} criteria are not evaluated yet.` : '',\n byAgent.length ? `${byAgent.length} criteria were decided by an AI agent and await confirmation by a person.` : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n const vpat = `# ${app.name} Accessibility Conformance Report\n\nWCAG Edition (Based on VPAT® Version 2.5Rev)\n\n${unconfirmed ? `> **Draft.** ${draftNote} Those rows are marked and can still change.\\n` : ''}\n**Name of Product/Version:** ${app.name} ${version}\n\n**Report Date:** ${ledger.auditedAt}\n\n**Product Description:** ${app.description}\n\n**Contact Information:** ${app.supportEmail}\n\n**Notes:** The report covers the website, the documentation and the signed-in app at ${app.frontendUrl}: ${ledger.scope.length} pages and states, each in light and dark mode.${\n ledger.contrast === 'more'\n ? ' Measured with increased contrast turned on. This is a user setting, not the default: it is switched on under Preferences, and follows the operating system for anyone who asks for more contrast there. With it off, the edges of form fields, buttons and separators are drawn more lightly than 1.4.11 requires.'\n : ''\n }\n\n**Evaluation Methods Used:** Automated testing with axe-core on every page and state. Scripted browser checks for reflow at 320px, 200% zoom, text spacing, orientation, keyboard focus (visibility, obscuring, order inside overlays, Escape), page titles, landmarks, page language, form errors and input purpose. Source review for media, motion, keyboard shortcuts, time limits, gestures and sign-in methods. ${\n byAgent.length\n ? `Review of ${byAgent.length} criteria by an AI agent from screenshots, the accessibility tree and the source, each decision recorded with its evidence. `\n : ''\n }${byPerson.length ? `Manual review of ${byPerson.length} criteria by a person.` : 'Manual testing by a person, including screen readers: not yet done.'}\n\n## Applicable Standards/Guidelines\n\n| Standard/Guideline | Included In Report |\n| --- | --- |\n| Web Content Accessibility Guidelines 2.0 | Level A (Yes), Level AA (Yes), Level AAA (No) |\n| Web Content Accessibility Guidelines 2.1 | Level A (Yes), Level AA (Yes), Level AAA (No) |\n| Web Content Accessibility Guidelines 2.2 | Level A (Yes), Level AA (Yes), Level AAA (No) |\n\n## Terms\n\n- **Supports:** The functionality of the product has at least one method that meets the criterion without known defects or meets with equivalent facilitation.\n- **Partially Supports:** Some functionality of the product does not meet the criterion.\n- **Does Not Support:** The majority of product functionality does not meet the criterion.\n- **Not Applicable:** The criterion is not relevant to the product.\n- **Not Evaluated:** The product has not been evaluated against the criterion. This can only be used in WCAG Level AAA criteria.\n\n## WCAG 2.x Report\n\n### Table 1: Success Criteria, Level A\n\n${table('A')}\n\n### Table 2: Success Criteria, Level AA\n\n${table('AA')}\n\n### Table 3: Success Criteria, Level AAA\n\nNot evaluated.\n\n## Legal Disclaimer (${app.company.name})\n\nThis report describes the product as tested on the report date. Accessibility can change as the product changes.\n`;\n\n /** Files a reviewer's evidence names that changed after the day of the decision: the decision may describe old code. */\n const tracked = spawnSync('git', ['ls-files', 'frontend/src', 'backend/src', 'locales'], {\n cwd: forkPath,\n encoding: 'utf8',\n }).stdout.split('\\n');\n function changedSince(r: LedgerRow) {\n const review = r.evidence.find((e) => e.check === `review:${r.decidedBy}`);\n if (!review?.date) return [];\n const cited = new Set(review.summary.match(/[\\w./-]+\\.(?:tsx?|css|json)\\b/g) ?? []);\n const files = [...cited].flatMap((name) => tracked.filter((file) => file.endsWith(`/${name}`)).slice(0, 1));\n return files.filter((file) =>\n spawnSync('git', ['log', '-1', `--since=${review.date}T23:59:59`, '--format=%h', '--', file], {\n cwd: forkPath,\n encoding: 'utf8',\n }).stdout.trim(),\n );\n }\n const stale = ledger.criteria\n .filter((r) => r.decidedBy === 'agent' || r.decidedBy === 'human')\n .map((r) => ({ row: r, files: changedSince(r) }))\n .filter(({ files }) => files.length);\n\n const failing = ledger.criteria.filter((r) => r.status === 'partially-supports' || r.status === 'does-not-support');\n const step = (id: string) => manualSteps[id] ?? (id.startsWith('1.2.') ? manualSteps['1.2.1'] : undefined);\n\n const checklist = `# Manual accessibility pass\n\nRecord a decision with \\`pnpm cella a11y decide --id <criterion> --status <status> --by human --evidence \"<what you checked>\"\\`\n(add \\`--remarks\\` for the report reader unless the status is supports). Test with VoiceOver and Safari on macOS and with\nNVDA and Firefox on Windows, keyboard only, in light and dark mode.\n\n## Confirm: decided by an agent (${byAgent.length})\n\nThe agent judged these from the review packets in \\`${join(resultsDir, 'review')}/\\`. Check its evidence, then record your own\ndecision; a wrong Supports here ends up in the published report.\n\n${byAgent\n .map((r) => {\n const review = r.evidence.find((e) => e.check === 'review:agent');\n return [\n `- [ ] **${r.id} ${r.name}** (${r.level}): ${statusLabel[r.status]}${r.remarks ? `. ${r.remarks}` : ''}`,\n ` - Agent's evidence (${review?.date}): ${review?.summary}`,\n ].join('\\n');\n })\n .join('\\n')}\n\n## Re-check: code changed since the decision (${stale.length})\n\nA reviewer's decision outlives the code it describes. For each row, look at the named files again and record the decision anew.\n\n${stale.map(({ row, files }) => `- [ ] **${row.id} ${row.name}**: ${files.join(', ')}`).join('\\n')}\n\n## Screen reader pass (4.1.2 and 4.1.3)\n\nGo through each page type and overlay of the scope with a screen reader on, and listen for:\n\n${screenReaderSteps.map((line) => `- [ ] ${line}`).join('\\n')}\n\nName in the decision which screen readers and browsers you used; the report lists only those.\n\n## Open criteria (${open.length})\n\n${open\n .map((r) => {\n const needsPerson = r.open.some((check) => check === 'manual' || check === 'review');\n const what = needsPerson\n ? (step(r.id) ?? 'Check the criterion by hand.')\n : `Run the full audit; these checks did not run: ${r.open.join(', ')}.`;\n const notes = r.evidence\n .filter((e) => e.result === 'review')\n .map((e) => ` - ${e.check === 'review:agent' ? 'Agent note' : 'Tool note'}: ${e.summary}`);\n return [`- [ ] **${r.id} ${r.name}** (${r.level}): ${what}`, ...notes].join('\\n');\n })\n .join('\\n')}\n\n## Failures to fix or describe (${failing.length})\n\nEach needs a fix, or a remark that tells the reader what does not work and how to get around it.\n\n${failing\n .map((r) => {\n const fails = r.evidence.filter((e) => e.result === 'fail').map((e) => ` - ${e.summary}`);\n return [`- [ ] **${r.id} ${r.name}** (${r.level})`, ...fails].join('\\n');\n })\n .join('\\n')}\n`;\n\n mkdirSync(resultsDir, { recursive: true });\n writeFileSync(join(resultsDir, 'vpat-draft.md'), vpat);\n writeFileSync(join(resultsDir, 'manual-pass.md'), checklist);\n\n // The same report as a document and as a tagged PDF with an outline, which a screen reader can navigate by heading and table\n const html = toHtml(vpat, `${app.name} Accessibility Conformance Report`);\n const pdfPath = join(resultsDir, 'conformance-report.pdf');\n writeFileSync(join(resultsDir, 'conformance-report.html'), html);\n const { chromium } = await loadPlaywright(forkPath);\n const browser = await chromium.launch();\n try {\n const page = await browser.newPage();\n await page.setContent(html);\n await page.pdf({\n path: pdfPath,\n format: 'A4',\n tagged: true,\n outline: true,\n margin: { top: '18mm', bottom: '18mm', left: '16mm', right: '16mm' },\n });\n } finally {\n await browser.close();\n }\n\n if (publish) {\n // Only what a person confirmed is published as final: an open row has no answer, and an agent's answer is provisional\n if (unconfirmed && !draft) {\n const ids = [...open, ...byAgent].map((r) => r.id).join(', ');\n throw new Error(\n `not published: ${open.length} criteria are open and ${byAgent.length} are decided by an agent only (${ids}). See ${join(resultsDir, 'manual-pass.md')}, or add --draft to publish it as a draft`,\n );\n }\n // Under static/common: that folder is the app's own, so one product's report never merges into another\n const publicPath = 'frontend/public/static/common/accessibility-conformance-report.pdf';\n mkdirSync(dirname(join(forkPath, publicPath)), { recursive: true });\n copyFileSync(pdfPath, join(forkPath, publicPath));\n const count = (status: LedgerRow['status']) => ledger.criteria.filter((r) => r.status === status).length;\n const review = {\n standard: ledger.standard,\n reviewedAt: ledger.auditedAt,\n ...(unconfirmed ? { provisional: true } : {}),\n results: {\n pagesAndStates: ledger.scope.length,\n supports: count('supports'),\n partiallySupports: count('partially-supports'),\n doesNotSupport: count('does-not-support'),\n notApplicable: count('not-applicable'),\n notEvaluated: open.map((r) => `${r.id} ${r.name}`),\n },\n limitations: failing.map((r) => ({ description: remarksOf(r), criteria: [r.id] })),\n report: { edition: ledger.edition, date: ledger.auditedAt, pdfUrl: publicPath.replace('frontend/public', '') },\n };\n console.info(\n `Published ${publicPath}${unconfirmed ? ' as a draft' : ''}.\\nPut this in frontend/src/modules/auth/legal/legal-config.ts, and shorten each description for the statement's reader:\\n`,\n );\n console.info(`export const accessibilityReview: AccessibilityReview = ${JSON.stringify(review, null, 2)};\\n`);\n }\n printStep('report', `${open.length} criteria open, ${byAgent.length} decided by an agent`);\n printStep('results', `${resultsDir}: vpat-draft.md, conformance-report.html and .pdf, manual-pass.md`);\n return 0;\n}\n","import type { ToolCommand } from '../../config/types';\nimport { toolDir } from '../../utils/app-facts';\nimport { requireChromium } from '../drive';\nimport { withTestbed } from '../testbed';\nimport { type AuditOptions, runAudit } from './audit';\nimport { type DecideOptions, runDecide } from './decide';\nimport { runReport } from './report';\nimport { loadAppConfig, loadScope } from './scope';\n\ntype A11yOptions =\n | { job: 'audit'; audit: AuditOptions }\n | { job: 'report'; publish: boolean; draft: boolean }\n | { job: 'decide'; decide: DecideOptions };\n\nconst jobs = ['audit', 'report', 'decide'] as const;\n\n/** The job each flag belongs to; a flag given to another job is refused, so it never goes unheeded. */\nconst flagJobs: Record<string, (typeof jobs)[number]> = {\n states: 'audit',\n workers: 'audit',\n email: 'audit',\n publish: 'report',\n draft: 'report',\n file: 'decide',\n id: 'decide',\n status: 'decide',\n by: 'decide',\n remarks: 'decide',\n evidence: 'decide',\n where: 'decide',\n};\n\nconst list = (value: unknown) => (typeof value === 'string' ? value.split(',').filter(Boolean) : []);\nconst text = (value: unknown) => (typeof value === 'string' ? value : undefined);\n\nfunction parseA11y({ job = 'audit', opts }: { job?: string; opts: Record<string, unknown> }): A11yOptions {\n const known = jobs.find((name) => name === job);\n if (!known) throw new Error(`unknown job '${job}'. expected one of: ${jobs.join(', ')}`);\n for (const [name, value] of Object.entries(opts)) {\n if (value !== undefined && flagJobs[name] !== known)\n throw new Error(`--${name} goes with \\`a11y ${flagJobs[name]}\\``);\n }\n if (known === 'report') return { job: known, publish: opts.publish === true, draft: opts.draft === true };\n if (known === 'decide') {\n const { file, ...decision } = opts;\n if (file !== undefined && Object.keys(decision).length > 0)\n throw new Error('--file holds the decisions: no other flags');\n return { job: known, decide: { file: text(file), decision: { ...decision, where: list(opts.where) } } };\n }\n const workers = opts.workers === undefined ? 4 : Number(opts.workers);\n if (!Number.isInteger(workers) || workers < 1) throw new Error('--workers takes a whole number, 1 or more');\n return { job: known, audit: { states: list(opts.states), workers, email: text(opts.email) } };\n}\n\nasync function runA11y(forkPath: string, options: A11yOptions): Promise<number> {\n const resultsDir = toolDir(forkPath, 'a11y');\n if (options.job === 'decide') return runDecide(forkPath, options.decide);\n if (options.job === 'report') return runReport(forkPath, resultsDir, options);\n\n // Before the testbed starts: a scope that does not fit this CLI, or a missing browser, fails in seconds\n const scope = await loadScope(forkPath);\n const unknown = options.audit.states.filter((id) => !scope.states.some((state) => state.id === id));\n if (unknown.length > 0) {\n throw new Error(`no state ${unknown.join(', ')} in the scope: ${scope.states.map((state) => state.id).join(', ')}`);\n }\n await requireChromium(forkPath);\n const app = await loadAppConfig(forkPath, 'development');\n return withTestbed(forkPath, (testbed) => runAudit({ forkPath, app, resultsDir }, scope, testbed, options.audit));\n}\n\nexport const a11yCommand: ToolCommand<A11yOptions> = {\n name: 'a11y',\n group: 'develop',\n description: 'audit the app against WCAG 2.2 AA on a testbed and keep the conformance ledger',\n jobs: [\n ['audit', 'axe, browser probes and code checks on every state; writes cella/a11y-ledger.json'],\n ['report', 'render the ledger as a draft VPAT and the checklist for the manual pass'],\n ['decide', \"record a reviewer's decisions with their evidence\"],\n ],\n options: [\n ['--states <ids>', 'audit: these states only, comma separated; writes ledger-partial.json, never the ledger'],\n ['--workers <n>', 'audit: states audited at the same time (default 4)'],\n ['--email <address>', 'audit: the audit user (default ADMIN_EMAIL in backend/.env)'],\n ['--publish', 'report: put the PDF where the app serves it and print what the statement needs'],\n ['--draft', 'report: publish while rows still need a person; the statement calls the results provisional'],\n ['--file <path>', 'decide: a JSON list of decisions'],\n ['--id <criterion>', 'decide: the criterion, such as 2.4.6'],\n ['--status <status>', 'decide: supports, partially-supports, does-not-support, not-applicable or open'],\n ['--by <reviewer>', 'decide: agent or human'],\n ['--remarks <text>', 'decide: what the report tells its reader'],\n ['--evidence <text>', 'decide: what the reviewer looked at and found'],\n ['--where <ids>', 'decide: the states or files the finding is about, comma separated'],\n ],\n parse: parseA11y,\n run: runA11y,\n};\n","import { existsSync, readdirSync } from 'node:fs';\nimport { basename, join } from 'node:path';\nimport type { ToolCommand } from '../../config/types';\nimport { toolDir } from '../../utils/app-facts';\nimport { getEnvSnapshot } from '../../utils/env';\nimport { runCommand, withTestbed } from '../testbed';\nimport { BENCH_REQUEST_ENV, type BenchRequest } from './request';\n\n/** The app's bench, in the backend so that it imports the backend's modules by `#/`. */\nconst BENCH_DIR = 'backend/bench';\n/**\n * The app's entry, run by the backend's tsx in the backend folder, so the backend's tsconfig paths resolve. Node's Web\n * Storage is off: it warns once a library probes `localStorage`.\n */\nconst ENTRY_COMMAND = ['pnpm', 'exec', 'tsx', '--no-experimental-webstorage', 'bench/run.ts'];\n\nexport interface BenchOptions {\n /** Unset: pick one from a list, unless `all`. */\n scenario?: string;\n all: boolean;\n short: boolean;\n skipSeed: boolean;\n /** Run on a testbed: this checkout's running one, else one started for the run and stopped after. */\n isolated: boolean;\n}\n\nasync function runBench(forkPath: string, options: BenchOptions): Promise<number> {\n if (!existsSync(join(forkPath, BENCH_DIR, 'run.ts'))) {\n throw new Error(`${BENCH_DIR}/run.ts is missing: upgrade the app from cella first`);\n }\n const scenariosDir = join(forkPath, BENCH_DIR, 'scenarios');\n const names = readdirSync(scenariosDir)\n .filter((file) => file.endsWith('.ts'))\n .map((file) => basename(file, '.ts'))\n .sort();\n if (options.scenario && !names.includes(options.scenario)) {\n throw new Error(`unknown scenario '${options.scenario}'. expected one of: ${names.join(', ')}`);\n }\n\n const request: BenchRequest = {\n scenarios: options.all ? names : options.scenario ? [options.scenario] : [],\n all: options.all,\n short: options.short,\n skipSeed: options.skipSeed,\n scenariosDir,\n dataDir: toolDir(forkPath, 'bench', 'repository'),\n };\n const run = (env: NodeJS.ProcessEnv) =>\n runCommand(join(forkPath, 'backend'), { ...env, [BENCH_REQUEST_ENV]: JSON.stringify(request) }, ENTRY_COMMAND);\n return options.isolated ? withTestbed(forkPath, (testbed) => run(testbed.env)) : run(getEnvSnapshot());\n}\n\nexport const benchCommand: ToolCommand<BenchOptions> = {\n name: 'bench',\n group: 'develop',\n description: 'load-test the running app and check what the stack did with the load',\n jobs: [],\n operands: ['[scenario]', 'a scenario of backend/bench/scenarios/ (default: pick one from a list)'],\n options: [\n ['--all', 'run every scenario in turn, one line each and a table at the end'],\n ['--short', 'smoke run: one VU per role, no thresholds, no baselines'],\n ['--isolated', 'run on a testbed, not on the stack `pnpm dev` runs'],\n ['--skip-seed', 'keep the bench data the last run seeded'],\n ],\n parse: ({ operands, opts }) => {\n const [scenario, ...extra] = operands;\n if (extra.length > 0) throw new Error(`unexpected argument '${extra[0]}'. bench runs one scenario, or --all`);\n if (scenario && opts.all === true) throw new Error('name a scenario or pass --all, not both');\n return {\n scenario,\n all: opts.all === true,\n short: opts.short === true,\n skipSeed: opts.skipSeed === true,\n isolated: opts.isolated === true,\n };\n },\n run: runBench,\n};\n","/** The variable that hands the app's bench entry what `pnpm cella bench` asks of it, as JSON. */\nexport const BENCH_REQUEST_ENV = 'CELLA_BENCH';\n\n/** What `pnpm cella bench` asks of the app's bench entry. */\nexport interface BenchRequest {\n /** Scenario names in run order; empty to pick one from a list. */\n scenarios: string[];\n /** Every scenario in turn: one line each, a cooldown between full runs and a table at the end. */\n all: boolean;\n short: boolean;\n skipSeed: boolean;\n /** Absolute path of the folder whose `<name>.ts` modules are the scenarios. */\n scenariosDir: string;\n /** Holds `baselines/`, `logs/` and `locks/`. */\n dataDir: string;\n}\n","import process from 'node:process';\nimport { input } from '@inquirer/prompts';\nimport type { ToolCommand } from '../../config/types';\nimport { setJsonMode } from '../../utils/display';\nimport { type RenameOptions, runRename } from './rename';\nimport { runStatus } from './status';\nimport { runUnused } from './unused';\n\nexport type I18nOptions = Partial<RenameOptions> & { job: 'status' | 'unused' | 'rename'; json: boolean };\n\nconst jobs = ['status', 'unused', 'rename'] as const;\nconst isJob = (job: string): job is (typeof jobs)[number] => (jobs as readonly string[]).includes(job);\n\n/** The two keys of a rename, asked for when the menu started it. */\nasync function renameKeys(options: Partial<RenameOptions>): Promise<RenameOptions> {\n if (options.from && options.to) return { from: options.from, to: options.to };\n if (!process.stdin.isTTY) throw new Error('rename takes two keys: cella i18n rename <ns:old> <ns:new>');\n const from = options.from ?? (await input({ message: 'key to rename (ns:key):' }));\n const to = options.to ?? (await input({ message: `new name for ${from}:` }));\n return { from: from.trim(), to: to.trim() };\n}\n\nexport const i18nCommand: ToolCommand<I18nOptions> = {\n name: 'i18n',\n group: 'develop',\n description: 'translation status, unused keys and renames across the locale files and the code',\n jobs: [\n ['status', 'per namespace and language: missing, orphaned and mismatched translations'],\n ['unused', 'keys no code names, here and in the local forks of the config'],\n ['rename', 'rename a key in every locale file and in the code: rename <ns:old> <ns:new>'],\n ],\n options: [['--json', 'machine-readable output for tooling/agents']],\n operands: ['[keys...]', 'with rename: the key and its new name, as ns:key'],\n parse: ({ job = 'status', operands, opts }) => {\n if (!isJob(job)) throw new Error(`unknown job '${job}'. expected one of: ${jobs.join(', ')}`);\n const json = opts.json === true;\n // Before the header prints, so stdout holds the payload alone\n if (json) setJsonMode(true);\n if (job !== 'rename') {\n if (operands.length > 0) throw new Error(`unexpected argument '${operands[0]}'. only rename takes keys`);\n return { job, json };\n }\n if (operands.length > 2) throw new Error(`unexpected argument '${operands[2]}'. rename takes <ns:old> <ns:new>`);\n const [from, to] = operands;\n return { job, json, from, to };\n },\n run: async (forkPath, options) => {\n if (options.job === 'status') return runStatus(forkPath, options.json);\n if (options.job === 'unused') return runUnused(forkPath, options.json);\n return runRename(forkPath, await renameKeys(options), options.json);\n },\n};\n","import { spawnSync } from 'node:child_process';\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport pc from '../../utils/colors';\nimport { checkMark, plural, warningMark, writeStdout } from '../../utils/display';\nimport { type LocaleFile, type Locales, type RawEntry, readLocales, withPluralForms, writeLocaleFile } from './locales';\nimport { escapeRegExp, isOpenPattern, listCodeFiles, loadTypeScript, patternTest, scanCode } from './scan';\n\nexport interface RenameOptions {\n from: string;\n to: string;\n}\n\ninterface RenameReport {\n from: string;\n to: string;\n localeFiles: string[];\n codeFiles: { file: string; literals: number }[];\n /** Places the rename cannot rewrite: a literal without its namespace, a template whose types build the old key. */\n check: { file: string; line: number; source: string }[];\n /** Whether the app's Biome sorted the locale files it changed. */\n sorted: boolean;\n}\n\n/** `c:accept` as its namespace and key. */\nexport function parseKey(value: string, locales: Locales): { namespace: string; key: string } {\n const colon = value.indexOf(':');\n const namespace = value.slice(0, colon);\n const key = value.slice(colon + 1);\n if (colon < 1 || !key) throw new Error(`'${value}' is no key: write it as ns:key, such as c:accept`);\n if (!locales.namespaces.has(namespace)) {\n throw new Error(`no namespace '${namespace}': expected one of ${[...locales.namespaces.keys()].join(', ')}`);\n }\n return { namespace, key };\n}\n\n/**\n * Renames a key and its plural forms in every language, keeping each entry where it stands, or moves it into a\n * namespace that reads one file.\n * @returns the locale files it changed\n * @throws when the old key is in no file, or the new one already exists\n */\nfunction renameInLocales(\n forkPath: string,\n locales: Locales,\n from: { namespace: string; key: string },\n to: { namespace: string; key: string },\n): string[] {\n const targetFiles = locales.namespaces.get(to.namespace) ?? [];\n if (from.namespace !== to.namespace && targetFiles.length > 1) {\n throw new Error(\n `${to.namespace} reads ${targetFiles.join(' and ')}: move a key into it by hand, into the file it belongs to`,\n );\n }\n const fromForms = new Set(withPluralForms(from.key));\n const renamed = (entry: RawEntry): RawEntry => {\n const key = `${to.key}${entry.key.slice(from.key.length)}`;\n return { ...entry, key, raw: [JSON.stringify(key), entry.raw[1]] };\n };\n\n const changed = new Map<string, LocaleFile>();\n for (const language of locales.languages) {\n const filesOf = (namespace: string) =>\n (locales.namespaces.get(namespace) ?? []).flatMap((name) => locales.files.get(`${language}/${name}`) ?? []);\n for (const file of filesOf(to.namespace)) {\n const taken = file.entries.find((entry) => withPluralForms(to.key).includes(entry.key));\n if (taken) throw new Error(`${to.namespace}:${taken.key} already exists in ${file.path}`);\n }\n for (const file of filesOf(from.namespace)) {\n if (!file.entries.some((entry) => fromForms.has(entry.key))) continue;\n changed.set(file.path, file);\n if (from.namespace === to.namespace) {\n file.entries = file.entries.map((entry) => (fromForms.has(entry.key) ? renamed(entry) : entry));\n continue;\n }\n const target = locales.files.get(`${language}/${targetFiles[0]}`);\n if (!target)\n throw new Error(`${language} has no ${targetFiles[0]}.json to move ${from.namespace}:${from.key} into`);\n target.entries.push(...file.entries.filter((entry) => fromForms.has(entry.key)).map(renamed));\n file.entries = file.entries.filter((entry) => !fromForms.has(entry.key));\n changed.set(target.path, target);\n }\n }\n if (changed.size === 0) throw new Error(`${from.namespace}:${from.key} is in no locale file`);\n for (const file of changed.values()) writeLocaleFile(forkPath, file);\n return [...changed.keys()];\n}\n\n/** Rewrites every `'ns:old'` literal, plural forms included, in the app's code. */\nfunction renameInCode(forkPath: string, from: string, to: string): { file: string; literals: number }[] {\n const literal = new RegExp(\n `(['\"\\`])${escapeRegExp(from)}((?:_(?:ordinal_)?(?:zero|one|two|few|many|other))?)(?=\\\\1)`,\n 'g',\n );\n const changed: { file: string; literals: number }[] = [];\n for (const file of listCodeFiles(forkPath)) {\n const path = join(forkPath, file);\n if (!existsSync(path)) continue;\n const text = readFileSync(path, 'utf8');\n if (!text.includes(from)) continue;\n let literals = 0;\n const next = text.replace(literal, (_match, quote: string, suffix: string) => {\n literals++;\n return `${quote}${to}${suffix}`;\n });\n if (literals === 0) continue;\n writeFileSync(path, next);\n changed.push({ file, literals });\n }\n return changed;\n}\n\n/** Sorts the changed locale files with the app's own Biome, whose config decides the key order. */\nfunction sortWithBiome(forkPath: string, files: string[]): boolean {\n const biome = join(forkPath, 'node_modules/.bin/biome');\n if (!existsSync(biome) || files.length === 0) return false;\n return spawnSync(biome, ['check', '--write', ...files], { cwd: forkPath, stdio: 'ignore' }).status === 0;\n}\n\nexport async function rename(forkPath: string, options: RenameOptions): Promise<RenameReport> {\n const locales = readLocales(forkPath);\n const from = parseKey(options.from, locales);\n const to = parseKey(options.to, locales);\n if (options.from === options.to) throw new Error('the new name is the old one');\n\n const localeFiles = renameInLocales(forkPath, locales, from, to);\n const codeFiles = renameInCode(forkPath, options.from, options.to);\n const sorted = sortWithBiome(forkPath, localeFiles);\n\n // What no literal rewrite reaches: a key without its namespace in `t()`, a template that builds the old key. An\n // error type is typed, so the typecheck finds it\n const ts = await loadTypeScript(forkPath);\n const scan = scanCode(ts, forkPath, '', [...locales.namespaces.keys()], new Set([from.key]));\n const check = [\n ...(scan.bare.get(from.key) ?? [])\n .filter((site) => site.keyArgument)\n .map(({ file, line }) => ({ file, line, source: `'${from.key}'` })),\n ...scan.dynamic\n .filter((site) => {\n const target = site.namespace ? options.from : from.key;\n if (site.namespace && site.namespace !== from.namespace) return false;\n return site.keys\n ? site.keys.includes(target)\n : !isOpenPattern(site.pattern) && patternTest(site.pattern)(target);\n })\n .map(({ file, line, source }) => ({ file, line, source: `\\`${source}\\`` })),\n ];\n return { from: options.from, to: options.to, localeFiles, codeFiles, check, sorted };\n}\n\n/** `cella i18n rename <ns:old> <ns:new>`: the key in every locale file and in the code. */\nexport async function runRename(forkPath: string, options: RenameOptions, json: boolean): Promise<number> {\n const report = await rename(forkPath, options);\n if (json) {\n writeStdout(JSON.stringify(report, null, 2));\n return 0;\n }\n console.info(`${checkMark} renamed ${report.from} to ${pc.bold(report.to)}`);\n console.info(\n ` ${pc.dim(`${report.localeFiles.join(', ')}${report.sorted ? ' · sorted by biome' : ' · pnpm lint:fix sorts the keys'}`)}`,\n );\n const literals = report.codeFiles.reduce((sum, file) => sum + file.literals, 0);\n console.info(` ${pc.dim(`code: ${plural(literals, 'literal')} in ${plural(report.codeFiles.length, 'file')}`)}`);\n for (const { file, literals: count } of report.codeFiles) console.info(` ${pc.dim(`${file} ${count}`)}`);\n if (report.check.length > 0) {\n console.info(`${warningMark} ${plural(report.check.length, 'place')} may still name ${report.from}: check by hand`);\n for (const { file, line, source } of report.check) console.info(` ${pc.dim(`${file}:${line}`)} ${source}`);\n }\n return 0;\n}\n","import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** Where an app keeps its translations: `locales/<language>/<file>.json`. */\nexport const LOCALES_DIR = 'locales';\n/** Runtime namespaces that merge several files, later files winning: `{ \"c\": [\"common\", \"app\"] }`. */\nconst MANIFEST = 'namespaces.json';\n/** English holds every key; every other language is measured against it. */\nexport const SOURCE_LANGUAGE = 'en';\n\n/** One `\"key\": \"value\"` line of a locale file, both tokens as written, escapes included. */\nexport interface RawEntry {\n key: string;\n value: string;\n /** The JSON-encoded key and value, written back unchanged. */\n raw: [key: string, value: string];\n}\n\n/** A flat locale file as `pnpm lint:fix` writes it: one entry per line, in file order. */\nexport interface LocaleFile {\n path: string;\n indent: string;\n entries: RawEntry[];\n}\n\nexport interface Locales {\n /** The source language first, the others sorted. */\n languages: string[];\n /** Each runtime namespace and the files it reads, in merge order. */\n namespaces: Map<string, string[]>;\n /** `<language>/<file>` to its file. */\n files: Map<string, LocaleFile>;\n}\n\nconst entryPattern = /^(\\s+)(\"(?:[^\"\\\\]|\\\\.)*\")\\s*:\\s*(\"(?:[^\"\\\\]|\\\\.)*\"),?\\s*$/;\n\n/**\n * A locale file's entries, or a reason it cannot be edited in place: anything but a flat object of strings with one\n * entry per line.\n */\nexport function parseLocaleFile(path: string, text: string): LocaleFile | string {\n if (text.trim() === '{}') return { path, indent: ' ', entries: [] };\n const lines = text.replace(/\\n$/, '').split('\\n');\n if (lines[0] !== '{' || lines.at(-1) !== '}') return 'not one JSON object with one entry per line';\n const entries: RawEntry[] = [];\n let indent = ' ';\n for (const line of lines.slice(1, -1)) {\n const match = entryPattern.exec(line);\n if (!match) return `cannot read the line ${JSON.stringify(line.trim())}`;\n indent = match[1];\n entries.push({ key: JSON.parse(match[2]), value: JSON.parse(match[3]), raw: [match[2], match[3]] });\n }\n return { path, indent, entries };\n}\n\nexport function serializeLocaleFile(file: LocaleFile): string {\n if (file.entries.length === 0) return '{}\\n';\n return `{\\n${file.entries.map(({ raw }) => `${file.indent}${raw[0]}: ${raw[1]}`).join(',\\n')}\\n}\\n`;\n}\n\nexport function writeLocaleFile(forkPath: string, file: LocaleFile): void {\n writeFileSync(join(forkPath, file.path), serializeLocaleFile(file));\n}\n\n/** A file's texts by key; a later duplicate wins, as `JSON.parse` does. */\nexport const textsOf = (file: LocaleFile | undefined): Record<string, string> =>\n Object.fromEntries((file?.entries ?? []).map(({ key, value }) => [key, value]));\n\nconst readJsonObject = (path: string): Record<string, unknown> => {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error(`${path} is not a JSON object`);\n return Object.fromEntries(Object.entries(parsed));\n};\n\n/**\n * Every locale file of the app, and its runtime namespaces from `locales/namespaces.json`.\n * @throws when the app has no `locales/en/` or no manifest, or a locale file is not flat\n */\nexport function readLocales(forkPath: string): Locales {\n const dir = join(forkPath, LOCALES_DIR);\n if (!existsSync(join(dir, SOURCE_LANGUAGE))) throw new Error(`no ${LOCALES_DIR}/${SOURCE_LANGUAGE}/ in ${forkPath}`);\n\n const languages = readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'))\n .map((entry) => entry.name)\n .sort((a, b) => (a === SOURCE_LANGUAGE ? -1 : b === SOURCE_LANGUAGE ? 1 : a.localeCompare(b)));\n\n const files = new Map<string, LocaleFile>();\n for (const language of languages) {\n for (const name of readdirSync(join(dir, language)).filter((name) => name.endsWith('.json'))) {\n const path = `${LOCALES_DIR}/${language}/${name}`;\n const parsed = parseLocaleFile(path, readFileSync(join(forkPath, path), 'utf8'));\n if (typeof parsed === 'string') throw new Error(`${path}: ${parsed}; pnpm lint:fix writes one entry per line`);\n files.set(`${language}/${name.slice(0, -'.json'.length)}`, parsed);\n }\n }\n\n const manifestPath = join(dir, MANIFEST);\n if (!existsSync(manifestPath)) throw new Error(`no ${LOCALES_DIR}/${MANIFEST}: upgrade the app from cella first`);\n const merged = readJsonObject(manifestPath);\n const namespaces = new Map<string, string[]>();\n for (const [namespace, sources] of Object.entries(merged)) {\n if (!Array.isArray(sources) || !sources.every((source) => typeof source === 'string')) {\n throw new Error(`${LOCALES_DIR}/${MANIFEST}: ${namespace} must list file names`);\n }\n namespaces.set(namespace, sources);\n }\n const mergedFiles = new Set([...namespaces.values()].flat());\n const ownFiles = [...new Set([...files.keys()].map((key) => key.split('/')[1]))].filter(\n (file) => !mergedFiles.has(file),\n );\n for (const file of ownFiles.sort()) namespaces.set(file, [file]);\n\n return { languages, namespaces, files };\n}\n\n/** A runtime namespace's texts in one language, merged as the app loads them. */\nexport function namespaceTexts(locales: Locales, language: string, namespace: string): Record<string, string> {\n const sources = locales.namespaces.get(namespace) ?? [];\n return Object.assign({}, ...sources.map((file) => textsOf(locales.files.get(`${language}/${file}`))));\n}\n\n/** The 1-based line of a key in a file, for a link into it. */\nexport const lineOf = (file: LocaleFile, key: string): number =>\n file.entries.findIndex((entry) => entry.key === key) + 2;\n\nconst pluralSuffix = /_(ordinal_)?(zero|one|two|few|many|other)$/;\n\n/** A plural form's base key and category: `member_other` is `member` for `other`; any other key has none. */\nexport function pluralForm(key: string): { base: string; category: string; ordinal: boolean } | undefined {\n const match = pluralSuffix.exec(key);\n if (!match) return undefined;\n return { base: key.slice(0, match.index), category: match[2], ordinal: !!match[1] };\n}\n\n/** A key with every plural form i18next may look it up by. */\nexport const withPluralForms = (key: string): string[] => [\n key,\n ...['zero', 'one', 'two', 'few', 'many', 'other'].flatMap((category) => [\n `${key}_${category}`,\n `${key}_ordinal_${category}`,\n ]),\n];\n","import { execFileSync } from 'node:child_process';\nimport { readFileSync, statSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type * as TS from 'typescript';\nimport { importFromWorkspace } from '../../utils/app-facts';\n\n/** A place in a repository's code. */\nexport interface Site {\n file: string;\n line: number;\n /** What `t()` or `i18nKey` reads as the key. */\n keyArgument?: boolean;\n}\n\n/**\n * A key the code builds at runtime: a template that starts with a namespace, `` `c:${role}` ``, or one passed to `t()`\n * or `i18nKey` without it, `` t(`${type}.text`) ``.\n */\nexport interface DynamicSite extends Site {\n /** Undefined when the template names none: its keys may be in any namespace. */\n namespace?: string;\n /** The template as written, without its backticks. */\n source: string;\n /** The key with `*` for each part the types leave open: `c:success.*_resource`. */\n pattern: string;\n /** Every key it builds, when the types close each part. */\n keys?: string[];\n}\n\nexport interface CodeScan {\n repo: string;\n files: number;\n ms: number;\n /** `ns:key` literals, by key. */\n literals: Map<string, Site[]>;\n /** Literals without a namespace that equal a key of some namespace: an error type, a `t()` default namespace. */\n bare: Map<string, Site[]>;\n dynamic: DynamicSite[];\n}\n\nconst codeFile = /\\.(?:[cm]?[jt]sx?)$/;\n/** Generated output, locale files and alignments, whose old keys are history: never a use. */\nconst skipped = (path: string) =>\n path.endsWith('.d.ts') ||\n path.startsWith('locales/') ||\n path.startsWith('cella/alignments/') ||\n path.split('/').some((segment) => segment === 'node_modules' || segment === 'gen' || segment.includes('.gen.'));\n/** A larger file is a bundle or a fixture. */\nconst MAX_FILE_BYTES = 1_000_000;\n/** A template whose parts combine into more keys than this is reported by its pattern. */\nconst MAX_COMBINATIONS = 500;\n\nexport const escapeRegExp = (value: string): string => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** The code files of a repository: tracked ones and new ones git does not ignore. */\nexport function listCodeFiles(repoPath: string): string[] {\n const output = execFileSync('git', ['ls-files', '-z', '--cached', '--others', '--exclude-standard'], {\n cwd: repoPath,\n encoding: 'utf8',\n maxBuffer: 64 * 1024 * 1024,\n });\n return [...new Set(output.split('\\0'))].filter((path) => codeFile.test(path) && !skipped(path));\n}\n\n/**\n * The app's own TypeScript, which parses the code and types the parts of a built key.\n * @throws when the repository root has no `typescript` with the compiler API\n */\nexport async function loadTypeScript(forkPath: string): Promise<typeof TS> {\n const ts = await importFromWorkspace<typeof TS>(forkPath, '.', 'typescript');\n if (typeof ts.createSourceFile !== 'function') {\n throw new Error('cella i18n reads the code with the TypeScript compiler API: the root `typescript` has none');\n }\n return ts;\n}\n\nconst scriptKind = (ts: typeof TS, path: string) =>\n path.endsWith('.tsx')\n ? ts.ScriptKind.TSX\n : path.endsWith('.jsx')\n ? ts.ScriptKind.JSX\n : /\\.[cm]?js$/.test(path)\n ? ts.ScriptKind.JS\n : ts.ScriptKind.TS;\n\n/** Whether a node is what `t()` or `i18nKey` reads as the key: the first argument, or a fallback in its key array. */\nfunction isKeyArgument(ts: typeof TS, node: TS.Node): boolean {\n const parent = ts.isArrayLiteralExpression(node.parent) ? node.parent : node;\n const call = parent.parent;\n if (call && ts.isCallExpression(call) && call.arguments[0] === parent) {\n const callee = call.expression;\n const name = ts.isIdentifier(callee) ? callee.text : ts.isPropertyAccessExpression(callee) ? callee.name.text : '';\n return name === 't';\n }\n return (\n ts.isJsxExpression(node.parent) &&\n ts.isJsxAttribute(node.parent.parent) &&\n node.parent.parent.name.getText() === 'i18nKey'\n );\n}\n\nconst add = (map: Map<string, Site[]>, key: string, site: Site) => {\n const sites = map.get(key);\n if (sites) sites.push(site);\n else map.set(key, [site]);\n};\n\n/** The string values a type closes to, or undefined when any member is open (`string`, a template type). */\nfunction literalValues(ts: typeof TS, checker: TS.TypeChecker, type: TS.Type): string[] | undefined {\n const values: string[] = [];\n for (const member of type.isUnion() ? type.types : [type]) {\n if (member.isStringLiteral()) values.push(member.value);\n else if (member.isNumberLiteral()) values.push(String(member.value));\n else if (member.flags & ts.TypeFlags.BooleanLiteral) values.push(checker.typeToString(member));\n else if (!(member.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Null | ts.TypeFlags.Never))) return undefined;\n }\n return values;\n}\n\n/** Every key a template builds from the values of its parts. */\nfunction combine(head: string, parts: { values: string[]; tail: string }[]): string[] | undefined {\n let keys = [head];\n for (const { values, tail } of parts) {\n keys = keys.flatMap((key) => values.map((value) => `${key}${value}${tail}`));\n if (keys.length > MAX_COMBINATIONS) return undefined;\n }\n return keys;\n}\n\ninterface PendingSite {\n site: DynamicSite;\n start: number;\n}\n\n/**\n * Types the parts of each built key with the program of the file's nearest `tsconfig.json`, rooted at the files that\n * build keys only: a checker types lazily, so this reads far less than a typecheck.\n */\nfunction resolveTemplates(ts: typeof TS, repoPath: string, pending: Map<string, PendingSite[]>): void {\n const byConfig = new Map<string, string[]>();\n for (const file of pending.keys()) {\n const config = ts.findConfigFile(dirname(join(repoPath, file)), ts.sys.fileExists) ?? '';\n byConfig.set(config, [...(byConfig.get(config) ?? []), file]);\n }\n for (const [config, files] of byConfig) {\n const parsed = config\n ? ts.getParsedCommandLineOfConfigFile(config, {}, { ...ts.sys, onUnRecoverableConfigFileDiagnostic: () => {} })\n : undefined;\n const program = ts.createProgram({\n rootNames: files.map((file) => join(repoPath, file)),\n options: { ...parsed?.options, noEmit: true, incremental: false, skipLibCheck: true },\n });\n const checker = program.getTypeChecker();\n const keysOf = (node: TS.TemplateExpression): string[] | undefined => {\n const parts: { values: string[]; tail: string }[] = [];\n for (const span of node.templateSpans) {\n const values = literalValues(ts, checker, checker.getTypeAtLocation(span.expression));\n if (!values) return undefined;\n parts.push({ values, tail: span.literal.text });\n }\n return combine(node.head.text, parts);\n };\n for (const file of files) {\n const sourceFile = program.getSourceFile(join(repoPath, file));\n if (!sourceFile) continue;\n const starts = new Map((pending.get(file) ?? []).map((entry) => [entry.start, entry.site]));\n const visit = (node: TS.Node): void => {\n const site = ts.isTemplateExpression(node) ? starts.get(node.getStart(sourceFile)) : undefined;\n if (site && ts.isTemplateExpression(node)) site.keys = keysOf(node);\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n }\n }\n}\n\n/**\n * Every translation key a repository's code names: `ns:key` literals, literals equal to a key, and templates that\n * build one, with the keys their parts' types allow.\n * @param namespaces - the runtime namespaces a literal may name before its `:`\n * @param keys - every key of every namespace, to recognize a literal without its namespace\n */\nexport function scanCode(\n ts: typeof TS,\n repoPath: string,\n repo: string,\n namespaces: string[],\n keys: Set<string>,\n): CodeScan {\n const started = performance.now();\n const prefix = new RegExp(`^(${namespaces.map(escapeRegExp).join('|')}):`);\n const scan: CodeScan = { repo, files: 0, ms: 0, literals: new Map(), bare: new Map(), dynamic: [] };\n const pending = new Map<string, PendingSite[]>();\n\n for (const file of listCodeFiles(repoPath)) {\n const path = join(repoPath, file);\n let text: string;\n try {\n if (statSync(path).size > MAX_FILE_BYTES) continue;\n text = readFileSync(path, 'utf8');\n } catch {\n // Listed by git but gone from the working tree\n continue;\n }\n scan.files++;\n const sourceFile = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true, scriptKind(ts, file));\n const lineOf = (node: TS.Node) => sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;\n\n const visit = (node: TS.Node): void => {\n if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {\n if (prefix.test(node.text)) add(scan.literals, node.text, { file, line: lineOf(node) });\n else if (keys.has(node.text))\n add(scan.bare, node.text, { file, line: lineOf(node), keyArgument: isKeyArgument(ts, node) });\n } else if (ts.isTemplateExpression(node)) {\n const match = prefix.exec(node.head.text);\n if (match || isKeyArgument(ts, node)) {\n const source = node.getText(sourceFile).slice(1, -1);\n const pattern = `${node.head.text}${node.templateSpans.map((span) => `*${span.literal.text}`).join('')}`;\n const site: DynamicSite = { file, line: lineOf(node), namespace: match?.[1], source, pattern };\n scan.dynamic.push(site);\n pending.set(file, [...(pending.get(file) ?? []), { site, start: node.getStart(sourceFile) }]);\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n }\n\n if (pending.size > 0) resolveTemplates(ts, repoPath, pending);\n scan.ms = Math.round(performance.now() - started);\n return scan;\n}\n\n/** Whether a pattern leaves the whole key open, `c:*`, so it says nothing about which keys are used. */\nexport const isOpenPattern = (pattern: string): boolean => /^(?:[^:*]+:)?\\*+$/.test(pattern);\n\n/** A pattern as a test for `ns:key`. */\nexport function patternTest(pattern: string): (key: string) => boolean {\n const regex = new RegExp(`^${pattern.split('*').map(escapeRegExp).join('.*')}$`);\n return (key) => regex.test(key);\n}\n","import { pluralForm } from './locales';\n\n/** What a translation adds or drops against the English text: interpolations, nested keys or tags. */\nexport interface Mismatch {\n key: string;\n missing: string[];\n extra: string[];\n}\n\n/**\n * Interpolation names and nested `$t()` keys, each once: `{{resource, lowercase}}` is `resource`, `{{- name}}` is\n * `name`. A translation may use a value once where English repeats it.\n */\nexport function placeholdersOf(text: string): string[] {\n const names = [...text.matchAll(/\\{\\{-?\\s*([^,}\\s]+)[^}]*\\}\\}/g)].map((match) => match[1]);\n const nested = [...text.matchAll(/\\$t\\(\\s*([^,)\\s]+)/g)].map((match) => `$t(${match[1]})`);\n return [...new Set([...names, ...nested])];\n}\n\n/** Opening and self-closing tags, by name and count: `<strong>a</strong> <br/>` is `br`, `strong`. */\nexport function tagsOf(text: string): string[] {\n return [...text.matchAll(/<([A-Za-z0-9]+)(?:\\s[^<>]*)?\\/?>/g)].map((match) => match[1]).sort();\n}\n\n/** The elements of `a` that `b` lacks, as a multiset: `[x, x]` against `[x]` lacks one `x`. */\nfunction without(a: string[], b: string[]): string[] {\n const left = [...b];\n return a.filter((item) => {\n const index = left.indexOf(item);\n if (index === -1) return true;\n left.splice(index, 1);\n return false;\n });\n}\n\n/** How a translation's placeholders or tags differ from the English text; undefined when they match. */\nexport function compare(\n key: string,\n english: string,\n translation: string,\n extract: (text: string) => string[],\n): Mismatch | undefined {\n const expected = extract(english);\n const actual = extract(translation);\n const missing = [...new Set(without(expected, actual))];\n const extra = [...new Set(without(actual, expected))];\n return missing.length + extra.length > 0 ? { key, missing, extra } : undefined;\n}\n\n/** A plural group of one language that lacks a form the language needs, or has one it never uses. */\nexport interface PluralGap {\n key: string;\n missing: string[];\n extra: string[];\n}\n\nconst categoriesOf = (language: string, ordinal: boolean): string[] => {\n try {\n return new Intl.PluralRules(language, { type: ordinal ? 'ordinal' : 'cardinal' }).resolvedOptions()\n .pluralCategories;\n } catch {\n return ['one', 'other'];\n }\n};\n\nconst groupKey = (base: string, ordinal: boolean) => `${base}${ordinal ? '_ordinal' : ''}`;\n\n/**\n * The plural groups of the English texts, by base (`_ordinal` appended for ordinals). A group holds the `_other` form\n * and the base or another form: `send_one` beside no `send_other` is a plain key, and so is an `_other` key called by\n * its full name with nothing beside it.\n */\nconst groupsCache = new WeakMap<Record<string, string>, Map<string, { base: string; ordinal: boolean }>>();\n\nfunction pluralGroups(english: Record<string, string>): Map<string, { base: string; ordinal: boolean }> {\n const cached = groupsCache.get(english);\n if (cached) return cached;\n const forms = new Map<string, { base: string; ordinal: boolean; count: number }>();\n for (const key of Object.keys(english)) {\n const form = pluralForm(key);\n if (!form) continue;\n const group = forms.get(groupKey(form.base, form.ordinal)) ?? { base: form.base, ordinal: form.ordinal, count: 0 };\n group.count++;\n forms.set(groupKey(form.base, form.ordinal), group);\n }\n const groups = new Map(\n [...forms]\n .filter(\n ([key, { base, ordinal, count }]) => `${key}_other` in english && (count > 1 || (!ordinal && base in english)),\n )\n .map(([key, { base, ordinal }]) => [key, { base, ordinal }]),\n );\n groupsCache.set(english, groups);\n return groups;\n}\n\n/**\n * The plural groups of `texts` in `language` that are incomplete: each category the language uses needs its form or\n * the base key, which i18next falls back to; a form for a category the language never uses is extra.\n */\nexport function pluralGaps(\n english: Record<string, string>,\n texts: Record<string, string>,\n language: string,\n): PluralGap[] {\n const groups = pluralGroups(english);\n const present = new Map<string, Set<string>>();\n for (const key of Object.keys(texts)) {\n const form = pluralForm(key);\n const group = form && groupKey(form.base, form.ordinal);\n if (form && group && groups.has(group)) present.set(group, (present.get(group) ?? new Set()).add(form.category));\n else if (groups.has(key)) present.set(key, present.get(key) ?? new Set());\n }\n\n const gaps: PluralGap[] = [];\n // A group the language has not started falls back to English as a whole: that is a missing key, no gap\n for (const [key, categoriesPresent] of present) {\n const { base, ordinal } = groups.get(key) ?? { base: key, ordinal: false };\n const categories = categoriesOf(language, ordinal);\n const missing = categories.filter((category) => !categoriesPresent.has(category) && !(base in texts));\n const extra = [...categoriesPresent].filter((category) => !categories.includes(category));\n if (missing.length + extra.length > 0) gaps.push({ key, missing, extra });\n }\n return gaps;\n}\n\n/** Whether `key` of a language is a plural form of an English group, so no orphan even when English lacks it. */\nexport function isPluralOf(english: Record<string, string>, key: string): boolean {\n const form = pluralForm(key);\n return !!form && pluralGroups(english).has(groupKey(form.base, form.ordinal));\n}\n\n/** The English text a translated key answers to: its own, or for a plural form English lacks, the `_other` form. */\nexport function englishFor(english: Record<string, string>, key: string): string | undefined {\n if (key in english) return english[key];\n const form = pluralForm(key);\n return form ? english[`${groupKey(form.base, form.ordinal)}_other`] : undefined;\n}\n","import pc from '../../utils/colors';\nimport { checkMark, warningMark, writeStdout } from '../../utils/display';\nimport {\n LOCALES_DIR,\n type Locales,\n namespaceTexts,\n pluralForm,\n readLocales,\n SOURCE_LANGUAGE,\n textsOf,\n} from './locales';\nimport {\n compare,\n englishFor,\n isPluralOf,\n type Mismatch,\n type PluralGap,\n placeholdersOf,\n pluralGaps,\n tagsOf,\n} from './parity';\n\n/** One runtime namespace in one language, measured against English. */\ninterface LanguageStatus {\n /** English keys this language translates. */\n translated: number;\n missing: string[];\n /** Keys English lacks. */\n orphans: string[];\n sameAsEnglish: string[];\n placeholders: Mismatch[];\n tags: Mismatch[];\n plurals: PluralGap[];\n}\n\ninterface NamespaceStatus {\n name: string;\n files: string[];\n keys: number;\n /** English plural groups that lack or add a form. */\n plurals: PluralGap[];\n /** Per language, the keys a later file of the namespace redefines: `app.json` over `common.json`. */\n overrides: Record<string, { key: string; files: string[] }[]>;\n /** Every language but English. */\n languages: Record<string, LanguageStatus>;\n}\n\nexport interface StatusReport {\n languages: string[];\n namespaces: NamespaceStatus[];\n}\n\n/** A key's text with at least one letter, so `{{count}}` or `·` equal to English is no finding. */\nconst hasWords = (text: string) => /\\p{L}/u.test(text);\n\nfunction overridesOf(locales: Locales, language: string, files: string[]): { key: string; files: string[] }[] {\n const definedIn = new Map<string, string[]>();\n for (const file of files) {\n for (const key of Object.keys(textsOf(locales.files.get(`${language}/${file}`)))) {\n definedIn.set(key, [...(definedIn.get(key) ?? []), file]);\n }\n }\n return [...definedIn].filter(([, inFiles]) => inFiles.length > 1).map(([key, inFiles]) => ({ key, files: inFiles }));\n}\n\nfunction measure(english: Record<string, string>, texts: Record<string, string>, language: string): LanguageStatus {\n const categories = new Intl.PluralRules(language).resolvedOptions().pluralCategories;\n // A plural form for a category this language never uses is no missing key: the plural gaps report it\n const expected = Object.keys(english).filter((key) => {\n const form = pluralForm(key);\n return (\n !form || form.ordinal || !isPluralOf(english, key) || categories.some((category) => category === form.category)\n );\n });\n const status: LanguageStatus = {\n translated: expected.filter((key) => key in texts).length,\n missing: expected.filter((key) => !(key in texts)),\n orphans: Object.keys(texts).filter((key) => !(key in english) && !isPluralOf(english, key)),\n sameAsEnglish: [],\n placeholders: [],\n tags: [],\n plurals: pluralGaps(english, texts, language),\n };\n for (const [key, text] of Object.entries(texts)) {\n const source = englishFor(english, key);\n if (source === undefined) continue;\n if (text === source && key in english && hasWords(text)) status.sameAsEnglish.push(key);\n const placeholders = compare(key, source, text, placeholdersOf);\n if (placeholders) status.placeholders.push(placeholders);\n const tags = compare(key, source, text, tagsOf);\n if (tags) status.tags.push(tags);\n }\n return status;\n}\n\nexport function buildStatus(locales: Locales): StatusReport {\n const others = locales.languages.filter((language) => language !== SOURCE_LANGUAGE);\n const namespaces = [...locales.namespaces].map(([name, files]): NamespaceStatus => {\n const english = namespaceTexts(locales, SOURCE_LANGUAGE, name);\n const languages = Object.fromEntries(\n others.map((language) => [language, measure(english, namespaceTexts(locales, language, name), language)]),\n );\n const overrides = Object.fromEntries(\n files.length > 1 ? locales.languages.map((language) => [language, overridesOf(locales, language, files)]) : [],\n );\n const plurals = pluralGaps(english, english, SOURCE_LANGUAGE);\n return { name, files, keys: Object.keys(english).length, plurals, overrides, languages };\n });\n return { languages: locales.languages, namespaces };\n}\n\n/** The findings that fail the status: a text that renders wrong, not one that is not translated yet. */\nexport const defectCount = (report: StatusReport): number =>\n report.namespaces.reduce(\n (sum, namespace) =>\n Object.values(namespace.languages).reduce(\n (count, status) =>\n count + status.orphans.length + status.placeholders.length + status.tags.length + status.plurals.length,\n sum + namespace.plurals.length,\n ),\n 0,\n );\n\nconst LIST_MAX = 8;\nconst percent = (part: number, whole: number) => (whole === 0 ? 100 : Math.floor((part / whole) * 100));\n\ntype Cell = string | [text: string, style: (text: string) => string];\nconst columns: [title: string, width: number][] = [\n ['namespace', 11],\n ['lang', 6],\n ['keys', 6],\n ['translated', 12],\n ['orphans', 9],\n ['same', 6],\n ['placeholders', 14],\n ['tags', 6],\n ['plurals', 0],\n];\n/** A table row; a styled cell is padded before it is styled, so color codes never shift a column. */\nconst row = (cells: Cell[]) =>\n ` ${cells\n .map((cell, index) => {\n const [text, style] = typeof cell === 'string' ? [cell, (value: string) => value] : cell;\n return style(text.padEnd(columns[index][1]));\n })\n .join('')}`.trimEnd();\nconst findings = (count: number): Cell => (count === 0 ? ['✓', pc.green] : [String(count), pc.yellow]);\n\nfunction printList(title: string, items: string[]): void {\n if (items.length === 0) return;\n const more = items.length > LIST_MAX ? `, … ${items.length - LIST_MAX} more (--json lists them)` : '';\n console.info(` ${warningMark} ${title}`);\n console.info(` ${pc.dim(`${items.slice(0, LIST_MAX).join(', ')}${more}`)}`);\n}\n\nconst describe = ({ key, missing, extra }: Mismatch | PluralGap) =>\n [key, ...missing.map((name) => `-${name}`), ...extra.map((name) => `+${name}`)].join(' ');\n\nfunction printStatus(report: StatusReport): void {\n const label = ({ name, files }: NamespaceStatus) =>\n files.length > 1 || files[0] !== name ? `${name} (${files.join(' + ')})` : name;\n console.info(\n `${pc.bold(`${LOCALES_DIR}/`)} ${pc.dim(`${report.languages.join(', ')} · namespaces ${report.namespaces.map(label).join(', ')}`)}`,\n );\n console.info();\n console.info(pc.dim(row(columns.map(([title]) => title))));\n for (const namespace of report.namespaces) {\n console.info(\n row([\n namespace.name,\n SOURCE_LANGUAGE,\n String(namespace.keys),\n '',\n '',\n '',\n '',\n '',\n findings(namespace.plurals.length),\n ]),\n );\n for (const [language, status] of Object.entries(namespace.languages)) {\n const expected = status.translated + status.missing.length;\n console.info(\n row([\n '',\n language,\n '',\n `${String(status.translated).padEnd(5)}${percent(status.translated, expected)}%`,\n findings(status.orphans.length),\n [String(status.sameAsEnglish.length), pc.dim],\n findings(status.placeholders.length),\n findings(status.tags.length),\n findings(status.plurals.length),\n ]),\n );\n }\n }\n console.info();\n\n for (const namespace of report.namespaces) {\n printList(\n `${namespace.name} ${SOURCE_LANGUAGE}: plural groups that lack or add a form`,\n namespace.plurals.map(describe),\n );\n for (const [language, status] of Object.entries(namespace.languages)) {\n const where = `${namespace.name} ${language}`;\n printList(`${where}: keys English lacks`, status.orphans);\n printList(`${where}: placeholders that differ from English`, status.placeholders.map(describe));\n printList(`${where}: tags that differ from English`, status.tags.map(describe));\n printList(`${where}: plural groups that lack or add a form`, status.plurals.map(describe));\n }\n const [first, ...later] = namespace.files;\n for (const [language, overrides] of Object.entries(namespace.overrides)) {\n printList(\n `${language}/${later.join(', ')} overrides ${overrides.length} keys of ${language}/${first}`,\n overrides.map(({ key }) => key),\n );\n }\n }\n\n const defects = defectCount(report);\n console.info(\n defects === 0\n ? `${checkMark} no orphans, placeholder, tag or plural mismatches`\n : `${pc.red('✗')} ${defects} findings above`,\n );\n for (const language of report.languages.filter((language) => language !== SOURCE_LANGUAGE)) {\n const statuses = report.namespaces.map((namespace) => namespace.languages[language]).filter((status) => !!status);\n const translated = statuses.reduce((sum, status) => sum + status.translated, 0);\n const expected = statuses.reduce((sum, status) => sum + status.translated + status.missing.length, 0);\n const same = statuses.reduce((sum, status) => sum + status.sameAsEnglish.length, 0);\n console.info(\n ` ${pc.dim(`${language} translates ${translated} of ${expected} keys (${percent(translated, expected)}%), ${same} the same as English`)}`,\n );\n }\n console.info(` ${pc.dim('missing and same-as-English keys: --json lists them · cella i18n unused')}`);\n}\n\n/** `cella i18n`: per runtime namespace and language, what is missing, orphaned or mismatched. Exit 1 on a mismatch. */\nexport function runStatus(forkPath: string, json: boolean): number {\n const report = buildStatus(readLocales(forkPath));\n if (json) writeStdout(JSON.stringify(report, null, 2));\n else printStatus(report);\n return defectCount(report) === 0 ? 0 : 1;\n}\n","import { existsSync } from 'node:fs';\nimport { basename, join } from 'node:path';\nimport { resolveForkBasePath, validateForkPath } from '../../services/fork-utils';\nimport pc from '../../utils/colors';\nimport { loadConfig } from '../../utils/config';\nimport { checkMark, createSpinner, plural, spinnerSuccess, warningMark, writeStdout } from '../../utils/display';\nimport { errorMessage } from '../../utils/errors';\nimport { CONFIG_FILE } from '../../utils/managed-files';\nimport {\n type Locales,\n lineOf,\n namespaceTexts,\n pluralForm,\n readLocales,\n SOURCE_LANGUAGE,\n withPluralForms,\n} from './locales';\nimport {\n type CodeScan,\n type DynamicSite,\n isOpenPattern,\n loadTypeScript,\n patternTest,\n type Site,\n scanCode,\n} from './scan';\n\n/** A repository to scan: this app, or a fork named in `cella/cella.config.ts`. */\ninterface Repo {\n name: string;\n path: string;\n}\n\ninterface KeyUse {\n /** Repositories that name the key: a literal, or a template whose types build it. */\n repos: string[];\n /** A literal without a namespace equals it: an error type, or a word such as `'color'`. */\n bare: boolean;\n /** A template's pattern may build it. */\n pattern: boolean;\n}\n\nexport interface UnusedReport {\n repos: { name: string; files: number; ms: number }[];\n /** Forks named in the config whose local path is missing, so their uses are unknown. */\n missingForks: string[];\n unused: { key: string; file: string; line: number }[];\n /** No code here names them; a fork does. */\n usedOnlyInForks: { key: string; repos: string[] }[];\n /**\n * No code names them for certain: a template's pattern may build them (`c:success.*_resource`), or a literal\n * without its namespace equals them, such as `'color'`.\n */\n unverified: { key: string; by: 'pattern' | 'literal' }[];\n /** Templates whose types leave the whole key open, so they may build any key of their namespace. */\n openSites: (DynamicSite & { repo: string })[];\n}\n\n/**\n * This app, and the forks of `cella/cella.config.ts` that exist on this machine, their paths relative to the main\n * checkout. The config loads only for this job.\n */\nasync function reposToScan(forkPath: string): Promise<{ repos: Repo[]; missingForks: string[] }> {\n const basePath = await resolveForkBasePath(forkPath);\n const repos: Repo[] = [{ name: basename(basePath), path: forkPath }];\n const missingForks: string[] = [];\n if (!existsSync(join(forkPath, CONFIG_FILE))) return { repos, missingForks };\n for (const fork of (await loadConfig(forkPath)).forks ?? []) {\n const validated = validateForkPath(fork, basePath);\n if (validated.valid) repos.push({ name: fork.name, path: validated.resolvedPath });\n else missingForks.push(`${fork.name} (${validated.error})`);\n }\n return { repos, missingForks };\n}\n\n/** Every English key as `ns:key`, with the file and line that define it. */\nfunction definedKeys(locales: Locales): Map<string, Site> {\n const keys = new Map<string, Site>();\n for (const [namespace, files] of locales.namespaces) {\n for (const key of Object.keys(namespaceTexts(locales, SOURCE_LANGUAGE, namespace))) {\n const file = [...files]\n .reverse()\n .map((name) => locales.files.get(`${SOURCE_LANGUAGE}/${name}`))\n .find((entry) => entry?.entries.some((e) => e.key === key));\n if (file) keys.set(`${namespace}:${key}`, { file: file.path, line: lineOf(file, key) });\n }\n }\n return keys;\n}\n\n/** How each defined key is used across the scanned repositories. */\nfunction classify(defined: Map<string, Site>, scans: CodeScan[]): Map<string, KeyUse> {\n const uses = new Map<string, KeyUse>();\n const use = (key: string) => {\n let entry = uses.get(key);\n if (!entry) {\n entry = { repos: [], bare: false, pattern: false };\n uses.set(key, entry);\n }\n return entry;\n };\n const markExact = (key: string, repo: string) => {\n for (const form of withPluralForms(key)) {\n if (!defined.has(form)) continue;\n const entry = use(form);\n if (!entry.repos.includes(repo)) entry.repos.push(repo);\n }\n };\n // A key without its namespace, from a bare literal or a template that names none, may be in any namespace\n const bareKeys = new Map<string, string[]>();\n for (const key of defined.keys()) {\n const bare = key.slice(key.indexOf(':') + 1);\n bareKeys.set(bare, [...(bareKeys.get(bare) ?? []), key]);\n }\n\n for (const scan of scans) {\n for (const key of scan.literals.keys()) markExact(key, scan.repo);\n for (const value of scan.bare.keys()) {\n for (const key of bareKeys.get(value) ?? []) {\n for (const form of withPluralForms(key)) if (defined.has(form)) use(form).bare = true;\n }\n }\n for (const site of scan.dynamic) {\n if (site.keys) {\n for (const key of site.keys) {\n for (const full of site.namespace ? [key] : (bareKeys.get(key) ?? [])) markExact(full, scan.repo);\n }\n } else if (!isOpenPattern(site.pattern)) {\n const test = patternTest(site.pattern);\n for (const key of defined.keys()) {\n if (site.namespace ? test(key) : test(key.slice(key.indexOf(':') + 1))) use(key).pattern = true;\n }\n }\n }\n }\n return uses;\n}\n\nexport async function buildUnused(forkPath: string): Promise<UnusedReport> {\n const locales = readLocales(forkPath);\n const defined = definedKeys(locales);\n const ts = await loadTypeScript(forkPath);\n const { repos, missingForks } = await reposToScan(forkPath);\n const namespaces = [...locales.namespaces.keys()];\n const bareKeys = new Set([...defined.keys()].map((key) => key.slice(key.indexOf(':') + 1)));\n // Plural forms are found through their base, so a literal of the base alone counts\n for (const key of [...bareKeys]) {\n const form = pluralForm(key);\n if (form) bareKeys.add(form.base);\n }\n\n const scans: CodeScan[] = [];\n for (const repo of repos) {\n const spinner = createSpinner(`scanning ${repo.name}`);\n try {\n scans.push(scanCode(ts, repo.path, repo.name, namespaces, bareKeys));\n } finally {\n spinner.stop();\n }\n }\n\n const uses = classify(defined, scans);\n const [here] = repos;\n const report: UnusedReport = {\n repos: scans.map(({ repo, files, ms }) => ({ name: repo, files, ms })),\n missingForks,\n unused: [],\n usedOnlyInForks: [],\n unverified: [],\n openSites: scans.flatMap((scan) =>\n scan.dynamic\n .filter((site) => !site.keys && isOpenPattern(site.pattern))\n .map((site) => ({ ...site, repo: scan.repo })),\n ),\n };\n for (const [key, site] of defined) {\n const entry = uses.get(key);\n if (entry?.repos.includes(here.name)) continue;\n if (entry && entry.repos.length > 0) report.usedOnlyInForks.push({ key, repos: entry.repos });\n else if (entry?.pattern) report.unverified.push({ key, by: 'pattern' });\n else if (entry?.bare) report.unverified.push({ key, by: 'literal' });\n else report.unused.push({ key, ...site });\n }\n return report;\n}\n\nconst LIST_MAX = 12;\n\nfunction printUnused(report: UnusedReport): void {\n const [here, ...forks] = report.repos;\n const forkLine =\n forks.length > 0\n ? ` · ${forks.map((fork) => fork.name).join(', ')} +${forks.reduce((sum, fork) => sum + fork.files, 0)} files`\n : '';\n spinnerSuccess(\n `${here.name} ${here.files} files${forkLine} in ${(report.repos.reduce((sum, repo) => sum + repo.ms, 0) / 1000).toFixed(1)} s`,\n );\n for (const fork of report.missingForks) console.info(`${warningMark} fork ${fork}: its uses are unknown`);\n console.info();\n\n const width = Math.min(48, Math.max(0, ...report.unused.slice(0, LIST_MAX).map(({ key }) => key.length)) + 2);\n console.info(`${pc.bold(forks.length > 0 ? 'unused everywhere' : 'unused')} ${pc.dim(String(report.unused.length))}`);\n for (const { key, file, line } of report.unused.slice(0, LIST_MAX))\n console.info(` ${key.padEnd(width)}${pc.dim(`${file}:${line}`)}`);\n if (report.unused.length > LIST_MAX)\n console.info(` ${pc.dim(`… ${report.unused.length - LIST_MAX} more, --json for the list`)}`);\n\n if (forks.length > 0) {\n console.info();\n console.info(`${pc.bold('used only in a fork')} ${pc.dim(`${report.usedOnlyInForks.length} · keep them`)}`);\n for (const { key, repos } of report.usedOnlyInForks.slice(0, LIST_MAX))\n console.info(` ${key.padEnd(width)}${pc.dim(repos.join(' · '))}`);\n if (report.usedOnlyInForks.length > LIST_MAX)\n console.info(` ${pc.dim(`… ${report.usedOnlyInForks.length - LIST_MAX} more`)}`);\n }\n\n const byLiteral = report.unverified.filter(({ by }) => by === 'literal').map(({ key }) => key);\n const byPattern = report.unverified.length - byLiteral.length;\n console.info();\n console.info(\n `${pc.bold('unverified')} ${pc.dim(`${report.unverified.length} · ${byPattern} a template's pattern may build, ${byLiteral.length} only a literal without the namespace names`)}`,\n );\n if (byLiteral.length > 0) {\n const more = byLiteral.length > LIST_MAX ? `, … ${byLiteral.length - LIST_MAX} more` : '';\n console.info(` ${pc.dim(`by a literal: ${byLiteral.slice(0, LIST_MAX).join(', ')}${more}`)}`);\n }\n if (report.openSites.length > 0)\n console.info(` ${pc.dim(`${plural(report.openSites.length, 'template')} that may build any key:`)}`);\n for (const site of report.openSites.slice(0, LIST_MAX)) {\n console.info(` ${pc.dim(`${forks.length > 0 ? `${site.repo} ` : ''}${site.file}:${site.line}`)} ${site.source}`);\n }\n if (report.openSites.length > LIST_MAX)\n console.info(` ${pc.dim(`… ${report.openSites.length - LIST_MAX} more, --json for the list`)}`);\n if (report.unused.length === 0) {\n console.info();\n console.info(`${checkMark} every key is used`);\n }\n}\n\n/** `cella i18n unused`: keys no code names, in this app and in the forks the config names. */\nexport async function runUnused(forkPath: string, json: boolean): Promise<number> {\n let report: UnusedReport;\n try {\n report = await buildUnused(forkPath);\n } catch (error) {\n throw new Error(`i18n unused: ${errorMessage(error)}`);\n }\n if (json) writeStdout(JSON.stringify(report, null, 2));\n else printUnused(report);\n return 0;\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 * 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/** Where a command shows in the menu and in `--help`; a gate shows in `--help` only, since scripts and CI run it. */\nexport type CommandGroup = 'develop' | 'security' | 'upstream' | 'gate';\n\nexport type CommandOption = [flags: string, description: string];\n\n/**\n * A command that runs without the upgrade config: no `cella.config.ts`, no override validation. It declares its own\n * options, parses them into its own shape and returns its exit code.\n */\nexport interface ToolCommand<Options = unknown> {\n name: string;\n group: Exclude<CommandGroup, 'upstream'>;\n description: string;\n /** The jobs its first operand names, the default first; the menu asks for one. Empty: the command has one job. */\n jobs: [name: string, description: string][];\n /**\n * The words it takes after the job, in commander's notation such as `[scenario]` or `[paths...]`; none when unset.\n * A command takes these or a passthrough, never both.\n */\n operands?: CommandOption;\n options?: CommandOption[];\n /** What the words after `--` are for, in `--help`. */\n passthrough?: CommandOption;\n parse(input: { job?: string; operands: string[]; opts: Record<string, unknown>; passthrough: string[] }): Options;\n run(forkPath: string, options: Options): Promise<number>;\n}\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 * 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","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { z } from 'zod';\nimport type { ToolCommand } from '../../config/types';\nimport { importFromApp, resolveImage, toolDir } from '../../utils/app-facts';\nimport { createSpinner, printStep, setJsonMode, writeStdout } from '../../utils/display';\nimport { onShutdown } from '../../utils/signals';\nimport { type TestbedHandle, withTestbed } from '../testbed';\nimport { appSchema, baseSchema, type PentestAdapter } from './adapter';\nimport { httpMethods, type OpenApiSpec, probeFindings, runProbe, selectProbeRoutes, specSchema } from './probe';\nimport {\n CHECKS,\n type Check,\n type CheckOutcome,\n failsRelease,\n newRunDir,\n printReport,\n type RunReport,\n readLastReport,\n writeReport,\n} from './report';\nimport { runNuclei, runZap, scannerImages } from './scanners';\nimport { endSessions, startSessions } from './sessions';\n\nexport interface PentestOptions {\n job: 'scan' | 'report';\n checks: Check[];\n json: boolean;\n}\n\nconst SPEC_FILE = 'backend/openapi.cache.json';\nconst BASE_FILE = 'cella/pentest.ts';\nconst APP_FILE = 'cella/pentest.app.ts';\n\nasync function loadFile<T>(forkPath: string, file: string, schema: z.ZodType<T>): Promise<T> {\n const parsed = schema.safeParse((await importFromApp(forkPath, file)).default);\n if (!parsed.success) throw new Error(`${file} does not fit this CLI:\\n${z.prettifyError(parsed.error)}`);\n return parsed.data;\n}\n\n/** The base merged with the app's delta, when the app has one. */\nexport async function loadAdapter(forkPath: string): Promise<PentestAdapter> {\n if (!existsSync(join(forkPath, BASE_FILE))) {\n throw new Error(`${BASE_FILE} is missing: upgrade the app from cella first`);\n }\n const base = await loadFile(forkPath, BASE_FILE, baseSchema);\n if (!existsSync(join(forkPath, APP_FILE))) return base;\n const app = await loadFile(forkPath, APP_FILE, appSchema);\n return {\n sessions: app.sessions ?? base.sessions,\n skip: [...base.skip, ...(app.skip ?? [])],\n scopeGuards: app.scopeGuards ?? base.scopeGuards,\n params: { ...base.params, ...app.params },\n };\n}\n\n/** The spec the testbed's backend wrote when it started. */\nfunction readSpec(forkPath: string): OpenApiSpec {\n const path = join(forkPath, SPEC_FILE);\n if (!existsSync(path)) throw new Error(`${SPEC_FILE} is missing: the backend writes it when it starts`);\n const parsed = specSchema.safeParse(JSON.parse(readFileSync(path, 'utf8')));\n if (!parsed.success) throw new Error(`${SPEC_FILE} is no OpenAPI document with paths`);\n return parsed.data;\n}\n\n/** Adapter entries that name no route: the template or the app moved one, and the entry protects nothing. */\nfunction staleEntries(spec: OpenApiSpec, adapter: PentestAdapter): string[] {\n const operations = new Set(\n Object.entries(spec.paths).flatMap(([path, item]) =>\n Object.keys(item)\n .filter((key) => httpMethods.includes(key))\n .map((method) => `${method.toUpperCase()} ${path}`),\n ),\n );\n return adapter.skip.filter((entry) => !operations.has(entry)).map((entry) => `skip entry matches no route: ${entry}`);\n}\n\nasync function scanTestbed(\n forkPath: string,\n testbed: TestbedHandle,\n { adapter, checks, runDir }: { adapter: PentestAdapter; checks: Check[]; runDir: string },\n) {\n const spec = readSpec(forkPath);\n const origin = new URL(testbed.frontendUrl).origin;\n const report: RunReport = {\n startedAt: new Date().toISOString(),\n origin,\n checks: [],\n probe: [],\n warnings: staleEntries(spec, adapter),\n };\n\n createSpinner('signing in as the seeded users');\n const sessions = await startSessions(forkPath, testbed, adapter.sessions);\n const end = () => endSessions(testbed.backendUrl, Object.values(sessions));\n const forget = onShutdown(end);\n const { admin, outsider } = sessions;\n printStep('sessions', `${admin.email} (admin), ${outsider.email} (outsider)`);\n\n const target = { origin, apiUrl: testbed.backendUrl, cookie: admin.cookie, runDir, spec, skip: adapter.skip };\n const cacheDir = toolDir(forkPath, 'pentest', 'repository');\n const run: Record<Check, () => Promise<CheckOutcome>> = {\n probe: async () => {\n createSpinner(\"calling the organization's routes as an outsider\");\n const routes = selectProbeRoutes(spec, adapter);\n report.probe = await runProbe(routes, { apiUrl: testbed.backendUrl, admin, outsider, params: adapter.params });\n return { check: 'probe', status: 'ran', findings: probeFindings(report.probe) };\n },\n nuclei: () => {\n createSpinner('running Nuclei');\n return runNuclei({ ...target, cacheDir });\n },\n zap: () => {\n createSpinner('running the ZAP API scan');\n return runZap({ ...target, cacheDir });\n },\n };\n\n try {\n // The probe goes first: the scanners write rows and run into the rate limits\n for (const check of CHECKS.filter((name) => checks.includes(name))) {\n report.checks.push(await run[check]());\n }\n } finally {\n await end();\n forget();\n writeReport(runDir, report);\n }\n return report;\n}\n\nasync function runPentest(forkPath: string, options: PentestOptions): Promise<number> {\n if (options.job === 'report') {\n const { dir, report } = readLastReport(forkPath);\n if (options.json) writeStdout(JSON.stringify(report, null, 2));\n else printReport(dir, report);\n return 0;\n }\n // Before the testbed starts: a broken adapter or a missing Docker fails at once, and a first pull shows its progress\n const adapter = await loadAdapter(forkPath);\n for (const check of options.checks) if (check !== 'probe') resolveImage(scannerImages[check]);\n const scan = { adapter, checks: options.checks, runDir: newRunDir(forkPath) };\n const report = await withTestbed(forkPath, (testbed) => scanTestbed(forkPath, testbed, scan), { destructive: true });\n console.info();\n if (options.json) writeStdout(JSON.stringify(report, null, 2));\n else printReport(scan.runDir, report);\n return failsRelease(report) ? 1 : 0;\n}\n\nexport const pentestCommand: ToolCommand<PentestOptions> = {\n name: 'pentest',\n group: 'security',\n description: 'scan a throwaway testbed of the app: a cross-tenant access probe, then Nuclei and ZAP',\n jobs: [\n ['scan', 'start a testbed on a new database, scan it, remove the database'],\n ['report', \"print the last run's findings\"],\n ],\n options: [\n ['--only <checks>', `run only these checks, comma-separated: ${CHECKS.join(', ')}`],\n ['--json', 'machine-readable output for tooling/agents'],\n ],\n parse: ({ job = 'scan', opts }) => {\n if (job !== 'scan' && job !== 'report') throw new Error(`unknown job '${job}'. expected one of: scan, report`);\n const only = typeof opts.only === 'string' ? opts.only.split(',').map((name) => name.trim()) : [...CHECKS];\n const checks = CHECKS.filter((check) => only.includes(check));\n const unknown = only.filter((name) => !checks.some((check) => check === name));\n if (unknown.length > 0) throw new Error(`unknown check '${unknown[0]}'. expected: ${CHECKS.join(', ')}`);\n if (job === 'report' && typeof opts.only === 'string') throw new Error('--only filters a scan, not a report');\n const json = opts.json === true;\n // Before the header prints: stdout carries the JSON alone\n if (json) setJsonMode(true);\n return { job, checks, json };\n },\n run: runPentest,\n};\n","import { z } from 'zod';\n\n/** An operation as `METHOD /path`, the path in the spec's own syntax. */\nconst operationSchema = z.string().regex(/^(GET|POST|PUT|PATCH|DELETE) \\/\\S*$/, 'expected `METHOD /path`');\n\n/**\n * What fills a parameter: the target organization's tenant or own id, the user id of its admin (`user`), or, for a\n * value that starts with `/`, the id of the first item its admin lists at that path.\n */\nconst paramSourceSchema = z.union([z.enum(['tenant', 'organization', 'user']), z.string().startsWith('/')]);\n\nexport const baseSchema = z\n .object({\n /**\n * SQL the testbed database answers with one row per session, columns `session, email, user_id, organization_id,\n * tenant_id`: `admin` of the target organization, `outsider` with no membership in its tenant.\n */\n sessions: z.string().min(1),\n /** Operations no scan calls: they end the scan's session or remove what its next request needs. */\n skip: z.array(operationSchema),\n /** A GET behind one of these guards is scoped to a tenant, an organization or a user, so the access probe calls it. */\n scopeGuards: z.array(z.string()).min(1),\n /** Parameters by name, or by `operationId.name` for one route, and what fills them. */\n params: z.record(z.string(), paramSourceSchema),\n })\n .strict();\n\nexport const appSchema = z\n .object({\n /** Replaces the base's query. */\n sessions: z.string().min(1).optional(),\n /** Added to the base's. */\n skip: z.array(operationSchema).optional(),\n /** Replaces the base's list. */\n scopeGuards: z.array(z.string()).min(1).optional(),\n /** Merged over the base's. */\n params: z.record(z.string(), paramSourceSchema).optional(),\n })\n .strict();\n\n/** `cella/pentest.ts`: synced from the template, it describes the template's routes, roles and tables. */\nexport type PentestBase = z.input<typeof baseSchema>;\n/** `cella/pentest.app.ts`: optional and the app's own (the template ships none), only what it adds or overrides. */\nexport type PentestApp = z.input<typeof appSchema>;\nexport type PentestAdapter = z.infer<typeof baseSchema>;\nexport type ParamSource = z.infer<typeof paramSourceSchema>;\n","import { z } from 'zod';\nimport type { ParamSource, PentestAdapter } from './adapter';\nimport type { Finding, Severity } from './report';\nimport type { Session } from './sessions';\n\nconst parameterSchema = z.object({\n name: z.string(),\n in: z.string(),\n required: z.boolean().optional(),\n schema: z.object({ enum: z.array(z.unknown()).optional(), default: z.unknown().optional() }).optional(),\n});\n\nconst operationSchema = z.object({\n operationId: z.string().optional(),\n 'x-guard': z.array(z.string()).optional(),\n parameters: z.array(parameterSchema).optional(),\n});\n\n/** The part of an OpenAPI document the probe and the scanners read; the rest passes through. */\nexport const specSchema = z.looseObject({ paths: z.record(z.string(), z.record(z.string(), z.unknown())) });\nexport type OpenApiSpec = z.infer<typeof specSchema>;\n\nexport const httpMethods = ['get', 'put', 'post', 'delete', 'patch', 'head', 'options', 'trace'];\n\n/** A parameter of a probed route and what fills it; `value` is a fixed one from the spec, such as an enum's first. */\nexport interface ProbeParam {\n name: string;\n in: 'path' | 'query';\n source: ParamSource | { value: string };\n}\n\n/** A GET the probe calls; `missing` names the parameter nothing fills, and such a route is listed, not called. */\nexport interface ProbeRoute {\n operationId: string;\n path: string;\n params: ProbeParam[];\n missing?: string;\n}\n\n/**\n * Every GET behind one of the adapter's scope guards, with what fills each parameter: the adapter's entry for\n * `operationId.name`, else for `name`, else for a path parameter the list route above it (`/a/{id}` takes the first id\n * of `/a`), else for a required query parameter its first enum value or its default. An optional query parameter\n * without an entry stays out of the request.\n */\nexport function selectProbeRoutes(spec: OpenApiSpec, adapter: Pick<PentestAdapter, 'scopeGuards' | 'params'>) {\n const routes: ProbeRoute[] = [];\n for (const [path, item] of Object.entries(spec.paths)) {\n const operation = operationSchema.safeParse(item.get);\n if (!operation.success || !operation.data.operationId) continue;\n const { operationId, parameters = [] } = operation.data;\n if (!operation.data['x-guard']?.some((guard) => adapter.scopeGuards.includes(guard))) continue;\n\n const route: ProbeRoute = { operationId, path, params: [] };\n for (const parameter of parameters) {\n if (parameter.in !== 'path' && parameter.in !== 'query') continue;\n const listPath = path.slice(0, path.indexOf(`/{${parameter.name}}`));\n const fixed = parameter.schema?.enum?.[0] ?? parameter.schema?.default;\n const source =\n adapter.params[`${operationId}.${parameter.name}`] ??\n adapter.params[parameter.name] ??\n (parameter.in === 'path' && spec.paths[listPath]?.get ? listPath : undefined) ??\n (parameter.required && fixed !== undefined ? { value: String(fixed) } : undefined);\n if (source) route.params.push({ name: parameter.name, in: parameter.in, source });\n else if (parameter.in === 'path' || parameter.required) route.missing ??= parameter.name;\n }\n routes.push(route);\n }\n return routes.sort((a, b) => a.path.localeCompare(b.path));\n}\n\n/** One probed route: what the admin and the outsider got back. */\nexport interface ProbeResult {\n operationId: string;\n /** The request path and query under the API URL; absent for a route not probed. */\n url?: string;\n admin?: number;\n outsider?: number;\n verdict: 'refused' | 'finding' | 'not probed';\n note?: string;\n}\n\n/** The target organization's facts the parameters read, and the two sessions that call. */\nexport interface ProbeContext {\n apiUrl: string;\n /** The target organization's admin: the control, and the one who lists ids. */\n admin: Session;\n outsider: Session;\n params: PentestAdapter['params'];\n}\n\nconst sleep = (ms: number) => new Promise((done) => setTimeout(done, ms));\n\n/** The status of a GET as `session`; a rate limit is waited out once. */\nasync function call(url: string, session: Session): Promise<{ status: number; body: string }> {\n for (let attempt = 0; ; attempt++) {\n const response = await fetch(url, {\n headers: { cookie: session.cookie, accept: 'application/json' },\n redirect: 'manual',\n signal: AbortSignal.timeout(15_000),\n });\n const body = await response.text();\n if (response.status !== 429 || attempt > 0) return { status: response.status, body };\n await sleep(Math.min(Number(response.headers.get('retry-after')) || 1, 10) * 1000);\n }\n}\n\nconst isRefusal = (status: number) => status === 403 || status === 404;\n\n/** Calls every route as the admin, then as the outsider, with the target organization's ids. */\nexport async function runProbe(routes: ProbeRoute[], context: ProbeContext): Promise<ProbeResult[]> {\n const { apiUrl, admin, outsider } = context;\n const listIds = new Map<string, string | undefined>();\n\n /** The target's own value for a fact, or the first id its admin lists at a path filled with those facts. */\n const resolve = async (source: ProbeParam['source']): Promise<string | undefined> => {\n if (typeof source === 'object') return source.value;\n if (source === 'tenant') return admin.tenantId;\n if (source === 'organization') return admin.organizationId;\n if (source === 'user') return admin.userId;\n if (!listIds.has(source)) {\n const facts = await fill(source, []);\n const listed = facts ? await call(`${apiUrl}${facts}`, admin) : undefined;\n let id: string | undefined;\n try {\n const json = listed?.status === 200 ? JSON.parse(listed.body) : undefined;\n const first = Array.isArray(json) ? json[0] : json?.items?.[0];\n id = typeof first?.id === 'string' ? first.id : undefined;\n } catch {\n // A list that answers no JSON gives no id\n }\n listIds.set(source, id);\n }\n return listIds.get(source);\n };\n\n /** `path` with its parameters filled and the query appended; undefined when one has no value. */\n const fill = async (path: string, params: ProbeParam[]): Promise<string | undefined> => {\n let filled = path;\n for (const name of path.match(/\\{[^}]+\\}/g) ?? []) {\n const key = name.slice(1, -1);\n const param = params.find((candidate) => candidate.name === key && candidate.in === 'path');\n const named = context.params[key];\n // A list path takes facts only: a list route behind another list route is never resolved\n const source = param?.source ?? (named?.startsWith('/') ? undefined : named);\n const value = source ? await resolve(source) : undefined;\n if (value === undefined) return undefined;\n filled = filled.replace(name, encodeURIComponent(value));\n }\n const query = new URLSearchParams();\n for (const param of params.filter((candidate) => candidate.in === 'query')) {\n const value = await resolve(param.source);\n if (value === undefined) return undefined;\n query.set(param.name, value);\n }\n return query.size > 0 ? `${filled}?${query}` : filled;\n };\n\n const results: ProbeResult[] = [];\n for (const route of routes) {\n const { operationId } = route;\n if (route.missing) {\n results.push({ operationId, verdict: 'not probed', note: `nothing fills {${route.missing}}` });\n continue;\n }\n const url = await fill(route.path, route.params);\n if (!url) {\n results.push({ operationId, verdict: 'not probed', note: 'the admin lists nothing to take an id from' });\n continue;\n }\n const control = await call(`${apiUrl}${url}`, admin);\n const probe = await call(`${apiUrl}${url}`, outsider);\n const refused = isRefusal(probe.status);\n results.push({\n operationId,\n url,\n admin: control.status,\n outsider: probe.status,\n verdict: refused ? 'refused' : 'finding',\n // A refusal proves the guard only when the same request reads as the admin\n ...(refused && control.status >= 300 ? { note: `the admin got ${control.status} too` } : {}),\n });\n }\n return results;\n}\n\n/** A 2xx or 3xx is a read across the boundary; a 5xx a route that breaks on another tenant's ids. */\nfunction severityOf(status: number): Severity {\n if (status < 400) return 'high';\n return status >= 500 ? 'medium' : 'low';\n}\n\nexport function probeFindings(results: ProbeResult[]): Finding[] {\n return results.flatMap(({ operationId, url, outsider, verdict }) =>\n verdict === 'finding' && outsider !== undefined && url\n ? [\n {\n check: 'probe' as const,\n severity: severityOf(outsider),\n title: `outsider got ${outsider} from ${operationId}, expected 403 or 404`,\n where: `GET ${url}`,\n },\n ]\n : [],\n );\n}\n","import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { toolDir } from '../../utils/app-facts';\nimport pc from '../../utils/colors';\nimport { printStep, warningMark } from '../../utils/display';\nimport type { ProbeResult } from './probe';\n\nexport const CHECKS = ['probe', 'nuclei', 'zap'] as const;\nexport type Check = (typeof CHECKS)[number];\n\nexport const SEVERITIES = ['critical', 'high', 'medium', 'low', 'info'] as const;\nexport type Severity = (typeof SEVERITIES)[number];\n\nexport interface Finding {\n check: Check;\n severity: Severity;\n title: string;\n /** `METHOD /path` under the testbed's origin. */\n where: string;\n detail?: string;\n /** `CWE-<n>`, as the scanner classifies it. */\n cwe?: string;\n}\n\n/** How one check ended: `failed` keeps what it found before. */\nexport interface CheckOutcome {\n check: Check;\n status: 'ran' | 'failed' | 'timed out';\n findings: Finding[];\n note?: string;\n}\n\nexport interface RunReport {\n startedAt: string;\n origin: string;\n checks: CheckOutcome[];\n probe: ProbeResult[];\n /** Adapter entries that match no route of the spec. */\n warnings: string[];\n}\n\n/** Runs kept per checkout; an older one goes when a new one starts. */\nconst KEPT_RUNS = 5;\nconst REPORT_FILE = 'report.json';\n\nconst runsDir = (forkPath: string) => join(toolDir(forkPath, 'pentest'), 'runs');\n\n/** A new run's folder, readable by this user only: scanner output can hold the session cookies. */\nexport function newRunDir(forkPath: string): string {\n const runs = runsDir(forkPath);\n mkdirSync(runs, { recursive: true });\n for (const old of readdirSync(runs)\n .sort()\n .reverse()\n .slice(KEPT_RUNS - 1)) {\n rmSync(join(runs, old), { recursive: true, force: true });\n }\n const dir = join(runs, new Date().toISOString().replace(/[-:]/g, '').replace(/\\..*/, ''));\n mkdirSync(dir, { recursive: true });\n chmodSync(dir, 0o700);\n return dir;\n}\n\nexport function writeReport(dir: string, report: RunReport): void {\n writeFileSync(join(dir, REPORT_FILE), `${JSON.stringify(report, null, 2)}\\n`);\n}\n\n/** The newest run's report and its folder. */\nexport function readLastReport(forkPath: string): { dir: string; report: RunReport } {\n const runs = existsSync(runsDir(forkPath)) ? readdirSync(runsDir(forkPath)).sort().reverse() : [];\n for (const run of runs) {\n const file = join(runsDir(forkPath), run, REPORT_FILE);\n if (existsSync(file)) return { dir: join(runsDir(forkPath), run), report: JSON.parse(readFileSync(file, 'utf8')) };\n }\n throw new Error('no pentest run yet: `pnpm cella pentest` runs one');\n}\n\n/** A run fails a release on a cross-tenant read or any high or critical finding. */\nexport const failsRelease = (report: RunReport) =>\n report.checks.some(({ findings }) => findings.some(({ severity }) => severity === 'critical' || severity === 'high'));\n\nconst severityColor: Record<Severity, (text: string) => string> = {\n critical: pc.red,\n high: pc.red,\n medium: pc.yellow,\n low: pc.cyan,\n info: pc.dim,\n};\n\nfunction countBySeverity(findings: Finding[]): string {\n const counts = SEVERITIES.map(\n (severity) => [severity, findings.filter((f) => f.severity === severity).length] as const,\n )\n .filter(([, count]) => count > 0)\n .map(([severity, count]) => `${count} ${severity}`);\n return counts.length > 0 ? counts.join(', ') : 'no findings';\n}\n\nexport function printReport(dir: string, report: RunReport): void {\n for (const warning of report.warnings) console.info(`${warningMark} ${warning}`);\n for (const outcome of report.checks) {\n const probed = outcome.check === 'probe' ? probeSummary(report.probe) : '';\n const mark = outcome.status === 'ran' ? undefined : warningMark;\n const status = outcome.status === 'ran' ? '' : pc.yellow(`${outcome.status}: `);\n printStep(outcome.check, `${status}${probed}${countBySeverity(outcome.findings)}`, mark);\n if (outcome.note) console.info(` ${pc.dim(outcome.note)}`);\n }\n\n // Info findings stay in the counts: the report file lists them\n const shown = report.checks\n .flatMap(({ findings }) => findings)\n .filter(({ severity }) => severity !== 'info')\n .sort((a, b) => SEVERITIES.indexOf(a.severity) - SEVERITIES.indexOf(b.severity));\n if (shown.length > 0) {\n console.info();\n for (const finding of shown) {\n const severity = severityColor[finding.severity](finding.severity.padEnd(8));\n console.info(` ${severity} ${finding.check.padEnd(7)} ${finding.title}`);\n console.info(` ${' '.repeat(17)}${pc.dim(finding.where)}`);\n }\n }\n\n const notProbed = report.probe.filter(({ verdict }) => verdict === 'not probed');\n if (notProbed.length > 0) {\n console.info();\n console.info(` ${pc.dim('not probed:')}`);\n for (const { operationId, note } of notProbed) console.info(` ${operationId.padEnd(24)} ${pc.dim(note ?? '')}`);\n }\n console.info();\n console.info(` ${pc.dim('results:')} ${dir}`);\n}\n\nfunction probeSummary(results: ProbeResult[]): string {\n const refused = results.filter(({ verdict }) => verdict === 'refused').length;\n return `${results.length} routes, ${refused} refused to the outsider, `;\n}\n","import { spawn, spawnSync } from 'node:child_process';\nimport {\n chmodSync,\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport { join } from 'node:path';\nimport process from 'node:process';\nimport { stringify } from 'yaml';\nimport { z } from 'zod';\nimport { getEnvSnapshot } from '../../utils/env';\nimport { onShutdown } from '../../utils/signals';\nimport { httpMethods, type OpenApiSpec } from './probe';\nimport type { CheckOutcome, Finding, Severity } from './report';\n\nconst NUCLEI_IMAGE =\n 'projectdiscovery/nuclei:v3.11.1@sha256:582d5546902e67052097cb2d07296c642d50a1afc5e44623cb038845df9a32eb';\n/** ZAP 2.17.0 with the automation, OpenAPI and report add-ons; amd64 only, so Apple silicon runs it emulated. */\nconst ZAP_IMAGE =\n 'ghcr.io/zaproxy/zaproxy:bare@sha256:30b1344efc23bcb7568c56e61a12b907c6e8072b43a49f86318c3f9b9e56f2a2';\n\n/** The images a scan runs, each pulled once by `resolveImage`. */\nexport const scannerImages = { nuclei: NUCLEI_IMAGE, zap: ZAP_IMAGE };\n\n/** Template tags of the generic checks: what leaks, what is misconfigured. */\nconst NUCLEI_TAGS = 'misconfig,exposure,cors,token,headers';\n/** The active scan's own cap; the container's cap adds the import and the reports. */\nconst ZAP_SCAN_MINUTES = 5;\nconst NUCLEI_TIMEOUT_MS = 15 * 60_000;\nconst ZAP_TIMEOUT_MS = (ZAP_SCAN_MINUTES + 10) * 60_000;\n\n/** Where a scanner aims and how it signs in. */\nexport interface ScanTarget {\n /** The testbed's one origin, frontend and API alike. */\n origin: string;\n apiUrl: string;\n /** `name=value` of the session the scanner sends. */\n cookie: string;\n runDir: string;\n /** Kept between runs and checkouts: the Nuclei templates. */\n cacheDir: string;\n spec: OpenApiSpec;\n skip: string[];\n}\n\n/**\n * Refuses any URL off the testbed's own origin: a scanner points at nothing else.\n * @throws for another origin or a host that is not this machine\n */\nexport function assertTestbedUrl(url: string, origin: string): void {\n const { origin: urlOrigin, hostname } = new URL(url);\n if (urlOrigin !== origin || !['localhost', '127.0.0.1', '[::1]'].includes(hostname)) {\n throw new Error(`refusing to scan ${url}: the only target is the testbed at ${origin}`);\n }\n}\n\n/** A folder the scanner's container user may write, whatever its uid; the run folder around it stays private. */\nfunction containerDir(path: string): string {\n mkdirSync(path, { recursive: true });\n chmodSync(path, 0o777);\n return path;\n}\n\n/**\n * Runs a scanner container on the host network, so `localhost` in it is this machine and requests carry the testbed's\n * own origin. Its output goes to `log`; ctrl-c and `timeoutMs` stop it. Resolves to its exit code, or undefined when it\n * timed out.\n */\nasync function runContainer(\n name: string,\n args: string[],\n options: { log: string; timeoutMs: number; env?: NodeJS.ProcessEnv },\n): Promise<number | undefined> {\n const container = `cella-pentest-${name}-${process.pid}`;\n const log = openSync(options.log, 'a');\n const child = spawn('docker', ['run', '--rm', '--name', container, '--network', 'host', ...args], {\n env: { ...getEnvSnapshot(), ...options.env },\n stdio: ['ignore', log, log],\n });\n const remove = () => {\n spawnSync('docker', ['rm', '-f', container], { stdio: 'ignore' });\n };\n const forget = onShutdown(remove);\n let timedOut = false;\n const timer = setTimeout(() => {\n timedOut = true;\n remove();\n }, options.timeoutMs);\n const code = await new Promise<number>((done) => {\n child.once('error', () => done(127));\n child.once('exit', (exitCode) => done(exitCode ?? 1));\n });\n clearTimeout(timer);\n forget();\n closeSync(log);\n return timedOut ? undefined : code;\n}\n\n/** `ran` once the scanner wrote its results, whatever its exit code says; `note` points at the log otherwise. */\nfunction outcome(\n check: CheckOutcome['check'],\n code: number | undefined,\n wrote: boolean,\n findings: Finding[],\n log: string,\n) {\n const status = code === undefined ? 'timed out' : wrote ? 'ran' : 'failed';\n return { check, status, findings, ...(status === 'ran' ? {} : { note: `see ${log}` }) } satisfies CheckOutcome;\n}\n\nconst pathOf = (url: string, origin: string) => (url.startsWith(origin) ? url.slice(origin.length) || '/' : url);\n\nconst nucleiResultSchema = z.object({\n 'template-id': z.string(),\n info: z.object({\n name: z.string(),\n severity: z.enum(['critical', 'high', 'medium', 'low', 'info', 'unknown']),\n classification: z.object({ 'cwe-id': z.array(z.string()).nullish() }).nullish(),\n }),\n /** Which of a template's matchers hit, such as the one missing header of several. */\n 'matcher-name': z.string().optional(),\n 'matched-at': z.string().optional(),\n host: z.string().optional(),\n});\n\n/** Nuclei's generic templates against the origin and the API, with the scan session; OAST callbacks stay off. */\nexport async function runNuclei(target: ScanTarget): Promise<CheckOutcome> {\n const urls = [target.origin, target.apiUrl];\n for (const url of urls) assertTestbedUrl(url, target.origin);\n const out = containerDir(join(target.runDir, 'nuclei'));\n const templates = containerDir(join(target.cacheDir, 'nuclei-templates'));\n const config = containerDir(join(target.cacheDir, 'nuclei-config'));\n // A header file keeps the cookie out of the process list\n writeFileSync(join(out, 'headers.txt'), `Cookie: ${target.cookie}\\n`);\n const log = join(target.runDir, 'nuclei.log');\n // The first run downloads the templates; later runs use the ones it kept\n const update = readdirSync(templates).length === 0 ? [] : ['-duc'];\n const code = await runContainer(\n 'nuclei',\n [\n ...['-v', `${out}:/out`, '-v', `${templates}:/root/nuclei-templates`, '-v', `${config}:/root/.config/nuclei`],\n NUCLEI_IMAGE,\n ...urls.flatMap((url) => ['-u', url]),\n ...['-H', '/out/headers.txt', '-tags', NUCLEI_TAGS, '-s', 'info,low,medium,high,critical', '-pt', 'http'],\n ...['-ni', '-rl', '50', '-c', '10', '-timeout', '5', '-jsonl', '-o', '/out/nuclei.jsonl', '-or', '-nc'],\n ...update,\n ],\n { log, timeoutMs: NUCLEI_TIMEOUT_MS },\n );\n rmSync(join(out, 'headers.txt'), { force: true });\n\n const wrote = existsSync(join(out, 'nuclei.jsonl'));\n const results = wrote ? readFileSync(join(out, 'nuclei.jsonl'), 'utf8') : '';\n const findings = results\n .split('\\n')\n .filter(Boolean)\n .flatMap((line): Finding[] => {\n const parsed = nucleiResultSchema.safeParse(JSON.parse(line));\n if (!parsed.success) return [];\n const { info, 'template-id': templateId, 'matcher-name': matcher, 'matched-at': matchedAt, host } = parsed.data;\n const severity: Severity = info.severity === 'unknown' ? 'info' : info.severity;\n const where = `GET ${pathOf(matchedAt ?? host ?? target.origin, target.origin)}`;\n const cwe = info.classification?.['cwe-id']?.[0]?.toUpperCase();\n const title = matcher ? `${info.name}: ${matcher}` : info.name;\n return [{ check: 'nuclei', severity, title, where, detail: templateId, ...(cwe ? { cwe } : {}) }];\n });\n return outcome('nuclei', code, wrote && code === 0, findings, log);\n}\n\n/** The spec a scan imports: the skipped operations left out, and the testbed's API as its server. */\nexport function scanSpec(spec: OpenApiSpec, skip: string[], apiUrl: string): OpenApiSpec {\n const paths = Object.entries(spec.paths).flatMap(([path, item]) => {\n const kept = Object.entries(item).filter(\n ([key]) => !httpMethods.includes(key) || !skip.includes(`${key.toUpperCase()} ${path}`),\n );\n return kept.some(([key]) => httpMethods.includes(key)) ? [[path, Object.fromEntries(kept)] as const] : [];\n });\n return { ...spec, servers: [{ url: apiUrl }], paths: Object.fromEntries(paths) };\n}\n\nconst zapReportSchema = z.object({\n site: z.array(\n z.object({\n alerts: z.array(\n z.object({\n name: z.string(),\n pluginid: z.string(),\n cweid: z.string().optional(),\n riskcode: z.string(),\n count: z.string().optional(),\n instances: z.array(z.object({ uri: z.string(), method: z.string() })).default([]),\n }),\n ),\n }),\n ),\n});\n\nconst zapRisks: Record<string, Severity> = { '3': 'high', '2': 'medium', '1': 'low', '0': 'info' };\n\nconst escapeRegex = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * ZAP's automation framework: import the spec, wait for the passive rules, run a time-capped active scan, write a\n * JSON report. The session goes in as a header ZAP adds to every request to the testbed's host.\n */\nexport async function runZap(target: ScanTarget): Promise<CheckOutcome> {\n assertTestbedUrl(target.apiUrl, target.origin);\n const work = containerDir(join(target.runDir, 'zap'));\n writeFileSync(join(work, 'openapi.json'), JSON.stringify(scanSpec(target.spec, target.skip, target.apiUrl)));\n const context = 'testbed';\n const plan = {\n env: {\n contexts: [{ name: context, urls: [target.apiUrl], includePaths: [`${escapeRegex(target.apiUrl)}.*`] }],\n parameters: { failOnError: false, failOnWarning: false, progressToStdout: true },\n },\n jobs: [\n { type: 'openapi', parameters: { apiFile: '/zap/wrk/openapi.json', targetUrl: target.apiUrl, context } },\n { type: 'passiveScan-wait', parameters: { maxDuration: 2 } },\n {\n type: 'activeScan',\n parameters: { context, maxRuleDurationInMins: 1, maxScanDurationInMins: ZAP_SCAN_MINUTES },\n },\n { type: 'passiveScan-wait', parameters: { maxDuration: 2 } },\n { type: 'report', parameters: { template: 'traditional-json', reportDir: '/zap/wrk', reportFile: 'zap.json' } },\n ],\n };\n writeFileSync(join(work, 'plan.yaml'), stringify(plan));\n const log = join(target.runDir, 'zap.log');\n const code = await runContainer(\n 'zap',\n [\n ...['--platform', 'linux/amd64', '-v', `${work}:/zap/wrk:rw`],\n // Without a value Docker takes each from its own env, which keeps the cookie out of the process list\n ...['-e', 'ZAP_AUTH_HEADER', '-e', 'ZAP_AUTH_HEADER_VALUE', '-e', 'ZAP_AUTH_HEADER_SITE'],\n ZAP_IMAGE,\n ...['zap.sh', '-cmd', '-autorun', '/zap/wrk/plan.yaml'],\n ],\n {\n log,\n timeoutMs: ZAP_TIMEOUT_MS,\n env: {\n ZAP_AUTH_HEADER: 'Cookie',\n ZAP_AUTH_HEADER_VALUE: target.cookie,\n ZAP_AUTH_HEADER_SITE: new URL(target.origin).host,\n },\n },\n );\n\n const reportFile = join(work, 'zap.json');\n const report = existsSync(reportFile)\n ? zapReportSchema.safeParse(JSON.parse(readFileSync(reportFile, 'utf8')))\n : undefined;\n const findings = (report?.success ? report.data.site : []).flatMap(({ alerts }) =>\n alerts.map((alert): Finding => {\n const [first] = alert.instances;\n const more = alert.instances.length > 1 ? ` (+${alert.instances.length - 1} more)` : '';\n const where = first ? `${first.method} ${pathOf(first.uri, target.origin)}${more}` : target.apiUrl;\n return {\n check: 'zap',\n severity: zapRisks[alert.riskcode] ?? 'info',\n title: alert.name,\n where,\n detail: `rule ${alert.pluginid}`,\n ...(alert.cweid && alert.cweid !== '-1' && alert.cweid !== '0' ? { cwe: `CWE-${alert.cweid}` } : {}),\n };\n }),\n );\n // ZAP exits non-zero on any plan error, such as an operation its OpenAPI import refuses, and scans the rest\n const errors = readFileSync(log, 'utf8').split('Automation plan failures:')[1]?.trim().split('\\n') ?? [];\n const result = outcome('zap', code, report?.success === true, findings, log);\n return errors.length > 0 ? { ...result, note: `ZAP: ${errors.map((line) => line.trim()).join('; ')}` } : result;\n}\n","import { spawnSync } from 'node:child_process';\nimport type { TestbedHandle } from '../testbed';\n\nconst SESSION_NAMES = ['admin', 'outsider'] as const;\nexport type SessionName = (typeof SESSION_NAMES)[number];\n\n/** A signed-in seeded user; `cookie` is the `name=value` pair a request sends. */\nexport interface Session {\n name: SessionName;\n email: string;\n userId: string;\n organizationId: string;\n tenantId: string;\n cookie: string;\n}\n\n/** The adapter's sessions query, run as the database superuser so row-level security hides nothing. */\nfunction findUsers(testbed: TestbedHandle, sql: string): Omit<Session, 'cookie'>[] {\n const psql = ['exec', '-i', testbed.container, 'psql', '-U', 'postgres', '-tA', '-F', '\\t', '-v', 'ON_ERROR_STOP=1'];\n const result = spawnSync('docker', psql, { input: sql, encoding: 'utf8' });\n if (result.status !== 0)\n throw new Error(`the sessions query of the pentest adapter failed:\\n${result.stderr.trim()}`);\n const rows = result.stdout\n .trim()\n .split('\\n')\n .map((line) => line.split('\\t'));\n return SESSION_NAMES.map((name) => {\n const row = rows.find(([session]) => session === name);\n if (!row || row.length < 5) throw new Error(`the sessions query of the pentest adapter returned no '${name}' row`);\n const [, email, userId, organizationId, tenantId] = row;\n return { name, email, userId, organizationId, tenantId };\n });\n}\n\n/** A two-hour session minted by the app's own script, which signs the cookie as sign-in would. */\nfunction mint(forkPath: string, testbed: TestbedHandle, user: Omit<Session, 'cookie'>): Session {\n const minted = spawnSync('pnpm', ['--silent', '--filter', 'backend', 'session:mint', user.email, '2'], {\n cwd: forkPath,\n env: testbed.env,\n encoding: 'utf8',\n });\n const cookie = /^([\\w-]+=\\S+)$/m.exec(minted.stdout)?.[1];\n if (minted.status !== 0 || !cookie) throw new Error(`could not mint a session for ${user.email}:\\n${minted.stderr}`);\n return { ...user, cookie };\n}\n\n/**\n * Signs in as each user the adapter's query names and checks that the API takes the session.\n * @throws when a row is missing, a mint fails, or the API refuses a minted session\n */\nexport async function startSessions(\n forkPath: string,\n testbed: TestbedHandle,\n sql: string,\n): Promise<Record<SessionName, Session>> {\n const sessions = findUsers(testbed, sql).map((user) => mint(forkPath, testbed, user));\n for (const session of sessions) {\n const me = await fetch(`${testbed.backendUrl}/me`, { headers: { cookie: session.cookie } });\n if (me.status !== 200) throw new Error(`the API answers ${me.status} to the ${session.name} session`);\n }\n const [admin, outsider] = sessions;\n return { admin, outsider };\n}\n\n/** Signs the sessions out, so no live session outlasts the run; a JSON body passes the CSRF check. */\nexport async function endSessions(apiUrl: string, sessions: Session[]): Promise<void> {\n const headers = (session: Session) => ({ cookie: session.cookie, 'content-type': 'application/json' });\n await Promise.all(\n sessions.map((session) =>\n fetch(`${apiUrl}/auth/sign-out`, { method: 'POST', headers: headers(session) }).catch(() => undefined),\n ),\n );\n}\n","import { spawnSync } from 'node:child_process';\nimport { mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport pc from '../../utils/colors';\nimport { printStep, warningMark } from '../../utils/display';\nimport { setEnv } from '../../utils/env';\nimport { onShutdown } from '../../utils/signals';\nimport { applyDelta, fillPath, loadAdapter, type Placeholders, type Prepare, signedIn } from '../adapters';\nimport { type Browser, loadPlaywright, mintSession, newContext, openPage, type Page, settle, signOut } from '../drive';\nimport type { TestbedHandle } from '../testbed';\nimport { appSchema, baseSchema, type Device, type ScreenshotsBase, type Shot } from './define';\n\n/** The shot list with the app's delta applied. */\nexport interface ShotList {\n format: ScreenshotsBase['format'];\n devices: Record<string, Device>;\n suppress: { alerts: string[]; hints: string[] };\n prepare: Prepare[];\n placeholders: Placeholders;\n shots: Shot[];\n}\n\nexport interface ShootOptions {\n /** Shot ids; all when empty. */\n ids: string[];\n /** A folder for a trial run; default the files the app ships. */\n out?: string;\n /** The shot user; default the testbed's `ADMIN_EMAIL`. */\n email?: string;\n}\n\n// The nav bar's first button shows the logo for three seconds after mount (`AppNavLoader`): every shot waits it out, so a pair never differs by it\nconst INTRO_MS = 3200;\n// The first signed-in page compiles most of the app on demand when the frontend is a dev server\nconst PAGE_MS = 120_000;\n\nexport async function loadShotList(forkPath: string): Promise<ShotList> {\n // The adapters read the app config, which takes the development ports and URLs in development mode only\n setEnv('NODE_ENV', 'development');\n const { base, app } = await loadAdapter(forkPath, 'screenshots', baseSchema, appSchema);\n const shots = app ? applyDelta(base.shots, app, 'cella/screenshots.app.ts') : base.shots;\n const devices = { ...base.devices, ...app?.devices };\n for (const shot of shots) {\n if (!devices[shot.device]) {\n throw new Error(`shot ${shot.id} takes device \"${shot.device}\", which neither adapter defines`);\n }\n }\n const both = (key: 'alerts' | 'hints') => [...(base.suppress?.[key] ?? []), ...(app?.suppress?.[key] ?? [])];\n return {\n format: app?.format ?? base.format,\n devices,\n suppress: { alerts: both('alerts'), hints: both('hints') },\n prepare: [base.prepare, app?.prepare].filter((step) => step !== undefined),\n placeholders: { ...base.placeholders, ...app?.placeholders },\n shots,\n };\n}\n\n/** Asked before the testbed starts: a missing encoder is known in a second, not after the last shot. */\nexport function requireEncoder(format: ShotList['format']): void {\n if (format === 'webp' && spawnSync('cwebp', ['-version']).status !== 0) {\n throw new Error(\n \"format 'webp' needs the cwebp encoder on the PATH: `brew install webp` or `apt install webp`, or set format to 'png'\",\n );\n }\n}\n\n/**\n * Resolves once no spinner has shown for `quiet` ms, or after `cap` ms. `settle` sees only the DOM, and a slow API can\n * leave that unchanged for longer than its quiet time, so a page whose rows and counts are still on their way passes it.\n */\nasync function spinnersGone(page: Page, quiet = 1000, cap = 45_000): Promise<void> {\n const deadline = Date.now() + cap;\n let since = Date.now();\n while (Date.now() < deadline) {\n if (await page.locator('.animate-spin').count()) since = Date.now();\n else if (Date.now() - since >= quiet) return;\n await page.waitForTimeout(100);\n }\n}\n\ninterface Written {\n id: string;\n mode: string;\n path: string;\n bytes: number;\n pixels: string;\n}\n\nconst hasMfaScript = (forkPath: string) =>\n Boolean(JSON.parse(readFileSync(join(forkPath, 'backend/package.json'), 'utf8')).scripts?.['showcase:mfa']);\n\n/**\n * Shoots the list on a testbed, a light and a dark shot each, and prints every file with its pixel and file size.\n * Resolves to the exit code: 1 when a shot failed.\n */\nexport async function shoot(forkPath: string, list: ShotList, testbed: TestbedHandle, options: ShootOptions) {\n const email = options.email ?? testbed.env.ADMIN_EMAIL;\n if (!email) throw new Error('no shot user: pass --email, or set ADMIN_EMAIL in backend/.env');\n const todo = options.ids.length > 0 ? list.shots.filter((shot) => options.ids.includes(shot.id)) : list.shots;\n\n const user = mintSession(email, { forkPath, env: testbed.env });\n const scratch = mkdtempSync(join(tmpdir(), 'cella-screenshots-'));\n let browser: Browser | undefined;\n const cleanup = async () => {\n await browser?.close();\n await signOut(user);\n rmSync(scratch, { recursive: true, force: true });\n };\n const forget = onShutdown(cleanup);\n const written: Written[] = [];\n const failures: { id: string; mode: string; error: string }[] = [];\n\n /**\n * Writes a screenshot in the list's format. WebP is lossless, so the pixels are the screenshot's own, at the encoder's\n * slowest and smallest setting: a third of the PNG for a page of flat color and text.\n */\n const writeShot = (png: Buffer, path: string) => {\n if (list.format === 'png') {\n writeFileSync(path, png);\n return;\n }\n const source = join(scratch, 'shot.png');\n writeFileSync(source, png);\n const encoded = spawnSync('cwebp', ['-quiet', '-lossless', '-z', '9', source, '-o', path], { encoding: 'utf8' });\n if (encoded.status !== 0) throw new Error(`cwebp could not write ${path}: ${encoded.stderr.trim()}`);\n };\n\n try {\n // MFA on for the shot user and a share of their members, so the account page and member tables show both states.\n // The showcase seed does that itself; an app without one does it through its `showcase:mfa` script, where it has it.\n // Nobody can sign in with the factors it adds, which is why it runs on a testbed only.\n if (testbed.data === 'seed' && hasMfaScript(forkPath)) {\n const showcase = spawnSync('pnpm', ['--silent', '--filter', 'backend', 'showcase:mfa', email], {\n cwd: forkPath,\n env: testbed.env,\n encoding: 'utf8',\n });\n if (showcase.status !== 0) throw new Error(`showcase:mfa failed:\\n${showcase.stdout}\\n${showcase.stderr}`);\n printStep('mfa', showcase.stdout.trim().split('\\n').at(-1));\n }\n\n for (const prepare of list.prepare) await prepare(signedIn(user));\n const values: Record<string, string | null> = {};\n for (const [name, resolve] of Object.entries(list.placeholders)) values[name] = await resolve(signedIn(user));\n\n const { chromium } = await loadPlaywright(forkPath);\n browser = await chromium.launch();\n\n // One context per device and mode: the UI store lives in the context, so it is written once and every shot in the\n // group inherits it. A pair is the same recipe run twice, which is what keeps the light and dark shot in register.\n for (const deviceName of [...new Set(todo.map((shot) => shot.device))]) {\n const device = list.devices[deviceName];\n for (const mode of ['light', 'dark'] as const) {\n const context = await newContext(browser, {\n viewport: { width: device.width, height: device.height },\n deviceScaleFactor: device.scale,\n colorScheme: mode,\n reducedMotion: 'reduce',\n serviceWorkers: 'block',\n locale: 'en-US',\n timezoneId: 'Europe/Amsterdam',\n session: user,\n uiStore: {\n slug: user.slug,\n state: { mode, publicAlertsSeen: list.suppress.alerts, hintsSeen: list.suppress.hints },\n },\n });\n\n for (const shot of todo.filter((entry) => entry.device === deviceName)) {\n const target = options.out ? join(resolve(options.out), basename(shot.out)) : join(forkPath, shot.out);\n const path = `${target}${mode === 'dark' ? '-dark' : ''}.${list.format}`;\n let page: Page | undefined;\n try {\n const route = fillPath(shot.path, values, 'the screenshots adapter');\n page = await openPage(context, `${user.frontendUrl}${route}`, { timeout: PAGE_MS });\n await page.waitForTimeout(INTRO_MS);\n await spinnersGone(page);\n await shot.open?.(page);\n await settle(page, { cap: 5000 });\n // A click in `open` leaves the control focused and the pointer over it: neither belongs in a marketing\n // shot. The pointer parks in the top right corner, which is page header or background in every layout;\n // the bottom corners are a table row and the sidebar, and both take a hover style.\n await page.mouse.move(device.width - 1, 0);\n await page.evaluate(() => document.activeElement instanceof HTMLElement && document.activeElement.blur());\n await settle(page, { quiet: 200, cap: 1000 });\n await spinnersGone(page, 1500);\n\n mkdirSync(dirname(path), { recursive: true });\n writeShot(await page.screenshot({ animations: 'disabled', caret: 'hide', scale: 'device' }), path);\n const pixels = `${device.width * device.scale}x${device.height * device.scale}`;\n written.push({ id: shot.id, mode, path, bytes: statSync(path).size, pixels });\n } catch (error) {\n failures.push({\n id: shot.id,\n mode,\n error: error instanceof Error ? error.message.split('\\n')[0] : String(error),\n });\n } finally {\n await page?.close();\n }\n }\n await context.close();\n }\n }\n } finally {\n await cleanup();\n forget();\n }\n\n console.info();\n for (const image of written) {\n const size = `${String(Math.round(image.bytes / 1024)).padStart(5)} KB`;\n console.info(\n ` ${image.id.padEnd(20)} ${image.mode.padEnd(5)} ${image.pixels.padEnd(10)} ${size} ${pc.dim(image.path)}`,\n );\n }\n for (const failure of failures) console.info(` ${warningMark} ${failure.id} ${failure.mode}: ${failure.error}`);\n console.info();\n printStep(\n 'written',\n `${written.length} of ${todo.length * 2}; look at every one against the screenshots skill's rubric`,\n );\n return failures.length > 0 ? 1 : 0;\n}\n","import { z } from 'zod';\nimport { fn, type Placeholders, type Prepare, placeholdersSchema } from '../adapters';\nimport type { Page } from '../drive';\n\ntype Opener = (page: Page) => Promise<void>;\n\n/** A viewport and its pixel ratio: scale 2 draws a 1280px-wide app at 2560px. */\nexport interface Device {\n width: number;\n height: number;\n scale: number;\n}\n\n/** UI that shows once per user, marked seen in the persisted UI store before the first page. */\nexport interface Suppress {\n /** `publicAlertsSeen` ids, such as the dev banner. */\n alerts?: string[];\n /** `hintsSeen` ids, such as a first-visit menu hint. */\n hints?: string[];\n}\n\n/** One screenshot, written in both color modes as `<out>.<format>` and `<out>-dark.<format>`. */\nexport interface Shot {\n id: string;\n /** A key of `devices`. */\n device: string;\n /** Route on the frontend; a `{name}` placeholder takes the value its resolver returns. */\n path: string;\n /** From the app's root, without the extension. */\n out: string;\n /** Brings the page into the state the shot wants, after the route has rendered and settled. */\n open?: Opener;\n}\n\n/** `cella/screenshots.ts`: the template's shots, synced with the UI they show. */\nexport interface ScreenshotsBase {\n /** The file type of every shot. WebP is written lossless by the system `cwebp` encoder. */\n format: 'webp' | 'png';\n devices: Record<string, Device>;\n suppress?: Suppress;\n /** Brings the shot user into the state the pages expect, before the first shot. */\n prepare?: Prepare;\n placeholders?: Placeholders;\n shots: Shot[];\n}\n\n/** `cella/screenshots.app.ts`, optional: what an app adds to the base, removes from it or overrides. */\nexport interface ScreenshotsApp {\n format?: ScreenshotsBase['format'];\n /** Join the base's; a name in both takes this one. */\n devices?: Record<string, Device>;\n /** Joins the base's lists. */\n suppress?: Suppress;\n /** Runs after the base's. */\n prepare?: Prepare;\n /** Joins the base's; a name in both takes this one. */\n placeholders?: Placeholders;\n /** Base shot ids the app does not ship. */\n remove?: string[];\n /** Shots of the app's own; one with a base shot's id replaces it in place. */\n add?: Shot[];\n}\n\nconst formatSchema = z.enum(['webp', 'png']);\n\nconst deviceSchema = z.strictObject({\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n scale: z.number().positive(),\n});\n\nconst suppressSchema = z.strictObject({\n alerts: z.array(z.string()).optional(),\n hints: z.array(z.string()).optional(),\n});\n\nconst shotSchema = z.strictObject({\n id: z.string().min(1),\n device: z.string().min(1),\n path: z.string().startsWith('/').or(z.string().startsWith('{')),\n out: z.string().min(1),\n open: fn<Opener>().optional(),\n}) satisfies z.ZodType<Shot>;\n\nexport const baseSchema = z.strictObject({\n format: formatSchema,\n devices: z.record(z.string(), deviceSchema),\n suppress: suppressSchema.optional(),\n prepare: fn<Prepare>().optional(),\n placeholders: placeholdersSchema.optional(),\n shots: z.array(shotSchema).min(1),\n}) satisfies z.ZodType<ScreenshotsBase>;\n\nexport const appSchema = z.strictObject({\n format: formatSchema.optional(),\n devices: z.record(z.string(), deviceSchema).optional(),\n suppress: suppressSchema.optional(),\n prepare: fn<Prepare>().optional(),\n placeholders: placeholdersSchema.optional(),\n remove: z.array(z.string()).optional(),\n add: z.array(shotSchema).optional(),\n}) satisfies z.ZodType<ScreenshotsApp>;\n\nexport const defineScreenshotsBase = (base: ScreenshotsBase): ScreenshotsBase => base;\n\nexport const defineScreenshotsApp = (app: ScreenshotsApp): ScreenshotsApp => app;\n","import type { ToolCommand } from '../../config/types';\nimport { requireChromium } from '../drive';\nimport { hasShowcase, withTestbed } from '../testbed';\nimport { loadShotList, requireEncoder, type ShootOptions, shoot } from './shoot';\n\nasync function runScreenshots(forkPath: string, options: ShootOptions): Promise<number> {\n // Before the testbed starts: an adapter that does not fit, an unknown id or a missing encoder fails in seconds\n const list = await loadShotList(forkPath);\n const unknown = options.ids.filter((id) => !list.shots.some((shot) => shot.id === id));\n if (unknown.length > 0) {\n throw new Error(`no shot ${unknown.join(', ')}: this app shoots ${list.shots.map((shot) => shot.id).join(', ')}`);\n }\n requireEncoder(list.format);\n await requireChromium(forkPath);\n // An app with a showcase shoots its curated data, on a database no other tool writes to\n const data = hasShowcase(forkPath) ? 'showcase' : 'seed';\n return withTestbed(forkPath, (testbed) => shoot(forkPath, list, testbed, options), { data });\n}\n\nexport const screenshotsCommand: ToolCommand<ShootOptions> = {\n name: 'screenshots',\n group: 'develop',\n description: 'shoot the marketing screenshots on a testbed, a light and a dark file each',\n jobs: [],\n operands: ['[ids...]', 'the shots to take (default: all)'],\n options: [\n ['--out <dir>', 'write into this folder, a trial run that leaves the working tree alone'],\n ['--email <address>', 'the shot user (default the showcase admin, else ADMIN_EMAIL in backend/.env)'],\n ],\n parse: ({ operands, opts }) => ({\n ids: operands,\n out: typeof opts.out === 'string' ? opts.out : undefined,\n email: typeof opts.email === 'string' ? opts.email : undefined,\n }),\n run: runScreenshots,\n};\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ToolCommand } from '../../config/types';\nimport { git } from '../../utils/git';\nimport { alignmentFindings, type BranchChanges, owedAlignmentFindings } from './alignment-rules';\nimport { commentFindings } from './comment-rules';\nimport { docFindings } from './doc-rules';\nimport { frontendFindings, frontendStores } from './frontend-rules';\nimport { type Finding, formatFinding, isRequested, openRepository, repoFiles, repoRoot } from './repo';\nimport { stampFindings } from './stamp-rules';\nimport { tailwindContext, tailwindFindings } from './tailwind-class-rules';\nimport { textColorFindings } from './text-color-rules';\nimport { tokenContrastFindings } from './token-contrast-rules';\nimport { loadAllowlist, productNameFindings, vocabularyFindings } from './vocabulary-rules';\n\nexport interface StyleOptions {\n /** Repo-relative paths whose files the in-file rules read; none reads every file. */\n paths: string[];\n}\n\n/** The branch's changes since its merge base with `origin/main`, uncommitted and untracked files included; empty without that ref. */\nasync function branchChanges(): Promise<BranchChanges> {\n const run = (...args: string[]) => git(args, repoRoot);\n try {\n const base = await run('merge-base', 'HEAD', 'origin/main');\n const untracked = await run('ls-files', '-o', '--exclude-standard');\n const paths = (diff: string) => `${diff}\\n${untracked}`.split('\\n').filter(Boolean);\n return {\n changed: paths(await run('diff', '--name-only', base)),\n added: paths(await run('diff', '--name-only', '--no-renames', '--diff-filter=A', base)),\n messages: await run('log', '--format=%B', `${base}..HEAD`),\n };\n } catch {\n return { changed: [], added: [], messages: '' };\n }\n}\n\n/** Runs every rule over the repository in `root` and prints the findings; 1 when there are any. */\nasync function runStyle(root: string, { paths }: StyleOptions): Promise<number> {\n await openRepository(root);\n const allowlist = await loadAllowlist();\n const files = repoFiles();\n const stores = frontendStores(files);\n const tailwind = await tailwindContext(files, allowlist.markerClasses);\n const read = (file: string) => readFileSync(join(repoRoot, file), 'utf8');\n\n const requested = files.filter((file) => isRequested(file, paths));\n const findings: Finding[] = paths\n .filter((path) => !files.some((file) => isRequested(file, [path])))\n .map((path) => ({ file: path, rule: 'path-argument', message: 'no file matches this path' }));\n findings.push(...alignmentFindings(requested, read));\n // Alignments are written where they live: an app's own changes to its own paths owe none. Every upgraded app has an\n // upgrade manifest, and an upgrade by a CLI before 0.5 also copied the alignments folder in, so the folder alone does\n // not mark the template.\n if (\n paths.length === 0 &&\n files.includes('cella/alignments/_TEMPLATE.md') &&\n !files.includes('cella/cella.manifest.json')\n ) {\n findings.push(...owedAlignmentFindings(await branchChanges(), read('cella/cella.config.ts')));\n }\n for (const file of requested) {\n const content = readFileSync(join(repoRoot, file));\n if (content.includes(0)) continue;\n const source = content.toString('utf8');\n const prose = allowlist.proseExclude?.some((prefix) => file.startsWith(prefix))\n ? []\n : [...docFindings(file, source), ...commentFindings(file, source)];\n const inFile = [\n ...vocabularyFindings(file, source, allowlist),\n ...productNameFindings(file, source),\n ...prose,\n ...frontendFindings(file, source, stores),\n ...stampFindings(file, source),\n ...tailwindFindings(file, source, tailwind),\n ...textColorFindings(file, source),\n ...tokenContrastFindings(file, source),\n ];\n findings.push(...inFile.sort((a, b) => (a.line ?? 0) - (b.line ?? 0) || (a.column ?? 0) - (b.column ?? 0)));\n }\n\n if (findings.length > 0) {\n console.error(\n [`[style] ${findings.length} finding(s):`, ...findings.map((finding) => ` ${formatFinding(finding)}`)].join(\n '\\n',\n ),\n );\n return 1;\n }\n console.info('[style] OK, terminology, documentation, comments and frontend code follow the required style.');\n return 0;\n}\n\nexport const styleCommand: ToolCommand<StyleOptions> = {\n name: 'style',\n group: 'gate',\n description: 'the style check: terminology, docs, comments and frontend code; exits 1 on any finding',\n jobs: [],\n operands: ['[paths...]', 'limit the files the in-file rules read to these repo-relative paths'],\n parse: ({ operands }) => ({ paths: operands }),\n run: runStyle,\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. */\nexport const 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\nexport const 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. */\nexport function 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. */\nexport function 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). */\nexport function 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","import { execFileSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type TypeScript from 'typescript';\nimport { importFromWorkspace } from '../../utils/app-facts';\n\n/** Absolute path of the repository a run checks; every repo-relative path here resolves against it. */\nexport let repoRoot = '';\n\n/** The TypeScript the app's root package installed, so the CLI ships none. */\nexport let ts: typeof TypeScript;\n\n/** The node types the rules name as `ts.<Type>`: a namespace of types merges with the binding above. */\nexport declare namespace ts {\n type ArrowFunction = TypeScript.ArrowFunction;\n type BindingName = TypeScript.BindingName;\n type CallExpression = TypeScript.CallExpression;\n type CommentRange = TypeScript.CommentRange;\n type Expression = TypeScript.Expression;\n type FunctionExpression = TypeScript.FunctionExpression;\n type FunctionLikeDeclaration = TypeScript.FunctionLikeDeclaration;\n type Node = TypeScript.Node;\n type ObjectLiteralExpression = TypeScript.ObjectLiteralExpression;\n type PropertyName = TypeScript.PropertyName;\n type SourceFile = TypeScript.SourceFile;\n type StringLiteralLike = TypeScript.StringLiteralLike;\n type TemplateExpression = TypeScript.TemplateExpression;\n type TemplateLiteralLikeNode = TypeScript.TemplateLiteralLikeNode;\n type VariableStatement = TypeScript.VariableStatement;\n}\n\n/**\n * Points the rules at the repository in `root` and loads its TypeScript. Call it before any other export of this\n * folder: they read `repoRoot` and `ts`.\n * @throws when the root package has no `typescript` installed\n */\nexport async function openRepository(root: string): Promise<void> {\n ts = await importFromWorkspace<typeof TypeScript>(root, '.', 'typescript');\n repoRoot = root;\n}\n\n/** One style finding. */\nexport interface Finding {\n file: string;\n /** 1-based, as is `column`; absent when the finding is about the path itself. */\n line?: number;\n column?: number;\n rule: string;\n /** The matched text, printed in quotes before the message; absent when the finding names no single term. */\n term?: string;\n message: string;\n}\n\n/** Repo-relative files git tracks, plus untracked ones it does not ignore, that exist on disk, in `git ls-files` order. */\nexport function repoFiles(): string[] {\n return execFileSync('git', ['ls-files', '-co', '--exclude-standard'], { cwd: repoRoot, encoding: 'utf8' })\n .split('\\n')\n .filter((file) => file && existsSync(join(repoRoot, file)));\n}\n\n/** Whether `file` is the path `entry` or inside it; `entry` may end in `/`. */\nexport function isUnder(file: string, entry: string): boolean {\n return file === entry || file.startsWith(entry.endsWith('/') ? entry : `${entry}/`);\n}\n\n/** Whether `file` is one of the requested roots or inside one; no roots requests every file. */\nexport function isRequested(file: string, roots: string[]): boolean {\n return roots.length === 0 || roots.some((root) => isUnder(file, root.replace(/^\\.\\//, '').replace(/\\/$/, '')));\n}\n\n/** App sources under frontend/src, outside generated files, content, stories and tests: the files the frontend convention rules read. */\nexport function isFrontendSource(file: string): boolean {\n return (\n /^frontend\\/src\\/.*\\.tsx?$/.test(file) &&\n !file.includes('.gen.') &&\n !file.includes('/content/') &&\n !file.includes('/stories/') &&\n !/\\.(?:stories|test)\\.tsx?$/.test(file)\n );\n}\n\n/** `text` with every character but a line break turned into a space, so offsets and line numbers into it still hold. */\nexport function blankOut(text: string): string {\n return text.replace(/[^\\n]/g, ' ');\n}\n\n/** 1-based line and column of `offset`, counting `\\n` line breaks only. */\nexport function lineColumn(source: string, offset: number): { line: number; column: number } {\n const lines = source.slice(0, offset).split('\\n');\n return { line: lines.length, column: lines.at(-1)!.length + 1 };\n}\n\n/** `file:line:column [rule] \"term\": message`; a finding about the path itself prints the path alone. */\nexport function formatFinding({ file, line, column, rule, term, message }: Finding): string {\n const location = line === undefined ? file : `${file}:${line}:${column}`;\n return `${location} [${rule}] ${term === undefined ? '' : `\"${term}\": `}${message}`;\n}\n","import { ALIGNMENT_ID, ALIGNMENTS_DIR, bodyLines, CAUGHT_BY, isCodemodFile, splitList } from '../../utils/alignments';\nimport { type Finding, isUnder } from './repo';\n\nconst alignmentsDir = `${ALIGNMENTS_DIR}/`;\n\n/** What checking one alignment README finds: the codemod's default scan roots it names and every shape problem. */\ninterface ReadmeCheck {\n roots: string[];\n errors: string[];\n}\n\nconst requiredBooleanKeys = ['breaking', 'clientCacheBump'];\nconst booleanKeys = [...requiredBooleanKeys, 'generate'];\n/** Comma-separated values: the terms `pnpm cella align` greps for, and the codemod's roots. */\nconst listKeys = ['grep', 'roots'];\n\n/** Checks an alignment README: its frontmatter, title and summary paragraph, and the `roots` it names. */\nexport function checkAlignmentReadme(source: string): ReadmeCheck {\n const errors: string[] = [];\n const lines = source.replace(/\\r\\n/g, '\\n').split('\\n');\n\n const close = lines[0] === '---' ? lines.indexOf('---', 1) : -1;\n if (close === -1) errors.push('must open with a `---` frontmatter block');\n const frontmatter = 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) {\n errors.push(`frontmatter line is not \\`key: value\\`: ${line}`);\n continue;\n }\n const [, key, value] = match;\n frontmatter.set(key, value);\n if (booleanKeys.includes(key)) {\n if (value !== 'true' && value !== 'false') errors.push(`${key} must be true or false`);\n } else if (key === 'caughtBy') {\n if (!CAUGHT_BY.some((caughtBy) => caughtBy === value))\n errors.push(`caughtBy must be one of ${CAUGHT_BY.join(', ')}`);\n } else if (!listKeys.includes(key)) errors.push(`unknown frontmatter key: ${key}`);\n }\n for (const key of requiredBooleanKeys)\n if (close !== -1 && !frontmatter.has(key)) errors.push(`frontmatter is missing ${key}`);\n if (frontmatter.get('breaking') === 'true' && !frontmatter.has('caughtBy'))\n errors.push('a breaking alignment says how an app finds its leftovers: caughtBy');\n\n // Body: the title, then the summary paragraph. Blank lines and HTML comments in between are skipped.\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 if (!/^# .+$/.test(blocks[0] ?? '')) errors.push('the first line after the frontmatter must be the `# ` title');\n const summary = blocks[1] ?? '';\n if (!summary || /^(#|>|[-*|]|```|\\d+\\.)/.test(summary))\n errors.push('the title must be followed by a one-paragraph summary');\n return { roots: splitList(frontmatter.get('roots')), errors };\n}\n\n/**\n * Findings for every alignment folder among `files`: folder name, README shape and `roots` exactly beside a codemod,\n * the shape `pnpm cella align` reads.\n */\nexport function alignmentFindings(files: string[], read: (file: string) => string): Finding[] {\n const folders = new Map<string, string[]>();\n for (const file of files) {\n if (!file.startsWith(alignmentsDir)) continue;\n const [folder, ...rest] = file.slice(alignmentsDir.length).split('/');\n if (rest.length === 0) continue;\n folders.set(folder, [...(folders.get(folder) ?? []), rest.join('/')]);\n }\n\n const findings: Finding[] = [];\n const finding = (file: string, message: string, line?: number) =>\n findings.push({ file, rule: 'alignment', message, ...(line === undefined ? {} : { line, column: 1 }) });\n for (const [folder, names] of folders) {\n const readme = `${alignmentsDir}${folder}/README.md`;\n if (!ALIGNMENT_ID.test(folder))\n finding(`${alignmentsDir}${folder}`, 'alignment folders are named <YYYYMMDDThhmm>-<slug>');\n if (!names.includes('README.md')) {\n finding(`${alignmentsDir}${folder}`, 'alignment folder has no README.md');\n continue;\n }\n const { roots, errors } = checkAlignmentReadme(read(readme));\n for (const error of errors) finding(readme, error, 1);\n const codemods = names.filter((name) => !name.includes('/') && isCodemodFile(name));\n if (codemods.length > 1) finding(readme, `one codemod per alignment, found ${codemods.join(', ')}`, 1);\n if (roots.length > 0 && codemods.length === 0) finding(readme, 'roots is only for an alignment with a codemod', 1);\n if (roots.length === 0 && codemods.length > 0)\n finding(readme, 'a codemod needs roots: the folders `pnpm cella align --run` scans by default', 1);\n }\n return findings;\n}\n\n/**\n * App-owned paths with nothing template code depends on: content, brand files and generated output. `shared/config` is\n * here too, because the config type already reports a key an app's config lacks.\n */\nconst alignmentExempt = [\n 'README.md',\n '.github/',\n 'cella/a11y-ledger.json',\n 'frontend/public/',\n 'frontend/src/content',\n 'frontend/src/routes/routeTree.gen.ts',\n 'frontend/src/styling/gradients.css',\n 'infra/',\n 'json/',\n 'locales/',\n 'sdk/gen',\n 'shared/config',\n];\n\n/** The `ignored` and `pinned` entries of the CLI config, read from its source text. */\nexport function ownedPaths(configSource: string): string[] {\n const lists = [...configSource.matchAll(/\\b(?:ignored|pinned): \\[([\\s\\S]*?)\\n {4}\\]/g)].map((match) => match[1]);\n return lists.flatMap((list) => [...list.matchAll(/^\\s*'([^']+)',?\\s*$/gm)].map((match) => match[1]));\n}\n\n/** What a branch changes against its base: every changed path, the paths it adds, and its commit messages. */\nexport interface BranchChanges {\n changed: string[];\n added: string[];\n messages: string;\n}\n\n/**\n * The finding for a branch that changes an app-owned path template code reads from (a pinned file, `logo-art.tsx`,\n * `backend/drizzle`) without adding an alignment. Such a change never reaches an app's copy, so the app's template code\n * breaks until someone tells it what to add. An `Alignment: none, <reason>` line in a commit message waives it.\n */\nexport function owedAlignmentFindings({ changed, added, messages }: BranchChanges, configSource: string): Finding[] {\n const owned = ownedPaths(configSource).filter((entry) => !alignmentExempt.some((exempt) => isUnder(entry, exempt)));\n // A Markdown file inside an owned folder is read by people, never by template code\n const touched = changed.filter((file) => !file.endsWith('.md') && owned.some((entry) => isUnder(file, entry)));\n if (touched.length === 0) return [];\n const addsAlignment = added.some((file) => {\n const [folder, name, ...rest] = file.slice(alignmentsDir.length).split('/');\n return file.startsWith(alignmentsDir) && ALIGNMENT_ID.test(folder) && name === 'README.md' && rest.length === 0;\n });\n if (addsAlignment || /^Alignment: none\\b.*\\w/m.test(messages)) return [];\n return touched.map((file) => ({\n file,\n rule: 'alignment',\n message:\n 'apps own this path and their template code reads from it: add an alignment under cella/alignments/ in this branch, or put `Alignment: none, <reason>` in a commit message',\n }));\n}\n","import { basename, extname } from 'node:path';\nimport { isProseExempt, proseRules, ruleFindings } from './prose-rules';\nimport { type Finding, lineColumn, ts } from './repo';\nimport { type Comment, parseSource, scriptExtensions, sourceComments } from './source-comments';\n\nconst sourceExtensions = new Set([...scriptExtensions, '.css', '.json', '.jsonc', '.scss', '.sql', '.yaml', '.yml']);\nconst textRules = proseRules.filter((rule) => rule.text);\nconst commentRules = proseRules.filter((rule) => !rule.text);\nconst placementAdvice = 'move shared context to a README or attach a concise local constraint to a declaration';\n\nfunction isSource(file: string): boolean {\n if (isProseExempt(file, 'source')) return false;\n const name = basename(file);\n return (\n sourceExtensions.has(extname(name)) ||\n name.startsWith('Dockerfile') ||\n name === 'Caddyfile' ||\n name.startsWith('.env')\n );\n}\n\nfunction groupedComments(comments: Comment[], source: string): Comment[] {\n const groups: Comment[] = [];\n for (const comment of comments) {\n const previous = groups.at(-1);\n if (\n comment.text.startsWith('//') &&\n previous?.text.startsWith('//') &&\n /^[\\t ]*\\r?\\n[\\t ]*$/.test(source.slice(previous.end, comment.offset))\n ) {\n previous.end = comment.end;\n previous.text += `\\n${comment.text}`;\n continue;\n }\n groups.push({ ...comment });\n }\n return groups;\n}\n\nfunction proseLineCount(text: string): number {\n return text\n .split(/\\r?\\n/)\n .map((line) =>\n line\n .replace(/^\\s*\\/\\/\\/?\\s?/, '')\n .replace(/^\\s*\\/\\*\\*?\\s?/, '')\n .replace(/^\\s*\\*\\/?\\s?/, '')\n .replace(/\\s*\\*\\/$/, '')\n .trim(),\n )\n .filter(Boolean).length;\n}\n\nfunction isRequiredHeader(text: string): boolean {\n return /\\b(?:copyright|licensed under|permission is hereby granted|the software is provided)\\b/i.test(text);\n}\n\n/** Whether a comment of more than three prose lines may sit directly above `statement`. */\nfunction isDeclaration(statement: ts.Node): boolean {\n return [\n ts.SyntaxKind.ClassDeclaration,\n ts.SyntaxKind.EnumDeclaration,\n ts.SyntaxKind.ExportAssignment,\n ts.SyntaxKind.ExportDeclaration,\n ts.SyntaxKind.FunctionDeclaration,\n ts.SyntaxKind.InterfaceDeclaration,\n ts.SyntaxKind.ModuleDeclaration,\n ts.SyntaxKind.TypeAliasDeclaration,\n ts.SyntaxKind.VariableStatement,\n ].includes(statement.kind);\n}\n\nfunction hasDirectDeclarationOwner(file: string, source: string, comment: Comment): boolean {\n if (!scriptExtensions.has(extname(file))) return false;\n\n const sourceFile = parseSource(file, source);\n const containingStatement = sourceFile.statements.find(\n (statement) => statement.getStart(sourceFile) < comment.offset && comment.end < statement.end,\n );\n if (containingStatement) return true;\n\n const nextStatement = sourceFile.statements.find((statement) => statement.getStart(sourceFile) >= comment.end);\n if (!nextStatement || !isDeclaration(nextStatement)) return false;\n\n const gap = source.slice(comment.end, nextStatement.getStart(sourceFile));\n return /^\\s*$/.test(gap) && !/\\r?\\n[\\t ]*\\r?\\n/.test(gap);\n}\n\n/** Rule findings in one source file, `text` rules over its whole text and the rest over its comments, and placement findings. */\nexport function commentFindings(file: string, source: string): Finding[] {\n if (!isSource(file)) return [];\n const comments = sourceComments(file, source);\n const findings: Finding[] = [\n ...textRules.flatMap((rule) => ruleFindings(rule, file, source, (index) => lineColumn(source, index))),\n ...comments.flatMap((comment) =>\n commentRules.flatMap((rule) =>\n ruleFindings(rule, file, comment.text, (index) => lineColumn(source, comment.offset + index)),\n ),\n ),\n ];\n\n for (const comment of groupedComments(comments, source)) {\n const lineCount = proseLineCount(comment.text);\n if (lineCount <= 3 || isRequiredHeader(comment.text) || hasDirectDeclarationOwner(file, source, comment)) continue;\n findings.push({\n file,\n ...lineColumn(source, comment.offset),\n rule: 'detached-long-comment',\n message: `${lineCount} prose lines; ${placementAdvice}`,\n });\n }\n return findings;\n}\n","import type { Finding } from './repo';\n\n/** A wording rule, read in every source comment. */\nexport interface ProseRule {\n /** The rule id each finding prints in brackets. */\n name: string;\n pattern: RegExp;\n /** The advice printed after the matched term. */\n message: string;\n /** Also read in Markdown and MDX prose. */\n docs?: boolean;\n /** Read in the whole text of a source file, strings and JSON values included, not only in its comments. */\n text?: boolean;\n /** Repo-relative paths the rule skips. */\n exclude?: RegExp;\n}\n\n/** Agent-associated wording, skipped in infra/ and in alignments, which address app maintainers. */\nconst agentWording = { docs: true, exclude: /^(?:cella\\/alignments\\/|infra\\/)/ } as const;\n\n/**\n * Files no prose rule reads, on top of a rule's own `exclude` and the app's `proseExclude`: in source, migrations,\n * the alignment folders and generated code; in docs, the changelogs release-please writes from commit messages.\n */\nexport function isProseExempt(file: string, kind: 'source' | 'doc'): boolean {\n if (kind === 'doc') return file.endsWith('CHANGELOG.md');\n return (\n ['backend/drizzle/', 'cella/alignments/', 'sdk/gen/'].some((prefix) => file.startsWith(prefix)) ||\n file.includes('.gen.')\n );\n}\n\n/** The rules the comment and doc checks apply; each gets its line in the README. */\nexport const proseRules: ProseRule[] = [\n {\n name: 'em-dash',\n pattern: /\\u2014/,\n message: 'split the sentence, use a colon, or drop the clause',\n docs: true,\n text: true,\n },\n {\n name: 'contrast-phrase',\n pattern: /\\b(?:instead|rather than|as opposed to)\\b/i,\n message: 'state the current behavior or local constraint directly',\n },\n {\n name: 'concrete-language',\n pattern: /\\binvariants?\\b/i,\n message: 'name the precise rule, constraint, guarantee, requirement, contract, precondition, or assumption',\n docs: true,\n },\n {\n name: 'change-history',\n pattern: /\\b(?:previously|formerly|used to|originally)\\b/i,\n message: 'move evolution history to the commit or an alignment',\n },\n {\n name: 'review-conversation',\n pattern: /\\b(?:maybe|perhaps|we (?:should|could|might)|(?:was|were) considered)\\b/i,\n message: 'resolve the question or track it outside the source comment',\n },\n {\n name: 'load-bearing',\n pattern: /\\bload(?:-| )bearing\\b/i,\n ...agentWording,\n message: 'name the dependency, requirement, or failure consequence directly',\n },\n {\n name: 'authoritative',\n pattern: /\\bauthoritative(?:ly)?\\b/i,\n ...agentWording,\n message: 'say who decides or which value counts: the backend decides, the stored row, the exact count',\n },\n];\n\n/** A finding for every match of `rule` in `text`; `locate` maps an index in `text` to its line and column in `file`. */\nexport function ruleFindings(\n rule: ProseRule,\n file: string,\n text: string,\n locate: (index: number) => { line: number; column: number },\n): Finding[] {\n if (rule.exclude?.test(file) || !rule.pattern.test(text)) return [];\n const pattern = new RegExp(rule.pattern.source, `${rule.pattern.flags}g`);\n return [...text.matchAll(pattern)].map((match) => ({\n file,\n ...locate(match.index),\n rule: rule.name,\n term: match[0],\n message: rule.message,\n }));\n}\n","import { extname } from 'node:path';\nimport { ts } from './repo';\n\n/** One comment of a source file, with its delimiters. */\nexport interface Comment {\n /** Offset of the comment's first character in the file. */\n offset: number;\n /** Offset just past its last character. */\n end: number;\n text: string;\n}\n\n/** Extensions of the script files, whose comments come from the TypeScript parse. */\nexport const scriptExtensions = new Set(['.cjs', '.js', '.jsx', '.mjs', '.ts', '.tsx']);\n\nlet lastParsed: ts.SourceFile | undefined;\n\n/** The TypeScript parse of a script file; the checks of one file share it. */\nexport function parseSource(file: string, source: string): ts.SourceFile {\n if (lastParsed?.fileName === file && lastParsed.text === source) return lastParsed;\n const kind = ['.tsx', '.jsx'].includes(extname(file)) ? ts.ScriptKind.TSX : ts.ScriptKind.TS;\n lastParsed = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, kind);\n return lastParsed;\n}\n\n/**\n * Comments at every token boundary, which reaches the ones after an opening bracket, in an empty JSX expression and\n * before a `.` that starts a line too: every comment trails a token on its line or leads the token after a line break.\n */\nfunction scriptComments(file: string, source: string): Comment[] {\n const sourceFile = parseSource(file, source);\n const comments = new Map<number, Comment>();\n const add = (ranges: readonly ts.CommentRange[] | undefined) => {\n for (const { pos, end } of ranges ?? []) comments.set(pos, { offset: pos, end, text: source.slice(pos, end) });\n };\n const visit = (node: ts.Node) => {\n if (ts.isJSDoc(node)) return;\n const children = node.getChildren(sourceFile);\n if (children.length === 0) {\n add(ts.getLeadingCommentRanges(source, node.pos));\n add(ts.getTrailingCommentRanges(source, node.end));\n }\n for (const child of children) visit(child);\n };\n visit(sourceFile);\n return [...comments.values()].sort((a, b) => a.offset - b.offset);\n}\n\nfunction jsoncComments(source: string): Comment[] {\n const comments: Comment[] = [];\n for (let i = 0; i < source.length; i++) {\n if (source[i] === '\"') {\n for (i++; i < source.length; i++) {\n if (source[i] === '\\\\') i++;\n else if (source[i] === '\"') break;\n }\n continue;\n }\n if (source[i] !== '/' || (source[i + 1] !== '/' && source[i + 1] !== '*')) continue;\n\n const start = i;\n if (source[++i] === '/') {\n while (i + 1 < source.length && source[i + 1] !== '\\n') i++;\n } else {\n while (i + 1 < source.length && !(source[i] === '*' && source[i + 1] === '/')) i++;\n if (i + 1 < source.length) i++;\n }\n comments.push({ offset: start, end: i + 1, text: source.slice(start, i + 1) });\n }\n return comments;\n}\n\n/** Index of the `#` that opens a comment on a YAML line, or -1; `#` inside a quoted scalar or a word is text. */\nfunction commentHash(line: string): number {\n let quote = '';\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n if (quote) {\n if (char === '\\\\' && quote === '\"') i++;\n else if (char === quote && quote === \"'\" && line[i + 1] === \"'\") i++;\n else if (char === quote) quote = '';\n } else if ((char === '\"' || char === \"'\") && /^$|[\\s[{,]$/.test(line.slice(0, i))) {\n quote = char;\n } else if (char === '#' && (i === 0 || line[i - 1] === ' ' || line[i - 1] === '\\t')) {\n return i;\n }\n }\n return -1;\n}\n\n/** Comments after a YAML value, outside block scalars, whose lines hold text in another language. */\nfunction yamlTrailingComments(source: string): Comment[] {\n const comments: Comment[] = [];\n let offset = 0;\n let blockIndent = -1;\n for (const line of source.split('\\n')) {\n const indent = line.length - line.trimStart().length;\n if (blockIndent < 0 || (line.trim() && indent <= blockIndent)) {\n const hash = commentHash(line);\n const value = hash < 0 ? line : line.slice(0, hash);\n if (hash >= 0 && value.trim()) {\n comments.push({ offset: offset + hash, end: offset + line.length, text: line.slice(hash) });\n }\n blockIndent = value.trim() && /(?:^|\\s)[|>][0-9+-]*\\s*$/.test(value) ? indent : -1;\n }\n offset += line.length + 1;\n }\n return comments;\n}\n\n/**\n * The comments of a source file: the TypeScript parse for scripts, a string-aware scanner for JSONC, block comments for\n * CSS and SCSS, block then line comments for SQL, and `#` lines for YAML (with the comments after a value, in document\n * order), Dockerfile, Caddyfile and env files. JSON has none.\n */\nexport function sourceComments(file: string, source: string): Comment[] {\n const extension = extname(file);\n if (scriptExtensions.has(extension)) return scriptComments(file, source);\n if (extension === '.jsonc') return jsoncComments(source);\n if (extension === '.json') return [];\n const patterns =\n extension === '.css' || extension === '.scss'\n ? [/\\/\\*[\\s\\S]*?\\*\\//g]\n : extension === '.sql'\n ? [/\\/\\*[\\s\\S]*?\\*\\//g, /--[^\\n]*/g]\n : [/^[\\t ]*#[^\\n]*/gm];\n const comments = patterns.flatMap((pattern) =>\n [...source.matchAll(pattern)].map((match) => ({\n offset: match.index,\n end: match.index + match[0].length,\n text: match[0],\n })),\n );\n if (extension !== '.yaml' && extension !== '.yml') return comments;\n return [...comments, ...yamlTrailingComments(source)].sort((a, b) => a.offset - b.offset);\n}\n","import { extname } from 'node:path';\nimport { isProseExempt, proseRules, ruleFindings } from './prose-rules';\nimport { blankOut, type Finding, lineColumn } from './repo';\n\nconst docExtensions = new Set(['.md', '.mdx']);\nconst docRules = proseRules.filter((rule) => rule.docs);\n\n/** Each line outside fenced code through `mask`; fences and fenced code blanked to spaces, so positions hold. */\nfunction outsideFences(source: string, mask: (line: string) => string): string {\n let inFence = false;\n return source\n .split('\\n')\n .map((line) => {\n if (/^\\s*(?:```|~~~)/.test(line)) inFence = !inFence;\n else if (!inFence) return mask(line);\n return blankOut(line);\n })\n .join('\\n');\n}\n\n/** The prose view: inline code, fenced code and link targets blanked to spaces, so positions hold. */\nfunction maskMarkdownCode(source: string): string {\n return outsideFences(source, (line) =>\n line.replace(/\\]\\([^)]+\\)/g, (match) => `]${blankOut(match.slice(1))}`).replace(/`[^`\\n]*`/g, blankOut),\n );\n}\n\n/** Inline code in a link label: the docs draw code as a chip that hides the link underline. Double-backtick spans show the pattern as an example. */\nfunction codeLinkFindings(file: string, source: string): Finding[] {\n const text = outsideFences(source, (line) => line.replace(/``.+?``/g, blankOut));\n return [...text.matchAll(/(?<!!)\\[[^[\\]\\n]*`[^`[\\]\\n]+`[^[\\]\\n]*\\](?=[([])/g)].map((match) => ({\n file,\n ...lineColumn(text, match.index),\n rule: 'code-in-link',\n term: match[0],\n message: 'drop the backticks inside the link label: the code chip hides the link underline',\n }));\n}\n\n/** Rule findings in the prose of one Markdown or MDX file, and inline code in its link labels. */\nexport function docFindings(file: string, source: string): Finding[] {\n if (!docExtensions.has(extname(file).toLowerCase()) || isProseExempt(file, 'doc')) return [];\n const prose = maskMarkdownCode(source);\n return [\n ...docRules.flatMap((rule) => ruleFindings(rule, file, prose, (index) => lineColumn(prose, index))),\n ...codeLinkFindings(file, source),\n ];\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { extname, join } from 'node:path';\nimport { type Finding, isFrontendSource, lineColumn, repoRoot, ts } from './repo';\nimport { parseSource } from './source-comments';\n\ntype Report = (node: ts.Node, rule: string, message: string) => void;\n\nfunction containsJsx(node: ts.Node): boolean {\n return (\n ts.isJsxElement(node) ||\n ts.isJsxFragment(node) ||\n ts.isJsxSelfClosingElement(node) ||\n !!ts.forEachChild(node, containsJsx)\n );\n}\n\n/** The import declarations of a file by module, each with the names it imports: `imported` as exported, `element` the binding. */\nfunction importsOf(sourceFile: ts.SourceFile) {\n return sourceFile.statements.filter(ts.isImportDeclaration).flatMap((declaration) => {\n if (!ts.isStringLiteral(declaration.moduleSpecifier)) return [];\n const bindings = declaration.importClause?.namedBindings;\n const elements = bindings && ts.isNamedImports(bindings) ? bindings.elements : [];\n const names = elements.map((element) => ({ imported: (element.propertyName ?? element.name).text, element }));\n return [{ module: declaration.moduleSpecifier.text, declaration, names }];\n });\n}\n\n/** A component is a named function declaration, and a helper such as `memo` wraps a function expression of its name. */\nfunction checkVariableStatement(sourceFile: ts.SourceFile, node: ts.VariableStatement, report: Report): void {\n if (extname(sourceFile.fileName) !== '.tsx') return;\n for (const declaration of node.declarationList.declarations) {\n const name = ts.isIdentifier(declaration.name) ? declaration.name.text : null;\n const initializer = declaration.initializer;\n if (!name || !/^[A-Z]/.test(name) || !initializer || !containsJsx(initializer)) continue;\n\n if (ts.isArrowFunction(initializer)) {\n report(\n declaration,\n 'component-declaration',\n `${name} is an ordinary component; use a named function declaration`,\n );\n continue;\n }\n\n if (!ts.isCallExpression(initializer)) continue;\n const wrappedRender = initializer.arguments.find(\n (argument): argument is ts.ArrowFunction | ts.FunctionExpression =>\n (ts.isArrowFunction(argument) || ts.isFunctionExpression(argument)) && containsJsx(argument),\n );\n if (!wrappedRender || (ts.isFunctionExpression(wrappedRender) && wrappedRender.name?.text === name)) continue;\n report(\n wrappedRender,\n 'component-declaration',\n `${name} is wrapped by a component helper; use a named function expression`,\n );\n }\n}\n\n/** Adds the stores `sourceFile` declares with zustand's `create` to `stores`. */\nfunction collectStores(sourceFile: ts.SourceFile, stores: Set<string>): void {\n const createNames = new Set(\n importsOf(sourceFile)\n .filter(({ module }) => module === 'zustand')\n .flatMap(({ names }) =>\n names.filter(({ imported }) => imported === 'create').map(({ element }) => element.name.text),\n ),\n );\n if (createNames.size === 0) return;\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n for (const declaration of statement.declarationList.declarations) {\n let callee: ts.Node | undefined = declaration.initializer;\n while (callee && ts.isCallExpression(callee)) callee = callee.expression;\n if (!callee || !ts.isIdentifier(callee) || !createNames.has(callee.text)) continue;\n if (ts.isIdentifier(declaration.name)) stores.add(declaration.name.text);\n }\n }\n}\n\n/** A store is read through a selector: called with no argument, it renders the component again on every field change. */\nfunction checkStoreSelector(node: ts.Node, stores: Set<string>, report: Report): void {\n if (!ts.isCallExpression(node) || node.arguments.length > 0 || !ts.isIdentifier(node.expression)) return;\n const name = node.expression.text;\n if (!stores.has(name)) return;\n report(node, 'store-selector', `${name}() subscribes to every field; select the values this component reads`);\n}\n\n/**\n * Route context is rebuilt on every navigation, search-only ones included, so a component that reads it whole renders\n * again on each one. `select` narrows the read to a value that stays equal between navigations.\n */\nfunction checkRouteContextSelector(sourceFile: ts.SourceFile, node: ts.Node, report: Report): void {\n if (!ts.isCallExpression(node)) return;\n const callee = node.expression;\n const name = ts.isPropertyAccessExpression(callee)\n ? callee.name.text\n : ts.isIdentifier(callee)\n ? callee.text\n : undefined;\n if (name !== 'useRouteContext') return;\n const [options] = node.arguments;\n // Options passed by name or spread have their `select` elsewhere\n if (options && (!ts.isObjectLiteralExpression(options) || options.properties.some(ts.isSpreadAssignment))) return;\n if (options?.properties.some((property) => property.name?.getText(sourceFile) === 'select')) return;\n report(\n node,\n 'route-context-selector',\n 'useRouteContext() renders again on every navigation; pass `select` and return the id or flag this component reads',\n );\n}\n\n/**\n * A Button's press nudge is a `transform` (`active:press`). `active:translate-y-0` sets `translate`, another property,\n * so it compiles and leaves the nudge in place; `press={false}` turns the nudge off.\n */\nfunction checkButtonPressCancel(sourceFile: ts.SourceFile, node: ts.Node, report: Report): void {\n if (!ts.isJsxOpeningElement(node) && !ts.isJsxSelfClosingElement(node)) return;\n if (node.tagName.getText(sourceFile) !== 'Button') return;\n for (const attribute of node.attributes.properties) {\n if (!ts.isJsxAttribute(attribute) || attribute.name.getText(sourceFile) !== 'className' || !attribute.initializer)\n continue;\n if (!/(?<![\\w-])!?active:translate-y-0!?(?![\\w-])/.test(attribute.initializer.getText(sourceFile))) continue;\n report(\n attribute,\n 'button-press-cancel',\n 'active:translate-y-0 does not cancel the press nudge, which is a transform; pass press={false} to the Button',\n );\n }\n}\n\n/**\n * A form react-hook-form validates shows why a field is refused under that field. Without `noValidate` the browser\n * refuses an email or web address first, in a bubble of its own and in the browser's language.\n */\nfunction checkFormNoValidate(sourceFile: ts.SourceFile, node: ts.Node, report: Report): void {\n if (\n (!ts.isJsxOpeningElement(node) && !ts.isJsxSelfClosingElement(node)) ||\n node.tagName.getText(sourceFile) !== 'form'\n )\n return;\n const attributes = node.attributes.properties.filter(ts.isJsxAttribute);\n const onSubmit = attributes.find((attribute) => attribute.name.getText(sourceFile) === 'onSubmit');\n if (!onSubmit?.initializer?.getText(sourceFile).includes('handleSubmit(')) return;\n if (attributes.some((attribute) => attribute.name.getText(sourceFile) === 'noValidate')) return;\n report(\n node,\n 'form-no-validate',\n 'a form react-hook-form validates takes noValidate, so its fields say what is wrong, not the browser',\n );\n}\n\n/**\n * A drag grip renders through `ReorderHandle` or `reorderColumn`, which give it the arrow keys and the move menu. A drag\n * preview (`*-preview.tsx`) only pictures the grip, and the editor's block handle moves blocks from its own menu.\n */\nfunction checkReorderGrip(file: string, sourceFile: ts.SourceFile, report: Report): void {\n if (file.endsWith('-preview.tsx') || file === 'frontend/src/modules/common/blocknote/custom-side-menu/side-menu.tsx')\n return;\n let grip: ts.Node | undefined;\n let hasHandle = false;\n for (const { module, names } of importsOf(sourceFile)) {\n for (const { imported, element } of names) {\n if (module === 'lucide-react' && /^Grip(?:Vertical|Horizontal)?Icon$/.test(imported)) grip = element;\n if (imported === 'ReorderHandle' || imported === 'reorderColumn') hasHandle = true;\n }\n }\n if (grip && !hasHandle) {\n report(\n grip,\n 'reorder-grip',\n 'render a drag grip through ReorderHandle or reorderColumn, so the keyboard and a pointer that cannot drag move it too',\n );\n }\n}\n\n/**\n * A memo whose dependency array names a value its callback never reads. The React Compiler memoizes on what the callback\n * reads, so that value stops triggering a recompute and the result goes stale; derive the result from the value itself.\n */\nfunction checkMemoDependencies(node: ts.Node, report: Report): void {\n if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression)) return;\n if (node.expression.text !== 'useMemo' && node.expression.text !== 'useCallback') return;\n const [callback, dependencies] = node.arguments;\n if (!callback || !dependencies || !ts.isArrayLiteralExpression(dependencies)) return;\n // A callback passed by name has its body elsewhere\n if (!ts.isArrowFunction(callback) && !ts.isFunctionExpression(callback)) return;\n\n const read = new Set<string>();\n callback.forEachChild(function collect(child) {\n if (ts.isIdentifier(child)) read.add(child.text);\n child.forEachChild(collect);\n });\n for (const dependency of dependencies.elements) {\n let root: ts.Expression = dependency;\n while (\n ts.isPropertyAccessExpression(root) ||\n ts.isElementAccessExpression(root) ||\n ts.isNonNullExpression(root) ||\n ts.isCallExpression(root)\n ) {\n root = root.expression;\n }\n if (!ts.isIdentifier(root) || read.has(root.text)) continue;\n report(\n dependency,\n 'memo-dependency-unread',\n `${root.text} is a dependency the callback never reads, so the compiled memo ignores it; read it or derive the result from it`,\n );\n }\n}\n\n/** The cache calls that clear a query's refetch mark, each with the helper in `~/query/basic/cache-mutations` that keeps it. */\nconst markKeepers: Record<string, string> = {\n setQueryData: 'writeKeepingMark',\n setQueriesData: 'writeKeepingMark',\n cancelQueries: 'cancelKeepingMark',\n};\n\n/** The calls in `sourceFile` that clear a refetch mark, and whether it registers a range fetch, which only a synced product does. */\nfunction markCalls(sourceFile: ts.SourceFile) {\n const calls: Array<{ node: ts.CallExpression; name: string }> = [];\n let registersRangeFetch = false;\n sourceFile.forEachChild(function visit(node) {\n if (ts.isCallExpression(node)) {\n const callee = node.expression;\n const name = ts.isPropertyAccessExpression(callee)\n ? callee.name.text\n : ts.isIdentifier(callee)\n ? callee.text\n : '';\n if (Object.hasOwn(markKeepers, name)) calls.push({ node, name });\n registersRangeFetch ||= name === 'registerEntityQueryKeys' && node.arguments.length > 2;\n }\n node.forEachChild(visit);\n });\n return { calls, registersRangeFetch };\n}\n\n/** Keyed by the `query.ts` path, absolute, so a process that checks two repositories reads each one's. */\nconst productModuleFolders = new Map<string, boolean>();\n\n/** Whether `file` lies in a module folder whose `query.ts` registers a range fetch. */\nfunction inProductModule(file: string): boolean {\n const folder = /^frontend\\/src\\/modules\\/[^/]+\\//.exec(file)?.[0];\n if (!folder) return false;\n const queryFile = join(repoRoot, `${folder}query.ts`);\n if (!productModuleFolders.has(queryFile)) {\n const source = existsSync(queryFile) ? readFileSync(queryFile, 'utf8') : '';\n productModuleFolders.set(\n queryFile,\n markCalls(ts.createSourceFile(queryFile, source, ts.ScriptTarget.Latest)).registersRangeFetch,\n );\n }\n return productModuleFolders.get(queryFile) === true;\n}\n\n/** Query code and the module of a synced product write and cancel through the helpers that keep a query's refetch mark. */\nfunction checkProductCacheWrite(file: string, sourceFile: ts.SourceFile, report: Report): void {\n if (file === 'frontend/src/query/basic/cache-mutations.ts') return;\n const { calls, registersRangeFetch } = markCalls(sourceFile);\n if (!calls.length || !(file.startsWith('frontend/src/query/') || registersRangeFetch || inProductModule(file)))\n return;\n for (const { node, name } of calls) {\n report(\n node,\n 'product-cache-write',\n `${name} clears the refetch mark; call ${markKeepers[name]} from ~/query/basic/cache-mutations`,\n );\n }\n}\n\n/** The zustand stores the frontend creates, read from every frontend file so a path-limited run still knows them. */\nexport function frontendStores(files: string[]): Set<string> {\n const stores = new Set<string>();\n for (const file of files.filter(isFrontendSource)) {\n const source = readFileSync(join(repoRoot, file), 'utf8');\n if (source.includes('zustand')) collectStores(parseSource(file, source), stores);\n }\n return stores;\n}\n\n/** Convention findings in one frontend file; `stores` comes from `frontendStores`. */\nexport function frontendFindings(file: string, source: string, stores: Set<string>): Finding[] {\n if (!isFrontendSource(file)) return [];\n const sourceFile = parseSource(file, source);\n const findings: Finding[] = [];\n const report: Report = (node, rule, message) =>\n findings.push({ file, ...lineColumn(source, node.getStart(sourceFile)), rule, message });\n\n for (const statement of sourceFile.statements) {\n if (ts.isVariableStatement(statement)) checkVariableStatement(sourceFile, statement, report);\n }\n checkReorderGrip(file, sourceFile, report);\n checkProductCacheWrite(file, sourceFile, report);\n sourceFile.forEachChild(function visit(node) {\n checkStoreSelector(node, stores, report);\n checkRouteContextSelector(sourceFile, node, report);\n checkButtonPressCancel(sourceFile, node, report);\n checkFormNoValidate(sourceFile, node, report);\n checkMemoDependencies(node, report);\n node.forEachChild(visit);\n });\n return findings;\n}\n","import { type Finding, lineColumn, ts } from './repo';\nimport { parseSource } from './source-comments';\n\n/** Backend sources outside the two helpers, tests and mock builders. */\nfunction isStampedSource(file: string): boolean {\n return (\n /^backend\\/src\\/.*\\.ts$/.test(file) &&\n !/(?:\\.test|-mocks)\\.ts$|\\/mocks\\//.test(file) &&\n !file.endsWith('/utils/iso-date.ts') &&\n !file.endsWith('/db/utils/stamps.ts')\n );\n}\n\nconst stampPairs = [\n ['updatedAt', 'updatedBy'],\n ['deletedAt', 'deletedBy'],\n] as const;\n\n/** A moment written by hand: the clock (`getIsoDate()`, `new Date`, sql`now()`) or a local holding one. */\nfunction isMoment(value: ts.Expression): boolean {\n if (ts.isIdentifier(value)) return value.text !== 'undefined';\n if (ts.isCallExpression(value) && ts.isIdentifier(value.expression) && value.expression.text === 'getIsoDate')\n return true;\n if (ts.isTaggedTemplateExpression(value))\n return value.tag.getText() === 'sql' && value.template.getText() === '`now()`';\n let root: ts.Expression = value;\n while (ts.isCallExpression(root) || ts.isPropertyAccessExpression(root)) root = root.expression;\n return ts.isNewExpression(root) && root.expression.getText() === 'Date';\n}\n\n/**\n * The pair in one object literal, in any order, shorthand included, with a moment for its time: a lone `updatedBy` in\n * an option bag, a column definition and a schema mask are no writes.\n */\nfunction stampPairFindings(file: string, source: string): Finding[] {\n if (!/\\b(?:updated|deleted)By\\b/.test(source)) return [];\n const sourceFile = parseSource(file, source);\n const findings: Finding[] = [];\n sourceFile.forEachChild(function visit(node) {\n if (ts.isObjectLiteralExpression(node)) {\n const values = new Map<string, ts.Expression>();\n for (const property of node.properties) {\n if (ts.isShorthandPropertyAssignment(property)) values.set(property.name.text, property.name);\n else if (\n ts.isPropertyAssignment(property) &&\n (ts.isIdentifier(property.name) || ts.isStringLiteral(property.name))\n ) {\n values.set(property.name.text, property.initializer);\n }\n }\n for (const [at, by] of stampPairs) {\n const moment = values.get(at);\n if (!moment || !values.has(by) || !isMoment(moment)) continue;\n findings.push({\n file,\n ...lineColumn(source, moment.parent.getStart(sourceFile)),\n rule: 'stamp-pair',\n term: `${at}, ${by}`,\n message: 'spread updateStamps(actorId) or deleteStamps(actorId) instead of writing the pair by hand',\n });\n }\n }\n node.forEachChild(visit);\n });\n return findings;\n}\n\n/** Stamp findings in one backend file: the clock read by hand, and a writer pair written by hand. */\nexport function stampFindings(file: string, source: string): Finding[] {\n if (!isStampedSource(file)) return [];\n const clock = [...source.matchAll(/new Date\\(\\)\\.toISOString\\(\\)/g)].map((match) => ({\n file,\n ...lineColumn(source, match.index),\n rule: 'stamp-clock',\n term: match[0],\n message: 'use getIsoDate() for the current moment',\n }));\n return [...clock, ...stampPairFindings(file, source)];\n}\n","import { readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, relative } from 'node:path';\nimport { importFromWorkspace } from '../../utils/app-facts';\nimport { splitToken, type Token } from './class-tokens';\nimport { type Finding, lineColumn, repoRoot, ts } from './repo';\nimport { parseSource } from './source-comments';\n\n/** Class names no frontend stylesheet, script or class string selects, each with the reason it stays. */\nconst markerClasses: Record<string, string> = {\n 'is-selected': 'BoardPanel state for apps whose board selects items (hasSelection), a hook for their styles',\n};\n\n/** Third-party class prefixes: the library's own stylesheet or DOM code reads them. */\nconst libraryPrefixes: Record<string, string> = {\n 'bn-': 'BlockNote editor parts',\n rdg: 'data grid rows, cells and states',\n};\n\n/** Calls whose arguments are class values; object keys are class names and object values conditions, as in clsx. */\nconst classFunctions = new Set(['clsx', 'cn', 'cx', 'tw', 'twJoin', 'twMerge']);\nconst classNamePattern =\n /^(?:class|classes|className|classNames|classList)$|[a-z](?:Class|Classes|Class[Nn]ames?|ClassList)$/;\nconst groupPattern = /^(?:group|peer)(?:\\/[\\w-]+)?$/;\nconst tailwindImport = /@import\\s+['\"]tailwindcss(?:\\/[\\w.-]+)?['\"]/;\n\ninterface DesignSystem {\n candidatesToCss(classes: string[]): (string | null)[];\n}\n\ninterface TailwindNode {\n __unstable__loadDesignSystem(css: string, options: { base: string }): Promise<DesignSystem>;\n}\n\n/** The loaded design system plus the class names that stylesheets, scripts and arbitrary selectors use. */\nexport interface TailwindContext {\n /** Repo-relative stylesheet that imports Tailwind. */\n entry: string;\n /** Absent when loading failed, as on an `@apply` of an unknown class; `loadError` then holds Tailwind's message. */\n designSystem?: DesignSystem;\n loadError?: string;\n /** Class names a stylesheet, script or arbitrary selector uses, and the marker classes. */\n knownClasses: Set<string>;\n /** Every candidate sent to Tailwind so far, and whether it compiled to CSS. */\n compiles: Map<string, boolean>;\n}\n\ntype Mode = 'class' | 'clsx';\n\n/** Text of one string or template piece in a class position; `open*` marks a side that touches a `${...}` placeholder. */\ninterface ClassText {\n /** Offset of `raw` in the source file. */\n start: number;\n /** The value, escapes resolved. */\n text: string;\n /** The source text of the value, which `start` locates. */\n raw: string;\n openStart: boolean;\n openEnd: boolean;\n}\n\nfunction isFrontendScript(file: string): boolean {\n return /^frontend\\/src\\/.*\\.tsx?$/.test(file) && !file.endsWith('.d.ts') && !file.includes('.gen.');\n}\n\nfunction isFrontendStylesheet(file: string): boolean {\n return /^frontend\\/src\\/.*\\.css$/.test(file);\n}\n\n/** Test files pass made-up class names to check prop forwarding and merging. */\nexport function isClassSource(file: string): boolean {\n return isFrontendScript(file) && !/\\.test\\.tsx?$/.test(file);\n}\n\n/** `@tailwindcss/node` from the frontend package, directly or through `@tailwindcss/vite`, which depends on it. */\nexport async function loadTailwindNode(): Promise<TailwindNode> {\n try {\n return await importFromWorkspace<TailwindNode>(repoRoot, 'frontend', '@tailwindcss/node');\n } catch {\n const plugin = createRequire(join(repoRoot, 'frontend/package.json')).resolve('@tailwindcss/vite');\n return importFromWorkspace<TailwindNode>(repoRoot, relative(repoRoot, dirname(plugin)), '@tailwindcss/node');\n }\n}\n\nfunction addMatches(target: Set<string>, text: string, pattern: RegExp): void {\n for (const match of text.matchAll(pattern)) target.add(match[1]);\n}\n\n/** Class names a stylesheet selects, a script queries or toggles, or an arbitrary selector such as `group-[.x]` names. */\nfunction usedClassNames(files: string[]): Set<string> {\n const names = new Set<string>();\n for (const file of files.filter(isFrontendStylesheet)) {\n const css = readFileSync(join(repoRoot, file), 'utf8').replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n addMatches(names, css, /(?<!\\\\)\\.(-?[_a-zA-Z][\\w-]*)/g);\n }\n for (const file of files.filter(isFrontendScript)) {\n const source = readFileSync(join(repoRoot, file), 'utf8');\n // Arbitrary selectors (`group-[.x]`, `[&_.x]`); a bracket after a name, `)`, `]` or `?.` indexes code.\n for (const [chunk] of source.matchAll(/(?<![\\w$)\\]?.])\\[[^\\s'\"`]*/g))\n addMatches(names, chunk, /(?<![a-zA-Z0-9$.)\\]?!])\\.(-?[_a-zA-Z][\\w-]*)/g);\n // Selector strings for querySelector, closest and the like.\n for (const [, , text] of source.matchAll(/(['\"`])((?:\\\\.|(?!\\1)[^\\\\\\n])*)\\1/g)) {\n if (/^[\\w\\s.#>+~,:()[\\]=\"*-]+$/.test(text)) addMatches(names, text, /(?:^|[\\s>+~,(])\\.(-?[_a-zA-Z][\\w-]*)/g);\n }\n for (const [, args] of source.matchAll(\n /(?:classList\\.(?:add|contains|remove|replace|toggle)|getElementsByClassName)\\(([^)]*)\\)/g,\n )) {\n for (const [, text] of args.matchAll(/['\"`]([^'\"`]+)['\"`]/g))\n for (const name of text.split(/\\s+/)) names.add(name);\n }\n }\n return names;\n}\n\n/** The design system from the frontend stylesheet that imports Tailwind; undefined in a repo without one. */\nexport async function tailwindContext(\n files: string[],\n appMarkerClasses: Record<string, string> = {},\n): Promise<TailwindContext | undefined> {\n const entry = files\n .filter(isFrontendStylesheet)\n .find((file) => tailwindImport.test(readFileSync(join(repoRoot, file), 'utf8')));\n if (!entry) return undefined;\n const path = join(repoRoot, entry);\n const knownClasses = usedClassNames(files);\n for (const name of Object.keys({ ...markerClasses, ...appMarkerClasses })) knownClasses.add(name);\n const context: TailwindContext = { entry, knownClasses, compiles: new Map() };\n try {\n context.designSystem = await (await loadTailwindNode()).__unstable__loadDesignSystem(readFileSync(path, 'utf8'), {\n base: dirname(path),\n });\n } catch (error) {\n context.loadError = error instanceof Error ? error.message : String(error);\n }\n return context;\n}\n\nfunction propertyName(name: ts.PropertyName | ts.BindingName | undefined): string | undefined {\n return name && (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isPrivateIdentifier(name))\n ? name.text\n : undefined;\n}\n\nfunction isClassNamed(...names: (string | undefined)[]): boolean {\n return names.some((name) => name !== undefined && classNamePattern.test(name));\n}\n\n/** Strings in class positions: class attributes, class helper calls, cva, `tw` templates and class-named values. */\nexport function classTexts(sourceFile: ts.SourceFile): ClassText[] {\n const texts: ClassText[] = [];\n const add = (node: ts.StringLiteralLike | ts.TemplateLiteralLikeNode, openStart = false, openEnd = false) => {\n const start = node.getStart(sourceFile) + 1;\n const end = node.end - (ts.isTemplateHead(node) || ts.isTemplateMiddle(node) ? 2 : 1);\n texts.push({ start, text: node.text, raw: sourceFile.text.slice(start, end), openStart, openEnd });\n };\n const addKey = (name: ts.Node) => {\n if (ts.isStringLiteral(name)) add(name);\n else if (ts.isIdentifier(name))\n texts.push({\n start: name.getStart(sourceFile),\n text: name.text,\n raw: name.text,\n openStart: false,\n openEnd: false,\n });\n else walk(name);\n };\n\n function collectTemplate(node: ts.TemplateExpression): void {\n add(node.head, false, true);\n let before = node.head.text;\n for (const [index, span] of node.templateSpans.entries()) {\n const last = index === node.templateSpans.length - 1;\n // A placeholder holds whole classes only when whitespace or the string edge separates it from the text around it.\n const leftClosed = /\\s$/.test(before) || (index === 0 && before === '');\n const rightClosed = /^\\s/.test(span.literal.text) || (last && span.literal.text === '');\n if (leftClosed && rightClosed) collect(span.expression, 'class');\n else walk(span.expression);\n add(span.literal, true, !last);\n before = span.literal.text;\n }\n }\n\n function collectObject(node: ts.ObjectLiteralExpression, mode: Mode): void {\n for (const property of node.properties) {\n if (mode === 'clsx' && (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property))) {\n addKey(property.name);\n if (ts.isPropertyAssignment(property)) walk(property.initializer);\n } else if (ts.isPropertyAssignment(property)) {\n walk(property.name);\n collect(property.initializer, 'class');\n } else walk(property);\n }\n }\n\n function collectCva(node: ts.CallExpression): void {\n const [base, config, ...rest] = node.arguments;\n collect(base, 'class');\n for (const argument of rest) walk(argument);\n if (!config || !ts.isObjectLiteralExpression(config)) {\n walk(config);\n return;\n }\n for (const property of config.properties) {\n if (\n !ts.isPropertyAssignment(property) ||\n propertyName(property.name) !== 'variants' ||\n !ts.isObjectLiteralExpression(property.initializer)\n ) {\n walk(property);\n continue;\n }\n for (const variant of property.initializer.properties) {\n if (ts.isPropertyAssignment(variant) && ts.isObjectLiteralExpression(variant.initializer))\n collectObject(variant.initializer, 'class');\n else walk(variant);\n }\n }\n }\n\n function calleeName(node: ts.CallExpression): string | undefined {\n const callee = node.expression;\n return ts.isIdentifier(callee) ? callee.text : ts.isPropertyAccessExpression(callee) ? callee.name.text : undefined;\n }\n\n /** Whether `node` starts a class position, collecting it when it does. */\n function collectCall(node: ts.CallExpression, mode?: Mode): boolean {\n const name = calleeName(node);\n if (name === 'cva') collectCva(node);\n else if (name && classFunctions.has(name)) {\n walk(node.expression);\n for (const argument of node.arguments) collect(argument, 'clsx');\n } else if (mode && (name === 'join' || name === 'filter') && ts.isPropertyAccessExpression(node.expression)) {\n collect(node.expression.expression, mode);\n for (const argument of node.arguments) walk(argument);\n } else return false;\n return true;\n }\n\n function collectReturns(node: ts.FunctionLikeDeclaration, mode: Mode): void {\n for (const parameter of node.parameters) walk(parameter);\n if (node.body && !ts.isBlock(node.body)) collect(node.body, mode);\n else walk(node.body, mode);\n }\n\n function collect(node: ts.Node | undefined, mode: Mode): void {\n if (!node) return;\n if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) add(node);\n else if (ts.isTemplateExpression(node)) collectTemplate(node);\n else if (\n ts.isParenthesizedExpression(node) ||\n ts.isAsExpression(node) ||\n ts.isSatisfiesExpression(node) ||\n ts.isNonNullExpression(node) ||\n ts.isSpreadElement(node) ||\n ts.isJsxExpression(node)\n )\n collect(node.expression, mode);\n else if (ts.isConditionalExpression(node)) {\n walk(node.condition);\n collect(node.whenTrue, mode);\n collect(node.whenFalse, mode);\n } else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {\n walk(node.left);\n collect(node.right, mode);\n } else if (\n ts.isBinaryExpression(node) &&\n [ts.SyntaxKind.BarBarToken, ts.SyntaxKind.QuestionQuestionToken].includes(node.operatorToken.kind)\n ) {\n collect(node.left, mode);\n collect(node.right, mode);\n } else if (ts.isArrayLiteralExpression(node)) {\n for (const element of node.elements) collect(element, mode);\n } else if (ts.isObjectLiteralExpression(node)) collectObject(node, mode);\n else if (ts.isElementAccessExpression(node)) {\n collect(node.expression, mode);\n walk(node.argumentExpression);\n } else if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) collectReturns(node, mode);\n else if (!ts.isCallExpression(node) || !collectCall(node, mode)) walk(node);\n }\n\n /** Collects `node` when it starts a class position; `returns` is set inside a class-named function. */\n function collectStart(node: ts.Node, returns?: Mode): boolean {\n if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name) && isClassNamed(node.name.text))\n collect(node.initializer, 'class');\n else if (ts.isCallExpression(node)) return collectCall(node);\n else if (ts.isTaggedTemplateExpression(node) && ts.isIdentifier(node.tag) && node.tag.text === 'tw')\n collect(node.template, 'class');\n else if (ts.isReturnStatement(node) && returns) collect(node.expression, returns);\n // Storybook argTypes describe controls (`className: { control: 'text' }`), never classes.\n else if (ts.isPropertyAssignment(node) && propertyName(node.name) === 'argTypes') return true;\n else if (\n (ts.isVariableDeclaration(node) ||\n ts.isPropertyAssignment(node) ||\n ts.isPropertyDeclaration(node) ||\n ts.isParameter(node)) &&\n node.initializer &&\n isClassNamed(propertyName(node.name))\n ) {\n walk(node.name);\n collect(node.initializer, 'class');\n } else if (\n ts.isBindingElement(node) &&\n node.initializer &&\n isClassNamed(propertyName(node.name), propertyName(node.propertyName))\n ) {\n collect(node.initializer, 'class');\n } else if (\n (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) &&\n isClassNamed(propertyName(node.name))\n ) {\n collectReturns(node, 'class');\n } else return false;\n return true;\n }\n\n /** Visits `node` and its children looking for class positions. */\n function walk(node: ts.Node | undefined, returns?: Mode): void {\n if (!node || ts.isTypeNode(node) || collectStart(node, returns)) return;\n const inner = ts.isFunctionLike(node) ? undefined : returns;\n ts.forEachChild(node, (child) => walk(child, inner));\n }\n\n walk(sourceFile);\n return texts;\n}\n\n/** Whole tokens of `text` with their offsets; a token touching an open side is part of a dynamic class and skipped. */\nexport function classTokens({ start, text, raw, openStart, openEnd }: ClassText): Token[] {\n const result: Token[] = [];\n for (const match of text.matchAll(/\\S+/g)) {\n const end = match.index + match[0].length;\n if ((openStart && match.index === 0) || (openEnd && end === text.length)) continue;\n result.push({ token: match[0], offset: start + (raw === text ? match.index : Math.max(0, raw.indexOf(match[0]))) });\n }\n return result;\n}\n\n/** Compiles the candidates `context.compiles` does not hold yet, in one call, and records each result there. */\nfunction compileCandidates(context: TailwindContext, designSystem: DesignSystem, candidates: string[]): void {\n const unknown = [...new Set(candidates)].filter((candidate) => !context.compiles.has(candidate));\n const css = designSystem.candidatesToCss(unknown);\n for (const [index, candidate] of unknown.entries()) context.compiles.set(candidate, css[index] !== null);\n}\n\n/** Why `token` produces nothing, or undefined when Tailwind compiles it or it is a known non-Tailwind class. */\nfunction problem(context: TailwindContext, token: string): string | undefined {\n if (context.compiles.get(token) || groupPattern.test(token) || context.knownClasses.has(token)) return undefined;\n if (Object.keys(libraryPrefixes).some((prefix) => token.startsWith(prefix))) return undefined;\n const { base } = splitToken(token);\n if (base !== token && (context.knownClasses.has(base) || groupPattern.test(base))) {\n return `${base} is a plain CSS class, so variants and ! do not apply to it; define it with @utility`;\n }\n return 'Tailwind compiles no CSS for it and no stylesheet or script selects it; fix the name, or list it under markerClasses in shared/config/vocabulary-allowlist.ts';\n}\n\n/**\n * Class names in one frontend file that compile to no CSS; `context` comes from `tailwindContext`. Tailwind itself\n * rejects an `@apply` of an unknown class while loading, which this reports on the entry stylesheet.\n */\nexport function tailwindFindings(file: string, source: string, context: TailwindContext | undefined): Finding[] {\n if (!context) return [];\n const { designSystem, loadError } = context;\n if (!designSystem)\n return file === context.entry\n ? [{ file, rule: 'tailwind-class', message: `Tailwind cannot load this stylesheet: ${loadError}` }]\n : [];\n if (!isClassSource(file)) return [];\n const sourceFile = parseSource(file, source);\n const found = classTexts(sourceFile).flatMap(classTokens);\n compileCandidates(\n context,\n designSystem,\n found.map(({ token }) => token),\n );\n return found.flatMap(({ token, offset }) => {\n const message = problem(context, token);\n if (!message) return [];\n return [{ file, ...lineColumn(source, offset), rule: 'tailwind-class', term: token, message }];\n });\n}\n","import { ts } from './repo';\n\n/** A whitespace-separated token of a string and its offset in the source file. */\nexport type Token = { token: string; offset: number };\n\n/**\n * The variants and the utility of a class token, without the important marker: `md:hover:x!` gives `['md', 'hover']`\n * and `x`. A `:` inside `[]` or `()` belongs to an arbitrary value or variant, as in `has-[a:hover]:x` or `text-[length:1em]`.\n */\nexport function splitToken(token: string): { variants: string[]; base: string } {\n const text = token.replace(/^!|!$/g, '');\n const variants: string[] = [];\n let depth = 0;\n let start = 0;\n for (let index = 0; index < text.length; index++) {\n const char = text[index];\n if (char === '[' || char === '(') depth++;\n else if (char === ']' || char === ')') depth--;\n else if (char === ':' && depth === 0) {\n variants.push(text.slice(start, index));\n start = index + 1;\n }\n }\n return { variants, base: text.slice(start).replace(/^!/, '') };\n}\n\n/** Whitespace-separated tokens of every string and template piece in `node` and under it, with their source offsets. */\nexport function stringTokens(sourceFile: ts.SourceFile, node: ts.Node): Token[] {\n const found: Token[] = [];\n (function visit(child: ts.Node) {\n if (\n ts.isStringLiteralLike(child) ||\n ts.isTemplateHead(child) ||\n ts.isTemplateMiddle(child) ||\n ts.isTemplateTail(child)\n ) {\n const start = child.getStart(sourceFile) + 1;\n for (const match of child.text.matchAll(/\\S+/g)) found.push({ token: match[0], offset: start + match.index });\n }\n child.forEachChild(visit);\n })(node);\n return found;\n}\n","import { splitToken, stringTokens } from './class-tokens';\nimport { type Finding, isFrontendSource, lineColumn } from './repo';\nimport { parseSource } from './source-comments';\n\n/** Paths that keep palette grays, each with its reason. */\nconst paletteExceptions: Record<string, string> = {\n 'frontend/src/modules/docs/': 'syntax, HTTP method and status colors, which carry meaning the theme steps do not',\n 'frontend/src/modules/common/json-viewer/theme.ts': 'syntax colors of the JSON viewer',\n 'frontend/src/modules/marketing/about/hero-stack.tsx':\n 'syntax colors of the code on the hero phone, an editor that stays dark in both modes',\n};\n\nconst tokenModifier = /^text-[a-z-]*foreground(?:-soft)?\\/[\\w.[\\]]+$/;\nconst paletteGray = /^text-(?:gray|slate|zinc|neutral|stone)-\\d+(?:\\/[\\w.[\\]]+)?$/;\n\n/** Text color findings in one frontend file: a modified text token, or a palette gray outside the excepted paths. */\nexport function textColorFindings(file: string, source: string): Finding[] {\n if (!isFrontendSource(file) || !/text-/.test(source)) return [];\n const sourceFile = parseSource(file, source);\n const findings = new Map<number, Finding>();\n const report = (offset: number, term: string, message: string) => {\n findings.set(offset, { file, ...lineColumn(source, offset), rule: 'text-color', term, message });\n };\n const paletteAllowed = Object.keys(paletteExceptions).some((path) => file.startsWith(path));\n\n for (const { token, offset } of stringTokens(sourceFile, sourceFile)) {\n const { variants, base } = splitToken(token);\n if (tokenModifier.test(base) && !variants.some((variant) => variant.includes('disabled'))) {\n report(\n offset,\n token,\n 'a text token takes no opacity modifier; pick the step: text-foreground-soft, text-muted-foreground or text-faint-foreground',\n );\n } else if (paletteGray.test(base) && !paletteAllowed) {\n report(\n offset,\n token,\n 'a palette gray skips the theme and the contrast setting; use a text step such as text-muted-foreground',\n );\n }\n }\n return [...findings.values()];\n}\n","import { type Finding, lineColumn } from './repo';\n\nconst themeFile = 'frontend/src/styling/tailwind.css';\n\n/** Fills that carry their `-foreground` text. */\nconst fills = [\n 'background',\n 'card',\n 'popover',\n 'primary',\n 'secondary',\n 'muted',\n 'accent',\n 'destructive',\n 'success',\n 'warning',\n 'brand',\n];\n/** Tokens also used as text on the page and on a card. */\nconst textTokens = ['destructive', 'success', 'warning'];\n/** The page and card fills that status text and a raised control edge sit on. */\nconst pageFills = ['background', 'card'];\n/** A hint can sit on a highlighted row, the lowest-contrast fill text meets. */\nconst hintFill = 'muted';\n\ntype Oklch = [lightness: number, chroma: number, hue: number];\n/** A declaration holds a color or names another token (`var(--foreground)`), which the mode resolves. */\ntype Declaration = { value?: Oklch; alias?: string; offset: number };\n\n/** `--name: oklch(L C H)` and `--name: var(--other)` declarations of the first `selector` block in the theme layer that declares `--background`. */\nfunction themeDeclarations(source: string, selector: string): Map<string, Declaration> {\n const found = new Map<string, Declaration>();\n const blockAt = (start: number) => source.slice(start, source.indexOf('\\n }', start));\n const opening = new RegExp(`^\\\\s*${selector.replace('.', '\\\\.')}\\\\s*\\\\{`, 'gm');\n const start = [...source.matchAll(opening)]\n .map(({ index }) => index)\n .find((index) => blockAt(index).includes('--background:'));\n if (start === undefined) return found;\n const block = blockAt(start);\n for (const match of block.matchAll(\n /--([a-z-]+):\\s*(?:oklch\\(([\\d.]+)%?\\s+([\\d.]+)\\s+([\\d.]+)\\)|var\\(--([a-z-]+)\\))/g,\n )) {\n const offset = start + (match.index ?? 0);\n if (match[5]) {\n found.set(match[1], { alias: match[5], offset });\n continue;\n }\n const lightness = Number(match[2]);\n found.set(match[1], {\n value: [lightness > 1 ? lightness / 100 : lightness, Number(match[3]), Number(match[4])],\n offset,\n });\n }\n return found;\n}\n\n/** The color a token holds in one mode, following aliases; undefined for a token the mode never gives a color. */\nfunction resolve(set: Map<string, Declaration>, name: string, seen = new Set<string>()): Oklch | undefined {\n const declaration = set.get(name);\n if (!declaration?.alias) return declaration?.value;\n if (seen.has(name)) return undefined;\n return resolve(set, declaration.alias, seen.add(name));\n}\n\n/** Relative luminance of an oklch color, clipped to sRGB. */\nfunction luminance([lightness, chroma, hue]: Oklch): number {\n const angle = (hue * Math.PI) / 180;\n const a = chroma * Math.cos(angle);\n const b = chroma * Math.sin(angle);\n const l = (lightness + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m = (lightness - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s = (lightness - 0.0894841775 * a - 1.291485548 * b) ** 3;\n const [red, green, blue] = [\n 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n ].map((value) => Math.min(1, Math.max(0, value)));\n return 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n}\n\n/** WCAG contrast ratio of two colors, from 1 to 21. */\nfunction ratio(one: Oklch, other: Oklch): number {\n const [x, y] = [luminance(one), luminance(other)];\n return (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05);\n}\n\n/** Findings for token pairs below their ratio. A token the dark block leaves out keeps its light value there. */\nexport function tokenContrastFindings(file: string, source: string): Finding[] {\n if (file !== themeFile) return [];\n const light = themeDeclarations(source, ':root');\n if (light.size === 0)\n return [{ file, rule: 'token-contrast', message: 'no :root block declares --background, so no token is measured' }];\n const dark = new Map([...light, ...themeDeclarations(source, '.dark')]);\n const findings: Finding[] = [];\n\n for (const [mode, set] of [\n ['light', light],\n ['dark', dark],\n ] as const) {\n const check = (text: string, behind: string, needed: number, what: string) => {\n const [front, back] = [resolve(set, text), resolve(set, behind)];\n if (!front || !back) return;\n const measured = ratio(front, back);\n if (measured >= needed) return;\n findings.push({\n file,\n ...lineColumn(source, set.get(text)?.offset ?? 0),\n rule: 'token-contrast',\n term: `--${text}`,\n message: `${what} is ${measured.toFixed(2)}:1 in ${mode} mode, below ${needed}:1 (--${text} on --${behind})`,\n });\n };\n for (const fill of fills)\n check(fill === 'background' ? 'foreground' : `${fill}-foreground`, fill, 4.5, 'text on its fill');\n for (const token of textTokens)\n for (const pageFill of pageFills) check(token, pageFill, 4.5, 'status color as text');\n check('faint-foreground', hintFill, 4.5, 'hint text on a highlighted row');\n // The tooltip (ui/tooltip.tsx) borrows the support text color as its fill\n check('primary-foreground', 'muted-foreground', 4.5, 'tooltip text on its fill');\n for (const pageFill of pageFills) check('edge-raised', pageFill, 3, 'raised control edge');\n\n // A theme that drops the token has nothing to measure, which would pass every check above in silence\n const anchor = set.get('background');\n if (anchor && !set.get('edge-raised')) {\n findings.push({\n file,\n ...lineColumn(source, anchor.offset),\n rule: 'token-contrast',\n term: '--edge-raised',\n message: `no --edge-raised in ${mode} mode: increased contrast has no value to paint, and the 3:1 edge goes unchecked`,\n });\n }\n }\n return findings;\n}\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { blankOut, type Finding, lineColumn, repoRoot } from './repo';\n\nconst disallowedTerm = /fork/gi;\n/** The product name as an identifier or wire string; prose may still contrast the template with the app. */\nconst productNameInLogic = /cella_[a-z0-9]|\\bCella[A-Z]|cellajs\\.com|_cella-/g;\n/** Logic roots the product-name rule covers; tests, config, docs and the marketing site are the template's own voice. */\nconst logicRoots = ['backend/src/', 'shared/src/', 'frontend/src/'];\nconst productNameAllowlist: VocabularyAllowlist = {\n files: [],\n prefixes: ['frontend/src/modules/marketing/', 'frontend/src/content/'],\n};\n/**\n * The app-side marker the cella-upgrade skill puts on intentional app edits: `// fork: <why>`, the css/md forms and a\n * ` * fork: <why>` line inside a JSDoc block. YAML has a `# fork: <why>` line, which elsewhere could be a private field.\n */\nconst markerComment =\n /\\/\\/[ \\t]*fork:[^\\n]*|\\/\\*[ \\t]*fork:[\\s\\S]*?\\*\\/|<!--[ \\t]*fork:[\\s\\S]*?-->|^[ \\t]*\\*[ \\t]*fork:[^\\n]*/gim;\n/** The YAML marker: a comment starts a line or follows whitespace, and a `#` inside a value is text. */\nconst yamlMarkerComment = /(^|[ \\t])#[ \\t]*fork:[^\\n]*/gim;\nconst sourceControlAdvice = 'use template/app terminology';\nconst productNameAdvice =\n 'derive it from appConfig or use a neutral name; the product name is not an identifier or wire string';\n\n/** What an app's `shared/config/vocabulary-allowlist.ts` exempts: files and path prefixes (repo-root relative) that may carry the term. */\nexport interface VocabularyAllowlist {\n files: string[];\n prefixes: string[];\n /** Path prefixes the comment and doc checks skip, such as reference code the app keeps but does not maintain. */\n proseExclude?: string[];\n /** Class names the app keeps as hooks with no Tailwind utility or stylesheet rule behind them, each with its reason. */\n markerClasses?: Record<string, string>;\n}\n\nconst templateAllowlist: VocabularyAllowlist = {\n files: [\n // release-please copies merged commit titles verbatim, so a title with the CLI's term must not fail the release PR\n 'CHANGELOG.md',\n 'cella/CHANGELOG.md',\n 'cella/cella.config.ts',\n // The cella-upgrade skill documents the CLI's upgrade workflow and the app-side marker, both in the CLI's term; it\n // stays byte-identical with the apps' copies, so `pnpm cella upgrade` reports it as identical\n 'cella/skills/cella-upgrade/SKILL.md',\n ],\n // Alignment READMEs address app maintainers pulling template changes, whom the CLI's term describes precisely\n prefixes: ['cella/alignments/'],\n};\n\n/** Relative to the repo root; `shared/config` never merges, so the file is the app's to fill. */\nconst appAllowlistPath = 'shared/config/vocabulary-allowlist.ts';\n\nfunction isAllowed(file: string, allowlist: VocabularyAllowlist): boolean {\n return allowlist.files.includes(file) || allowlist.prefixes.some((prefix) => file.startsWith(prefix));\n}\n\n/** The CLI's source-control term in a file's path and text, outside the fork markers and the allowlisted files. */\nexport function vocabularyFindings(\n file: string,\n source: string,\n allowlist: VocabularyAllowlist = templateAllowlist,\n): Finding[] {\n if (isAllowed(file, allowlist)) return [];\n\n const finding = (term: string) => ({ file, rule: 'source-control-term', term, message: sourceControlAdvice });\n const markers = source.replace(markerComment, blankOut);\n const scanned = /\\.ya?ml$/.test(file) ? markers.replace(yamlMarkerComment, blankOut) : markers;\n return [\n ...[...file.matchAll(disallowedTerm)].map((match) => finding(match[0])),\n ...[...scanned.matchAll(disallowedTerm)].map((match) => ({\n ...finding(match[0]),\n ...lineColumn(scanned, match.index),\n })),\n ];\n}\n\n/** An identifier, claim or URL carrying the product name: an app derives such names from `appConfig` or picks a neutral one. */\nexport function productNameFindings(file: string, source: string): Finding[] {\n const inLogic = logicRoots.some((root) => file.startsWith(root)) && !/\\.test\\.tsx?$/.test(file);\n if (!inLogic || isAllowed(file, productNameAllowlist)) return [];\n return [...source.matchAll(productNameInLogic)].map((match) => ({\n file,\n ...lineColumn(source, match.index),\n rule: 'product-name',\n term: match[0],\n message: productNameAdvice,\n }));\n}\n\n/** Template allowlist merged with the app's, when the app-owned file exists. */\nexport async function loadAllowlist(root = repoRoot): Promise<VocabularyAllowlist> {\n const path = join(root, appAllowlistPath);\n if (!existsSync(path)) return templateAllowlist;\n\n const module: { vocabularyAllowlist?: Partial<VocabularyAllowlist> } = await import(pathToFileURL(path).href);\n const app = module.vocabularyAllowlist ?? {};\n return {\n files: [...templateAllowlist.files, ...(app.files ?? [])],\n prefixes: [...templateAllowlist.prefixes, ...(app.prefixes ?? [])],\n proseExclude: app.proseExclude ?? [],\n markerClasses: app.markerClasses ?? {},\n };\n}\n","import type { ToolCommand } from '../config/types';\nimport { a11yCommand } from './a11y';\nimport { benchCommand } from './bench/command';\nimport { i18nCommand } from './i18n';\nimport { pentestCommand } from './pentest';\nimport { screenshotsCommand } from './screenshots';\nimport { styleCommand } from './style';\nimport { testbedCommand } from './testbed';\n\n/** The develop, security and gate commands, in menu and help order. */\nexport const toolCommands: ToolCommand[] = [\n testbedCommand,\n benchCommand,\n a11yCommand,\n screenshotsCommand,\n i18nCommand,\n pentestCommand,\n styleCommand,\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, git, listChangedSinceRef, revParse } from './git';\nimport { CONFIG_FILE, isGeneratedFile, isManagedFile } from './managed-files';\nimport { parseOverrideLists } from './upstream-overrides';\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 // A pin upstream's own config lists is a file the template leaves to the app: identical until the app fills it in.\n const upstreamSource = await git(['show', `${upstream}:${CONFIG_FILE}`], forkPath, { ignoreErrors: true });\n const upstreamPins = (upstreamSource && parseOverrideLists(upstreamSource)?.pinned.map(normalizeEntry)) || [];\n for (const entry of pinsUpstreamHas) {\n if (differs.some((changed) => isUnderAnyFolder(changed, [entry]))) continue;\n if (upstreamPins.includes(normalizeEntry(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 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 * 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 * 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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\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), and what pnpm audit\n * reports before the prompt that the security pass waits for.\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 { checkMark, 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 { type Advisory, 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 advisories = auditResult ? advisoriesFromAudit(auditResult) : null;\n const rows = [\n ...packageRows(outdated as Record<string, OutdatedPackage>, advisories ?? []),\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 printReported(advisories);\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 most severe advisory on a package; null when it has none. */\nconst worstSeverity = (advisories: Advisory[], name: string) =>\n SEVERITIES.find((severity) => advisories.some((a) => a.module === name && a.severity === severity)) ?? null;\n\n/** The outdated packages as table rows, sorted by the workspaces that depend on them. */\nfunction packageRows(outdated: Record<string, OutdatedPackage>, advisories: Advisory[]) {\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: worstSeverity(advisories, 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/**\n * What pnpm audit reports on the workspace as it stands, most severe first. A transitive package has\n * no row in the table, and a cancelled prompt never reaches the security pass.\n */\nfunction printReported(advisories: Advisory[] | null): void {\n if (!advisories) {\n console.info(`${warningMark} pnpm audit gave no answer: a row in the table can lack its dot`);\n console.info();\n return;\n }\n if (advisories.length === 0) {\n console.info(`${checkMark} pnpm audit reports nothing ${pc.dim('· with the current overrides and ignores')}`);\n console.info();\n return;\n }\n\n const modules = [...new Set(advisories.map((a) => a.module))].map((name) => {\n const own = advisories.filter((a) => a.module === name);\n return {\n name,\n severity: worstSeverity(own, name) ?? own[0].severity,\n installed: [...new Set(own.flatMap((a) => a.installed))].join(', '),\n via: formatDependents([...new Set(own.flatMap((a) => a.via))]),\n direct: own.some((a) => a.direct),\n };\n });\n modules.sort((a, b) => SEVERITIES.indexOf(a.severity) - SEVERITIES.indexOf(b.severity));\n const nameWidth = Math.min(30, Math.max(...modules.map((m) => m.name.length)));\n const versionWidth = Math.max(...modules.map((m) => m.installed.length));\n\n console.info(`${pc.bold('pnpm audit')} ${pc.dim('· with the current overrides and ignores')}`);\n for (const m of modules) {\n const name = pc.white(middleTruncate(m.name, nameWidth).padEnd(nameWidth));\n const source = `${m.via}${m.direct ? ' (direct)' : ''}`;\n console.info(\n `${getVulnIcon(m.severity)} ${name} ${m.severity.padEnd(8)} ${m.installed.padEnd(versionWidth)} ${pc.dim(source)}`,\n );\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 * 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","parsed","require","flag","spawnSync","existsSync","process","process","existsSync","spawnSync","resolve","spawnSync","existsSync","readFileSync","join","process","process","process","text","resolve","process","existsSync","mkdir","dirname","join","resolve","dirname","join","parsed","text","existsSync","resolve","dirname","join","mkdir","fn","process","columns","text","seconds","count","process","text","resolve","columns","row","files","byPath","count","pluralForm","list","process","join","existsSync","readFileSync","process","spawnSync","testbed","mkdirSync","writeFileSync","join","process","existsSync","join","pathToFileURL","z","z","pathToFileURL","join","baseSchema","appSchema","existsSync","add","z","z","z","appConfigSchema","z","parsed","resolve","spawnSync","findings","criteria","existsSync","readFileSync","writeFileSync","join","readFileSync","join","existsSync","row","writeFileSync","readFileSync","join","readFileSync","join","findings","shot","ratio","text","luminance","resolve","input","findings","mkdirSync","rmSync","writeFileSync","join","join","mkdirSync","writeFileSync","rmSync","text","controls","resolve","x","y","pad","clip","count","list","findings","reachable","text","findings","record","findings","scan","hint","join","findings","mkdirSync","axe","writeFileSync","skipped","count","row","readFileSync","resolve","input","readFileSync","resolve","count","row","spawnSync","mkdirSync","writeFileSync","dirname","join","text","spawnSync","files","join","row","mkdirSync","writeFileSync","dirname","count","existsSync","join","existsSync","join","process","spawnSync","existsSync","readFileSync","writeFileSync","join","existsSync","readdirSync","readFileSync","writeFileSync","join","text","parsed","files","language","name","execFileSync","readFileSync","statSync","dirname","join","execFileSync","ts","call","dirname","join","files","parsed","text","statSync","readFileSync","lineOf","language","join","existsSync","text","readFileSync","writeFileSync","files","spawnSync","ts","count","text","language","count","text","language","files","count","row","cell","existsSync","basename","join","existsSync","dirname","resolve","dirname","resolve","existsSync","existsSync","readFileSync","join","resolve","z","z","z","existsSync","basename","join","call","readFileSync","join","pad","existsSync","resolve","z","basename","existsSync","join","files","ts","LIST_MAX","jobs","process","existsSync","readFileSync","join","z","z","baseSchema","appSchema","z","operationSchema","sleep","resolve","existsSync","mkdirSync","readdirSync","readFileSync","rmSync","writeFileSync","join","join","mkdirSync","readdirSync","rmSync","writeFileSync","existsSync","readFileSync","findings","count","outcome","spawn","spawnSync","chmodSync","closeSync","existsSync","mkdirSync","openSync","readdirSync","readFileSync","rmSync","writeFileSync","join","process","z","mkdirSync","chmodSync","process","openSync","spawn","spawnSync","closeSync","findings","z","join","writeFileSync","readdirSync","rmSync","existsSync","readFileSync","parsed","text","spawnSync","row","parsed","z","loadAdapter","existsSync","join","baseSchema","appSchema","readFileSync","report","spawnSync","mkdirSync","readFileSync","rmSync","statSync","writeFileSync","basename","dirname","join","resolve","z","z","baseSchema","appSchema","baseSchema","appSchema","shot","spawnSync","readFileSync","join","list","rmSync","writeFileSync","resolve","basename","mkdirSync","dirname","statSync","list","shot","readFileSync","join","existsSync","mkdir","readFile","writeFile","dirname","join","files","text","join","existsSync","parsed","readFile","mkdir","dirname","writeFile","execFileSync","existsSync","join","execFileSync","existsSync","join","text","files","findings","list","basename","extname","text","add","basename","extname","text","findings","extname","text","extname","existsSync","readFileSync","extname","join","extname","join","existsSync","readFileSync","files","findings","findings","readFileSync","createRequire","dirname","join","relative","text","createRequire","join","relative","dirname","text","files","readFileSync","add","findings","start","resolve","findings","text","existsSync","join","pathToFileURL","join","existsSync","pathToFileURL","files","readFileSync","join","findings","existsSync","join","Node","Project","SyntaxKind","Node","call","SyntaxKind","Project","list","count","list","files","existsSync","join","jobs","hint","process","execFileSync","spawnSync","mkdir","writeFile","dirname","join","process","existsSync","rm","join","status","upstreamChanged","upstreamOnly","files","files","upstreamShort","hint","existsSync","join","rm","process","files","join","execFileSync","mkdir","dirname","writeFile","spawnSync","basename","cell","row","text","count","files","columns","basename","existsSync","rmSync","basename","process","pathToFileURL","execFileSync","mkdirSync","writeFileSync","dirname","join","process","execFileSync","text","index","files","count","hint","mkdirSync","dirname","writeFileSync","join","process","count","basename","process","rmSync","existsSync","pathToFileURL","readFileSync","basename","join","relative","execFile","promisify","execFileAsync","promisify","execFile","parsed","str","execFile","existsSync","realpathSync","tmpdir","dirname","join","sep","promisify","readFileSync","basename","dirname","join","basename","text","readFileSync","join","parsed","list","plural","dirname","SEVERITIES","input","execFileAsync","promisify","execFile","sep","existsSync","join","realpathSync","dirname","tmpdir","SEVERITIES","list","spawnSync","existsSync","mkdirSync","mkdtempSync","readFileSync","rmSync","writeFileSync","tmpdir","dirname","join","relative","select","existsSync","readFileSync","count","plural","mkdtempSync","join","tmpdir","files","relative","mkdirSync","dirname","writeFileSync","select","without","spawnSync","rmSync","readFileSync","join","runAudit","SEVERITIES","row","basename","count","packageJsonPath","relative","text","select","rmSync","dirname","join","resolve","dirname","files","resolve","join","rmSync","page","checkbox","select","fork","files","resolve","process","Separator","select","spawnSync","select","spawnSync","parsed","existsSync","readFileSync","writeFileSync","join","existsSync","readFileSync","statSync","join","MAX_FILE_BYTES","escapeRegExp","statSync","text","readFileSync","join","existsSync","existsSync","readFileSync","join","writeFileSync","result","skipped","kept","input","compare","spawnSync","select","outcome","resolve","Separator","select","process","readFile","join","existsSync","readFileSync","statSync","join","relative","sep","join","problem","existsSync","statSync","readFileSync","relative","sep","sourceExtensions","readFile","join","sep","c","docExtensions","sourceExtensions","text","files","record","add","row","columns","resolve","existsSync","statSync","process","join","runAudit"]}