@sushanglewis/lincoln 1.8.0 → 1.8.3

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/install.ts","../src/lib/paths.ts","../src/lib/versionMarker.ts","../src/lib/packageInfo.ts","../src/lib/syncClaude.ts","../src/lib/claudeMdMerge.ts","../src/lib/runHarnessAdapter.ts","../src/lib/syncHarness.ts","../src/lib/harnessDetect.ts","../src/lib/harnessSelect.ts","../src/lib/prompt.ts","../src/postinstall.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport type { LincolnPaths } from '../lib/paths.js'\nimport { resolveLincolnPaths } from '../lib/paths.js'\nimport { writeVersionMarker } from '../lib/versionMarker.js'\nimport { readLocalPackageVersion, resolvePayloadRoot } from '../lib/packageInfo.js'\nimport type { HarnessSyncReport, SyncHarnessesOptions } from '../lib/syncHarness.js'\nimport { syncHarnesses } from '../lib/syncHarness.js'\nimport { detectGlobalHarnesses, installedHarnessIds, isValidHarnessId, HARNESS_IDS } from '../lib/harnessDetect.js'\nimport type { HarnessId } from '../lib/harnessDetect.js'\nimport { buildHarnessOptions, resolveHarnessSelection } from '../lib/harnessSelect.js'\nimport { createPrompt } from '../lib/prompt.js'\nimport type { Prompt } from '../lib/prompt.js'\n\nexport interface InstallOptions {\n yes: boolean\n dryRun: boolean\n force: boolean\n harnesses: string[]\n noVenv: boolean\n noInteractive: boolean\n}\n\nexport interface InstallDeps {\n paths: LincolnPaths\n payloadRoot: string\n syncHarnesses: (opts: SyncHarnessesOptions) => Promise<HarnessSyncReport>\n createPrompt: () => Prompt\n resolvePythonForVenv: (\n envOverride?: string,\n candidates?: string[],\n queryVersion?: (cmd: string) => Promise<string | undefined>\n ) => Promise<string | undefined>\n isTTY: boolean\n}\n\nexport function createDefaultDeps(): InstallDeps {\n return {\n paths: resolveLincolnPaths(),\n payloadRoot: resolvePayloadRoot() || '',\n syncHarnesses,\n createPrompt,\n resolvePythonForVenv,\n isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY)\n }\n}\n\nexport async function install(\n options: InstallOptions,\n deps: InstallDeps = createDefaultDeps()\n): Promise<number> {\n const version = readLocalPackageVersion()\n if (!version) {\n console.error('Could not determine Lincoln version')\n return 1\n }\n\n const payloadRoot = deps.payloadRoot\n if (!payloadRoot || !fs.existsSync(payloadRoot)) {\n console.error('Lincoln payload not found. Run \"npm install -g @sushanglewis/lincoln\" first.')\n return 1\n }\n\n if (!options.dryRun && !options.yes && (options.noInteractive || !deps.isTTY)) {\n console.error(\n 'This will install Lincoln globally. Run with --yes to proceed, or run interactively in a TTY.'\n )\n return 1\n }\n\n const harnesses = await resolveHarnesses(options, deps)\n if (harnesses.length === 0) {\n return 1\n }\n\n const pythonPath = await resolvePythonIfNeeded(options, deps, harnesses)\n if (pythonPath === null) {\n return 1\n }\n\n if (!options.dryRun) {\n const versionDir = path.join(deps.paths.versionsDir, version)\n fs.mkdirSync(versionDir, { recursive: true })\n fs.cpSync(payloadRoot, versionDir, { recursive: true, force: true })\n try {\n fs.rmSync(deps.paths.currentDir, { recursive: true, force: true })\n fs.symlinkSync(versionDir, deps.paths.currentDir)\n } catch {\n fs.rmSync(deps.paths.currentDir, { recursive: true, force: true })\n fs.cpSync(versionDir, deps.paths.currentDir, { recursive: true, force: true })\n }\n }\n\n const reports = await deps.syncHarnesses({\n harnesses,\n payloadRoot: deps.paths.currentDir,\n paths: deps.paths,\n projectDir: deps.paths.lincolnHome,\n version,\n dryRun: options.dryRun,\n pythonPath\n })\n\n if (!options.dryRun) {\n writeVersionMarker(deps.paths, {\n version,\n installedAt: new Date().toISOString(),\n harnesses,\n managedFiles: collectManagedFiles(reports)\n })\n }\n\n printSummary(options, version, harnesses, reports)\n return 0\n}\n\nasync function resolvePythonIfNeeded(\n options: InstallOptions,\n deps: InstallDeps,\n harnesses: HarnessId[]\n): Promise<string | undefined | null> {\n const needsPython =\n !options.dryRun && !options.noVenv && harnesses.some((id) => id === 'codex' || id === 'opencode')\n if (!needsPython) {\n return undefined\n }\n\n const pythonCommand = await deps.resolvePythonForVenv()\n if (!pythonCommand) {\n console.error(\n 'Python 3.10+ is required for Codex/OpenCode sync but was not found. Set LINCOLN_PYTHON to a compatible Python executable, or run with --no-venv.'\n )\n return null\n }\n\n await setupVenv(deps.paths, deps.payloadRoot, pythonCommand)\n return venvPythonPath(deps.paths)\n}\n\nasync function resolveHarnesses(options: InstallOptions, deps: InstallDeps): Promise<HarnessId[]> {\n const detected = detectGlobalHarnesses(deps.paths.homeDir)\n\n if (options.harnesses.length > 0) {\n const invalid = options.harnesses.filter((id) => !isValidHarnessId(id))\n if (invalid.length > 0) {\n console.error(`Unknown harness id(s): ${invalid.join(', ')}`)\n console.error(`Valid ids: ${HARNESS_IDS.join(', ')}`)\n return []\n }\n return options.harnesses as HarnessId[]\n }\n\n const selected = installedHarnessIds(deps.paths.homeDir)\n if (selected.length > 0 && !options.dryRun && !options.yes && !options.noInteractive && deps.isTTY) {\n const prompt = deps.createPrompt()\n try {\n const answer = await prompt.multiSelect(\n 'Select agent harnesses to install Lincoln into:',\n buildHarnessOptions(detected)\n )\n const resolved = resolveHarnessSelection(detected, answer)\n if (resolved.length === 0) {\n console.error('No harnesses selected. Aborting.')\n return []\n }\n return resolved\n } catch (err) {\n console.error(`Interactive selection failed: ${err instanceof Error ? err.message : String(err)}`)\n return []\n } finally {\n prompt.close()\n }\n }\n\n if (selected.length === 0 && !options.dryRun) {\n console.error('No agent harness detected. Install Claude Code, Codex, or OpenCode first.')\n return []\n }\n\n return selected\n}\n\nfunction collectManagedFiles(reports: HarnessSyncReport): string[] {\n const files: string[] = []\n for (const report of Object.values(reports)) {\n files.push(...report.written, ...report.skipped, ...report.preserved)\n }\n return files\n}\n\nfunction printSummary(\n options: InstallOptions,\n version: string,\n harnesses: HarnessId[],\n reports: HarnessSyncReport\n): void {\n const warnings = collectWarnings(reports)\n if (options.dryRun) {\n console.log(`Dry run: would install Lincoln ${version} for harnesses: ${harnesses.join(', ')}`)\n } else {\n console.log(`Installed Lincoln ${version} for harnesses: ${harnesses.join(', ')}`)\n }\n for (const [harnessId, report] of Object.entries(reports)) {\n const count = report.written.length + report.skipped.length + report.preserved.length\n console.log(` ${harnessId}: ${count} file(s)`)\n }\n for (const warning of warnings) {\n console.warn(` warning: ${warning}`)\n }\n}\n\nfunction collectWarnings(reports: HarnessSyncReport): string[] {\n const warnings: string[] = []\n for (const report of Object.values(reports)) {\n warnings.push(...report.warnings)\n }\n return warnings\n}\n\nfunction runCommand(command: string, args: string[]): Promise<number> {\n return new Promise((resolvePromise, rejectPromise) => {\n const child = spawn(command, args, { stdio: 'inherit' })\n child.on('close', (code) => resolvePromise(code ?? 1))\n child.on('error', (err) => rejectPromise(err))\n })\n}\n\nconst MIN_PYTHON_MAJOR = 3\nconst MIN_PYTHON_MINOR = 10\nconst DEFAULT_PYTHON_CANDIDATES = ['python3.12', 'python3.11', 'python3.10', 'python3']\n\nfunction parsePythonVersion(version: string): { major: number; minor: number } | undefined {\n const match = /(\\d+)\\.(\\d+)/.exec(version)\n if (!match) {\n return undefined\n }\n return { major: Number(match[1]), minor: Number(match[2]) }\n}\n\nasync function queryPythonVersion(command: string): Promise<string | undefined> {\n return new Promise((resolvePromise) => {\n const child = spawn(command, ['--version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n shell: process.platform === 'win32'\n })\n let stdout = ''\n child.stdout?.on('data', (chunk: Buffer | string) => {\n stdout += chunk.toString()\n })\n child.on('close', (code) => {\n const text = stdout.trim()\n resolvePromise(code === 0 && text.length > 0 ? text : undefined)\n })\n child.on('error', () => resolvePromise(undefined))\n })\n}\n\nexport async function resolvePythonForVenv(\n envOverride: string | undefined = process.env.LINCOLN_PYTHON,\n candidates: string[] = DEFAULT_PYTHON_CANDIDATES,\n queryVersion: (cmd: string) => Promise<string | undefined> = queryPythonVersion\n): Promise<string | undefined> {\n const list = envOverride ? [envOverride] : candidates\n for (const cmd of list) {\n const version = await queryVersion(cmd)\n if (!version) {\n continue\n }\n const parsed = parsePythonVersion(version)\n if (\n parsed &&\n parsed.major >= MIN_PYTHON_MAJOR &&\n (parsed.major > MIN_PYTHON_MAJOR || parsed.minor >= MIN_PYTHON_MINOR)\n ) {\n return cmd\n }\n }\n return undefined\n}\n\nfunction venvPythonPath(paths: LincolnPaths): string {\n return path.join(\n paths.venvDir,\n process.platform === 'win32' ? 'Scripts' : 'bin',\n process.platform === 'win32' ? 'python.exe' : 'python'\n )\n}\n\nasync function setupVenv(paths: LincolnPaths, payloadRoot: string, pythonCommand: string): Promise<void> {\n const pythonExe = venvPythonPath(paths)\n\n if (!fs.existsSync(pythonExe)) {\n console.log('Creating Lincoln virtual environment...')\n const venvCode = await runCommand(pythonCommand, ['-m', 'venv', paths.venvDir])\n if (venvCode !== 0) {\n throw new Error(`Failed to create virtual environment (exit code ${venvCode})`)\n }\n }\n\n const requirementsPath = path.join(payloadRoot, 'requirements.txt')\n if (fs.existsSync(requirementsPath)) {\n console.log('Installing Python dependencies...')\n const pipExe = path.join(\n paths.venvDir,\n process.platform === 'win32' ? 'Scripts' : 'bin',\n process.platform === 'win32' ? 'pip.exe' : 'pip'\n )\n const pipCode = await runCommand(pipExe, ['install', '-r', requirementsPath])\n if (pipCode !== 0) {\n throw new Error(`Failed to install Python dependencies (exit code ${pipCode})`)\n }\n }\n}\n","import path from 'node:path'\nimport os from 'node:os'\n\nexport interface LincolnPaths {\n homeDir: string\n lincolnHome: string\n versionsDir: string\n currentDir: string\n versionMarker: string\n venvDir: string\n claudeDir: string\n codexDir: string\n opencodeDir: string\n}\n\nexport function resolveLincolnPaths(overrideHomeDir?: string): LincolnPaths {\n const homeDir = overrideHomeDir ?? os.homedir()\n const lincolnHome = process.env.LINCOLN_HOME\n ? path.resolve(process.env.LINCOLN_HOME)\n : path.join(homeDir, '.lincoln')\n\n return {\n homeDir,\n lincolnHome,\n versionsDir: path.join(lincolnHome, 'versions'),\n currentDir: path.join(lincolnHome, 'current'),\n versionMarker: path.join(lincolnHome, 'marker.json'),\n venvDir: path.join(lincolnHome, 'venv'),\n claudeDir: path.join(homeDir, '.claude'),\n codexDir: path.join(homeDir, '.codex'),\n opencodeDir: path.join(homeDir, '.opencode')\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { LincolnPaths } from './paths.js'\n\nexport interface VersionMarker {\n version: string\n installedAt: string\n harnesses: string[]\n managedFiles: string[]\n}\n\nexport function readVersionMarker(paths: LincolnPaths): VersionMarker | undefined {\n try {\n const raw = fs.readFileSync(paths.versionMarker, 'utf8')\n const parsed = JSON.parse(raw) as VersionMarker\n if (\n typeof parsed.version === 'string' &&\n typeof parsed.installedAt === 'string' &&\n Array.isArray(parsed.harnesses)\n ) {\n return parsed\n }\n return undefined\n } catch {\n return undefined\n }\n}\n\nexport function writeVersionMarker(\n paths: LincolnPaths,\n marker: VersionMarker\n): void {\n fs.mkdirSync(path.dirname(paths.versionMarker), { recursive: true })\n fs.writeFileSync(paths.versionMarker, JSON.stringify(marker, null, 2) + '\\n')\n}\n\nexport function isUpToDate(paths: LincolnPaths, version: string): boolean {\n const marker = readVersionMarker(paths)\n return marker?.version === version\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/**\n * Finds the directory containing the running lincoln package's package.json.\n * Returns undefined when no package.json can be located.\n */\nexport function readLocalPackageRoot(): string | undefined {\n try {\n let dir = path.dirname(fileURLToPath(import.meta.url))\n const root = path.parse(dir).root\n while (dir !== root) {\n const pkgPath = path.join(dir, 'package.json')\n if (fs.existsSync(pkgPath)) {\n const parsed = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as { name?: string }\n if (parsed.name === '@sushanglewis/lincoln') {\n return dir\n }\n }\n dir = path.dirname(dir)\n }\n } catch {\n // ignore and return undefined\n }\n return undefined\n}\n\n/**\n * Reads the version of the running lincoln package from its own package.json.\n * Walks upward from the current module file until it finds the package.json.\n * Returns undefined when the package.json cannot be located or parsed.\n */\nexport function readLocalPackageVersion(): string | undefined {\n try {\n const root = readLocalPackageRoot()\n if (!root) return undefined\n const parsed = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')) as {\n version?: string\n }\n return typeof parsed.version === 'string' ? parsed.version : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Resolves the bundled framework payload directory inside the running package.\n */\nexport function resolvePayloadRoot(): string | undefined {\n const root = readLocalPackageRoot()\n if (!root) return undefined\n const payload = path.join(root, 'framework')\n return fs.existsSync(payload) ? payload : undefined\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport { mergeManagedBlock } from './claudeMdMerge.js'\n\nexport interface SyncOptions {\n payloadRoot: string\n targetDir: string\n version: string\n dryRun: boolean\n}\n\nexport interface SyncReport {\n written: string[]\n skipped: string[]\n preserved: string[]\n warnings: string[]\n settingsTouched?: string[]\n}\n\nconst COPY_SUBDIRS = [\n 'agents',\n 'skills',\n 'workflows',\n 'stages',\n 'schemas',\n 'templates',\n 'harnesses'\n]\n\nfunction sha256(filePath: string): string {\n const data = fs.readFileSync(filePath)\n return crypto.createHash('sha256').update(data).digest('hex')\n}\n\nfunction sameContent(a: string, b: string): boolean {\n return sha256(a) === sha256(b)\n}\n\nfunction deepMergeSettings(existing: unknown, incoming: unknown): unknown {\n if (Array.isArray(existing) && Array.isArray(incoming)) {\n return incoming\n }\n if (\n typeof existing === 'object' &&\n existing !== null &&\n typeof incoming === 'object' &&\n incoming !== null\n ) {\n const result: Record<string, unknown> = { ...existing }\n for (const [key, value] of Object.entries(incoming)) {\n if (key in result) {\n result[key] = deepMergeSettings(result[key], value)\n } else {\n result[key] = value\n }\n }\n return result\n }\n return incoming\n}\n\nexport function syncClaudeCode(opts: SyncOptions): SyncReport {\n const report: SyncReport = {\n written: [],\n skipped: [],\n preserved: [],\n warnings: [],\n settingsTouched: []\n }\n\n const payloadClaude = path.join(opts.payloadRoot, '.claude')\n if (!fs.existsSync(payloadClaude)) {\n report.warnings.push(`payload .claude directory not found: ${payloadClaude}`)\n return report\n }\n\n if (!opts.dryRun) {\n fs.mkdirSync(opts.targetDir, { recursive: true })\n }\n\n for (const subdir of COPY_SUBDIRS) {\n const srcDir = path.join(payloadClaude, subdir)\n if (!fs.existsSync(srcDir)) {\n continue\n }\n\n const destDir = path.join(opts.targetDir, subdir)\n if (!opts.dryRun) {\n fs.mkdirSync(destDir, { recursive: true })\n }\n\n for (const entry of walkSync(srcDir)) {\n const relativePath = path.relative(srcDir, entry)\n const srcFile = entry\n const destFile = path.join(destDir, relativePath)\n\n if (fs.existsSync(destFile) && sameContent(srcFile, destFile)) {\n report.skipped.push(path.join('.claude', subdir, relativePath))\n continue\n }\n\n if (!opts.dryRun) {\n fs.mkdirSync(path.dirname(destFile), { recursive: true })\n fs.copyFileSync(srcFile, destFile)\n }\n report.written.push(path.join('.claude', subdir, relativePath))\n }\n }\n\n // settings.json merge\n const payloadSettings = path.join(payloadClaude, 'settings.json')\n const targetSettings = path.join(opts.targetDir, 'settings.json')\n if (fs.existsSync(payloadSettings)) {\n const incoming = JSON.parse(fs.readFileSync(payloadSettings, 'utf8'))\n let merged = incoming\n if (fs.existsSync(targetSettings)) {\n const existing = JSON.parse(fs.readFileSync(targetSettings, 'utf8'))\n merged = deepMergeSettings(existing, incoming)\n }\n\n const wouldChange =\n !fs.existsSync(targetSettings) ||\n JSON.stringify(merged) !== JSON.stringify(JSON.parse(fs.readFileSync(targetSettings, 'utf8')))\n\n if (wouldChange) {\n if (!opts.dryRun) {\n fs.writeFileSync(targetSettings, JSON.stringify(merged, null, 2) + '\\n')\n }\n report.written.push('.claude/settings.json')\n report.settingsTouched = ['.claude/settings.json']\n } else {\n report.skipped.push('.claude/settings.json')\n }\n }\n\n // CLAUDE.md merge\n const payloadClaudeMd = path.join(opts.payloadRoot, 'CLAUDE.md')\n const targetClaudeMd = path.join(path.dirname(opts.targetDir), 'CLAUDE.md')\n if (fs.existsSync(payloadClaudeMd)) {\n const incomingBlock = fs.readFileSync(payloadClaudeMd, 'utf8')\n const existing = fs.existsSync(targetClaudeMd)\n ? fs.readFileSync(targetClaudeMd, 'utf8')\n : undefined\n const merged = mergeManagedBlock(existing, incomingBlock)\n\n if (merged !== existing) {\n if (!opts.dryRun) {\n fs.writeFileSync(targetClaudeMd, merged)\n }\n report.written.push('CLAUDE.md')\n } else {\n report.skipped.push('CLAUDE.md')\n }\n }\n\n return report\n}\n\nfunction* walkSync(dir: string): Generator<string> {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n yield* walkSync(fullPath)\n } else {\n yield fullPath\n }\n }\n}\n","const BEGIN = '<!-- lincoln:begin -->'\nconst END = '<!-- lincoln:end -->'\n\nexport function mergeManagedBlock(\n existing: string | undefined,\n block: string\n): string {\n const wrapped = `${BEGIN}\\n${block}\\n${END}`\n const text = existing ?? ''\n\n const beginIndex = text.indexOf(BEGIN)\n const endIndex = text.indexOf(END)\n\n if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {\n return (\n text.slice(0, beginIndex) +\n wrapped +\n text.slice(endIndex + END.length)\n )\n }\n\n if (text.trim().length === 0) {\n return wrapped\n }\n\n return `${text.trimEnd()}\\n\\n${wrapped}\\n`\n}\n\nexport function extractManagedBlock(existing: string): string | undefined {\n const beginIndex = existing.indexOf(BEGIN)\n const endIndex = existing.indexOf(END)\n if (beginIndex === -1 || endIndex === -1 || endIndex <= beginIndex) {\n return undefined\n }\n return existing\n .slice(beginIndex + BEGIN.length, endIndex)\n .replace(/^\\n+|\\n+$/g, '')\n}\n","import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process'\nimport type { SyncReport } from './syncClaude.js'\n\nexport interface RunHarnessAdapterOptions {\n harnessId: 'codex' | 'opencode'\n payloadRoot: string\n projectDir: string\n homeDir: string\n pythonPath: string\n dryRun: boolean\n spawnCommand?: SpawnCommand\n}\n\ntype SpawnCommand = (command: string, args: string[], options?: SpawnOptions) => ChildProcess\n\nfunction runCommand(\n command: string,\n args: string[],\n spawnCommand: SpawnCommand\n): Promise<number | null> {\n return new Promise((resolvePromise, rejectPromise) => {\n const child = spawnCommand(command, args, { stdio: 'inherit' })\n child.on('close', (code) => {\n resolvePromise(code)\n })\n child.on('error', (err) => {\n rejectPromise(err)\n })\n })\n}\n\nexport async function runHarnessAdapter(opts: RunHarnessAdapterOptions): Promise<SyncReport> {\n const report: SyncReport = {\n written: [],\n skipped: [],\n preserved: [],\n warnings: []\n }\n\n if (opts.dryRun) {\n report.written.push(`${opts.harnessId} (dry run)`)\n return report\n }\n\n const args = [\n `${opts.payloadRoot}/scripts/lincoln_harness_adapter.py`,\n '--harness',\n opts.harnessId,\n '--root',\n opts.payloadRoot,\n '--project-dir',\n opts.projectDir,\n '--home-dir',\n opts.homeDir\n ]\n\n try {\n const spawnCommand = (opts.spawnCommand ?? spawn) as SpawnCommand\n const code = await runCommand(opts.pythonPath, args, spawnCommand)\n if (code === 0) {\n report.written.push(opts.harnessId)\n } else {\n report.warnings.push(\n `Adapter for ${opts.harnessId} exited with code ${code}. Run manually to diagnose.`\n )\n }\n } catch (err) {\n report.warnings.push(\n `Failed to run adapter for ${opts.harnessId}: ${err instanceof Error ? err.message : String(err)}`\n )\n }\n\n return report\n}\n","import type { SyncReport } from './syncClaude.js'\nimport { syncClaudeCode } from './syncClaude.js'\nimport type { HarnessId } from './harnessDetect.js'\nimport type { LincolnPaths } from './paths.js'\nimport { runHarnessAdapter } from './runHarnessAdapter.js'\n\nexport interface SyncHarnessesOptions {\n harnesses: HarnessId[]\n payloadRoot: string\n paths: LincolnPaths\n projectDir: string\n version: string\n dryRun: boolean\n pythonPath?: string\n syncClaude?: (opts: {\n payloadRoot: string\n targetDir: string\n version: string\n dryRun: boolean\n }) => SyncReport\n}\n\nexport type HarnessSyncReport = Record<HarnessId, SyncReport>\n\nfunction emptyReport(): SyncReport {\n return {\n written: [],\n skipped: [],\n preserved: [],\n warnings: []\n }\n}\n\nexport async function syncHarnesses(opts: SyncHarnessesOptions): Promise<HarnessSyncReport> {\n const reports: HarnessSyncReport = {} as HarnessSyncReport\n const syncClaude = opts.syncClaude ?? syncClaudeCode\n\n for (const harnessId of opts.harnesses) {\n reports[harnessId] = await syncHarness(harnessId, opts, syncClaude)\n }\n\n return reports\n}\n\nasync function syncHarness(\n harnessId: HarnessId,\n opts: SyncHarnessesOptions,\n syncClaude: NonNullable<SyncHarnessesOptions['syncClaude']>\n): Promise<SyncReport> {\n if (harnessId === 'claude-code') {\n return syncClaude({\n payloadRoot: opts.payloadRoot,\n targetDir: opts.paths.claudeDir,\n version: opts.version,\n dryRun: opts.dryRun\n })\n }\n\n if (harnessId === 'codex' || harnessId === 'opencode') {\n if (opts.dryRun) {\n const report = emptyReport()\n report.written.push(`${harnessId} (dry run)`)\n return report\n }\n if (!opts.pythonPath) {\n const report = emptyReport()\n report.warnings.push(\n `Skipped ${harnessId} sync because Python is not available. Install Python 3.10+ or run without --no-venv.`\n )\n return report\n }\n return runHarnessAdapter({\n harnessId,\n payloadRoot: opts.payloadRoot,\n projectDir: opts.projectDir,\n homeDir: opts.paths.homeDir,\n pythonPath: opts.pythonPath,\n dryRun: opts.dryRun\n })\n }\n\n const report = emptyReport()\n report.warnings.push(`Unsupported harness: ${harnessId}`)\n return report\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\n\nexport type HarnessId = 'claude-code' | 'codex' | 'opencode'\n\nexport interface GlobalHarnessInfo {\n id: HarnessId\n installed: boolean\n configDir: string\n pluginManaged: boolean\n}\n\ninterface HarnessSpec {\n id: HarnessId\n configDirName: string\n pluginMarker?: string\n}\n\nconst HARNESS_SPECS: HarnessSpec[] = [\n {\n id: 'claude-code',\n configDirName: '.claude',\n pluginMarker: 'plugins/lincoln'\n },\n { id: 'codex', configDirName: '.codex' },\n { id: 'opencode', configDirName: '.opencode' }\n]\n\nexport function detectGlobalHarnesses(\n overrideHomeDir?: string\n): GlobalHarnessInfo[] {\n const homeDir = overrideHomeDir ?? os.homedir()\n\n return HARNESS_SPECS.map((spec) => {\n const configDir = path.join(homeDir, spec.configDirName)\n const installed = fs.existsSync(configDir)\n const pluginManaged = spec.pluginMarker\n ? fs.existsSync(path.join(configDir, spec.pluginMarker))\n : false\n\n return {\n id: spec.id,\n installed,\n configDir,\n pluginManaged\n }\n })\n}\n\nexport function installedHarnessIds(homeDir?: string): HarnessId[] {\n return detectGlobalHarnesses(homeDir)\n .filter((h) => h.installed)\n .map((h) => h.id)\n}\n\nexport const HARNESS_IDS: HarnessId[] = HARNESS_SPECS.map((spec) => spec.id)\n\nexport function isValidHarnessId(value: string): value is HarnessId {\n return HARNESS_SPECS.some((spec) => spec.id === value)\n}\n","import type { GlobalHarnessInfo, HarnessId } from './harnessDetect.js'\nimport type { MultiSelectOption } from './prompt.js'\n\nexport const HARNESS_LABELS: Record<HarnessId, string> = {\n 'claude-code': 'Claude Code',\n codex: 'Codex',\n opencode: 'OpenCode'\n}\n\nexport function buildHarnessOptions(\n detected: ReadonlyArray<GlobalHarnessInfo>\n): MultiSelectOption[] {\n return detected.map((harness) => ({\n id: harness.id,\n label: HARNESS_LABELS[harness.id],\n checked: harness.installed\n }))\n}\n\nexport function resolveHarnessSelection(\n detected: ReadonlyArray<GlobalHarnessInfo>,\n selection: string[] | undefined\n): HarnessId[] {\n if (selection === undefined) {\n return detected.filter((harness) => harness.installed).map((harness) => harness.id)\n }\n const validIds = new Set<HarnessId>()\n for (const id of selection) {\n const match = detected.find((harness) => harness.id === id)\n if (match) {\n validIds.add(match.id)\n }\n }\n return Array.from(validIds)\n}\n","import type { Readable, Writable } from 'node:stream'\n\nexport interface PromptOptions {\n input?: Readable\n output?: Writable\n}\n\nexport interface MultiSelectOption {\n id: string\n label: string\n checked: boolean\n}\n\nexport interface Prompt {\n confirm(question: string, defaultValue?: boolean): Promise<boolean>\n multiSelect(question: string, options: ReadonlyArray<MultiSelectOption>): Promise<string[]>\n close(): void\n}\n\ninterface LineReader {\n readLine(prompt: string): Promise<string>\n close(): void\n}\n\nfunction createLineReader(input: Readable, output: Writable): LineReader {\n const buffer: string[] = []\n const queue: Array<{ resolve: (line: string) => void; reject: (err: Error) => void }> = []\n let remainder = ''\n let ended = false\n\n function flushQueue(): void {\n while (queue.length > 0 && buffer.length > 0) {\n const next = queue.shift()\n const line = buffer.shift()\n if (next && line !== undefined) {\n next.resolve(line)\n }\n }\n }\n\n input.on('data', (chunk: Buffer | string) => {\n const text = remainder + chunk.toString('utf-8')\n const lines = text.split('\\n')\n remainder = lines.pop() ?? ''\n for (const line of lines) {\n buffer.push(line.replace(/\\r$/, ''))\n }\n flushQueue()\n })\n\n input.on('end', () => {\n ended = true\n if (remainder.length > 0) {\n buffer.push(remainder.replace(/\\r$/, ''))\n remainder = ''\n }\n flushQueue()\n while (queue.length > 0) {\n const next = queue.shift()\n next?.resolve('')\n }\n })\n\n input.on('error', (err) => {\n while (queue.length > 0) {\n queue.shift()?.reject(err)\n }\n })\n\n return {\n readLine(prompt: string): Promise<string> {\n output.write(prompt)\n if (buffer.length > 0) {\n return Promise.resolve(buffer.shift() ?? '')\n }\n if (ended) {\n return Promise.resolve('')\n }\n return new Promise<string>((resolve, reject) => {\n queue.push({ resolve, reject })\n })\n },\n close(): void {\n // nothing to close for raw streams\n }\n }\n}\n\nfunction normalizeAnswer(text: string): string {\n return text.trim().toLowerCase()\n}\n\nexport function createPrompt(streams: PromptOptions = {}): Prompt {\n const input = streams.input ?? process.stdin\n const output = streams.output ?? process.stdout\n const reader = createLineReader(input, output)\n\n async function ask(question: string): Promise<string> {\n return reader.readLine(question)\n }\n\n return {\n async confirm(question: string, defaultValue = true): Promise<boolean> {\n const hint = defaultValue ? '[Y/n]' : '[y/N]'\n const first = await ask(`${question} ${hint} `)\n const normalized = normalizeAnswer(first)\n if (normalized === 'y' || normalized === 'yes') {\n return true\n }\n if (normalized === 'n' || normalized === 'no') {\n return false\n }\n if (normalized === '') {\n return defaultValue\n }\n const second = await ask('Please answer y or n: ')\n const secondNormalized = normalizeAnswer(second)\n if (secondNormalized === 'y' || secondNormalized === 'yes') {\n return true\n }\n if (secondNormalized === 'n' || secondNormalized === 'no') {\n return false\n }\n return defaultValue\n },\n\n async multiSelect(\n question: string,\n options: ReadonlyArray<MultiSelectOption>\n ): Promise<string[]> {\n const lines = options.map((opt, index) => {\n const mark = opt.checked ? 'x' : ' '\n return ` [${mark}] ${index + 1}. ${opt.label}`\n })\n const promptText = `${question}\\n${lines.join('\\n')}\\nEnter numbers (e.g. 1,3), 'all', 'none', or harness names: `\n\n async function parse(answer: string): Promise<string[] | undefined> {\n const normalized = normalizeAnswer(answer)\n if (normalized === 'all') {\n return options.map((opt) => opt.id)\n }\n if (normalized === 'none') {\n return []\n }\n if (normalized === '') {\n return options.filter((opt) => opt.checked).map((opt) => opt.id)\n }\n const parts = normalized.split(/[,\\s]+/).filter((part) => part.length > 0)\n const selected = new Set<string>()\n for (const part of parts) {\n const index = Number(part)\n if (!Number.isNaN(index) && index >= 1 && index <= options.length) {\n selected.add(options[index - 1].id)\n continue\n }\n const match = options.find((opt) => opt.id === part)\n if (match) {\n selected.add(match.id)\n continue\n }\n return undefined\n }\n return Array.from(selected)\n }\n\n let result = await parse(await ask(promptText))\n if (result !== undefined) {\n return result\n }\n const retry = await ask('Invalid selection. Please try again: ')\n result = await parse(retry)\n return result ?? []\n },\n\n close(): void {\n reader.close()\n }\n }\n}\n","import { install as runInstall } from './commands/install.js'\nimport { createPrompt } from './lib/prompt.js'\n\nexport interface PostinstallDeps {\n isTTY: boolean\n confirm: (question: string) => Promise<boolean>\n install: () => Promise<number>\n env: Record<string, string | undefined>\n}\n\nfunction isSkipped(env: Record<string, string | undefined>): boolean {\n if (env.CI) {\n return true\n }\n if (env.NODE_ENV === 'test') {\n return true\n }\n if (env.LINCOLN_SKIP_POSTINSTALL) {\n return true\n }\n return false\n}\n\nexport function createDefaultDeps(): PostinstallDeps {\n return {\n isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY),\n confirm: async (question: string) => {\n const prompt = createPrompt()\n try {\n return await prompt.confirm(question, true)\n } finally {\n prompt.close()\n }\n },\n install: async () =>\n runInstall({ yes: false, dryRun: false, force: false, harnesses: [], noVenv: false, noInteractive: false }),\n env: process.env\n }\n}\n\nexport async function runPostinstall(deps: PostinstallDeps = createDefaultDeps()): Promise<number> {\n if (isSkipped(deps.env)) {\n return 0\n }\n\n if (!deps.isTTY) {\n console.log('Lincoln installed globally.')\n console.log('Run \"lincoln install\" to finish setup.')\n return 0\n }\n\n try {\n const ok = await deps.confirm('Configure Lincoln harnesses now?')\n if (!ok) {\n console.log('Run \"lincoln install\" anytime to finish setup.')\n return 0\n }\n await deps.install()\n return 0\n } catch (err) {\n console.log('Lincoln installed globally.')\n console.log('Run \"lincoln install\" anytime to finish setup.')\n if (err instanceof Error) {\n console.error(`Postinstall setup skipped: ${err.message}`)\n }\n return 0\n }\n}\n\nif (import.meta.url === `file://${process.argv[1]}`) {\n runPostinstall()\n .then((code) => process.exit(code))\n .catch(() => process.exit(0))\n}\n"],"mappings":";;;AAAA,OAAOA,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,SAAAC,cAAa;;;ACFtB,OAAO,UAAU;AACjB,OAAO,QAAQ;AAcR,SAAS,oBAAoB,iBAAwC;AAC1E,QAAM,UAAU,mBAAmB,GAAG,QAAQ;AAC9C,QAAM,cAAc,QAAQ,IAAI,eAC5B,KAAK,QAAQ,QAAQ,IAAI,YAAY,IACrC,KAAK,KAAK,SAAS,UAAU;AAEjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,KAAK,KAAK,aAAa,UAAU;AAAA,IAC9C,YAAY,KAAK,KAAK,aAAa,SAAS;AAAA,IAC5C,eAAe,KAAK,KAAK,aAAa,aAAa;AAAA,IACnD,SAAS,KAAK,KAAK,aAAa,MAAM;AAAA,IACtC,WAAW,KAAK,KAAK,SAAS,SAAS;AAAA,IACvC,UAAU,KAAK,KAAK,SAAS,QAAQ;AAAA,IACrC,aAAa,KAAK,KAAK,SAAS,WAAW;AAAA,EAC7C;AACF;;;AChCA,OAAO,QAAQ;AACf,OAAOC,WAAU;AA2BV,SAAS,mBACd,OACA,QACM;AACN,KAAG,UAAUC,MAAK,QAAQ,MAAM,aAAa,GAAG,EAAE,WAAW,KAAK,CAAC;AACnE,KAAG,cAAc,MAAM,eAAe,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAC9E;;;AClCA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,qBAAqB;AAMvB,SAAS,uBAA2C;AACzD,MAAI;AACF,QAAI,MAAMA,MAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AACrD,UAAM,OAAOA,MAAK,MAAM,GAAG,EAAE;AAC7B,WAAO,QAAQ,MAAM;AACnB,YAAM,UAAUA,MAAK,KAAK,KAAK,cAAc;AAC7C,UAAID,IAAG,WAAW,OAAO,GAAG;AAC1B,cAAM,SAAS,KAAK,MAAMA,IAAG,aAAa,SAAS,MAAM,CAAC;AAC1D,YAAI,OAAO,SAAS,yBAAyB;AAC3C,iBAAO;AAAA,QACT;AAAA,MACF;AACA,YAAMC,MAAK,QAAQ,GAAG;AAAA,IACxB;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAOO,SAAS,0BAA8C;AAC5D,MAAI;AACF,UAAM,OAAO,qBAAqB;AAClC,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,SAAS,KAAK,MAAMD,IAAG,aAAaC,MAAK,KAAK,MAAM,cAAc,GAAG,MAAM,CAAC;AAGlF,WAAO,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,EAC/D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,qBAAyC;AACvD,QAAM,OAAO,qBAAqB;AAClC,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,UAAUA,MAAK,KAAK,MAAM,WAAW;AAC3C,SAAOD,IAAG,WAAW,OAAO,IAAI,UAAU;AAC5C;;;ACtDA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,YAAY;;;ACFnB,IAAM,QAAQ;AACd,IAAM,MAAM;AAEL,SAAS,kBACd,UACA,OACQ;AACR,QAAM,UAAU,GAAG,KAAK;AAAA,EAAK,KAAK;AAAA,EAAK,GAAG;AAC1C,QAAM,OAAO,YAAY;AAEzB,QAAM,aAAa,KAAK,QAAQ,KAAK;AACrC,QAAM,WAAW,KAAK,QAAQ,GAAG;AAEjC,MAAI,eAAe,MAAM,aAAa,MAAM,WAAW,YAAY;AACjE,WACE,KAAK,MAAM,GAAG,UAAU,IACxB,UACA,KAAK,MAAM,WAAW,IAAI,MAAM;AAAA,EAEpC;AAEA,MAAI,KAAK,KAAK,EAAE,WAAW,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,KAAK,QAAQ,CAAC;AAAA;AAAA,EAAO,OAAO;AAAA;AACxC;;;ADNA,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,OAAO,UAA0B;AACxC,QAAM,OAAOC,IAAG,aAAa,QAAQ;AACrC,SAAO,OAAO,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AAC9D;AAEA,SAAS,YAAY,GAAW,GAAoB;AAClD,SAAO,OAAO,CAAC,MAAM,OAAO,CAAC;AAC/B;AAEA,SAAS,kBAAkB,UAAmB,UAA4B;AACxE,MAAI,MAAM,QAAQ,QAAQ,KAAK,MAAM,QAAQ,QAAQ,GAAG;AACtD,WAAO;AAAA,EACT;AACA,MACE,OAAO,aAAa,YACpB,aAAa,QACb,OAAO,aAAa,YACpB,aAAa,MACb;AACA,UAAM,SAAkC,EAAE,GAAG,SAAS;AACtD,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,UAAI,OAAO,QAAQ;AACjB,eAAO,GAAG,IAAI,kBAAkB,OAAO,GAAG,GAAG,KAAK;AAAA,MACpD,OAAO;AACL,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,eAAe,MAA+B;AAC5D,QAAM,SAAqB;AAAA,IACzB,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,IACX,iBAAiB,CAAC;AAAA,EACpB;AAEA,QAAM,gBAAgBC,MAAK,KAAK,KAAK,aAAa,SAAS;AAC3D,MAAI,CAACD,IAAG,WAAW,aAAa,GAAG;AACjC,WAAO,SAAS,KAAK,wCAAwC,aAAa,EAAE;AAC5E,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,KAAK,QAAQ;AAChB,IAAAA,IAAG,UAAU,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAClD;AAEA,aAAW,UAAU,cAAc;AACjC,UAAM,SAASC,MAAK,KAAK,eAAe,MAAM;AAC9C,QAAI,CAACD,IAAG,WAAW,MAAM,GAAG;AAC1B;AAAA,IACF;AAEA,UAAM,UAAUC,MAAK,KAAK,KAAK,WAAW,MAAM;AAChD,QAAI,CAAC,KAAK,QAAQ;AAChB,MAAAD,IAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,IAC3C;AAEA,eAAW,SAAS,SAAS,MAAM,GAAG;AACpC,YAAM,eAAeC,MAAK,SAAS,QAAQ,KAAK;AAChD,YAAM,UAAU;AAChB,YAAM,WAAWA,MAAK,KAAK,SAAS,YAAY;AAEhD,UAAID,IAAG,WAAW,QAAQ,KAAK,YAAY,SAAS,QAAQ,GAAG;AAC7D,eAAO,QAAQ,KAAKC,MAAK,KAAK,WAAW,QAAQ,YAAY,CAAC;AAC9D;AAAA,MACF;AAEA,UAAI,CAAC,KAAK,QAAQ;AAChB,QAAAD,IAAG,UAAUC,MAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACxD,QAAAD,IAAG,aAAa,SAAS,QAAQ;AAAA,MACnC;AACA,aAAO,QAAQ,KAAKC,MAAK,KAAK,WAAW,QAAQ,YAAY,CAAC;AAAA,IAChE;AAAA,EACF;AAGA,QAAM,kBAAkBA,MAAK,KAAK,eAAe,eAAe;AAChE,QAAM,iBAAiBA,MAAK,KAAK,KAAK,WAAW,eAAe;AAChE,MAAID,IAAG,WAAW,eAAe,GAAG;AAClC,UAAM,WAAW,KAAK,MAAMA,IAAG,aAAa,iBAAiB,MAAM,CAAC;AACpE,QAAI,SAAS;AACb,QAAIA,IAAG,WAAW,cAAc,GAAG;AACjC,YAAM,WAAW,KAAK,MAAMA,IAAG,aAAa,gBAAgB,MAAM,CAAC;AACnE,eAAS,kBAAkB,UAAU,QAAQ;AAAA,IAC/C;AAEA,UAAM,cACJ,CAACA,IAAG,WAAW,cAAc,KAC7B,KAAK,UAAU,MAAM,MAAM,KAAK,UAAU,KAAK,MAAMA,IAAG,aAAa,gBAAgB,MAAM,CAAC,CAAC;AAE/F,QAAI,aAAa;AACf,UAAI,CAAC,KAAK,QAAQ;AAChB,QAAAA,IAAG,cAAc,gBAAgB,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAAA,MACzE;AACA,aAAO,QAAQ,KAAK,uBAAuB;AAC3C,aAAO,kBAAkB,CAAC,uBAAuB;AAAA,IACnD,OAAO;AACL,aAAO,QAAQ,KAAK,uBAAuB;AAAA,IAC7C;AAAA,EACF;AAGA,QAAM,kBAAkBC,MAAK,KAAK,KAAK,aAAa,WAAW;AAC/D,QAAM,iBAAiBA,MAAK,KAAKA,MAAK,QAAQ,KAAK,SAAS,GAAG,WAAW;AAC1E,MAAID,IAAG,WAAW,eAAe,GAAG;AAClC,UAAM,gBAAgBA,IAAG,aAAa,iBAAiB,MAAM;AAC7D,UAAM,WAAWA,IAAG,WAAW,cAAc,IACzCA,IAAG,aAAa,gBAAgB,MAAM,IACtC;AACJ,UAAM,SAAS,kBAAkB,UAAU,aAAa;AAExD,QAAI,WAAW,UAAU;AACvB,UAAI,CAAC,KAAK,QAAQ;AAChB,QAAAA,IAAG,cAAc,gBAAgB,MAAM;AAAA,MACzC;AACA,aAAO,QAAQ,KAAK,WAAW;AAAA,IACjC,OAAO;AACL,aAAO,QAAQ,KAAK,WAAW;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AACT;AAEA,UAAU,SAAS,KAAgC;AACjD,QAAM,UAAUA,IAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAC3D,aAAW,SAAS,SAAS;AAC3B,UAAM,WAAWC,MAAK,KAAK,KAAK,MAAM,IAAI;AAC1C,QAAI,MAAM,YAAY,GAAG;AACvB,aAAO,SAAS,QAAQ;AAAA,IAC1B,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AEzKA,SAAS,aAAmD;AAe5D,SAAS,WACP,SACA,MACA,cACwB;AACxB,SAAO,IAAI,QAAQ,CAAC,gBAAgB,kBAAkB;AACpD,UAAM,QAAQ,aAAa,SAAS,MAAM,EAAE,OAAO,UAAU,CAAC;AAC9D,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,qBAAe,IAAI;AAAA,IACrB,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,oBAAc,GAAG;AAAA,IACnB,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,kBAAkB,MAAqD;AAC3F,QAAM,SAAqB;AAAA,IACzB,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,EACb;AAEA,MAAI,KAAK,QAAQ;AACf,WAAO,QAAQ,KAAK,GAAG,KAAK,SAAS,YAAY;AACjD,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AAAA,IACX,GAAG,KAAK,WAAW;AAAA,IACnB;AAAA,IACA,KAAK;AAAA,IACL;AAAA,IACA,KAAK;AAAA,IACL;AAAA,IACA,KAAK;AAAA,IACL;AAAA,IACA,KAAK;AAAA,EACP;AAEA,MAAI;AACF,UAAM,eAAgB,KAAK,gBAAgB;AAC3C,UAAM,OAAO,MAAM,WAAW,KAAK,YAAY,MAAM,YAAY;AACjE,QAAI,SAAS,GAAG;AACd,aAAO,QAAQ,KAAK,KAAK,SAAS;AAAA,IACpC,OAAO;AACL,aAAO,SAAS;AAAA,QACd,eAAe,KAAK,SAAS,qBAAqB,IAAI;AAAA,MACxD;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,SAAS;AAAA,MACd,6BAA6B,KAAK,SAAS,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAClG;AAAA,EACF;AAEA,SAAO;AACT;;;ACjDA,SAAS,cAA0B;AACjC,SAAO;AAAA,IACL,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,EACb;AACF;AAEA,eAAsB,cAAc,MAAwD;AAC1F,QAAM,UAA6B,CAAC;AACpC,QAAM,aAAa,KAAK,cAAc;AAEtC,aAAW,aAAa,KAAK,WAAW;AACtC,YAAQ,SAAS,IAAI,MAAM,YAAY,WAAW,MAAM,UAAU;AAAA,EACpE;AAEA,SAAO;AACT;AAEA,eAAe,YACb,WACA,MACA,YACqB;AACrB,MAAI,cAAc,eAAe;AAC/B,WAAO,WAAW;AAAA,MAChB,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK,MAAM;AAAA,MACtB,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,MAAI,cAAc,WAAW,cAAc,YAAY;AACrD,QAAI,KAAK,QAAQ;AACf,YAAMC,UAAS,YAAY;AAC3B,MAAAA,QAAO,QAAQ,KAAK,GAAG,SAAS,YAAY;AAC5C,aAAOA;AAAA,IACT;AACA,QAAI,CAAC,KAAK,YAAY;AACpB,YAAMA,UAAS,YAAY;AAC3B,MAAAA,QAAO,SAAS;AAAA,QACd,WAAW,SAAS;AAAA,MACtB;AACA,aAAOA;AAAA,IACT;AACA,WAAO,kBAAkB;AAAA,MACvB;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK,MAAM;AAAA,MACpB,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,YAAY;AAC3B,SAAO,SAAS,KAAK,wBAAwB,SAAS,EAAE;AACxD,SAAO;AACT;;;ACpFA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AAiBf,IAAM,gBAA+B;AAAA,EACnC;AAAA,IACE,IAAI;AAAA,IACJ,eAAe;AAAA,IACf,cAAc;AAAA,EAChB;AAAA,EACA,EAAE,IAAI,SAAS,eAAe,SAAS;AAAA,EACvC,EAAE,IAAI,YAAY,eAAe,YAAY;AAC/C;AAEO,SAAS,sBACd,iBACqB;AACrB,QAAM,UAAU,mBAAmBA,IAAG,QAAQ;AAE9C,SAAO,cAAc,IAAI,CAAC,SAAS;AACjC,UAAM,YAAYD,MAAK,KAAK,SAAS,KAAK,aAAa;AACvD,UAAM,YAAYD,IAAG,WAAW,SAAS;AACzC,UAAM,gBAAgB,KAAK,eACvBA,IAAG,WAAWC,MAAK,KAAK,WAAW,KAAK,YAAY,CAAC,IACrD;AAEJ,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,SAAS,oBAAoB,SAA+B;AACjE,SAAO,sBAAsB,OAAO,EACjC,OAAO,CAAC,MAAM,EAAE,SAAS,EACzB,IAAI,CAAC,MAAM,EAAE,EAAE;AACpB;AAEO,IAAM,cAA2B,cAAc,IAAI,CAAC,SAAS,KAAK,EAAE;AAEpE,SAAS,iBAAiB,OAAmC;AAClE,SAAO,cAAc,KAAK,CAAC,SAAS,KAAK,OAAO,KAAK;AACvD;;;ACzDO,IAAM,iBAA4C;AAAA,EACvD,eAAe;AAAA,EACf,OAAO;AAAA,EACP,UAAU;AACZ;AAEO,SAAS,oBACd,UACqB;AACrB,SAAO,SAAS,IAAI,CAAC,aAAa;AAAA,IAChC,IAAI,QAAQ;AAAA,IACZ,OAAO,eAAe,QAAQ,EAAE;AAAA,IAChC,SAAS,QAAQ;AAAA,EACnB,EAAE;AACJ;AAEO,SAAS,wBACd,UACA,WACa;AACb,MAAI,cAAc,QAAW;AAC3B,WAAO,SAAS,OAAO,CAAC,YAAY,QAAQ,SAAS,EAAE,IAAI,CAAC,YAAY,QAAQ,EAAE;AAAA,EACpF;AACA,QAAM,WAAW,oBAAI,IAAe;AACpC,aAAW,MAAM,WAAW;AAC1B,UAAM,QAAQ,SAAS,KAAK,CAAC,YAAY,QAAQ,OAAO,EAAE;AAC1D,QAAI,OAAO;AACT,eAAS,IAAI,MAAM,EAAE;AAAA,IACvB;AAAA,EACF;AACA,SAAO,MAAM,KAAK,QAAQ;AAC5B;;;ACVA,SAAS,iBAAiB,OAAiB,QAA8B;AACvE,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAkF,CAAC;AACzF,MAAI,YAAY;AAChB,MAAI,QAAQ;AAEZ,WAAS,aAAmB;AAC1B,WAAO,MAAM,SAAS,KAAK,OAAO,SAAS,GAAG;AAC5C,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,OAAO,OAAO,MAAM;AAC1B,UAAI,QAAQ,SAAS,QAAW;AAC9B,aAAK,QAAQ,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,GAAG,QAAQ,CAAC,UAA2B;AAC3C,UAAM,OAAO,YAAY,MAAM,SAAS,OAAO;AAC/C,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,gBAAY,MAAM,IAAI,KAAK;AAC3B,eAAW,QAAQ,OAAO;AACxB,aAAO,KAAK,KAAK,QAAQ,OAAO,EAAE,CAAC;AAAA,IACrC;AACA,eAAW;AAAA,EACb,CAAC;AAED,QAAM,GAAG,OAAO,MAAM;AACpB,YAAQ;AACR,QAAI,UAAU,SAAS,GAAG;AACxB,aAAO,KAAK,UAAU,QAAQ,OAAO,EAAE,CAAC;AACxC,kBAAY;AAAA,IACd;AACA,eAAW;AACX,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,QAAQ,EAAE;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,MAAM,GAAG,OAAO,GAAG;AAAA,IAC3B;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,SAAS,QAAiC;AACxC,aAAO,MAAM,MAAM;AACnB,UAAI,OAAO,SAAS,GAAG;AACrB,eAAO,QAAQ,QAAQ,OAAO,MAAM,KAAK,EAAE;AAAA,MAC7C;AACA,UAAI,OAAO;AACT,eAAO,QAAQ,QAAQ,EAAE;AAAA,MAC3B;AACA,aAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9C,cAAM,KAAK,EAAE,SAAS,OAAO,CAAC;AAAA,MAChC,CAAC;AAAA,IACH;AAAA,IACA,QAAc;AAAA,IAEd;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,MAAsB;AAC7C,SAAO,KAAK,KAAK,EAAE,YAAY;AACjC;AAEO,SAAS,aAAa,UAAyB,CAAC,GAAW;AAChE,QAAM,QAAQ,QAAQ,SAAS,QAAQ;AACvC,QAAM,SAAS,QAAQ,UAAU,QAAQ;AACzC,QAAM,SAAS,iBAAiB,OAAO,MAAM;AAE7C,iBAAe,IAAI,UAAmC;AACpD,WAAO,OAAO,SAAS,QAAQ;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ,UAAkB,eAAe,MAAwB;AACrE,YAAM,OAAO,eAAe,UAAU;AACtC,YAAM,QAAQ,MAAM,IAAI,GAAG,QAAQ,IAAI,IAAI,GAAG;AAC9C,YAAM,aAAa,gBAAgB,KAAK;AACxC,UAAI,eAAe,OAAO,eAAe,OAAO;AAC9C,eAAO;AAAA,MACT;AACA,UAAI,eAAe,OAAO,eAAe,MAAM;AAC7C,eAAO;AAAA,MACT;AACA,UAAI,eAAe,IAAI;AACrB,eAAO;AAAA,MACT;AACA,YAAM,SAAS,MAAM,IAAI,wBAAwB;AACjD,YAAM,mBAAmB,gBAAgB,MAAM;AAC/C,UAAI,qBAAqB,OAAO,qBAAqB,OAAO;AAC1D,eAAO;AAAA,MACT;AACA,UAAI,qBAAqB,OAAO,qBAAqB,MAAM;AACzD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,YACJ,UACA,SACmB;AACnB,YAAM,QAAQ,QAAQ,IAAI,CAAC,KAAK,UAAU;AACxC,cAAM,OAAO,IAAI,UAAU,MAAM;AACjC,eAAO,MAAM,IAAI,KAAK,QAAQ,CAAC,KAAK,IAAI,KAAK;AAAA,MAC/C,CAAC;AACD,YAAM,aAAa,GAAG,QAAQ;AAAA,EAAK,MAAM,KAAK,IAAI,CAAC;AAAA;AAEnD,qBAAe,MAAM,QAA+C;AAClE,cAAM,aAAa,gBAAgB,MAAM;AACzC,YAAI,eAAe,OAAO;AACxB,iBAAO,QAAQ,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,QACpC;AACA,YAAI,eAAe,QAAQ;AACzB,iBAAO,CAAC;AAAA,QACV;AACA,YAAI,eAAe,IAAI;AACrB,iBAAO,QAAQ,OAAO,CAAC,QAAQ,IAAI,OAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,QACjE;AACA,cAAM,QAAQ,WAAW,MAAM,QAAQ,EAAE,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACzE,cAAM,WAAW,oBAAI,IAAY;AACjC,mBAAW,QAAQ,OAAO;AACxB,gBAAM,QAAQ,OAAO,IAAI;AACzB,cAAI,CAAC,OAAO,MAAM,KAAK,KAAK,SAAS,KAAK,SAAS,QAAQ,QAAQ;AACjE,qBAAS,IAAI,QAAQ,QAAQ,CAAC,EAAE,EAAE;AAClC;AAAA,UACF;AACA,gBAAM,QAAQ,QAAQ,KAAK,CAAC,QAAQ,IAAI,OAAO,IAAI;AACnD,cAAI,OAAO;AACT,qBAAS,IAAI,MAAM,EAAE;AACrB;AAAA,UACF;AACA,iBAAO;AAAA,QACT;AACA,eAAO,MAAM,KAAK,QAAQ;AAAA,MAC5B;AAEA,UAAI,SAAS,MAAM,MAAM,MAAM,IAAI,UAAU,CAAC;AAC9C,UAAI,WAAW,QAAW;AACxB,eAAO;AAAA,MACT;AACA,YAAM,QAAQ,MAAM,IAAI,uCAAuC;AAC/D,eAAS,MAAM,MAAM,KAAK;AAC1B,aAAO,UAAU,CAAC;AAAA,IACpB;AAAA,IAEA,QAAc;AACZ,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;;;AV7IO,SAAS,oBAAiC;AAC/C,SAAO;AAAA,IACL,OAAO,oBAAoB;AAAA,IAC3B,aAAa,mBAAmB,KAAK;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK;AAAA,EAC5D;AACF;AAEA,eAAsB,QACpB,SACA,OAAoB,kBAAkB,GACrB;AACjB,QAAM,UAAU,wBAAwB;AACxC,MAAI,CAAC,SAAS;AACZ,YAAQ,MAAM,qCAAqC;AACnD,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,KAAK;AACzB,MAAI,CAAC,eAAe,CAACE,IAAG,WAAW,WAAW,GAAG;AAC/C,YAAQ,MAAM,8EAA8E;AAC5F,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,QAAQ,QAAQ,iBAAiB,CAAC,KAAK,QAAQ;AAC7E,YAAQ;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM,iBAAiB,SAAS,IAAI;AACtD,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,sBAAsB,SAAS,MAAM,SAAS;AACvE,MAAI,eAAe,MAAM;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ,QAAQ;AACnB,UAAM,aAAaC,MAAK,KAAK,KAAK,MAAM,aAAa,OAAO;AAC5D,IAAAD,IAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,IAAAA,IAAG,OAAO,aAAa,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACnE,QAAI;AACF,MAAAA,IAAG,OAAO,KAAK,MAAM,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjE,MAAAA,IAAG,YAAY,YAAY,KAAK,MAAM,UAAU;AAAA,IAClD,QAAQ;AACN,MAAAA,IAAG,OAAO,KAAK,MAAM,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjE,MAAAA,IAAG,OAAO,YAAY,KAAK,MAAM,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IAC/E;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,KAAK,cAAc;AAAA,IACvC;AAAA,IACA,aAAa,KAAK,MAAM;AAAA,IACxB,OAAO,KAAK;AAAA,IACZ,YAAY,KAAK,MAAM;AAAA,IACvB;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,QAAQ,QAAQ;AACnB,uBAAmB,KAAK,OAAO;AAAA,MAC7B;AAAA,MACA,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,MACA,cAAc,oBAAoB,OAAO;AAAA,IAC3C,CAAC;AAAA,EACH;AAEA,eAAa,SAAS,SAAS,WAAW,OAAO;AACjD,SAAO;AACT;AAEA,eAAe,sBACb,SACA,MACA,WACoC;AACpC,QAAM,cACJ,CAAC,QAAQ,UAAU,CAAC,QAAQ,UAAU,UAAU,KAAK,CAAC,OAAO,OAAO,WAAW,OAAO,UAAU;AAClG,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,MAAM,KAAK,qBAAqB;AACtD,MAAI,CAAC,eAAe;AAClB,YAAQ;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,KAAK,OAAO,KAAK,aAAa,aAAa;AAC3D,SAAO,eAAe,KAAK,KAAK;AAClC;AAEA,eAAe,iBAAiB,SAAyB,MAAyC;AAChG,QAAM,WAAW,sBAAsB,KAAK,MAAM,OAAO;AAEzD,MAAI,QAAQ,UAAU,SAAS,GAAG;AAChC,UAAM,UAAU,QAAQ,UAAU,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;AACtE,QAAI,QAAQ,SAAS,GAAG;AACtB,cAAQ,MAAM,0BAA0B,QAAQ,KAAK,IAAI,CAAC,EAAE;AAC5D,cAAQ,MAAM,cAAc,YAAY,KAAK,IAAI,CAAC,EAAE;AACpD,aAAO,CAAC;AAAA,IACV;AACA,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,WAAW,oBAAoB,KAAK,MAAM,OAAO;AACvD,MAAI,SAAS,SAAS,KAAK,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAAO,CAAC,QAAQ,iBAAiB,KAAK,OAAO;AAClG,UAAM,SAAS,KAAK,aAAa;AACjC,QAAI;AACF,YAAM,SAAS,MAAM,OAAO;AAAA,QAC1B;AAAA,QACA,oBAAoB,QAAQ;AAAA,MAC9B;AACA,YAAM,WAAW,wBAAwB,UAAU,MAAM;AACzD,UAAI,SAAS,WAAW,GAAG;AACzB,gBAAQ,MAAM,kCAAkC;AAChD,eAAO,CAAC;AAAA,MACV;AACA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,cAAQ,MAAM,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACjG,aAAO,CAAC;AAAA,IACV,UAAE;AACA,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,KAAK,CAAC,QAAQ,QAAQ;AAC5C,YAAQ,MAAM,2EAA2E;AACzF,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;AAEA,SAAS,oBAAoB,SAAsC;AACjE,QAAM,QAAkB,CAAC;AACzB,aAAW,UAAU,OAAO,OAAO,OAAO,GAAG;AAC3C,UAAM,KAAK,GAAG,OAAO,SAAS,GAAG,OAAO,SAAS,GAAG,OAAO,SAAS;AAAA,EACtE;AACA,SAAO;AACT;AAEA,SAAS,aACP,SACA,SACA,WACA,SACM;AACN,QAAM,WAAW,gBAAgB,OAAO;AACxC,MAAI,QAAQ,QAAQ;AAClB,YAAQ,IAAI,kCAAkC,OAAO,mBAAmB,UAAU,KAAK,IAAI,CAAC,EAAE;AAAA,EAChG,OAAO;AACL,YAAQ,IAAI,qBAAqB,OAAO,mBAAmB,UAAU,KAAK,IAAI,CAAC,EAAE;AAAA,EACnF;AACA,aAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,UAAM,QAAQ,OAAO,QAAQ,SAAS,OAAO,QAAQ,SAAS,OAAO,UAAU;AAC/E,YAAQ,IAAI,KAAK,SAAS,KAAK,KAAK,UAAU;AAAA,EAChD;AACA,aAAW,WAAW,UAAU;AAC9B,YAAQ,KAAK,cAAc,OAAO,EAAE;AAAA,EACtC;AACF;AAEA,SAAS,gBAAgB,SAAsC;AAC7D,QAAM,WAAqB,CAAC;AAC5B,aAAW,UAAU,OAAO,OAAO,OAAO,GAAG;AAC3C,aAAS,KAAK,GAAG,OAAO,QAAQ;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAASE,YAAW,SAAiB,MAAiC;AACpE,SAAO,IAAI,QAAQ,CAAC,gBAAgB,kBAAkB;AACpD,UAAM,QAAQC,OAAM,SAAS,MAAM,EAAE,OAAO,UAAU,CAAC;AACvD,UAAM,GAAG,SAAS,CAAC,SAAS,eAAe,QAAQ,CAAC,CAAC;AACrD,UAAM,GAAG,SAAS,CAAC,QAAQ,cAAc,GAAG,CAAC;AAAA,EAC/C,CAAC;AACH;AAEA,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,4BAA4B,CAAC,cAAc,cAAc,cAAc,SAAS;AAEtF,SAAS,mBAAmB,SAA+D;AACzF,QAAM,QAAQ,eAAe,KAAK,OAAO;AACzC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,SAAO,EAAE,OAAO,OAAO,MAAM,CAAC,CAAC,GAAG,OAAO,OAAO,MAAM,CAAC,CAAC,EAAE;AAC5D;AAEA,eAAe,mBAAmB,SAA8C;AAC9E,SAAO,IAAI,QAAQ,CAAC,mBAAmB;AACrC,UAAM,QAAQA,OAAM,SAAS,CAAC,WAAW,GAAG;AAAA,MAC1C,OAAO,CAAC,UAAU,QAAQ,QAAQ;AAAA,MAClC,OAAO,QAAQ,aAAa;AAAA,IAC9B,CAAC;AACD,QAAI,SAAS;AACb,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAA2B;AACnD,gBAAU,MAAM,SAAS;AAAA,IAC3B,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,YAAM,OAAO,OAAO,KAAK;AACzB,qBAAe,SAAS,KAAK,KAAK,SAAS,IAAI,OAAO,MAAS;AAAA,IACjE,CAAC;AACD,UAAM,GAAG,SAAS,MAAM,eAAe,MAAS,CAAC;AAAA,EACnD,CAAC;AACH;AAEA,eAAsB,qBACpB,cAAkC,QAAQ,IAAI,gBAC9C,aAAuB,2BACvB,eAA6D,oBAChC;AAC7B,QAAM,OAAO,cAAc,CAAC,WAAW,IAAI;AAC3C,aAAW,OAAO,MAAM;AACtB,UAAM,UAAU,MAAM,aAAa,GAAG;AACtC,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,UAAM,SAAS,mBAAmB,OAAO;AACzC,QACE,UACA,OAAO,SAAS,qBACf,OAAO,QAAQ,oBAAoB,OAAO,SAAS,mBACpD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAA6B;AACnD,SAAOF,MAAK;AAAA,IACV,MAAM;AAAA,IACN,QAAQ,aAAa,UAAU,YAAY;AAAA,IAC3C,QAAQ,aAAa,UAAU,eAAe;AAAA,EAChD;AACF;AAEA,eAAe,UAAU,OAAqB,aAAqB,eAAsC;AACvG,QAAM,YAAY,eAAe,KAAK;AAEtC,MAAI,CAACD,IAAG,WAAW,SAAS,GAAG;AAC7B,YAAQ,IAAI,yCAAyC;AACrD,UAAM,WAAW,MAAME,YAAW,eAAe,CAAC,MAAM,QAAQ,MAAM,OAAO,CAAC;AAC9E,QAAI,aAAa,GAAG;AAClB,YAAM,IAAI,MAAM,mDAAmD,QAAQ,GAAG;AAAA,IAChF;AAAA,EACF;AAEA,QAAM,mBAAmBD,MAAK,KAAK,aAAa,kBAAkB;AAClE,MAAID,IAAG,WAAW,gBAAgB,GAAG;AACnC,YAAQ,IAAI,mCAAmC;AAC/C,UAAM,SAASC,MAAK;AAAA,MAClB,MAAM;AAAA,MACN,QAAQ,aAAa,UAAU,YAAY;AAAA,MAC3C,QAAQ,aAAa,UAAU,YAAY;AAAA,IAC7C;AACA,UAAM,UAAU,MAAMC,YAAW,QAAQ,CAAC,WAAW,MAAM,gBAAgB,CAAC;AAC5E,QAAI,YAAY,GAAG;AACjB,YAAM,IAAI,MAAM,oDAAoD,OAAO,GAAG;AAAA,IAChF;AAAA,EACF;AACF;;;AW/SA,SAAS,UAAU,KAAkD;AACnE,MAAI,IAAI,IAAI;AACV,WAAO;AAAA,EACT;AACA,MAAI,IAAI,aAAa,QAAQ;AAC3B,WAAO;AAAA,EACT;AACA,MAAI,IAAI,0BAA0B;AAChC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAASE,qBAAqC;AACnD,SAAO;AAAA,IACL,OAAO,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK;AAAA,IAC1D,SAAS,OAAO,aAAqB;AACnC,YAAM,SAAS,aAAa;AAC5B,UAAI;AACF,eAAO,MAAM,OAAO,QAAQ,UAAU,IAAI;AAAA,MAC5C,UAAE;AACA,eAAO,MAAM;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS,YACP,QAAW,EAAE,KAAK,OAAO,QAAQ,OAAO,OAAO,OAAO,WAAW,CAAC,GAAG,QAAQ,OAAO,eAAe,MAAM,CAAC;AAAA,IAC5G,KAAK,QAAQ;AAAA,EACf;AACF;AAEA,eAAsB,eAAe,OAAwBA,mBAAkB,GAAoB;AACjG,MAAI,UAAU,KAAK,GAAG,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,KAAK,OAAO;AACf,YAAQ,IAAI,6BAA6B;AACzC,YAAQ,IAAI,wCAAwC;AACpD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,KAAK,MAAM,KAAK,QAAQ,kCAAkC;AAChE,QAAI,CAAC,IAAI;AACP,cAAQ,IAAI,gDAAgD;AAC5D,aAAO;AAAA,IACT;AACA,UAAM,KAAK,QAAQ;AACnB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,YAAQ,IAAI,6BAA6B;AACzC,YAAQ,IAAI,gDAAgD;AAC5D,QAAI,eAAe,OAAO;AACxB,cAAQ,MAAM,8BAA8B,IAAI,OAAO,EAAE;AAAA,IAC3D;AACA,WAAO;AAAA,EACT;AACF;AAEA,IAAI,YAAY,QAAQ,UAAU,QAAQ,KAAK,CAAC,CAAC,IAAI;AACnD,iBAAe,EACZ,KAAK,CAAC,SAAS,QAAQ,KAAK,IAAI,CAAC,EACjC,MAAM,MAAM,QAAQ,KAAK,CAAC,CAAC;AAChC;","names":["fs","path","spawn","path","path","fs","path","fs","path","fs","path","report","fs","path","os","fs","path","runCommand","spawn","createDefaultDeps"]}
1
+ {"version":3,"sources":["../src/commands/install.ts","../src/lib/paths.ts","../src/lib/versionMarker.ts","../src/lib/packageInfo.ts","../src/lib/syncClaude.ts","../src/lib/claudeMdMerge.ts","../src/lib/runHarnessAdapter.ts","../src/lib/syncHarness.ts","../src/lib/syncSkills.ts","../src/lib/semver.ts","../src/lib/harnessDetect.ts","../src/lib/harnessSelect.ts","../src/lib/prompt.ts","../src/postinstall.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport type { LincolnPaths } from '../lib/paths.js'\nimport { resolveLincolnPaths } from '../lib/paths.js'\nimport { writeVersionMarker } from '../lib/versionMarker.js'\nimport { readLocalPackageVersion, resolvePayloadRoot } from '../lib/packageInfo.js'\nimport type { HarnessSyncReport, SyncHarnessesOptions } from '../lib/syncHarness.js'\nimport { syncHarnesses } from '../lib/syncHarness.js'\nimport type { SkillSyncReport, SyncExternalSkillsOptions } from '../lib/syncSkills.js'\nimport { syncExternalSkills } from '../lib/syncSkills.js'\nimport { detectGlobalHarnesses, installedHarnessIds, isValidHarnessId, HARNESS_IDS } from '../lib/harnessDetect.js'\nimport type { HarnessId } from '../lib/harnessDetect.js'\nimport { buildHarnessOptions, resolveHarnessSelection } from '../lib/harnessSelect.js'\nimport { createPrompt } from '../lib/prompt.js'\nimport type { Prompt } from '../lib/prompt.js'\n\nexport interface InstallOptions {\n yes: boolean\n dryRun: boolean\n force: boolean\n harnesses: string[]\n noVenv: boolean\n noInteractive: boolean\n}\n\nexport interface InstallDeps {\n paths: LincolnPaths\n payloadRoot: string\n syncHarnesses: (opts: SyncHarnessesOptions) => Promise<HarnessSyncReport>\n syncExternalSkills?: (opts: SyncExternalSkillsOptions) => Promise<SkillSyncReport>\n createPrompt: () => Prompt\n resolvePythonForVenv: (\n envOverride?: string,\n candidates?: string[],\n queryVersion?: (cmd: string) => Promise<string | undefined>\n ) => Promise<string | undefined>\n isTTY: boolean\n}\n\nexport function createDefaultDeps(): InstallDeps {\n return {\n paths: resolveLincolnPaths(),\n payloadRoot: resolvePayloadRoot() || '',\n syncHarnesses,\n syncExternalSkills,\n createPrompt,\n resolvePythonForVenv,\n isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY)\n }\n}\n\nexport async function install(\n options: InstallOptions,\n deps: InstallDeps = createDefaultDeps()\n): Promise<number> {\n const version = readLocalPackageVersion()\n if (!version) {\n console.error('Could not determine Lincoln version')\n return 1\n }\n\n const payloadRoot = deps.payloadRoot\n if (!payloadRoot || !fs.existsSync(payloadRoot)) {\n console.error('Lincoln payload not found. Run \"npm install -g @sushanglewis/lincoln\" first.')\n return 1\n }\n\n if (!options.dryRun && !options.yes && (options.noInteractive || !deps.isTTY)) {\n console.error(\n 'This will install Lincoln globally. Run with --yes to proceed, or run interactively in a TTY.'\n )\n return 1\n }\n\n const harnesses = await resolveHarnesses(options, deps)\n if (harnesses.length === 0) {\n return 1\n }\n\n const pythonPath = await resolvePythonIfNeeded(options, deps, harnesses)\n if (pythonPath === null) {\n return 1\n }\n\n if (!options.dryRun) {\n const versionDir = path.join(deps.paths.versionsDir, version)\n fs.mkdirSync(versionDir, { recursive: true })\n fs.cpSync(payloadRoot, versionDir, { recursive: true, force: true })\n try {\n fs.rmSync(deps.paths.currentDir, { recursive: true, force: true })\n fs.symlinkSync(versionDir, deps.paths.currentDir)\n } catch {\n fs.rmSync(deps.paths.currentDir, { recursive: true, force: true })\n fs.cpSync(versionDir, deps.paths.currentDir, { recursive: true, force: true })\n }\n }\n\n const reports = await deps.syncHarnesses({\n harnesses,\n payloadRoot: deps.paths.currentDir,\n paths: deps.paths,\n projectDir: deps.paths.lincolnHome,\n version,\n dryRun: options.dryRun,\n pythonPath\n })\n\n if (!options.dryRun) {\n writeVersionMarker(deps.paths, {\n version,\n installedAt: new Date().toISOString(),\n harnesses,\n managedFiles: collectManagedFiles(reports)\n })\n }\n\n const skillReport = await syncSkillLibraries(options, deps, harnesses)\n\n printSummary(options, version, harnesses, reports, skillReport)\n return 0\n}\n\nasync function syncSkillLibraries(\n options: InstallOptions,\n deps: InstallDeps,\n harnesses: HarnessId[]\n): Promise<SkillSyncReport | undefined> {\n if (!harnesses.includes('claude-code') || !deps.syncExternalSkills) {\n return undefined\n }\n const payloadRoot = deps.paths.currentDir\n const manifestPath = path.join(payloadRoot, '.claude', 'skills', 'dependencies.yaml')\n if (!fs.existsSync(manifestPath)) {\n return undefined\n }\n try {\n return await deps.syncExternalSkills({\n payloadRoot,\n skillsDir: path.join(deps.paths.claudeDir, 'skills'),\n dryRun: options.dryRun\n })\n } catch (err) {\n console.warn(` warning: external skill sync failed: ${err instanceof Error ? err.message : String(err)}`)\n return undefined\n }\n}\n\nasync function resolvePythonIfNeeded(\n options: InstallOptions,\n deps: InstallDeps,\n harnesses: HarnessId[]\n): Promise<string | undefined | null> {\n const needsPython =\n !options.dryRun && !options.noVenv && harnesses.some((id) => id === 'codex' || id === 'opencode')\n if (!needsPython) {\n return undefined\n }\n\n const pythonCommand = await deps.resolvePythonForVenv()\n if (!pythonCommand) {\n console.error(\n 'Python 3.10+ is required for Codex/OpenCode sync but was not found. Set LINCOLN_PYTHON to a compatible Python executable, or run with --no-venv.'\n )\n return null\n }\n\n await setupVenv(deps.paths, deps.payloadRoot, pythonCommand)\n return venvPythonPath(deps.paths)\n}\n\nasync function resolveHarnesses(options: InstallOptions, deps: InstallDeps): Promise<HarnessId[]> {\n const detected = detectGlobalHarnesses(deps.paths.homeDir)\n\n if (options.harnesses.length > 0) {\n const invalid = options.harnesses.filter((id) => !isValidHarnessId(id))\n if (invalid.length > 0) {\n console.error(`Unknown harness id(s): ${invalid.join(', ')}`)\n console.error(`Valid ids: ${HARNESS_IDS.join(', ')}`)\n return []\n }\n return options.harnesses as HarnessId[]\n }\n\n const selected = installedHarnessIds(deps.paths.homeDir)\n if (selected.length > 0 && !options.dryRun && !options.yes && !options.noInteractive && deps.isTTY) {\n const prompt = deps.createPrompt()\n try {\n const answer = await prompt.multiSelect(\n 'Select agent harnesses to install Lincoln into:',\n buildHarnessOptions(detected)\n )\n const resolved = resolveHarnessSelection(detected, answer)\n if (resolved.length === 0) {\n console.error('No harnesses selected. Aborting.')\n return []\n }\n return resolved\n } catch (err) {\n console.error(`Interactive selection failed: ${err instanceof Error ? err.message : String(err)}`)\n return []\n } finally {\n prompt.close()\n }\n }\n\n if (selected.length === 0 && !options.dryRun) {\n console.error('No agent harness detected. Install Claude Code, Codex, or OpenCode first.')\n return []\n }\n\n return selected\n}\n\nfunction collectManagedFiles(reports: HarnessSyncReport): string[] {\n const files: string[] = []\n for (const report of Object.values(reports)) {\n files.push(...report.written, ...report.skipped, ...report.preserved)\n }\n return files\n}\n\nfunction printSummary(\n options: InstallOptions,\n version: string,\n harnesses: HarnessId[],\n reports: HarnessSyncReport,\n skillReport?: SkillSyncReport\n): void {\n const warnings = collectWarnings(reports)\n if (options.dryRun) {\n console.log(`Dry run: would install Lincoln ${version} for harnesses: ${harnesses.join(', ')}`)\n } else {\n console.log(`Installed Lincoln ${version} for harnesses: ${harnesses.join(', ')}`)\n }\n for (const [harnessId, report] of Object.entries(reports)) {\n const count = report.written.length + report.skipped.length + report.preserved.length\n console.log(` ${harnessId}: ${count} file(s)`)\n }\n if (skillReport) {\n for (const entry of skillReport.entries) {\n const detail = entry.detail ? ` (${entry.detail})` : ''\n console.log(` skill ${entry.name}: ${entry.status}${detail}`)\n }\n warnings.push(...skillReport.warnings)\n }\n for (const warning of warnings) {\n console.warn(` warning: ${warning}`)\n }\n}\n\nfunction collectWarnings(reports: HarnessSyncReport): string[] {\n const warnings: string[] = []\n for (const report of Object.values(reports)) {\n warnings.push(...report.warnings)\n }\n return warnings\n}\n\nfunction runCommand(command: string, args: string[]): Promise<number> {\n return new Promise((resolvePromise, rejectPromise) => {\n const child = spawn(command, args, { stdio: 'inherit' })\n child.on('close', (code) => resolvePromise(code ?? 1))\n child.on('error', (err) => rejectPromise(err))\n })\n}\n\nconst MIN_PYTHON_MAJOR = 3\nconst MIN_PYTHON_MINOR = 10\nconst DEFAULT_PYTHON_CANDIDATES = ['python3.12', 'python3.11', 'python3.10', 'python3']\n\nfunction parsePythonVersion(version: string): { major: number; minor: number } | undefined {\n const match = /(\\d+)\\.(\\d+)/.exec(version)\n if (!match) {\n return undefined\n }\n return { major: Number(match[1]), minor: Number(match[2]) }\n}\n\nasync function queryPythonVersion(command: string): Promise<string | undefined> {\n return new Promise((resolvePromise) => {\n const child = spawn(command, ['--version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n shell: process.platform === 'win32'\n })\n let stdout = ''\n child.stdout?.on('data', (chunk: Buffer | string) => {\n stdout += chunk.toString()\n })\n child.on('close', (code) => {\n const text = stdout.trim()\n resolvePromise(code === 0 && text.length > 0 ? text : undefined)\n })\n child.on('error', () => resolvePromise(undefined))\n })\n}\n\nexport async function resolvePythonForVenv(\n envOverride: string | undefined = process.env.LINCOLN_PYTHON,\n candidates: string[] = DEFAULT_PYTHON_CANDIDATES,\n queryVersion: (cmd: string) => Promise<string | undefined> = queryPythonVersion\n): Promise<string | undefined> {\n const list = envOverride ? [envOverride] : candidates\n for (const cmd of list) {\n const version = await queryVersion(cmd)\n if (!version) {\n continue\n }\n const parsed = parsePythonVersion(version)\n if (\n parsed &&\n parsed.major >= MIN_PYTHON_MAJOR &&\n (parsed.major > MIN_PYTHON_MAJOR || parsed.minor >= MIN_PYTHON_MINOR)\n ) {\n return cmd\n }\n }\n return undefined\n}\n\nfunction venvPythonPath(paths: LincolnPaths): string {\n return path.join(\n paths.venvDir,\n process.platform === 'win32' ? 'Scripts' : 'bin',\n process.platform === 'win32' ? 'python.exe' : 'python'\n )\n}\n\nasync function setupVenv(paths: LincolnPaths, payloadRoot: string, pythonCommand: string): Promise<void> {\n const pythonExe = venvPythonPath(paths)\n\n if (!fs.existsSync(pythonExe)) {\n console.log('Creating Lincoln virtual environment...')\n const venvCode = await runCommand(pythonCommand, ['-m', 'venv', paths.venvDir])\n if (venvCode !== 0) {\n throw new Error(`Failed to create virtual environment (exit code ${venvCode})`)\n }\n }\n\n const requirementsPath = path.join(payloadRoot, 'requirements.txt')\n if (fs.existsSync(requirementsPath)) {\n console.log('Installing Python dependencies...')\n const pipExe = path.join(\n paths.venvDir,\n process.platform === 'win32' ? 'Scripts' : 'bin',\n process.platform === 'win32' ? 'pip.exe' : 'pip'\n )\n const pipCode = await runCommand(pipExe, ['install', '-r', requirementsPath])\n if (pipCode !== 0) {\n throw new Error(`Failed to install Python dependencies (exit code ${pipCode})`)\n }\n }\n}\n","import path from 'node:path'\nimport os from 'node:os'\n\nexport interface LincolnPaths {\n homeDir: string\n lincolnHome: string\n versionsDir: string\n currentDir: string\n versionMarker: string\n venvDir: string\n claudeDir: string\n codexDir: string\n opencodeDir: string\n}\n\nexport function resolveLincolnPaths(overrideHomeDir?: string): LincolnPaths {\n const homeDir = overrideHomeDir ?? os.homedir()\n const lincolnHome = process.env.LINCOLN_HOME\n ? path.resolve(process.env.LINCOLN_HOME)\n : path.join(homeDir, '.lincoln')\n\n return {\n homeDir,\n lincolnHome,\n versionsDir: path.join(lincolnHome, 'versions'),\n currentDir: path.join(lincolnHome, 'current'),\n versionMarker: path.join(lincolnHome, 'marker.json'),\n venvDir: path.join(lincolnHome, 'venv'),\n claudeDir: path.join(homeDir, '.claude'),\n codexDir: path.join(homeDir, '.codex'),\n opencodeDir: path.join(homeDir, '.opencode')\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { LincolnPaths } from './paths.js'\n\nexport interface VersionMarker {\n version: string\n installedAt: string\n harnesses: string[]\n managedFiles: string[]\n}\n\nexport function readVersionMarker(paths: LincolnPaths): VersionMarker | undefined {\n try {\n const raw = fs.readFileSync(paths.versionMarker, 'utf8')\n const parsed = JSON.parse(raw) as VersionMarker\n if (\n typeof parsed.version === 'string' &&\n typeof parsed.installedAt === 'string' &&\n Array.isArray(parsed.harnesses)\n ) {\n return parsed\n }\n return undefined\n } catch {\n return undefined\n }\n}\n\nexport function writeVersionMarker(\n paths: LincolnPaths,\n marker: VersionMarker\n): void {\n fs.mkdirSync(path.dirname(paths.versionMarker), { recursive: true })\n fs.writeFileSync(paths.versionMarker, JSON.stringify(marker, null, 2) + '\\n')\n}\n\nexport function isUpToDate(paths: LincolnPaths, version: string): boolean {\n const marker = readVersionMarker(paths)\n return marker?.version === version\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/**\n * Finds the directory containing the running lincoln package's package.json.\n * Returns undefined when no package.json can be located.\n */\nexport function readLocalPackageRoot(): string | undefined {\n try {\n let dir = path.dirname(fileURLToPath(import.meta.url))\n const root = path.parse(dir).root\n while (dir !== root) {\n const pkgPath = path.join(dir, 'package.json')\n if (fs.existsSync(pkgPath)) {\n const parsed = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as { name?: string }\n if (parsed.name === '@sushanglewis/lincoln') {\n return dir\n }\n }\n dir = path.dirname(dir)\n }\n } catch {\n // ignore and return undefined\n }\n return undefined\n}\n\n/**\n * Reads the version of the running lincoln package from its own package.json.\n * Walks upward from the current module file until it finds the package.json.\n * Returns undefined when the package.json cannot be located or parsed.\n */\nexport function readLocalPackageVersion(): string | undefined {\n try {\n const root = readLocalPackageRoot()\n if (!root) return undefined\n const parsed = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')) as {\n version?: string\n }\n return typeof parsed.version === 'string' ? parsed.version : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Resolves the bundled framework payload directory inside the running package.\n */\nexport function resolvePayloadRoot(): string | undefined {\n const root = readLocalPackageRoot()\n if (!root) return undefined\n const payload = path.join(root, 'framework')\n return fs.existsSync(payload) ? payload : undefined\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport { mergeManagedBlock } from './claudeMdMerge.js'\n\nexport interface SyncOptions {\n payloadRoot: string\n targetDir: string\n version: string\n dryRun: boolean\n}\n\nexport interface SyncReport {\n written: string[]\n skipped: string[]\n preserved: string[]\n warnings: string[]\n settingsTouched?: string[]\n}\n\nconst COPY_SUBDIRS = [\n 'agents',\n 'skills',\n 'workflows',\n 'stages',\n 'schemas',\n 'templates',\n 'harnesses',\n // Policies are data files consumed by hooks at runtime (e.g.\n // .claude/policies/less-is-more.md read by on-session-start.sh,\n // security.yaml read by pre-tool-use.sh). Without syncing them into the\n // project, vendored installs silently skip those guardrails (#126).\n 'policies'\n]\n\nfunction sha256(filePath: string): string {\n const data = fs.readFileSync(filePath)\n return crypto.createHash('sha256').update(data).digest('hex')\n}\n\nfunction sameContent(a: string, b: string): boolean {\n return sha256(a) === sha256(b)\n}\n\nfunction deepMergeSettings(existing: unknown, incoming: unknown): unknown {\n if (Array.isArray(existing) && Array.isArray(incoming)) {\n return incoming\n }\n if (\n typeof existing === 'object' &&\n existing !== null &&\n typeof incoming === 'object' &&\n incoming !== null\n ) {\n const result: Record<string, unknown> = { ...existing }\n for (const [key, value] of Object.entries(incoming)) {\n if (key in result) {\n result[key] = deepMergeSettings(result[key], value)\n } else {\n result[key] = value\n }\n }\n return result\n }\n return incoming\n}\n\nexport function syncClaudeCode(opts: SyncOptions): SyncReport {\n const report: SyncReport = {\n written: [],\n skipped: [],\n preserved: [],\n warnings: [],\n settingsTouched: []\n }\n\n const payloadClaude = path.join(opts.payloadRoot, '.claude')\n if (!fs.existsSync(payloadClaude)) {\n report.warnings.push(`payload .claude directory not found: ${payloadClaude}`)\n return report\n }\n\n if (!opts.dryRun) {\n fs.mkdirSync(opts.targetDir, { recursive: true })\n }\n\n for (const subdir of COPY_SUBDIRS) {\n const srcDir = path.join(payloadClaude, subdir)\n if (!fs.existsSync(srcDir)) {\n continue\n }\n\n const destDir = path.join(opts.targetDir, subdir)\n if (!opts.dryRun) {\n fs.mkdirSync(destDir, { recursive: true })\n }\n\n for (const entry of walkSync(srcDir)) {\n const relativePath = path.relative(srcDir, entry)\n const srcFile = entry\n const destFile = path.join(destDir, relativePath)\n\n if (fs.existsSync(destFile) && sameContent(srcFile, destFile)) {\n report.skipped.push(path.join('.claude', subdir, relativePath))\n continue\n }\n\n if (!opts.dryRun) {\n fs.mkdirSync(path.dirname(destFile), { recursive: true })\n fs.copyFileSync(srcFile, destFile)\n }\n report.written.push(path.join('.claude', subdir, relativePath))\n }\n }\n\n // settings.json merge\n const payloadSettings = path.join(payloadClaude, 'settings.json')\n const targetSettings = path.join(opts.targetDir, 'settings.json')\n if (fs.existsSync(payloadSettings)) {\n const incoming = JSON.parse(fs.readFileSync(payloadSettings, 'utf8'))\n let merged = incoming\n if (fs.existsSync(targetSettings)) {\n const existing = JSON.parse(fs.readFileSync(targetSettings, 'utf8'))\n merged = deepMergeSettings(existing, incoming)\n }\n\n const wouldChange =\n !fs.existsSync(targetSettings) ||\n JSON.stringify(merged) !== JSON.stringify(JSON.parse(fs.readFileSync(targetSettings, 'utf8')))\n\n if (wouldChange) {\n if (!opts.dryRun) {\n fs.writeFileSync(targetSettings, JSON.stringify(merged, null, 2) + '\\n')\n }\n report.written.push('.claude/settings.json')\n report.settingsTouched = ['.claude/settings.json']\n } else {\n report.skipped.push('.claude/settings.json')\n }\n }\n\n // CLAUDE.md merge\n const payloadClaudeMd = path.join(opts.payloadRoot, 'CLAUDE.md')\n const targetClaudeMd = path.join(path.dirname(opts.targetDir), 'CLAUDE.md')\n if (fs.existsSync(payloadClaudeMd)) {\n const incomingBlock = fs.readFileSync(payloadClaudeMd, 'utf8')\n const existing = fs.existsSync(targetClaudeMd)\n ? fs.readFileSync(targetClaudeMd, 'utf8')\n : undefined\n const merged = mergeManagedBlock(existing, incomingBlock)\n\n if (merged !== existing) {\n if (!opts.dryRun) {\n fs.writeFileSync(targetClaudeMd, merged)\n }\n report.written.push('CLAUDE.md')\n } else {\n report.skipped.push('CLAUDE.md')\n }\n }\n\n return report\n}\n\nfunction* walkSync(dir: string): Generator<string> {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n yield* walkSync(fullPath)\n } else {\n yield fullPath\n }\n }\n}\n","const BEGIN = '<!-- lincoln:begin -->'\nconst END = '<!-- lincoln:end -->'\n\nexport function mergeManagedBlock(\n existing: string | undefined,\n block: string\n): string {\n const wrapped = `${BEGIN}\\n${block}\\n${END}`\n const text = existing ?? ''\n\n const beginIndex = text.indexOf(BEGIN)\n const endIndex = text.indexOf(END)\n\n if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {\n return (\n text.slice(0, beginIndex) +\n wrapped +\n text.slice(endIndex + END.length)\n )\n }\n\n if (text.trim().length === 0) {\n return wrapped\n }\n\n return `${text.trimEnd()}\\n\\n${wrapped}\\n`\n}\n\nexport function extractManagedBlock(existing: string): string | undefined {\n const beginIndex = existing.indexOf(BEGIN)\n const endIndex = existing.indexOf(END)\n if (beginIndex === -1 || endIndex === -1 || endIndex <= beginIndex) {\n return undefined\n }\n return existing\n .slice(beginIndex + BEGIN.length, endIndex)\n .replace(/^\\n+|\\n+$/g, '')\n}\n","import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process'\nimport type { SyncReport } from './syncClaude.js'\n\nexport interface RunHarnessAdapterOptions {\n harnessId: 'codex' | 'opencode'\n payloadRoot: string\n projectDir: string\n homeDir: string\n pythonPath: string\n dryRun: boolean\n spawnCommand?: SpawnCommand\n}\n\ntype SpawnCommand = (command: string, args: string[], options?: SpawnOptions) => ChildProcess\n\nfunction runCommand(\n command: string,\n args: string[],\n spawnCommand: SpawnCommand\n): Promise<number | null> {\n return new Promise((resolvePromise, rejectPromise) => {\n const child = spawnCommand(command, args, { stdio: 'inherit' })\n child.on('close', (code) => {\n resolvePromise(code)\n })\n child.on('error', (err) => {\n rejectPromise(err)\n })\n })\n}\n\nexport async function runHarnessAdapter(opts: RunHarnessAdapterOptions): Promise<SyncReport> {\n const report: SyncReport = {\n written: [],\n skipped: [],\n preserved: [],\n warnings: []\n }\n\n if (opts.dryRun) {\n report.written.push(`${opts.harnessId} (dry run)`)\n return report\n }\n\n const args = [\n `${opts.payloadRoot}/scripts/lincoln_harness_adapter.py`,\n '--harness',\n opts.harnessId,\n '--root',\n opts.payloadRoot,\n '--project-dir',\n opts.projectDir,\n '--home-dir',\n opts.homeDir\n ]\n\n try {\n const spawnCommand = (opts.spawnCommand ?? spawn) as SpawnCommand\n const code = await runCommand(opts.pythonPath, args, spawnCommand)\n if (code === 0) {\n report.written.push(opts.harnessId)\n } else {\n report.warnings.push(\n `Adapter for ${opts.harnessId} exited with code ${code}. Run manually to diagnose.`\n )\n }\n } catch (err) {\n report.warnings.push(\n `Failed to run adapter for ${opts.harnessId}: ${err instanceof Error ? err.message : String(err)}`\n )\n }\n\n return report\n}\n","import type { SyncReport } from './syncClaude.js'\nimport { syncClaudeCode } from './syncClaude.js'\nimport type { HarnessId } from './harnessDetect.js'\nimport type { LincolnPaths } from './paths.js'\nimport { runHarnessAdapter } from './runHarnessAdapter.js'\n\nexport interface SyncHarnessesOptions {\n harnesses: HarnessId[]\n payloadRoot: string\n paths: LincolnPaths\n projectDir: string\n version: string\n dryRun: boolean\n pythonPath?: string\n syncClaude?: (opts: {\n payloadRoot: string\n targetDir: string\n version: string\n dryRun: boolean\n }) => SyncReport\n}\n\nexport type HarnessSyncReport = Record<HarnessId, SyncReport>\n\nfunction emptyReport(): SyncReport {\n return {\n written: [],\n skipped: [],\n preserved: [],\n warnings: []\n }\n}\n\nexport async function syncHarnesses(opts: SyncHarnessesOptions): Promise<HarnessSyncReport> {\n const reports: HarnessSyncReport = {} as HarnessSyncReport\n const syncClaude = opts.syncClaude ?? syncClaudeCode\n\n for (const harnessId of opts.harnesses) {\n reports[harnessId] = await syncHarness(harnessId, opts, syncClaude)\n }\n\n return reports\n}\n\nasync function syncHarness(\n harnessId: HarnessId,\n opts: SyncHarnessesOptions,\n syncClaude: NonNullable<SyncHarnessesOptions['syncClaude']>\n): Promise<SyncReport> {\n if (harnessId === 'claude-code') {\n return syncClaude({\n payloadRoot: opts.payloadRoot,\n targetDir: opts.paths.claudeDir,\n version: opts.version,\n dryRun: opts.dryRun\n })\n }\n\n if (harnessId === 'codex' || harnessId === 'opencode') {\n if (opts.dryRun) {\n const report = emptyReport()\n report.written.push(`${harnessId} (dry run)`)\n return report\n }\n if (!opts.pythonPath) {\n const report = emptyReport()\n report.warnings.push(\n `Skipped ${harnessId} sync because Python is not available. Install Python 3.10+ or run without --no-venv.`\n )\n return report\n }\n return runHarnessAdapter({\n harnessId,\n payloadRoot: opts.payloadRoot,\n projectDir: opts.projectDir,\n homeDir: opts.paths.homeDir,\n pythonPath: opts.pythonPath,\n dryRun: opts.dryRun\n })\n }\n\n const report = emptyReport()\n report.warnings.push(`Unsupported harness: ${harnessId}`)\n return report\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { execFile } from 'node:child_process'\nimport yaml from 'js-yaml'\nimport { compareVersions } from './semver.js'\n\nexport type CommandRunner = (\n cmd: string,\n args: string[]\n) => Promise<{ code: number; stdout: string; stderr: string }>\n\nexport type SkillSyncStatus =\n | 'installed'\n | 'updated'\n | 'current'\n | 'failed'\n | 'skipped-optional'\n | 'skipped-dirty'\n | 'dry-run'\n\nexport interface SkillSyncEntry {\n name: string\n status: SkillSyncStatus\n detail?: string\n}\n\nexport interface SkillSyncReport {\n entries: SkillSyncEntry[]\n warnings: string[]\n}\n\nexport interface SyncExternalSkillsOptions {\n payloadRoot: string\n skillsDir: string\n dryRun: boolean\n runCommand?: CommandRunner\n platform?: string\n}\n\ninterface ManifestEntry {\n source?: string\n ref?: string\n type?: string\n required?: boolean\n default_install?: boolean\n binary?: string\n platforms?: Record<string, string>\n}\n\ninterface SkillManifest {\n skills?: Record<string, ManifestEntry>\n}\n\nconst GIT_SOURCE = /^(https?:\\/\\/|git@)/\nconst FULL_SHA = /^[0-9a-f]{40}$/i\nconst PINNED_SEMVER = /^v?(\\d+\\.\\d+\\.\\d+)$/\nconst NPM_GLOBAL_INSTALL = /^npm install -g (\\S+)$/\nconst MAX_BUFFER = 16 * 1024 * 1024\n\nconst defaultRunner: CommandRunner = (cmd, args) =>\n new Promise((resolvePromise, rejectPromise) => {\n execFile(cmd, args, { maxBuffer: MAX_BUFFER }, (err, stdout, stderr) => {\n if (err && !('code' in err && typeof err.code === 'number')) {\n rejectPromise(err)\n return\n }\n const code = err && typeof err.code === 'number' ? err.code : 0\n resolvePromise({ code, stdout: String(stdout), stderr: String(stderr) })\n })\n })\n\nexport async function syncExternalSkills(options: SyncExternalSkillsOptions): Promise<SkillSyncReport> {\n const report: SkillSyncReport = { entries: [], warnings: [] }\n const manifestPath = path.join(options.payloadRoot, '.claude', 'skills', 'dependencies.yaml')\n if (!fs.existsSync(manifestPath)) {\n report.warnings.push(`skill dependency manifest not found at ${manifestPath}; skipping external skill sync`)\n return report\n }\n\n let manifest: SkillManifest\n try {\n manifest = (yaml.load(fs.readFileSync(manifestPath, 'utf8')) as SkillManifest) ?? {}\n } catch (err) {\n report.warnings.push(\n `failed to parse ${manifestPath}: ${err instanceof Error ? err.message : String(err)}`\n )\n return report\n }\n\n const runCommand = options.runCommand ?? defaultRunner\n const platform =\n options.platform ?? (process.platform === 'darwin' ? 'macos' : process.platform === 'linux' ? 'linux' : process.platform)\n for (const [name, cfg] of Object.entries(manifest.skills ?? {})) {\n if (!cfg.source || cfg.source === 'inline' || !GIT_SOURCE.test(cfg.source)) {\n continue\n }\n const enabled = cfg.default_install ?? cfg.required ?? true\n if (!enabled) {\n report.entries.push({ name, status: 'skipped-optional', detail: 'default_install is false' })\n continue\n }\n if (cfg.type === 'cli') {\n await syncCli(name, cfg, options, platform, runCommand, report)\n } else {\n await syncGitSkill(name, cfg, options, runCommand, report)\n }\n }\n return report\n}\n\nasync function syncGitSkill(\n name: string,\n cfg: ManifestEntry,\n options: SyncExternalSkillsOptions,\n runCommand: CommandRunner,\n report: SkillSyncReport\n): Promise<void> {\n const source = cfg.source as string\n const ref = cfg.ref ?? ''\n const target = path.join(options.skillsDir, name)\n\n if (options.dryRun) {\n const planned = fs.existsSync(target) ? 'verify pinned ref and update if behind' : `clone and pin to ${ref}`\n report.entries.push({ name, status: 'dry-run', detail: `would ${planned}` })\n return\n }\n\n if (!fs.existsSync(target)) {\n const clone = await runCommand('git', ['clone', source, target])\n if (clone.code !== 0) {\n fail(report, name, `git clone failed: ${clone.stderr.trim() || `exit code ${clone.code}`}`)\n return\n }\n const checkout = await runCommand('git', ['-C', target, 'checkout', ref])\n if (checkout.code !== 0) {\n fail(report, name, `git checkout ${ref} failed: ${checkout.stderr.trim() || `exit code ${checkout.code}`}`)\n return\n }\n report.entries.push({ name, status: 'installed', detail: ref })\n return\n }\n\n const status = await runCommand('git', ['-C', target, 'status', '--porcelain'])\n if (status.code !== 0) {\n fail(report, name, `git status failed (not a git repository?): ${status.stderr.trim() || `exit code ${status.code}`}`)\n return\n }\n if (status.stdout.trim() !== '') {\n const detail = 'working tree is dirty; skipping update (commit or stash local changes first)'\n report.entries.push({ name, status: 'skipped-dirty', detail })\n report.warnings.push(`${name}: ${detail}`)\n return\n }\n\n const head = await runCommand('git', ['-C', target, 'rev-parse', 'HEAD'])\n if (head.code !== 0) {\n fail(report, name, `git rev-parse failed: ${head.stderr.trim() || `exit code ${head.code}`}`)\n return\n }\n if (head.stdout.trim() === ref) {\n report.entries.push({ name, status: 'current', detail: ref })\n return\n }\n\n const advertised = await isPinAdvertised(source, ref, runCommand)\n if (advertised) {\n const fetch = await runCommand('git', ['-C', target, 'fetch', 'origin', ref])\n if (fetch.code === 0 && (await checkoutFetchHead(name, target, runCommand, report))) {\n return\n }\n if (fetch.code !== 0) {\n fail(report, name, `git fetch origin ${ref} failed: ${fetch.stderr.trim() || `exit code ${fetch.code}`}`)\n return\n }\n return\n }\n\n const fetch = await runCommand('git', ['-C', target, 'fetch', 'origin', ref])\n if (fetch.code === 0) {\n await checkoutFetchHead(name, target, runCommand, report)\n return\n }\n if (FULL_SHA.test(ref)) {\n const fetchAll = await runCommand('git', ['-C', target, 'fetch', 'origin'])\n if (fetchAll.code !== 0) {\n fail(report, name, `git fetch origin failed: ${fetchAll.stderr.trim() || `exit code ${fetchAll.code}`}`)\n return\n }\n const checkout = await runCommand('git', ['-C', target, 'checkout', ref])\n if (checkout.code !== 0) {\n fail(report, name, `git checkout ${ref} failed: ${checkout.stderr.trim() || `exit code ${checkout.code}`}`)\n return\n }\n report.entries.push({ name, status: 'updated', detail: ref })\n return\n }\n fail(report, name, `git fetch origin ${ref} failed: ${fetch.stderr.trim() || `exit code ${fetch.code}`}`)\n}\n\nasync function isPinAdvertised(\n source: string,\n ref: string,\n runCommand: CommandRunner\n): Promise<boolean> {\n const remote = await runCommand('git', ['ls-remote', source])\n if (remote.code !== 0) {\n return false\n }\n return remote.stdout\n .split('\\n')\n .some((line) => line.split('\\t')[0]?.trim() === ref)\n}\n\nasync function checkoutFetchHead(\n name: string,\n target: string,\n runCommand: CommandRunner,\n report: SkillSyncReport\n): Promise<boolean> {\n const checkout = await runCommand('git', ['-C', target, 'checkout', 'FETCH_HEAD'])\n if (checkout.code !== 0) {\n fail(report, name, `git checkout FETCH_HEAD failed: ${checkout.stderr.trim() || `exit code ${checkout.code}`}`)\n return false\n }\n report.entries.push({ name, status: 'updated', detail: 'checked out FETCH_HEAD' })\n return true\n}\n\nasync function syncCli(\n name: string,\n cfg: ManifestEntry,\n options: SyncExternalSkillsOptions,\n platform: string,\n runCommand: CommandRunner,\n report: SkillSyncReport\n): Promise<void> {\n const binary = cfg.binary ?? name\n const installCommand = cfg.platforms?.[platform] ?? cfg.platforms?.linux\n const npmPackage = installCommand ? parseNpmGlobalInstall(installCommand) : undefined\n const pinned = cfg.ref ? pinnedSemver(cfg.ref) : undefined\n\n if (options.dryRun) {\n const managed = npmPackage && pinned ? `install ${npmPackage}@${pinned} if missing or older` : 'verify presence'\n report.entries.push({ name, status: 'dry-run', detail: `would ${managed}` })\n return\n }\n\n const whichCmd = process.platform === 'win32' ? 'where' : 'which'\n const found = await runCommand(whichCmd, [binary])\n if (found.code !== 0) {\n if (npmPackage && pinned) {\n await npmInstall(name, npmPackage, pinned, runCommand, report, 'installed')\n return\n }\n fail(report, name, `CLI '${binary}' not found. Install manually (${platform}): ${installCommand ?? 'see dependency manifest'}`)\n return\n }\n\n if (!npmPackage || !pinned) {\n report.entries.push({ name, status: 'current', detail: `${binary} present` })\n return\n }\n\n const version = await runCommand(binary, ['--version'])\n const installed = version.code === 0 ? version.stdout.split('\\n')[0]?.trim() ?? '' : ''\n const comparison = installed ? compareVersions(installed, pinned) : undefined\n if (comparison === undefined) {\n report.entries.push({\n name,\n status: 'current',\n detail: `could not parse installed version '${installed}'; leaving ${binary} as-is`\n })\n return\n }\n if (comparison >= 0) {\n report.entries.push({ name, status: 'current', detail: `${binary} ${installed}` })\n return\n }\n await npmInstall(name, npmPackage, pinned, runCommand, report, 'updated')\n}\n\nasync function npmInstall(\n name: string,\n npmPackage: string,\n version: string,\n runCommand: CommandRunner,\n report: SkillSyncReport,\n status: 'installed' | 'updated'\n): Promise<void> {\n const result = await runCommand('npm', ['install', '-g', `${npmPackage}@${version}`])\n if (result.code !== 0) {\n fail(report, name, `npm install -g ${npmPackage}@${version} failed: ${result.stderr.trim() || `exit code ${result.code}`}`)\n return\n }\n report.entries.push({ name, status, detail: `${npmPackage}@${version}` })\n}\n\nfunction parseNpmGlobalInstall(command: string): string | undefined {\n const match = NPM_GLOBAL_INSTALL.exec(command.trim())\n return match?.[1]\n}\n\nfunction pinnedSemver(ref: string): string | undefined {\n const match = PINNED_SEMVER.exec(ref.trim())\n return match?.[0].replace(/^v/, '')\n}\n\nfunction fail(report: SkillSyncReport, name: string, detail: string): void {\n report.entries.push({ name, status: 'failed', detail })\n report.warnings.push(`${name}: ${detail}`)\n}\n","const SEMVER_CORE = /^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/\nconst NUMERIC_IDENTIFIER = /^\\d+$/\n\ninterface ParsedVersion {\n major: number\n minor: number\n patch: number\n prerelease: string[]\n}\n\n/**\n * Compares two semver strings per semver.org precedence rules (build metadata\n * ignored). Returns a negative number when a < b, 0 when equal, a positive\n * number when a > b, or undefined when either input is not a parseable semver.\n */\nexport function compareVersions(a: string, b: string): number | undefined {\n const pa = parseVersion(a)\n const pb = parseVersion(b)\n if (!pa || !pb) {\n return undefined\n }\n if (pa.major !== pb.major) return pa.major - pb.major\n if (pa.minor !== pb.minor) return pa.minor - pb.minor\n if (pa.patch !== pb.patch) return pa.patch - pb.patch\n return comparePrerelease(pa.prerelease, pb.prerelease)\n}\n\nfunction parseVersion(version: string): ParsedVersion | undefined {\n const match = SEMVER_CORE.exec(version.trim())\n if (!match) {\n return undefined\n }\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n prerelease: match[4] ? match[4].split('.') : []\n }\n}\n\nfunction comparePrerelease(a: string[], b: string[]): number {\n if (a.length === 0 && b.length === 0) return 0\n // A version without a prerelease has higher precedence than one with it.\n if (a.length === 0) return 1\n if (b.length === 0) return -1\n const shared = Math.min(a.length, b.length)\n for (let i = 0; i < shared; i++) {\n const x = a[i]\n const y = b[i]\n if (x === y) continue\n const xNumeric = NUMERIC_IDENTIFIER.test(x)\n const yNumeric = NUMERIC_IDENTIFIER.test(y)\n if (xNumeric && yNumeric) return Number(x) - Number(y)\n // Numeric identifiers have lower precedence than alphanumeric ones.\n if (xNumeric) return -1\n if (yNumeric) return 1\n return x < y ? -1 : 1\n }\n return a.length - b.length\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\n\nexport type HarnessId = 'claude-code' | 'codex' | 'opencode'\n\nexport interface GlobalHarnessInfo {\n id: HarnessId\n installed: boolean\n configDir: string\n pluginManaged: boolean\n}\n\ninterface HarnessSpec {\n id: HarnessId\n configDirName: string\n pluginMarker?: string\n}\n\nconst HARNESS_SPECS: HarnessSpec[] = [\n {\n id: 'claude-code',\n configDirName: '.claude',\n pluginMarker: 'plugins/lincoln'\n },\n { id: 'codex', configDirName: '.codex' },\n { id: 'opencode', configDirName: '.opencode' }\n]\n\nexport function detectGlobalHarnesses(\n overrideHomeDir?: string\n): GlobalHarnessInfo[] {\n const homeDir = overrideHomeDir ?? os.homedir()\n\n return HARNESS_SPECS.map((spec) => {\n const configDir = path.join(homeDir, spec.configDirName)\n const installed = fs.existsSync(configDir)\n const pluginManaged = spec.pluginMarker\n ? fs.existsSync(path.join(configDir, spec.pluginMarker))\n : false\n\n return {\n id: spec.id,\n installed,\n configDir,\n pluginManaged\n }\n })\n}\n\nexport function installedHarnessIds(homeDir?: string): HarnessId[] {\n return detectGlobalHarnesses(homeDir)\n .filter((h) => h.installed)\n .map((h) => h.id)\n}\n\nexport const HARNESS_IDS: HarnessId[] = HARNESS_SPECS.map((spec) => spec.id)\n\nexport function isValidHarnessId(value: string): value is HarnessId {\n return HARNESS_SPECS.some((spec) => spec.id === value)\n}\n","import type { GlobalHarnessInfo, HarnessId } from './harnessDetect.js'\nimport type { MultiSelectOption } from './prompt.js'\n\nexport const HARNESS_LABELS: Record<HarnessId, string> = {\n 'claude-code': 'Claude Code',\n codex: 'Codex',\n opencode: 'OpenCode'\n}\n\nexport function buildHarnessOptions(\n detected: ReadonlyArray<GlobalHarnessInfo>\n): MultiSelectOption[] {\n return detected.map((harness) => ({\n id: harness.id,\n label: HARNESS_LABELS[harness.id],\n checked: harness.installed\n }))\n}\n\nexport function resolveHarnessSelection(\n detected: ReadonlyArray<GlobalHarnessInfo>,\n selection: string[] | undefined\n): HarnessId[] {\n if (selection === undefined) {\n return detected.filter((harness) => harness.installed).map((harness) => harness.id)\n }\n const validIds = new Set<HarnessId>()\n for (const id of selection) {\n const match = detected.find((harness) => harness.id === id)\n if (match) {\n validIds.add(match.id)\n }\n }\n return Array.from(validIds)\n}\n","import type { Readable, Writable } from 'node:stream'\n\nexport interface PromptOptions {\n input?: Readable\n output?: Writable\n}\n\nexport interface MultiSelectOption {\n id: string\n label: string\n checked: boolean\n}\n\nexport interface Prompt {\n confirm(question: string, defaultValue?: boolean): Promise<boolean>\n multiSelect(question: string, options: ReadonlyArray<MultiSelectOption>): Promise<string[]>\n close(): void\n}\n\ninterface LineReader {\n readLine(prompt: string): Promise<string>\n close(): void\n}\n\nfunction createLineReader(input: Readable, output: Writable): LineReader {\n const buffer: string[] = []\n const queue: Array<{ resolve: (line: string) => void; reject: (err: Error) => void }> = []\n let remainder = ''\n let ended = false\n\n function flushQueue(): void {\n while (queue.length > 0 && buffer.length > 0) {\n const next = queue.shift()\n const line = buffer.shift()\n if (next && line !== undefined) {\n next.resolve(line)\n }\n }\n }\n\n input.on('data', (chunk: Buffer | string) => {\n const text = remainder + chunk.toString('utf-8')\n const lines = text.split('\\n')\n remainder = lines.pop() ?? ''\n for (const line of lines) {\n buffer.push(line.replace(/\\r$/, ''))\n }\n flushQueue()\n })\n\n input.on('end', () => {\n ended = true\n if (remainder.length > 0) {\n buffer.push(remainder.replace(/\\r$/, ''))\n remainder = ''\n }\n flushQueue()\n while (queue.length > 0) {\n const next = queue.shift()\n next?.resolve('')\n }\n })\n\n input.on('error', (err) => {\n while (queue.length > 0) {\n queue.shift()?.reject(err)\n }\n })\n\n return {\n readLine(prompt: string): Promise<string> {\n output.write(prompt)\n if (buffer.length > 0) {\n return Promise.resolve(buffer.shift() ?? '')\n }\n if (ended) {\n return Promise.resolve('')\n }\n return new Promise<string>((resolve, reject) => {\n queue.push({ resolve, reject })\n })\n },\n close(): void {\n // nothing to close for raw streams\n }\n }\n}\n\nfunction normalizeAnswer(text: string): string {\n return text.trim().toLowerCase()\n}\n\nexport function createPrompt(streams: PromptOptions = {}): Prompt {\n const input = streams.input ?? process.stdin\n const output = streams.output ?? process.stdout\n const reader = createLineReader(input, output)\n\n async function ask(question: string): Promise<string> {\n return reader.readLine(question)\n }\n\n return {\n async confirm(question: string, defaultValue = true): Promise<boolean> {\n const hint = defaultValue ? '[Y/n]' : '[y/N]'\n const first = await ask(`${question} ${hint} `)\n const normalized = normalizeAnswer(first)\n if (normalized === 'y' || normalized === 'yes') {\n return true\n }\n if (normalized === 'n' || normalized === 'no') {\n return false\n }\n if (normalized === '') {\n return defaultValue\n }\n const second = await ask('Please answer y or n: ')\n const secondNormalized = normalizeAnswer(second)\n if (secondNormalized === 'y' || secondNormalized === 'yes') {\n return true\n }\n if (secondNormalized === 'n' || secondNormalized === 'no') {\n return false\n }\n return defaultValue\n },\n\n async multiSelect(\n question: string,\n options: ReadonlyArray<MultiSelectOption>\n ): Promise<string[]> {\n const lines = options.map((opt, index) => {\n const mark = opt.checked ? 'x' : ' '\n return ` [${mark}] ${index + 1}. ${opt.label}`\n })\n const promptText = `${question}\\n${lines.join('\\n')}\\nEnter numbers (e.g. 1,3), 'all', 'none', or harness names: `\n\n async function parse(answer: string): Promise<string[] | undefined> {\n const normalized = normalizeAnswer(answer)\n if (normalized === 'all') {\n return options.map((opt) => opt.id)\n }\n if (normalized === 'none') {\n return []\n }\n if (normalized === '') {\n return options.filter((opt) => opt.checked).map((opt) => opt.id)\n }\n const parts = normalized.split(/[,\\s]+/).filter((part) => part.length > 0)\n const selected = new Set<string>()\n for (const part of parts) {\n const index = Number(part)\n if (!Number.isNaN(index) && index >= 1 && index <= options.length) {\n selected.add(options[index - 1].id)\n continue\n }\n const match = options.find((opt) => opt.id === part)\n if (match) {\n selected.add(match.id)\n continue\n }\n return undefined\n }\n return Array.from(selected)\n }\n\n let result = await parse(await ask(promptText))\n if (result !== undefined) {\n return result\n }\n const retry = await ask('Invalid selection. Please try again: ')\n result = await parse(retry)\n return result ?? []\n },\n\n close(): void {\n reader.close()\n }\n }\n}\n","import { install as runInstall } from './commands/install.js'\nimport { createPrompt } from './lib/prompt.js'\n\nexport interface PostinstallDeps {\n isTTY: boolean\n confirm: (question: string) => Promise<boolean>\n install: () => Promise<number>\n env: Record<string, string | undefined>\n}\n\nfunction isSkipped(env: Record<string, string | undefined>): boolean {\n if (env.CI) {\n return true\n }\n if (env.NODE_ENV === 'test') {\n return true\n }\n if (env.LINCOLN_SKIP_POSTINSTALL) {\n return true\n }\n return false\n}\n\nexport function createDefaultDeps(): PostinstallDeps {\n return {\n isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY),\n confirm: async (question: string) => {\n const prompt = createPrompt()\n try {\n return await prompt.confirm(question, true)\n } finally {\n prompt.close()\n }\n },\n install: async () =>\n runInstall({ yes: false, dryRun: false, force: false, harnesses: [], noVenv: false, noInteractive: false }),\n env: process.env\n }\n}\n\nexport async function runPostinstall(deps: PostinstallDeps = createDefaultDeps()): Promise<number> {\n if (isSkipped(deps.env)) {\n return 0\n }\n\n if (!deps.isTTY) {\n console.log('Lincoln installed globally.')\n console.log('Run \"lincoln install\" to finish setup.')\n return 0\n }\n\n try {\n const ok = await deps.confirm('Configure Lincoln harnesses now?')\n if (!ok) {\n console.log('Run \"lincoln install\" anytime to finish setup.')\n return 0\n }\n await deps.install()\n return 0\n } catch (err) {\n console.log('Lincoln installed globally.')\n console.log('Run \"lincoln install\" anytime to finish setup.')\n if (err instanceof Error) {\n console.error(`Postinstall setup skipped: ${err.message}`)\n }\n return 0\n }\n}\n\nif (import.meta.url === `file://${process.argv[1]}`) {\n runPostinstall()\n .then((code) => process.exit(code))\n .catch(() => process.exit(0))\n}\n"],"mappings":";;;AAAA,OAAOA,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,SAAAC,cAAa;;;ACFtB,OAAO,UAAU;AACjB,OAAO,QAAQ;AAcR,SAAS,oBAAoB,iBAAwC;AAC1E,QAAM,UAAU,mBAAmB,GAAG,QAAQ;AAC9C,QAAM,cAAc,QAAQ,IAAI,eAC5B,KAAK,QAAQ,QAAQ,IAAI,YAAY,IACrC,KAAK,KAAK,SAAS,UAAU;AAEjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,KAAK,KAAK,aAAa,UAAU;AAAA,IAC9C,YAAY,KAAK,KAAK,aAAa,SAAS;AAAA,IAC5C,eAAe,KAAK,KAAK,aAAa,aAAa;AAAA,IACnD,SAAS,KAAK,KAAK,aAAa,MAAM;AAAA,IACtC,WAAW,KAAK,KAAK,SAAS,SAAS;AAAA,IACvC,UAAU,KAAK,KAAK,SAAS,QAAQ;AAAA,IACrC,aAAa,KAAK,KAAK,SAAS,WAAW;AAAA,EAC7C;AACF;;;AChCA,OAAO,QAAQ;AACf,OAAOC,WAAU;AA2BV,SAAS,mBACd,OACA,QACM;AACN,KAAG,UAAUC,MAAK,QAAQ,MAAM,aAAa,GAAG,EAAE,WAAW,KAAK,CAAC;AACnE,KAAG,cAAc,MAAM,eAAe,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAC9E;;;AClCA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,qBAAqB;AAMvB,SAAS,uBAA2C;AACzD,MAAI;AACF,QAAI,MAAMA,MAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AACrD,UAAM,OAAOA,MAAK,MAAM,GAAG,EAAE;AAC7B,WAAO,QAAQ,MAAM;AACnB,YAAM,UAAUA,MAAK,KAAK,KAAK,cAAc;AAC7C,UAAID,IAAG,WAAW,OAAO,GAAG;AAC1B,cAAM,SAAS,KAAK,MAAMA,IAAG,aAAa,SAAS,MAAM,CAAC;AAC1D,YAAI,OAAO,SAAS,yBAAyB;AAC3C,iBAAO;AAAA,QACT;AAAA,MACF;AACA,YAAMC,MAAK,QAAQ,GAAG;AAAA,IACxB;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAOO,SAAS,0BAA8C;AAC5D,MAAI;AACF,UAAM,OAAO,qBAAqB;AAClC,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,SAAS,KAAK,MAAMD,IAAG,aAAaC,MAAK,KAAK,MAAM,cAAc,GAAG,MAAM,CAAC;AAGlF,WAAO,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,EAC/D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,qBAAyC;AACvD,QAAM,OAAO,qBAAqB;AAClC,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,UAAUA,MAAK,KAAK,MAAM,WAAW;AAC3C,SAAOD,IAAG,WAAW,OAAO,IAAI,UAAU;AAC5C;;;ACtDA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,YAAY;;;ACFnB,IAAM,QAAQ;AACd,IAAM,MAAM;AAEL,SAAS,kBACd,UACA,OACQ;AACR,QAAM,UAAU,GAAG,KAAK;AAAA,EAAK,KAAK;AAAA,EAAK,GAAG;AAC1C,QAAM,OAAO,YAAY;AAEzB,QAAM,aAAa,KAAK,QAAQ,KAAK;AACrC,QAAM,WAAW,KAAK,QAAQ,GAAG;AAEjC,MAAI,eAAe,MAAM,aAAa,MAAM,WAAW,YAAY;AACjE,WACE,KAAK,MAAM,GAAG,UAAU,IACxB,UACA,KAAK,MAAM,WAAW,IAAI,MAAM;AAAA,EAEpC;AAEA,MAAI,KAAK,KAAK,EAAE,WAAW,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,KAAK,QAAQ,CAAC;AAAA;AAAA,EAAO,OAAO;AAAA;AACxC;;;ADNA,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA;AACF;AAEA,SAAS,OAAO,UAA0B;AACxC,QAAM,OAAOC,IAAG,aAAa,QAAQ;AACrC,SAAO,OAAO,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AAC9D;AAEA,SAAS,YAAY,GAAW,GAAoB;AAClD,SAAO,OAAO,CAAC,MAAM,OAAO,CAAC;AAC/B;AAEA,SAAS,kBAAkB,UAAmB,UAA4B;AACxE,MAAI,MAAM,QAAQ,QAAQ,KAAK,MAAM,QAAQ,QAAQ,GAAG;AACtD,WAAO;AAAA,EACT;AACA,MACE,OAAO,aAAa,YACpB,aAAa,QACb,OAAO,aAAa,YACpB,aAAa,MACb;AACA,UAAM,SAAkC,EAAE,GAAG,SAAS;AACtD,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,UAAI,OAAO,QAAQ;AACjB,eAAO,GAAG,IAAI,kBAAkB,OAAO,GAAG,GAAG,KAAK;AAAA,MACpD,OAAO;AACL,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,eAAe,MAA+B;AAC5D,QAAM,SAAqB;AAAA,IACzB,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,IACX,iBAAiB,CAAC;AAAA,EACpB;AAEA,QAAM,gBAAgBC,MAAK,KAAK,KAAK,aAAa,SAAS;AAC3D,MAAI,CAACD,IAAG,WAAW,aAAa,GAAG;AACjC,WAAO,SAAS,KAAK,wCAAwC,aAAa,EAAE;AAC5E,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,KAAK,QAAQ;AAChB,IAAAA,IAAG,UAAU,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAClD;AAEA,aAAW,UAAU,cAAc;AACjC,UAAM,SAASC,MAAK,KAAK,eAAe,MAAM;AAC9C,QAAI,CAACD,IAAG,WAAW,MAAM,GAAG;AAC1B;AAAA,IACF;AAEA,UAAM,UAAUC,MAAK,KAAK,KAAK,WAAW,MAAM;AAChD,QAAI,CAAC,KAAK,QAAQ;AAChB,MAAAD,IAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,IAC3C;AAEA,eAAW,SAAS,SAAS,MAAM,GAAG;AACpC,YAAM,eAAeC,MAAK,SAAS,QAAQ,KAAK;AAChD,YAAM,UAAU;AAChB,YAAM,WAAWA,MAAK,KAAK,SAAS,YAAY;AAEhD,UAAID,IAAG,WAAW,QAAQ,KAAK,YAAY,SAAS,QAAQ,GAAG;AAC7D,eAAO,QAAQ,KAAKC,MAAK,KAAK,WAAW,QAAQ,YAAY,CAAC;AAC9D;AAAA,MACF;AAEA,UAAI,CAAC,KAAK,QAAQ;AAChB,QAAAD,IAAG,UAAUC,MAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACxD,QAAAD,IAAG,aAAa,SAAS,QAAQ;AAAA,MACnC;AACA,aAAO,QAAQ,KAAKC,MAAK,KAAK,WAAW,QAAQ,YAAY,CAAC;AAAA,IAChE;AAAA,EACF;AAGA,QAAM,kBAAkBA,MAAK,KAAK,eAAe,eAAe;AAChE,QAAM,iBAAiBA,MAAK,KAAK,KAAK,WAAW,eAAe;AAChE,MAAID,IAAG,WAAW,eAAe,GAAG;AAClC,UAAM,WAAW,KAAK,MAAMA,IAAG,aAAa,iBAAiB,MAAM,CAAC;AACpE,QAAI,SAAS;AACb,QAAIA,IAAG,WAAW,cAAc,GAAG;AACjC,YAAM,WAAW,KAAK,MAAMA,IAAG,aAAa,gBAAgB,MAAM,CAAC;AACnE,eAAS,kBAAkB,UAAU,QAAQ;AAAA,IAC/C;AAEA,UAAM,cACJ,CAACA,IAAG,WAAW,cAAc,KAC7B,KAAK,UAAU,MAAM,MAAM,KAAK,UAAU,KAAK,MAAMA,IAAG,aAAa,gBAAgB,MAAM,CAAC,CAAC;AAE/F,QAAI,aAAa;AACf,UAAI,CAAC,KAAK,QAAQ;AAChB,QAAAA,IAAG,cAAc,gBAAgB,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAAA,MACzE;AACA,aAAO,QAAQ,KAAK,uBAAuB;AAC3C,aAAO,kBAAkB,CAAC,uBAAuB;AAAA,IACnD,OAAO;AACL,aAAO,QAAQ,KAAK,uBAAuB;AAAA,IAC7C;AAAA,EACF;AAGA,QAAM,kBAAkBC,MAAK,KAAK,KAAK,aAAa,WAAW;AAC/D,QAAM,iBAAiBA,MAAK,KAAKA,MAAK,QAAQ,KAAK,SAAS,GAAG,WAAW;AAC1E,MAAID,IAAG,WAAW,eAAe,GAAG;AAClC,UAAM,gBAAgBA,IAAG,aAAa,iBAAiB,MAAM;AAC7D,UAAM,WAAWA,IAAG,WAAW,cAAc,IACzCA,IAAG,aAAa,gBAAgB,MAAM,IACtC;AACJ,UAAM,SAAS,kBAAkB,UAAU,aAAa;AAExD,QAAI,WAAW,UAAU;AACvB,UAAI,CAAC,KAAK,QAAQ;AAChB,QAAAA,IAAG,cAAc,gBAAgB,MAAM;AAAA,MACzC;AACA,aAAO,QAAQ,KAAK,WAAW;AAAA,IACjC,OAAO;AACL,aAAO,QAAQ,KAAK,WAAW;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AACT;AAEA,UAAU,SAAS,KAAgC;AACjD,QAAM,UAAUA,IAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAC3D,aAAW,SAAS,SAAS;AAC3B,UAAM,WAAWC,MAAK,KAAK,KAAK,MAAM,IAAI;AAC1C,QAAI,MAAM,YAAY,GAAG;AACvB,aAAO,SAAS,QAAQ;AAAA,IAC1B,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AE9KA,SAAS,aAAmD;AAe5D,SAAS,WACP,SACA,MACA,cACwB;AACxB,SAAO,IAAI,QAAQ,CAAC,gBAAgB,kBAAkB;AACpD,UAAM,QAAQ,aAAa,SAAS,MAAM,EAAE,OAAO,UAAU,CAAC;AAC9D,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,qBAAe,IAAI;AAAA,IACrB,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,oBAAc,GAAG;AAAA,IACnB,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,kBAAkB,MAAqD;AAC3F,QAAM,SAAqB;AAAA,IACzB,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,EACb;AAEA,MAAI,KAAK,QAAQ;AACf,WAAO,QAAQ,KAAK,GAAG,KAAK,SAAS,YAAY;AACjD,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AAAA,IACX,GAAG,KAAK,WAAW;AAAA,IACnB;AAAA,IACA,KAAK;AAAA,IACL;AAAA,IACA,KAAK;AAAA,IACL;AAAA,IACA,KAAK;AAAA,IACL;AAAA,IACA,KAAK;AAAA,EACP;AAEA,MAAI;AACF,UAAM,eAAgB,KAAK,gBAAgB;AAC3C,UAAM,OAAO,MAAM,WAAW,KAAK,YAAY,MAAM,YAAY;AACjE,QAAI,SAAS,GAAG;AACd,aAAO,QAAQ,KAAK,KAAK,SAAS;AAAA,IACpC,OAAO;AACL,aAAO,SAAS;AAAA,QACd,eAAe,KAAK,SAAS,qBAAqB,IAAI;AAAA,MACxD;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,SAAS;AAAA,MACd,6BAA6B,KAAK,SAAS,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAClG;AAAA,EACF;AAEA,SAAO;AACT;;;ACjDA,SAAS,cAA0B;AACjC,SAAO;AAAA,IACL,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,EACb;AACF;AAEA,eAAsB,cAAc,MAAwD;AAC1F,QAAM,UAA6B,CAAC;AACpC,QAAM,aAAa,KAAK,cAAc;AAEtC,aAAW,aAAa,KAAK,WAAW;AACtC,YAAQ,SAAS,IAAI,MAAM,YAAY,WAAW,MAAM,UAAU;AAAA,EACpE;AAEA,SAAO;AACT;AAEA,eAAe,YACb,WACA,MACA,YACqB;AACrB,MAAI,cAAc,eAAe;AAC/B,WAAO,WAAW;AAAA,MAChB,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK,MAAM;AAAA,MACtB,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,MAAI,cAAc,WAAW,cAAc,YAAY;AACrD,QAAI,KAAK,QAAQ;AACf,YAAMC,UAAS,YAAY;AAC3B,MAAAA,QAAO,QAAQ,KAAK,GAAG,SAAS,YAAY;AAC5C,aAAOA;AAAA,IACT;AACA,QAAI,CAAC,KAAK,YAAY;AACpB,YAAMA,UAAS,YAAY;AAC3B,MAAAA,QAAO,SAAS;AAAA,QACd,WAAW,SAAS;AAAA,MACtB;AACA,aAAOA;AAAA,IACT;AACA,WAAO,kBAAkB;AAAA,MACvB;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK,MAAM;AAAA,MACpB,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,YAAY;AAC3B,SAAO,SAAS,KAAK,wBAAwB,SAAS,EAAE;AACxD,SAAO;AACT;;;ACpFA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,gBAAgB;AACzB,OAAO,UAAU;;;ACHjB,IAAM,cAAc;AACpB,IAAM,qBAAqB;AAcpB,SAAS,gBAAgB,GAAW,GAA+B;AACxE,QAAM,KAAK,aAAa,CAAC;AACzB,QAAM,KAAK,aAAa,CAAC;AACzB,MAAI,CAAC,MAAM,CAAC,IAAI;AACd,WAAO;AAAA,EACT;AACA,MAAI,GAAG,UAAU,GAAG,MAAO,QAAO,GAAG,QAAQ,GAAG;AAChD,MAAI,GAAG,UAAU,GAAG,MAAO,QAAO,GAAG,QAAQ,GAAG;AAChD,MAAI,GAAG,UAAU,GAAG,MAAO,QAAO,GAAG,QAAQ,GAAG;AAChD,SAAO,kBAAkB,GAAG,YAAY,GAAG,UAAU;AACvD;AAEA,SAAS,aAAa,SAA4C;AAChE,QAAM,QAAQ,YAAY,KAAK,QAAQ,KAAK,CAAC;AAC7C,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,IACtB,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,IACtB,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,IACtB,YAAY,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;AAAA,EAChD;AACF;AAEA,SAAS,kBAAkB,GAAa,GAAqB;AAC3D,MAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EAAG,QAAO;AAE7C,MAAI,EAAE,WAAW,EAAG,QAAO;AAC3B,MAAI,EAAE,WAAW,EAAG,QAAO;AAC3B,QAAM,SAAS,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,IAAI,EAAE,CAAC;AACb,UAAM,IAAI,EAAE,CAAC;AACb,QAAI,MAAM,EAAG;AACb,UAAM,WAAW,mBAAmB,KAAK,CAAC;AAC1C,UAAM,WAAW,mBAAmB,KAAK,CAAC;AAC1C,QAAI,YAAY,SAAU,QAAO,OAAO,CAAC,IAAI,OAAO,CAAC;AAErD,QAAI,SAAU,QAAO;AACrB,QAAI,SAAU,QAAO;AACrB,WAAO,IAAI,IAAI,KAAK;AAAA,EACtB;AACA,SAAO,EAAE,SAAS,EAAE;AACtB;;;ADNA,IAAM,aAAa;AACnB,IAAM,WAAW;AACjB,IAAM,gBAAgB;AACtB,IAAM,qBAAqB;AAC3B,IAAM,aAAa,KAAK,OAAO;AAE/B,IAAM,gBAA+B,CAAC,KAAK,SACzC,IAAI,QAAQ,CAAC,gBAAgB,kBAAkB;AAC7C,WAAS,KAAK,MAAM,EAAE,WAAW,WAAW,GAAG,CAAC,KAAK,QAAQ,WAAW;AACtE,QAAI,OAAO,EAAE,UAAU,OAAO,OAAO,IAAI,SAAS,WAAW;AAC3D,oBAAc,GAAG;AACjB;AAAA,IACF;AACA,UAAM,OAAO,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO;AAC9D,mBAAe,EAAE,MAAM,QAAQ,OAAO,MAAM,GAAG,QAAQ,OAAO,MAAM,EAAE,CAAC;AAAA,EACzE,CAAC;AACH,CAAC;AAEH,eAAsB,mBAAmB,SAA8D;AACrG,QAAM,SAA0B,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAC5D,QAAM,eAAeC,MAAK,KAAK,QAAQ,aAAa,WAAW,UAAU,mBAAmB;AAC5F,MAAI,CAACC,IAAG,WAAW,YAAY,GAAG;AAChC,WAAO,SAAS,KAAK,0CAA0C,YAAY,gCAAgC;AAC3G,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI;AACF,eAAY,KAAK,KAAKA,IAAG,aAAa,cAAc,MAAM,CAAC,KAAuB,CAAC;AAAA,EACrF,SAAS,KAAK;AACZ,WAAO,SAAS;AAAA,MACd,mBAAmB,YAAY,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACtF;AACA,WAAO;AAAA,EACT;AAEA,QAAMC,cAAa,QAAQ,cAAc;AACzC,QAAM,WACJ,QAAQ,aAAa,QAAQ,aAAa,WAAW,UAAU,QAAQ,aAAa,UAAU,UAAU,QAAQ;AAClH,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,SAAS,UAAU,CAAC,CAAC,GAAG;AAC/D,QAAI,CAAC,IAAI,UAAU,IAAI,WAAW,YAAY,CAAC,WAAW,KAAK,IAAI,MAAM,GAAG;AAC1E;AAAA,IACF;AACA,UAAM,UAAU,IAAI,mBAAmB,IAAI,YAAY;AACvD,QAAI,CAAC,SAAS;AACZ,aAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,oBAAoB,QAAQ,2BAA2B,CAAC;AAC5F;AAAA,IACF;AACA,QAAI,IAAI,SAAS,OAAO;AACtB,YAAM,QAAQ,MAAM,KAAK,SAAS,UAAUA,aAAY,MAAM;AAAA,IAChE,OAAO;AACL,YAAM,aAAa,MAAM,KAAK,SAASA,aAAY,MAAM;AAAA,IAC3D;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,aACb,MACA,KACA,SACAA,aACA,QACe;AACf,QAAM,SAAS,IAAI;AACnB,QAAM,MAAM,IAAI,OAAO;AACvB,QAAM,SAASF,MAAK,KAAK,QAAQ,WAAW,IAAI;AAEhD,MAAI,QAAQ,QAAQ;AAClB,UAAM,UAAUC,IAAG,WAAW,MAAM,IAAI,2CAA2C,oBAAoB,GAAG;AAC1G,WAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,WAAW,QAAQ,SAAS,OAAO,GAAG,CAAC;AAC3E;AAAA,EACF;AAEA,MAAI,CAACA,IAAG,WAAW,MAAM,GAAG;AAC1B,UAAM,QAAQ,MAAMC,YAAW,OAAO,CAAC,SAAS,QAAQ,MAAM,CAAC;AAC/D,QAAI,MAAM,SAAS,GAAG;AACpB,WAAK,QAAQ,MAAM,qBAAqB,MAAM,OAAO,KAAK,KAAK,aAAa,MAAM,IAAI,EAAE,EAAE;AAC1F;AAAA,IACF;AACA,UAAM,WAAW,MAAMA,YAAW,OAAO,CAAC,MAAM,QAAQ,YAAY,GAAG,CAAC;AACxE,QAAI,SAAS,SAAS,GAAG;AACvB,WAAK,QAAQ,MAAM,gBAAgB,GAAG,YAAY,SAAS,OAAO,KAAK,KAAK,aAAa,SAAS,IAAI,EAAE,EAAE;AAC1G;AAAA,IACF;AACA,WAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,aAAa,QAAQ,IAAI,CAAC;AAC9D;AAAA,EACF;AAEA,QAAM,SAAS,MAAMA,YAAW,OAAO,CAAC,MAAM,QAAQ,UAAU,aAAa,CAAC;AAC9E,MAAI,OAAO,SAAS,GAAG;AACrB,SAAK,QAAQ,MAAM,8CAA8C,OAAO,OAAO,KAAK,KAAK,aAAa,OAAO,IAAI,EAAE,EAAE;AACrH;AAAA,EACF;AACA,MAAI,OAAO,OAAO,KAAK,MAAM,IAAI;AAC/B,UAAM,SAAS;AACf,WAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,iBAAiB,OAAO,CAAC;AAC7D,WAAO,SAAS,KAAK,GAAG,IAAI,KAAK,MAAM,EAAE;AACzC;AAAA,EACF;AAEA,QAAM,OAAO,MAAMA,YAAW,OAAO,CAAC,MAAM,QAAQ,aAAa,MAAM,CAAC;AACxE,MAAI,KAAK,SAAS,GAAG;AACnB,SAAK,QAAQ,MAAM,yBAAyB,KAAK,OAAO,KAAK,KAAK,aAAa,KAAK,IAAI,EAAE,EAAE;AAC5F;AAAA,EACF;AACA,MAAI,KAAK,OAAO,KAAK,MAAM,KAAK;AAC9B,WAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,WAAW,QAAQ,IAAI,CAAC;AAC5D;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,gBAAgB,QAAQ,KAAKA,WAAU;AAChE,MAAI,YAAY;AACd,UAAMC,SAAQ,MAAMD,YAAW,OAAO,CAAC,MAAM,QAAQ,SAAS,UAAU,GAAG,CAAC;AAC5E,QAAIC,OAAM,SAAS,KAAM,MAAM,kBAAkB,MAAM,QAAQD,aAAY,MAAM,GAAI;AACnF;AAAA,IACF;AACA,QAAIC,OAAM,SAAS,GAAG;AACpB,WAAK,QAAQ,MAAM,oBAAoB,GAAG,YAAYA,OAAM,OAAO,KAAK,KAAK,aAAaA,OAAM,IAAI,EAAE,EAAE;AACxG;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,QAAQ,MAAMD,YAAW,OAAO,CAAC,MAAM,QAAQ,SAAS,UAAU,GAAG,CAAC;AAC5E,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,kBAAkB,MAAM,QAAQA,aAAY,MAAM;AACxD;AAAA,EACF;AACA,MAAI,SAAS,KAAK,GAAG,GAAG;AACtB,UAAM,WAAW,MAAMA,YAAW,OAAO,CAAC,MAAM,QAAQ,SAAS,QAAQ,CAAC;AAC1E,QAAI,SAAS,SAAS,GAAG;AACvB,WAAK,QAAQ,MAAM,4BAA4B,SAAS,OAAO,KAAK,KAAK,aAAa,SAAS,IAAI,EAAE,EAAE;AACvG;AAAA,IACF;AACA,UAAM,WAAW,MAAMA,YAAW,OAAO,CAAC,MAAM,QAAQ,YAAY,GAAG,CAAC;AACxE,QAAI,SAAS,SAAS,GAAG;AACvB,WAAK,QAAQ,MAAM,gBAAgB,GAAG,YAAY,SAAS,OAAO,KAAK,KAAK,aAAa,SAAS,IAAI,EAAE,EAAE;AAC1G;AAAA,IACF;AACA,WAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,WAAW,QAAQ,IAAI,CAAC;AAC5D;AAAA,EACF;AACA,OAAK,QAAQ,MAAM,oBAAoB,GAAG,YAAY,MAAM,OAAO,KAAK,KAAK,aAAa,MAAM,IAAI,EAAE,EAAE;AAC1G;AAEA,eAAe,gBACb,QACA,KACAA,aACkB;AAClB,QAAM,SAAS,MAAMA,YAAW,OAAO,CAAC,aAAa,MAAM,CAAC;AAC5D,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO;AAAA,EACT;AACA,SAAO,OAAO,OACX,MAAM,IAAI,EACV,KAAK,CAAC,SAAS,KAAK,MAAM,GAAI,EAAE,CAAC,GAAG,KAAK,MAAM,GAAG;AACvD;AAEA,eAAe,kBACb,MACA,QACAA,aACA,QACkB;AAClB,QAAM,WAAW,MAAMA,YAAW,OAAO,CAAC,MAAM,QAAQ,YAAY,YAAY,CAAC;AACjF,MAAI,SAAS,SAAS,GAAG;AACvB,SAAK,QAAQ,MAAM,mCAAmC,SAAS,OAAO,KAAK,KAAK,aAAa,SAAS,IAAI,EAAE,EAAE;AAC9G,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,WAAW,QAAQ,yBAAyB,CAAC;AACjF,SAAO;AACT;AAEA,eAAe,QACb,MACA,KACA,SACA,UACAA,aACA,QACe;AACf,QAAM,SAAS,IAAI,UAAU;AAC7B,QAAM,iBAAiB,IAAI,YAAY,QAAQ,KAAK,IAAI,WAAW;AACnE,QAAM,aAAa,iBAAiB,sBAAsB,cAAc,IAAI;AAC5E,QAAM,SAAS,IAAI,MAAM,aAAa,IAAI,GAAG,IAAI;AAEjD,MAAI,QAAQ,QAAQ;AAClB,UAAM,UAAU,cAAc,SAAS,WAAW,UAAU,IAAI,MAAM,yBAAyB;AAC/F,WAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,WAAW,QAAQ,SAAS,OAAO,GAAG,CAAC;AAC3E;AAAA,EACF;AAEA,QAAM,WAAW,QAAQ,aAAa,UAAU,UAAU;AAC1D,QAAM,QAAQ,MAAMA,YAAW,UAAU,CAAC,MAAM,CAAC;AACjD,MAAI,MAAM,SAAS,GAAG;AACpB,QAAI,cAAc,QAAQ;AACxB,YAAM,WAAW,MAAM,YAAY,QAAQA,aAAY,QAAQ,WAAW;AAC1E;AAAA,IACF;AACA,SAAK,QAAQ,MAAM,QAAQ,MAAM,kCAAkC,QAAQ,MAAM,kBAAkB,yBAAyB,EAAE;AAC9H;AAAA,EACF;AAEA,MAAI,CAAC,cAAc,CAAC,QAAQ;AAC1B,WAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,WAAW,QAAQ,GAAG,MAAM,WAAW,CAAC;AAC5E;AAAA,EACF;AAEA,QAAM,UAAU,MAAMA,YAAW,QAAQ,CAAC,WAAW,CAAC;AACtD,QAAM,YAAY,QAAQ,SAAS,IAAI,QAAQ,OAAO,MAAM,IAAI,EAAE,CAAC,GAAG,KAAK,KAAK,KAAK;AACrF,QAAM,aAAa,YAAY,gBAAgB,WAAW,MAAM,IAAI;AACpE,MAAI,eAAe,QAAW;AAC5B,WAAO,QAAQ,KAAK;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,sCAAsC,SAAS,cAAc,MAAM;AAAA,IAC7E,CAAC;AACD;AAAA,EACF;AACA,MAAI,cAAc,GAAG;AACnB,WAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,WAAW,QAAQ,GAAG,MAAM,IAAI,SAAS,GAAG,CAAC;AACjF;AAAA,EACF;AACA,QAAM,WAAW,MAAM,YAAY,QAAQA,aAAY,QAAQ,SAAS;AAC1E;AAEA,eAAe,WACb,MACA,YACA,SACAA,aACA,QACA,QACe;AACf,QAAM,SAAS,MAAMA,YAAW,OAAO,CAAC,WAAW,MAAM,GAAG,UAAU,IAAI,OAAO,EAAE,CAAC;AACpF,MAAI,OAAO,SAAS,GAAG;AACrB,SAAK,QAAQ,MAAM,kBAAkB,UAAU,IAAI,OAAO,YAAY,OAAO,OAAO,KAAK,KAAK,aAAa,OAAO,IAAI,EAAE,EAAE;AAC1H;AAAA,EACF;AACA,SAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,QAAQ,GAAG,UAAU,IAAI,OAAO,GAAG,CAAC;AAC1E;AAEA,SAAS,sBAAsB,SAAqC;AAClE,QAAM,QAAQ,mBAAmB,KAAK,QAAQ,KAAK,CAAC;AACpD,SAAO,QAAQ,CAAC;AAClB;AAEA,SAAS,aAAa,KAAiC;AACrD,QAAM,QAAQ,cAAc,KAAK,IAAI,KAAK,CAAC;AAC3C,SAAO,QAAQ,CAAC,EAAE,QAAQ,MAAM,EAAE;AACpC;AAEA,SAAS,KAAK,QAAyB,MAAc,QAAsB;AACzE,SAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,UAAU,OAAO,CAAC;AACtD,SAAO,SAAS,KAAK,GAAG,IAAI,KAAK,MAAM,EAAE;AAC3C;;;AEtTA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AAiBf,IAAM,gBAA+B;AAAA,EACnC;AAAA,IACE,IAAI;AAAA,IACJ,eAAe;AAAA,IACf,cAAc;AAAA,EAChB;AAAA,EACA,EAAE,IAAI,SAAS,eAAe,SAAS;AAAA,EACvC,EAAE,IAAI,YAAY,eAAe,YAAY;AAC/C;AAEO,SAAS,sBACd,iBACqB;AACrB,QAAM,UAAU,mBAAmBA,IAAG,QAAQ;AAE9C,SAAO,cAAc,IAAI,CAAC,SAAS;AACjC,UAAM,YAAYD,MAAK,KAAK,SAAS,KAAK,aAAa;AACvD,UAAM,YAAYD,IAAG,WAAW,SAAS;AACzC,UAAM,gBAAgB,KAAK,eACvBA,IAAG,WAAWC,MAAK,KAAK,WAAW,KAAK,YAAY,CAAC,IACrD;AAEJ,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,SAAS,oBAAoB,SAA+B;AACjE,SAAO,sBAAsB,OAAO,EACjC,OAAO,CAAC,MAAM,EAAE,SAAS,EACzB,IAAI,CAAC,MAAM,EAAE,EAAE;AACpB;AAEO,IAAM,cAA2B,cAAc,IAAI,CAAC,SAAS,KAAK,EAAE;AAEpE,SAAS,iBAAiB,OAAmC;AAClE,SAAO,cAAc,KAAK,CAAC,SAAS,KAAK,OAAO,KAAK;AACvD;;;ACzDO,IAAM,iBAA4C;AAAA,EACvD,eAAe;AAAA,EACf,OAAO;AAAA,EACP,UAAU;AACZ;AAEO,SAAS,oBACd,UACqB;AACrB,SAAO,SAAS,IAAI,CAAC,aAAa;AAAA,IAChC,IAAI,QAAQ;AAAA,IACZ,OAAO,eAAe,QAAQ,EAAE;AAAA,IAChC,SAAS,QAAQ;AAAA,EACnB,EAAE;AACJ;AAEO,SAAS,wBACd,UACA,WACa;AACb,MAAI,cAAc,QAAW;AAC3B,WAAO,SAAS,OAAO,CAAC,YAAY,QAAQ,SAAS,EAAE,IAAI,CAAC,YAAY,QAAQ,EAAE;AAAA,EACpF;AACA,QAAM,WAAW,oBAAI,IAAe;AACpC,aAAW,MAAM,WAAW;AAC1B,UAAM,QAAQ,SAAS,KAAK,CAAC,YAAY,QAAQ,OAAO,EAAE;AAC1D,QAAI,OAAO;AACT,eAAS,IAAI,MAAM,EAAE;AAAA,IACvB;AAAA,EACF;AACA,SAAO,MAAM,KAAK,QAAQ;AAC5B;;;ACVA,SAAS,iBAAiB,OAAiB,QAA8B;AACvE,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAkF,CAAC;AACzF,MAAI,YAAY;AAChB,MAAI,QAAQ;AAEZ,WAAS,aAAmB;AAC1B,WAAO,MAAM,SAAS,KAAK,OAAO,SAAS,GAAG;AAC5C,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,OAAO,OAAO,MAAM;AAC1B,UAAI,QAAQ,SAAS,QAAW;AAC9B,aAAK,QAAQ,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,GAAG,QAAQ,CAAC,UAA2B;AAC3C,UAAM,OAAO,YAAY,MAAM,SAAS,OAAO;AAC/C,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,gBAAY,MAAM,IAAI,KAAK;AAC3B,eAAW,QAAQ,OAAO;AACxB,aAAO,KAAK,KAAK,QAAQ,OAAO,EAAE,CAAC;AAAA,IACrC;AACA,eAAW;AAAA,EACb,CAAC;AAED,QAAM,GAAG,OAAO,MAAM;AACpB,YAAQ;AACR,QAAI,UAAU,SAAS,GAAG;AACxB,aAAO,KAAK,UAAU,QAAQ,OAAO,EAAE,CAAC;AACxC,kBAAY;AAAA,IACd;AACA,eAAW;AACX,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,QAAQ,EAAE;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,MAAM,GAAG,OAAO,GAAG;AAAA,IAC3B;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,SAAS,QAAiC;AACxC,aAAO,MAAM,MAAM;AACnB,UAAI,OAAO,SAAS,GAAG;AACrB,eAAO,QAAQ,QAAQ,OAAO,MAAM,KAAK,EAAE;AAAA,MAC7C;AACA,UAAI,OAAO;AACT,eAAO,QAAQ,QAAQ,EAAE;AAAA,MAC3B;AACA,aAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9C,cAAM,KAAK,EAAE,SAAS,OAAO,CAAC;AAAA,MAChC,CAAC;AAAA,IACH;AAAA,IACA,QAAc;AAAA,IAEd;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,MAAsB;AAC7C,SAAO,KAAK,KAAK,EAAE,YAAY;AACjC;AAEO,SAAS,aAAa,UAAyB,CAAC,GAAW;AAChE,QAAM,QAAQ,QAAQ,SAAS,QAAQ;AACvC,QAAM,SAAS,QAAQ,UAAU,QAAQ;AACzC,QAAM,SAAS,iBAAiB,OAAO,MAAM;AAE7C,iBAAe,IAAI,UAAmC;AACpD,WAAO,OAAO,SAAS,QAAQ;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ,UAAkB,eAAe,MAAwB;AACrE,YAAM,OAAO,eAAe,UAAU;AACtC,YAAM,QAAQ,MAAM,IAAI,GAAG,QAAQ,IAAI,IAAI,GAAG;AAC9C,YAAM,aAAa,gBAAgB,KAAK;AACxC,UAAI,eAAe,OAAO,eAAe,OAAO;AAC9C,eAAO;AAAA,MACT;AACA,UAAI,eAAe,OAAO,eAAe,MAAM;AAC7C,eAAO;AAAA,MACT;AACA,UAAI,eAAe,IAAI;AACrB,eAAO;AAAA,MACT;AACA,YAAM,SAAS,MAAM,IAAI,wBAAwB;AACjD,YAAM,mBAAmB,gBAAgB,MAAM;AAC/C,UAAI,qBAAqB,OAAO,qBAAqB,OAAO;AAC1D,eAAO;AAAA,MACT;AACA,UAAI,qBAAqB,OAAO,qBAAqB,MAAM;AACzD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,YACJ,UACA,SACmB;AACnB,YAAM,QAAQ,QAAQ,IAAI,CAAC,KAAK,UAAU;AACxC,cAAM,OAAO,IAAI,UAAU,MAAM;AACjC,eAAO,MAAM,IAAI,KAAK,QAAQ,CAAC,KAAK,IAAI,KAAK;AAAA,MAC/C,CAAC;AACD,YAAM,aAAa,GAAG,QAAQ;AAAA,EAAK,MAAM,KAAK,IAAI,CAAC;AAAA;AAEnD,qBAAe,MAAM,QAA+C;AAClE,cAAM,aAAa,gBAAgB,MAAM;AACzC,YAAI,eAAe,OAAO;AACxB,iBAAO,QAAQ,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,QACpC;AACA,YAAI,eAAe,QAAQ;AACzB,iBAAO,CAAC;AAAA,QACV;AACA,YAAI,eAAe,IAAI;AACrB,iBAAO,QAAQ,OAAO,CAAC,QAAQ,IAAI,OAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,QACjE;AACA,cAAM,QAAQ,WAAW,MAAM,QAAQ,EAAE,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACzE,cAAM,WAAW,oBAAI,IAAY;AACjC,mBAAW,QAAQ,OAAO;AACxB,gBAAM,QAAQ,OAAO,IAAI;AACzB,cAAI,CAAC,OAAO,MAAM,KAAK,KAAK,SAAS,KAAK,SAAS,QAAQ,QAAQ;AACjE,qBAAS,IAAI,QAAQ,QAAQ,CAAC,EAAE,EAAE;AAClC;AAAA,UACF;AACA,gBAAM,QAAQ,QAAQ,KAAK,CAAC,QAAQ,IAAI,OAAO,IAAI;AACnD,cAAI,OAAO;AACT,qBAAS,IAAI,MAAM,EAAE;AACrB;AAAA,UACF;AACA,iBAAO;AAAA,QACT;AACA,eAAO,MAAM,KAAK,QAAQ;AAAA,MAC5B;AAEA,UAAI,SAAS,MAAM,MAAM,MAAM,IAAI,UAAU,CAAC;AAC9C,UAAI,WAAW,QAAW;AACxB,eAAO;AAAA,MACT;AACA,YAAM,QAAQ,MAAM,IAAI,uCAAuC;AAC/D,eAAS,MAAM,MAAM,KAAK;AAC1B,aAAO,UAAU,CAAC;AAAA,IACpB;AAAA,IAEA,QAAc;AACZ,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;;;AZ1IO,SAAS,oBAAiC;AAC/C,SAAO;AAAA,IACL,OAAO,oBAAoB;AAAA,IAC3B,aAAa,mBAAmB,KAAK;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK;AAAA,EAC5D;AACF;AAEA,eAAsB,QACpB,SACA,OAAoB,kBAAkB,GACrB;AACjB,QAAM,UAAU,wBAAwB;AACxC,MAAI,CAAC,SAAS;AACZ,YAAQ,MAAM,qCAAqC;AACnD,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,KAAK;AACzB,MAAI,CAAC,eAAe,CAACE,IAAG,WAAW,WAAW,GAAG;AAC/C,YAAQ,MAAM,8EAA8E;AAC5F,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,QAAQ,QAAQ,iBAAiB,CAAC,KAAK,QAAQ;AAC7E,YAAQ;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM,iBAAiB,SAAS,IAAI;AACtD,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,sBAAsB,SAAS,MAAM,SAAS;AACvE,MAAI,eAAe,MAAM;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ,QAAQ;AACnB,UAAM,aAAaC,MAAK,KAAK,KAAK,MAAM,aAAa,OAAO;AAC5D,IAAAD,IAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,IAAAA,IAAG,OAAO,aAAa,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACnE,QAAI;AACF,MAAAA,IAAG,OAAO,KAAK,MAAM,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjE,MAAAA,IAAG,YAAY,YAAY,KAAK,MAAM,UAAU;AAAA,IAClD,QAAQ;AACN,MAAAA,IAAG,OAAO,KAAK,MAAM,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjE,MAAAA,IAAG,OAAO,YAAY,KAAK,MAAM,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IAC/E;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,KAAK,cAAc;AAAA,IACvC;AAAA,IACA,aAAa,KAAK,MAAM;AAAA,IACxB,OAAO,KAAK;AAAA,IACZ,YAAY,KAAK,MAAM;AAAA,IACvB;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,QAAQ,QAAQ;AACnB,uBAAmB,KAAK,OAAO;AAAA,MAC7B;AAAA,MACA,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,MACA,cAAc,oBAAoB,OAAO;AAAA,IAC3C,CAAC;AAAA,EACH;AAEA,QAAM,cAAc,MAAM,mBAAmB,SAAS,MAAM,SAAS;AAErE,eAAa,SAAS,SAAS,WAAW,SAAS,WAAW;AAC9D,SAAO;AACT;AAEA,eAAe,mBACb,SACA,MACA,WACsC;AACtC,MAAI,CAAC,UAAU,SAAS,aAAa,KAAK,CAAC,KAAK,oBAAoB;AAClE,WAAO;AAAA,EACT;AACA,QAAM,cAAc,KAAK,MAAM;AAC/B,QAAM,eAAeC,MAAK,KAAK,aAAa,WAAW,UAAU,mBAAmB;AACpF,MAAI,CAACD,IAAG,WAAW,YAAY,GAAG;AAChC,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,MAAM,KAAK,mBAAmB;AAAA,MACnC;AAAA,MACA,WAAWC,MAAK,KAAK,KAAK,MAAM,WAAW,QAAQ;AAAA,MACnD,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,KAAK,0CAA0C,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACzG,WAAO;AAAA,EACT;AACF;AAEA,eAAe,sBACb,SACA,MACA,WACoC;AACpC,QAAM,cACJ,CAAC,QAAQ,UAAU,CAAC,QAAQ,UAAU,UAAU,KAAK,CAAC,OAAO,OAAO,WAAW,OAAO,UAAU;AAClG,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,MAAM,KAAK,qBAAqB;AACtD,MAAI,CAAC,eAAe;AAClB,YAAQ;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,KAAK,OAAO,KAAK,aAAa,aAAa;AAC3D,SAAO,eAAe,KAAK,KAAK;AAClC;AAEA,eAAe,iBAAiB,SAAyB,MAAyC;AAChG,QAAM,WAAW,sBAAsB,KAAK,MAAM,OAAO;AAEzD,MAAI,QAAQ,UAAU,SAAS,GAAG;AAChC,UAAM,UAAU,QAAQ,UAAU,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;AACtE,QAAI,QAAQ,SAAS,GAAG;AACtB,cAAQ,MAAM,0BAA0B,QAAQ,KAAK,IAAI,CAAC,EAAE;AAC5D,cAAQ,MAAM,cAAc,YAAY,KAAK,IAAI,CAAC,EAAE;AACpD,aAAO,CAAC;AAAA,IACV;AACA,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,WAAW,oBAAoB,KAAK,MAAM,OAAO;AACvD,MAAI,SAAS,SAAS,KAAK,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAAO,CAAC,QAAQ,iBAAiB,KAAK,OAAO;AAClG,UAAM,SAAS,KAAK,aAAa;AACjC,QAAI;AACF,YAAM,SAAS,MAAM,OAAO;AAAA,QAC1B;AAAA,QACA,oBAAoB,QAAQ;AAAA,MAC9B;AACA,YAAM,WAAW,wBAAwB,UAAU,MAAM;AACzD,UAAI,SAAS,WAAW,GAAG;AACzB,gBAAQ,MAAM,kCAAkC;AAChD,eAAO,CAAC;AAAA,MACV;AACA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,cAAQ,MAAM,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACjG,aAAO,CAAC;AAAA,IACV,UAAE;AACA,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,KAAK,CAAC,QAAQ,QAAQ;AAC5C,YAAQ,MAAM,2EAA2E;AACzF,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;AAEA,SAAS,oBAAoB,SAAsC;AACjE,QAAM,QAAkB,CAAC;AACzB,aAAW,UAAU,OAAO,OAAO,OAAO,GAAG;AAC3C,UAAM,KAAK,GAAG,OAAO,SAAS,GAAG,OAAO,SAAS,GAAG,OAAO,SAAS;AAAA,EACtE;AACA,SAAO;AACT;AAEA,SAAS,aACP,SACA,SACA,WACA,SACA,aACM;AACN,QAAM,WAAW,gBAAgB,OAAO;AACxC,MAAI,QAAQ,QAAQ;AAClB,YAAQ,IAAI,kCAAkC,OAAO,mBAAmB,UAAU,KAAK,IAAI,CAAC,EAAE;AAAA,EAChG,OAAO;AACL,YAAQ,IAAI,qBAAqB,OAAO,mBAAmB,UAAU,KAAK,IAAI,CAAC,EAAE;AAAA,EACnF;AACA,aAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,UAAM,QAAQ,OAAO,QAAQ,SAAS,OAAO,QAAQ,SAAS,OAAO,UAAU;AAC/E,YAAQ,IAAI,KAAK,SAAS,KAAK,KAAK,UAAU;AAAA,EAChD;AACA,MAAI,aAAa;AACf,eAAW,SAAS,YAAY,SAAS;AACvC,YAAM,SAAS,MAAM,SAAS,KAAK,MAAM,MAAM,MAAM;AACrD,cAAQ,IAAI,WAAW,MAAM,IAAI,KAAK,MAAM,MAAM,GAAG,MAAM,EAAE;AAAA,IAC/D;AACA,aAAS,KAAK,GAAG,YAAY,QAAQ;AAAA,EACvC;AACA,aAAW,WAAW,UAAU;AAC9B,YAAQ,KAAK,cAAc,OAAO,EAAE;AAAA,EACtC;AACF;AAEA,SAAS,gBAAgB,SAAsC;AAC7D,QAAM,WAAqB,CAAC;AAC5B,aAAW,UAAU,OAAO,OAAO,OAAO,GAAG;AAC3C,aAAS,KAAK,GAAG,OAAO,QAAQ;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAASC,YAAW,SAAiB,MAAiC;AACpE,SAAO,IAAI,QAAQ,CAAC,gBAAgB,kBAAkB;AACpD,UAAM,QAAQC,OAAM,SAAS,MAAM,EAAE,OAAO,UAAU,CAAC;AACvD,UAAM,GAAG,SAAS,CAAC,SAAS,eAAe,QAAQ,CAAC,CAAC;AACrD,UAAM,GAAG,SAAS,CAAC,QAAQ,cAAc,GAAG,CAAC;AAAA,EAC/C,CAAC;AACH;AAEA,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,4BAA4B,CAAC,cAAc,cAAc,cAAc,SAAS;AAEtF,SAAS,mBAAmB,SAA+D;AACzF,QAAM,QAAQ,eAAe,KAAK,OAAO;AACzC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,SAAO,EAAE,OAAO,OAAO,MAAM,CAAC,CAAC,GAAG,OAAO,OAAO,MAAM,CAAC,CAAC,EAAE;AAC5D;AAEA,eAAe,mBAAmB,SAA8C;AAC9E,SAAO,IAAI,QAAQ,CAAC,mBAAmB;AACrC,UAAM,QAAQA,OAAM,SAAS,CAAC,WAAW,GAAG;AAAA,MAC1C,OAAO,CAAC,UAAU,QAAQ,QAAQ;AAAA,MAClC,OAAO,QAAQ,aAAa;AAAA,IAC9B,CAAC;AACD,QAAI,SAAS;AACb,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAA2B;AACnD,gBAAU,MAAM,SAAS;AAAA,IAC3B,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,YAAM,OAAO,OAAO,KAAK;AACzB,qBAAe,SAAS,KAAK,KAAK,SAAS,IAAI,OAAO,MAAS;AAAA,IACjE,CAAC;AACD,UAAM,GAAG,SAAS,MAAM,eAAe,MAAS,CAAC;AAAA,EACnD,CAAC;AACH;AAEA,eAAsB,qBACpB,cAAkC,QAAQ,IAAI,gBAC9C,aAAuB,2BACvB,eAA6D,oBAChC;AAC7B,QAAM,OAAO,cAAc,CAAC,WAAW,IAAI;AAC3C,aAAW,OAAO,MAAM;AACtB,UAAM,UAAU,MAAM,aAAa,GAAG;AACtC,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,UAAM,SAAS,mBAAmB,OAAO;AACzC,QACE,UACA,OAAO,SAAS,qBACf,OAAO,QAAQ,oBAAoB,OAAO,SAAS,mBACpD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAA6B;AACnD,SAAOF,MAAK;AAAA,IACV,MAAM;AAAA,IACN,QAAQ,aAAa,UAAU,YAAY;AAAA,IAC3C,QAAQ,aAAa,UAAU,eAAe;AAAA,EAChD;AACF;AAEA,eAAe,UAAU,OAAqB,aAAqB,eAAsC;AACvG,QAAM,YAAY,eAAe,KAAK;AAEtC,MAAI,CAACD,IAAG,WAAW,SAAS,GAAG;AAC7B,YAAQ,IAAI,yCAAyC;AACrD,UAAM,WAAW,MAAME,YAAW,eAAe,CAAC,MAAM,QAAQ,MAAM,OAAO,CAAC;AAC9E,QAAI,aAAa,GAAG;AAClB,YAAM,IAAI,MAAM,mDAAmD,QAAQ,GAAG;AAAA,IAChF;AAAA,EACF;AAEA,QAAM,mBAAmBD,MAAK,KAAK,aAAa,kBAAkB;AAClE,MAAID,IAAG,WAAW,gBAAgB,GAAG;AACnC,YAAQ,IAAI,mCAAmC;AAC/C,UAAM,SAASC,MAAK;AAAA,MAClB,MAAM;AAAA,MACN,QAAQ,aAAa,UAAU,YAAY;AAAA,MAC3C,QAAQ,aAAa,UAAU,YAAY;AAAA,IAC7C;AACA,UAAM,UAAU,MAAMC,YAAW,QAAQ,CAAC,WAAW,MAAM,gBAAgB,CAAC;AAC5E,QAAI,YAAY,GAAG;AACjB,YAAM,IAAI,MAAM,oDAAoD,OAAO,GAAG;AAAA,IAChF;AAAA,EACF;AACF;;;AatVA,SAAS,UAAU,KAAkD;AACnE,MAAI,IAAI,IAAI;AACV,WAAO;AAAA,EACT;AACA,MAAI,IAAI,aAAa,QAAQ;AAC3B,WAAO;AAAA,EACT;AACA,MAAI,IAAI,0BAA0B;AAChC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAASE,qBAAqC;AACnD,SAAO;AAAA,IACL,OAAO,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK;AAAA,IAC1D,SAAS,OAAO,aAAqB;AACnC,YAAM,SAAS,aAAa;AAC5B,UAAI;AACF,eAAO,MAAM,OAAO,QAAQ,UAAU,IAAI;AAAA,MAC5C,UAAE;AACA,eAAO,MAAM;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS,YACP,QAAW,EAAE,KAAK,OAAO,QAAQ,OAAO,OAAO,OAAO,WAAW,CAAC,GAAG,QAAQ,OAAO,eAAe,MAAM,CAAC;AAAA,IAC5G,KAAK,QAAQ;AAAA,EACf;AACF;AAEA,eAAsB,eAAe,OAAwBA,mBAAkB,GAAoB;AACjG,MAAI,UAAU,KAAK,GAAG,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,KAAK,OAAO;AACf,YAAQ,IAAI,6BAA6B;AACzC,YAAQ,IAAI,wCAAwC;AACpD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,KAAK,MAAM,KAAK,QAAQ,kCAAkC;AAChE,QAAI,CAAC,IAAI;AACP,cAAQ,IAAI,gDAAgD;AAC5D,aAAO;AAAA,IACT;AACA,UAAM,KAAK,QAAQ;AACnB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,YAAQ,IAAI,6BAA6B;AACzC,YAAQ,IAAI,gDAAgD;AAC5D,QAAI,eAAe,OAAO;AACxB,cAAQ,MAAM,8BAA8B,IAAI,OAAO,EAAE;AAAA,IAC3D;AACA,WAAO;AAAA,EACT;AACF;AAEA,IAAI,YAAY,QAAQ,UAAU,QAAQ,KAAK,CAAC,CAAC,IAAI;AACnD,iBAAe,EACZ,KAAK,CAAC,SAAS,QAAQ,KAAK,IAAI,CAAC,EACjC,MAAM,MAAM,QAAQ,KAAK,CAAC,CAAC;AAChC;","names":["fs","path","spawn","path","path","fs","path","fs","path","fs","path","report","fs","path","path","fs","runCommand","fetch","fs","path","os","fs","path","runCommand","spawn","createDefaultDeps"]}
@@ -39,6 +39,10 @@ commands:
39
39
  description: 研究员角色,用于开源调研、可行性研究与 PM 主导的市场/产品/竞品/用户研究阶段
40
40
  action: python3 "$LINCOLN_ROOT/scripts/lincoln_role.py" --role researcher
41
41
  args_hint: $ARGUMENTS
42
+ lc-agent-security-reviewer:
43
+ description: Lincoln 安全审查员角色,专注于框架策略、hook 门控与实现中的安全风险识别。
44
+ action: python3 "$LINCOLN_ROOT/scripts/lincoln_role.py" --role security-reviewer
45
+ args_hint: $ARGUMENTS
42
46
  lc-approve:
43
47
  description: 人类 PM 确认当前阶段 gate 通过(仅 human_gate 阶段)
44
48
  action: python3 "${CLAUDE_PLUGIN_ROOT:-${LINCOLN_HOME:-$HOME/.lincoln/current}}/scripts/stage_loader.py"
@@ -245,7 +249,7 @@ commands:
245
249
  action: python3 "$LINCOLN_ROOT/scripts/lincoln_workflow.py"
246
250
  args_hint: start --workflow existing-project-iteration
247
251
  lc-wf-framework-self-improvement:
248
- description: Lincoln 框架自身持续改进工作流(安全门控、harness 分发、摩擦学习、事件追踪、子代理委托)
252
+ description: 持续改进 Lincoln 框架本身的工作流(安全门控、harness 分发、摩擦学习、事件追踪、子代理委托)
249
253
  action: python3 "$LINCOLN_ROOT/scripts/lincoln_workflow.py"
250
254
  args_hint: start --workflow framework-self-improvement --issue-number <N>
251
255
  lc-wf-interview-to-knowledge:
@@ -350,6 +350,21 @@ PY
350
350
  echo "=== End Workflow Template ==="
351
351
  echo ""
352
352
  fi
353
+
354
+ # Inject the artifact-writing discipline (issue #126). This is the single
355
+ # deterministic load point: it fires once per session, only when an issue
356
+ # package is active, so research/exploration outside issue work and the
357
+ # individual skill prompts stay free of it.
358
+ POLICY_FILE="$FRAMEWORK_ROOT/.claude/policies/less-is-more.md"
359
+ if [[ -f "$POLICY_FILE" ]]; then
360
+ echo "=== 制品生成纪律(少即是多) ==="
361
+ echo "Source: .claude/policies/less-is-more.md"
362
+ echo ""
363
+ cat "$POLICY_FILE"
364
+ echo ""
365
+ echo "=== End 制品生成纪律 ==="
366
+ echo ""
367
+ fi
353
368
  else
354
369
  NEEDS_OPENING_GUIDANCE="true"
355
370
  fi
@@ -0,0 +1,24 @@
1
+ # 少即是多(Less is More)——制品生成纪律
2
+
3
+ ## 适用范围
4
+
5
+ 本纪律只在**生成制品**时生效:PRD、需求/设计文档、门户页面、交接文档、研究报告、原型注释等面向读者交付的内容。
6
+
7
+ 前期的思考、调研、深度研究阶段**不适用**本纪律:探索阶段应当充分收集、充分展开,信息越完整越好。只有在把已收集的信息凝练为制品时,才按本纪律删减——删减的依据是读者、用途与目的,而不是信息本身的数量。
8
+
9
+ 固定模板无法控制现实需求的复杂度,但以下纪律可以让任何制品保持简洁、精准、明确:信息量不等于价值,被淹没的关键信息等于没有信息。
10
+
11
+ ## 生成前先回答三个问题
12
+
13
+ 1. **读者是谁**——人类 PM、下游 Agent、还是工程师?读者决定详略与措辞。
14
+ 2. **用途是什么**——评审决策、交接执行、还是存档追溯?用途决定保留哪些信息。
15
+ 3. **读者要做什么**——读完这份制品,读者需要做出的决定或执行的动作是什么?不为这个决定服务的内容都是候选删除项。
16
+
17
+ ## 六条纪律
18
+
19
+ 1. **结论先行**:每份制品、每个章节把结论或需要读者做的事放在最前面;读者 30 秒内必须知道"这份制品讲什么、我需要做什么"。背景与推理过程放在结论之后,或移入归档页。
20
+ 2. **一件制品回答一个问题**:每份制品只回答一个核心问题(与文档页的"页面意图/边界"纪律一致)。想塞入第二个问题时,拆出新制品并互相链接,而不是加长当前制品。
21
+ 3. **删除测试**:落笔后逐段自问——"删掉这段,读者会做出错误决策吗?"不会就删。AI 初稿默认冗余,交付前必须做一轮纯删减评审(只删不增)。
22
+ 4. **结构优于段落**:表达关系、流程、对比时优先用表格、Mermaid 流程图/时序图;段落只用于必须的推理与叙事。表格单元格一句话,不写段落。
23
+ 5. **链接优于复制**:过程性信息与细节保留在源产物中,制品只放链接(与可追溯性一致),绝不复述或跨页复制内容。
24
+ 6. **三分钟可读**:每份主阅读路径制品以 3 分钟读完为目标。超出时优先删减与拆分,而不是指望读者自己筛选;辅助细节移入归档分组(如 `feasibility`、`version-log`),主路径只留决策所需内容。
@@ -15,9 +15,9 @@ description: |
15
15
  skills:
16
16
  superpowers:
17
17
  source: https://github.com/obra/superpowers.git
18
- ref: 6fd4507659784c351abbd2bc264c7162cfd386dc
18
+ ref: 8ca22dba9a94f28898bbce59f2537ff4d87c747d
19
19
  pinned_from: main
20
- pinned_at: 2026-07-15
20
+ pinned_at: 2026-10-07
21
21
  type: skill
22
22
  required: true
23
23
  license: MIT
@@ -60,14 +60,14 @@ skills:
60
60
 
61
61
  openspec:
62
62
  source: https://github.com/Fission-AI/openspec.git
63
- ref: v0.5.0
63
+ ref: v1.14.1
64
64
  type: cli
65
65
  binary: openspec
66
66
  required: true
67
67
  platforms:
68
68
  macos: npm install -g @fission-ai/openspec
69
69
  linux: npm install -g @fission-ai/openspec
70
- install_note: Requires Node.js >= 20.
70
+ install_note: Requires Node.js >= 20.19.0.
71
71
 
72
72
  gh:
73
73
  source: https://cli.github.com/
@@ -120,16 +120,16 @@ skills:
120
120
  # oh-my-claudecode — optional multi-agent orchestration layer, installed by default
121
121
  oh-my-claudecode:
122
122
  source: https://github.com/Yeachan-Heo/oh-my-claudecode.git
123
- ref: 590fb988931d34a12604be0ca4215c818079018e
123
+ ref: 454bae017356ed1d056182cd929b6eb6cf6143ad
124
124
  pinned_from: main
125
- pinned_at: 2026-07-15
125
+ pinned_at: 2026-10-07
126
126
  type: plugin
127
127
  required: false
128
128
  default_install: true
129
129
  license: MIT
130
130
  platforms:
131
- macos: git clone https://github.com/Yeachan-Heo/oh-my-claudecode.git ~/.claude/skills/oh-my-claudecode && git -C ~/.claude/skills/oh-my-claudecode checkout 590fb988931d34a12604be0ca4215c818079018e
132
- linux: git clone https://github.com/Yeachan-Heo/oh-my-claudecode.git ~/.claude/skills/oh-my-claudecode && git -C ~/.claude/skills/oh-my-claudecode checkout 590fb988931d34a12604be0ca4215c818079018e
131
+ macos: git clone https://github.com/Yeachan-Heo/oh-my-claudecode.git ~/.claude/skills/oh-my-claudecode && git -C ~/.claude/skills/oh-my-claudecode checkout 454bae017356ed1d056182cd929b6eb6cf6143ad
132
+ linux: git clone https://github.com/Yeachan-Heo/oh-my-claudecode.git ~/.claude/skills/oh-my-claudecode && git -C ~/.claude/skills/oh-my-claudecode checkout 454bae017356ed1d056182cd929b6eb6cf6143ad
133
133
  install_note: Optional but recommended. Installed as a skill under ~/.claude/skills/.
134
134
  recommended_skills:
135
135
  - oh-my-claudecode:plan
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "name": "lincoln",
11
11
  "description": "AI-Native product R&D collaboration system for Conductor + Claude Code. Orchestrates stages, gates, artifacts, skills, and roles across product, design, and engineering into a repeatable workflow from recordings to GitHub Issues to Obsidian knowledge base.",
12
- "version": "1.8.0",
12
+ "version": "1.8.3",
13
13
  "author": {
14
14
  "name": "Lincoln contributors"
15
15
  },
@@ -28,5 +28,5 @@
28
28
  ]
29
29
  }
30
30
  ],
31
- "version": "1.8.0"
31
+ "version": "1.8.3"
32
32
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lincoln",
3
- "version": "1.8.0",
3
+ "version": "1.8.3",
4
4
  "description": "AI-Native product R&D collaboration system for Conductor + Claude Code + OpenSpec + GitHub + Obsidian",
5
5
  "author": {
6
6
  "name": "Lincoln contributors"
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.0",
2
+ "version": "1.8.3",
3
3
  "manifests": [
4
4
  {
5
5
  "path": ".claude-plugin/plugin.json",
@@ -12,9 +12,9 @@ Lincoln is an AI-Native R&D workflow system spanning **IDEs, agent harnesses, co
12
12
 
13
13
  ## Latest Release
14
14
 
15
- [![Release](https://img.shields.io/badge/release-v1.8.0-blue)](RELEASE.md)
15
+ [![Release](https://img.shields.io/badge/release-v1.8.3-blue)](RELEASE.md)
16
16
 
17
- **v1.8.0** is released: SecurityAnalyzer pre-tool-use gating, Trace 2.0 event log, session friction scoring and knowledge recall, plus multi-dimensional stakeholder analysis in the clarify stage.
17
+ **v1.8.3** is released: SecurityAnalyzer pre-tool-use gating, Trace 2.0 event log, session friction scoring and knowledge recall, plus multi-dimensional stakeholder analysis in the clarify stage.
18
18
 
19
19
  See the full release notes in [RELEASE.md](RELEASE.md).
20
20
 
@@ -152,6 +152,12 @@ Lincoln assigns stable IDs such as `feature/*`, `page/*`, `field/*`, and `doc/*`
152
152
 
153
153
  See [`.claude/workflows/README.md`](.claude/workflows/README.md) for the full template catalog.
154
154
 
155
+ ### Less-is-More Artifact Discipline
156
+
157
+ AI-generated handoff artifacts tend to bury key information under bulk. Lincoln enforces a "less is more" discipline that applies **only when generating deliverables** ([`.claude/policies/less-is-more.md`](.claude/policies/less-is-more.md)): before writing, identify the reader, the purpose, and the decision the reader must make; then write conclusion-first, one artifact per question, pass a deletion test, prefer tables/diagrams over prose, link instead of duplicating, and keep the main reading path under three minutes. Research and deep-exploration stages are exempt and encouraged to expand fully.
158
+
159
+ The discipline is injected automatically by the session hook whenever an active issue package is detected — no manual step required.
160
+
155
161
  ### Markdown-First Issue Work Packages
156
162
 
157
163
  Every requirement maps to one GitHub issue and one Lincoln feature branch. The `issue-<N>/` work package contains:
@@ -230,6 +236,7 @@ Before submitting a PR, please read:
230
236
 
231
237
  | Version | Date | Key capabilities |
232
238
  |---|---|---|
239
+ | v1.8.3 | 2026-10-08 | Less-is-more artifact discipline (hook-injected); platform-aware install hints for non-npm CLIs; `lincoln update` refreshes external skill libraries |
233
240
  | v1.7.0 | 2026-09-05 | SecurityAnalyzer gating; Trace 2.0 event log; friction scoring/knowledge recall/trace condensation/MR mining; parallel specialist delegation; stakeholder analysis model |
234
241
  | v1.6.3 | 2026-08-15 | Markdown-first issue-package documents; `--render-stage` batch rendering; local `mermaid.min.js` runtime |
235
242
  | v1.6.2 | 2026-08-12 | `lc-init-branch` reads global Lincoln templates |
@@ -12,9 +12,9 @@ Lincoln 是一个贯穿 **IDE、Agent Harness、代码托管、知识管理、
12
12
 
13
13
  ## 最新版本
14
14
 
15
- [![Release](https://img.shields.io/badge/release-v1.8.0-blue)](RELEASE.md)
15
+ [![Release](https://img.shields.io/badge/release-v1.8.3-blue)](RELEASE.md)
16
16
 
17
- **v1.8.0** 已发布:新增 SecurityAnalyzer 安全门控、Trace 2.0 事件日志与会话摩擦学习/知识召回能力,clarify 阶段支持多维度相关者分析。
17
+ **v1.8.3** 已发布:新增 SecurityAnalyzer 安全门控、Trace 2.0 事件日志与会话摩擦学习/知识召回能力,clarify 阶段支持多维度相关者分析。
18
18
 
19
19
  查看完整发布说明:[RELEASE.md](RELEASE.md)
20
20
 
@@ -94,13 +94,15 @@ lincoln init-project
94
94
 
95
95
  ### 更新 Lincoln
96
96
 
97
- 已安装过 Lincoln 的用户,一条命令即可升级——`lincoln update` 会自动拉取 npm 最新版本,并重新把框架同步到各 harness:
97
+ 已安装过 Lincoln 的用户,一条命令即可升级——`lincoln update` 会自动拉取 npm 最新版本,重新把框架同步到各 harness,并按新版本中 pin 的版本刷新外部技能库(superpowers、gsd、oh-my-claudecode 等 `~/.claude/skills/` 下的 git 仓库,以及 openspec 等 npm 管理的 CLI):
98
98
 
99
99
  ```bash
100
- lincoln update # 升级到最新版本并重新同步框架
100
+ lincoln update # 升级本体 + 同步框架 + 刷新外部技能库到最新 pin
101
101
  lincoln update --check # 只检查是否有新版本,不安装
102
102
  ```
103
103
 
104
+ 技能库同步遵循 dependencies.yaml 的 pin 策略:本地有未提交修改的仓库会被跳过并警告(不会被强制覆盖),非 npm 管理的 CLI(如 gh)缺失时只提示安装命令。同步失败降级为警告,不会阻断升级。
105
+
104
106
  如果还是旧版安装(例如 bin 名是 `lincoln-install` 的时代),或更新时 npm 报 `EEXIST: file already exists`,说明有旧包残留的 bin 文件挡住了安装,先清理再重装:
105
107
 
106
108
  ```bash
@@ -152,6 +154,12 @@ Lincoln 为需求、页面、字段、文档等产物分配 `feature/*`、`page/
152
154
 
153
155
  完整模板说明见 [`.claude/workflows/README.md`](.claude/workflows/README.md)。
154
156
 
157
+ ### 少即是多的制品生成纪律
158
+
159
+ AI 生成的交接产物容易内容堆积、重点淹没。Lincoln 把「少即是多」固化为一条只在**制品生成**时生效的纪律([`.claude/policies/less-is-more.md`](.claude/policies/less-is-more.md)):生成前先明确读者、用途与读者要做的决定;写作遵循结论先行、一件制品回答一个问题、删除测试、结构优于段落、链接优于复制、三分钟可读六条原则。调研与深度研究阶段不受其约束,鼓励充分展开。
160
+
161
+ 该纪律由 session hook 在检测到活跃 issue 工作包时自动注入,无需任何手动操作。
162
+
155
163
  ### Markdown-first Issue 工作包
156
164
 
157
165
  每个需求对应一个 GitHub issue 和一个 Lincoln feature 分支。工作包目录 `issue-<N>/` 包含:
@@ -230,6 +238,7 @@ Lincoln 的 `.claude/` 是开放的系统提示层,欢迎基于同一套元模
230
238
 
231
239
  | 版本 | 日期 | 关键能力 |
232
240
  |---|---|---|
241
+ | v1.8.3 | 2026-10-08 | 少即是多制品生成纪律(hook 注入);非 npm CLI 平台化安装提示;`lincoln update` 同步刷新外部技能库 |
233
242
  | v1.7.0 | 2026-09-05 | SecurityAnalyzer 安全门控;Trace 2.0 事件日志;摩擦学习/知识召回/Trace 浓缩/MR 挖掘;并行专家子代理委托;相关者分析模型 |
234
243
  | v1.6.3 | 2026-08-15 | Markdown-first issue-package 文档;`--render-stage` 批量渲染;Mermaid 图表本地渲染 |
235
244
  | v1.6.2 | 2026-08-12 | `lc-init-branch` 改读全局 Lincoln 模板 |
@@ -1,3 +1,39 @@
1
+ # Lincoln v1.8.3 Release Notes
2
+
3
+ **Release date:** 2026-10-08
4
+
5
+ ## Highlights
6
+
7
+ - **少即是多制品生成纪律 (#126 / #128)** — 新增 `.claude/policies/less-is-more.md`,把「少即是多」固化为一条只在生成制品时生效的写作纪律:生成前先明确读者、用途与读者要做的决定;写作遵循结论先行、一件制品回答一个问题、删除测试、结构优于段落、链接优于复制、三分钟可读六条原则。调研与深度研究阶段不受其约束。该纪律由 session hook 在检测到活跃 issue 工作包(`current_stage != not_started`)时自动注入全文——单一注入点,skill prompt、stage YAML 与通用 Agent 契约均不重复携带,零额外上下文压力。
8
+ - **修复 policies 目录未同步进项目的问题** — `syncClaudeCode` 的 `COPY_SUBDIRS` 新增 `policies`:此前 vendored 项目中 `.claude/policies/` 缺失,导致 `pre-tool-use.sh` 的 security.yaml 安全门控与本次新增的 less-is-more.md 在项目内静默跳过。修复后两类政策文件都会随 `lincoln install` / `lincoln update` 同步进项目。
9
+
10
+ ## Migration Notes
11
+
12
+ - 无破坏性变更。升级到本版本后,下一次 issue 会话启动即自动获得少即是多纪律注入,无需手动操作。
13
+ - 注意:npm 上 1.8.1 与 1.8.2 因发布令牌问题未曾发布(见 v1.8.2 说明),从 1.8.0 直接升级到 1.8.3 会一并获得这两个版本的能力(外部技能库自动刷新、非 npm CLI 平台化安装提示),升级后建议执行一次 `lincoln update`。
14
+
15
+ ---
16
+
17
+ # Lincoln v1.8.2 Release Notes
18
+
19
+ **Release date:** 2026-10-07
20
+
21
+ ## Highlights
22
+
23
+ - **修复非 npm CLI 安装提示的平台命令选择** — 技能库同步在非 npm CLI(gh、ffmpeg、faster-whisper 等)缺失时,按当前运行平台(可用 `platform` 参数覆盖,便于跨平台测试)从 `dependencies.yaml` 的 `platforms` 映射中选择对应的安装提示命令。
24
+ - **一条命令更新 Lincoln 与全部外部技能库 (#124 / LEW-73)** — `lincoln update`(以及 `lincoln install`)现在会读取新安装 payload 中的 `.claude/skills/dependencies.yaml`,把外部依赖刷新到当前 pin 的稳定版本,不再需要手动逐个仓库升级:
25
+ - git 类技能库(superpowers、oh-my-claudecode):缺失时自动 clone + checkout 到 pin;本地 HEAD 落后时 `git fetch origin <pin>` 后 checkout FETCH_HEAD;pin 不在任何远端 ref 尖端时回退全量 fetch + checkout SHA。工作区有本地修改(dirty)的仓库一律跳过并警告,绝不强制覆盖。
26
+ - npm 管理的 CLI(openspec):缺失或版本低于 pin 时自动 `npm install -g <pkg>@<pin>` 升级;非 npm 管理的 CLI(gh、ffmpeg、faster-whisper 等)缺失时只提示对应平台的手动安装命令,不会擅自执行 brew/apt/pip。
27
+ - 单个依赖的同步失败(网络故障、上游不可用等)降级为警告,不会阻断 Lincoln 本体升级;`--dry-run` 下只报告计划动作,不执行任何命令。
28
+ - **外部依赖 pin 升级至 2026-10-07 上游版本 (#124 / LEW-73)** — superpowers → `8ca22db`(v6.4.2,快进 242 个上游提交),oh-my-claudecode → `454bae0`(v5.6.2,快进 1599 个上游提交),openspec → v1.14.1(npm 同版本发布,要求 Node.js >= 20.19.0);gsd 与上游无漂移,保持 `bdcaab2` 不变。用户升级 Lincoln 到本版本后,一次 `lincoln update` 即把本地技能库同步到这些 pin。
29
+
30
+ ## Migration Notes
31
+
32
+ - 无破坏性变更:框架文件、issue 工作包、阶段协议与 hooks 均保持兼容。
33
+ - 升级后首次运行 `lincoln update` 会自动补齐或刷新技能库;若某个技能仓库有本地未提交修改,同步会跳过该仓库并给出警告,手动 commit/stash 后重跑即可。
34
+
35
+ ---
36
+
1
37
  # Lincoln v1.8.0 Release Notes
2
38
 
3
39
  **Release date:** 2026-09-21