@sushanglewis/lincoln 1.7.0 → 1.8.2

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.
Files changed (28) hide show
  1. package/dist/main.js +347 -107
  2. package/dist/main.js.map +1 -1
  3. package/dist/postinstall.js +306 -21
  4. package/dist/postinstall.js.map +1 -1
  5. package/framework/.claude/skills/build-product-prototype/prompts/main.md +6 -1
  6. package/framework/.claude/skills/clarify-requirements/prompts/main.md +6 -0
  7. package/framework/.claude/skills/dependencies.yaml +8 -8
  8. package/framework/.claude/skills/draft-product-design/SKILL.md +1 -0
  9. package/framework/.claude/skills/draft-product-design/prompts/main.md +26 -3
  10. package/framework/.claude/skills/lc-workflow/validators/validate.py +1 -0
  11. package/framework/.claude/stages/product-design-docs.yaml +2 -0
  12. package/framework/.claude/workflows/bug-fix.yaml +1 -0
  13. package/framework/.claude/workflows/design-spike.yaml +1 -0
  14. package/framework/.claude/workflows/existing-project-iteration.yaml +1 -0
  15. package/framework/.claude/workflows/interview-to-knowledge.yaml +1 -0
  16. package/framework/.claude/workflows/oss-first-design.yaml +1 -0
  17. package/framework/.claude-plugin/marketplace.json +2 -2
  18. package/framework/.claude-plugin/plugin.json +1 -1
  19. package/framework/.version-bump.json +1 -1
  20. package/framework/README.en.md +21 -3
  21. package/framework/README.md +23 -3
  22. package/framework/RELEASE.md +41 -1
  23. package/framework/manifest.json +24 -24
  24. package/framework/scripts/lincoln_index.py +8 -1
  25. package/framework/tools/lincoln/package-lock.json +2 -2
  26. package/framework/tools/lincoln/package.json +1 -1
  27. package/framework/tools/lincoln-installer/package.json +1 -1
  28. package/package.json +1 -1
@@ -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]\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;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,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"]}
@@ -60,7 +60,9 @@ You may still read the categorized example templates under `.claude/templates/is
60
60
 
61
61
  Use the structured renderer with `--data` containing `sections`, `pages`, and `interactions` as appropriate.
62
62
 
63
- 5. **Plan prototype generation granularity.** Before writing prototype pages, list every screen from `flows.html` and `page-map.html`. Group them into cohesive clusters (e.g. onboarding, main shell, settings, overlays, tray). Generate one cluster at a time. After each cluster, verify that every page has complete annotation meta tags before starting the next cluster.
63
+ 5. **Plan prototype generation granularity.** Before writing prototype pages, derive a **角色×场景矩阵** from `scenarios.html` and `page-map.html`: rows are the user roles/personas, columns are the key scenarios (including boundary cases such as empty, loading, error, success). Every cell that a real user can reach must map to exactly one prototype sub-page; the matrix itself is written into `ui-spec.html` (章节 `## 角色×场景矩阵`) and serves as the splitting contract. Then group the sub-pages into cohesive clusters (e.g. onboarding, main shell, settings, overlays, tray). Generate one cluster at a time. After each cluster, verify that every page has complete annotation meta tags before starting the next cluster.
64
+
65
+ Each cluster is organized by one main shell page (e.g. `pages/prototype/{app,web,mobile}/main/page.html`) whose `navItems` link to all sub-pages of that cluster, so the portal viewer can walk every role/scenario state from a single entry page.
64
66
 
65
67
  6. Create interactive HTML prototypes under `{process_slug}/pages/prototype/{app,web,mobile}/` using the structured prototype renderer:
66
68
 
@@ -112,6 +114,7 @@ You may still read the categorized example templates under `.claude/templates/is
112
114
  - Include `<meta name="prototype-base" content="../../../">` (or `../../../../` for depth 4).
113
115
  - Include `<meta name="page-uid" content="...">`, `<meta name="nav-group" content="...">`, and `<meta name="nav-label" content="...">` (injected by the renderer from CLI args; annotations come from the YAML `annotations` block).
114
116
  - Provide the full annotation meta tags so the portal right panel explains functionality, layout, fields, boundary cases, and exception flows.
117
+ - State the applicable role(s), scenario, page state (default / empty / loading / error / success), and which functions are visible and usable in that state via the `doc-purpose`, `doc-rules`, and `doc-boundaries` annotations, so each sub-page precisely depicts what a given role sees and can do in that case.
115
118
  - Use `LincolnPrototype.ui` builders and `prototype.css` tokens for every visual element so both light and dark themes render correctly; verify both themes by toggling the portal theme switch.
116
119
  - Assign a stable `data-uid` attribute to every interactive element, screen region, and WebView placeholder.
117
120
  - Override `LincolnPrototype.data` in the page script for issue-specific mock data (user, org, webviews, settings, unread items).
@@ -131,6 +134,8 @@ You may still read the categorized example templates under `.claude/templates/is
131
134
 
132
135
  ## Rules
133
136
 
137
+ - `fields.html` and `ui-spec.html` are doc pages: each opens with `## 页面意图` and `## 边界`, follows standard Markdown structure (single H1, H2 chapters, tables over prose), and links instead of duplicating content from `flows.html` / `page-map.html` / `scenarios.html`.
138
+ - The prototype sub-pages are the interactive GUI evidence for the PM stage: each one must precisely depict the page state and available functions of a specific role in a specific scenario (see the 角色×场景矩阵 in `ui-spec.html`). Do not merge multiple roles/scenarios into one page when their visible states differ.
134
139
  - The HTML prototype is the primary review artifact; Pencil is optional.
135
140
  - Always reuse the shared `prototype.css` and `prototype.js` assets. Do not inline all styles or rebuild the component library from scratch.
136
141
  - Keep controls and states complete enough for implementation: default, hover/focus where relevant, disabled, empty, loading, error, and success.
@@ -117,6 +117,12 @@ Produce a clear, agreed-upon `{process_slug}/pages/docs/requirements.html` and t
117
117
  - If the PM edits `requirements.html`, `stakeholders.html`, or `prd.html` directly and runs `workflow-continue`, re-read the file and continue from there.
118
118
  - Do not proceed to the next step until the PM explicitly confirms (e.g., says "confirm" or "确认").
119
119
 
120
+ ## 页面纪律
121
+
122
+ - Every document page opens with `## 页面意图` (目标读者 + 本页回答什么问题) and `## 边界` (本页不覆盖什么 + 单一事实来源链接).
123
+ - Content follows standard Markdown: a single H1, H2 chapters, and tables/Mermaid over long prose. Never duplicate content across pages — link to the single source of truth instead.
124
+ - These pages are business-facing: 需求背景、用户角色、旅程、业务状态、业务流程、验收标准. Technical research or solution comparisons performed while clarifying are only background for the PM's decision — do not register them into any page; they may be summarized later into the archived `feasibility.html` by the design stage.
125
+
120
126
  ## 认知象限确认(Johari)
121
127
 
122
128
  澄清问题按 Johari 四象限设计与标注:
@@ -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
@@ -13,6 +13,7 @@ inputs:
13
13
  required: true
14
14
  outputs:
15
15
  - "{process_slug}/pages/docs/design-review.html"
16
+ - "{process_slug}/pages/docs/decisions.html"
16
17
  - "{process_slug}/pages/docs/scenarios.html"
17
18
  - "{process_slug}/pages/docs/feature-catalog.html"
18
19
  - "{process_slug}/pages/docs/data-model.html"
@@ -45,14 +45,35 @@ Create `{process_slug}/pages/docs/` HTML design documents with enough product, d
45
45
  ```
46
46
  This creates only the pages that do not yet exist. If a matching `.md` file exists, it is used automatically; otherwise the page is created empty for you to fill afterwards.
47
47
 
48
- Page-specific guidance:
49
- - `design-review.md`: H2 chapters such as `## 决策摘要`, `## 范围`, `## 链接`, `## 开放问题`, `## 审批清单`.
48
+ Page-specific guidance (every doc page starts with `## 页面意图` — target reader and the question this page answers — and `## 边界` — what it deliberately does not cover plus links to the single source of truth; do not duplicate content across pages, link instead):
49
+ - `design-review.md`: H2 chapters such as `## 页面意图`, `## 范围`, `## 链接`, `## 开放问题`, `## 审批清单`. Do **not** include a decision log here — decisions live only in `decisions.html`.
50
+ - `decisions.md`: the archive of important communication records and decisions from both the clarify and design stages. H2 chapters such as `## 页面意图`, `## 决策清单`; each entry is a Markdown table row with 日期 / 场景 / 选项 / 决定 / 理由 / 影响 / 状态. Render it with an explicit archive nav group:
51
+
52
+ ```bash
53
+ python scripts/lincoln_render.py \
54
+ --stage product-design-docs \
55
+ --target issue-<N>/pages/docs/decisions.html \
56
+ --title "决策归档" \
57
+ --nav-label "决策归档" \
58
+ --nav-group "归档" \
59
+ --markdown issue-<N>/pages/docs/decisions.md
60
+ ```
50
61
  - `scenarios.md`: `## 主要场景`, `## 边界场景`, `## 非目标`, plus persona descriptions and Mermaid flowcharts.
51
62
  - `feature-catalog.md`: either a Markdown table or a YAML `features` array.
52
63
  - `data-model.md`: either Markdown entity sections or a YAML `entities` array.
53
64
  - `flows.md`: Markdown with ` ```mermaid ` flowcharts and numbered step lists.
54
65
  - `page-map.md`: either a Markdown table or a YAML `pages` array.
55
- - `feasibility.md`: H2 chapters such as `## 风险`, `## 方案对比`, `## 建议`.
66
+ - `feasibility.md`: H2 chapters such as `## 风险`, `## 方案对比`, `## 建议`. This page holds all technical research; render it with `--nav-group "归档"` so it stays out of the main reading path:
67
+
68
+ ```bash
69
+ python scripts/lincoln_render.py \
70
+ --stage product-design-docs \
71
+ --target issue-<N>/pages/docs/feasibility.html \
72
+ --title "可行性研究" \
73
+ --nav-label "可行性" \
74
+ --nav-group "归档" \
75
+ --markdown issue-<N>/pages/docs/feasibility.md
76
+ ```
56
77
  - `version-log.md`: H2 chapters plus a Markdown table of version entries.
57
78
  - `api-list.md`: either a Markdown table or a YAML `apis` array.
58
79
  4. Create the PM→UX handoff contract at `{process_slug}/handoffs/pm-to-ux/pm-to-ux.handoff.yaml` referencing the approved design docs and PRD versions.
@@ -67,6 +88,8 @@ Create `{process_slug}/pages/docs/` HTML design documents with enough product, d
67
88
 
68
89
  - Use Chinese for PM-facing content unless the requirements are in English.
69
90
  - Keep documents short and reviewable; prefer tables and Mermaid diagrams over long prose.
91
+ - Every document page must open with `## 页面意图` and `## 边界`; content must follow standard Markdown (a single H1, H2 chapters, tables/Mermaid over long prose). Never copy content across pages — link to the single source of truth instead.
92
+ - Technical research and solution comparisons (frameworks, open-source options, trade-off analysis) belong **only** in `feasibility.html` (archived) or the PM→UX handoff contract. They must not appear in `prd.html`, `requirements.html`, `design-review.html`, `scenarios.html`, `feature-catalog.html`, or any other main-path page. PM-stage pages focus on business clarity: background, user roles, journeys, business states, flows, page routes/elements/interactions.
70
93
  - For technical frameworks and open-source projects, check current official docs or primary repositories before recommending.
71
94
  - Do not create UI specs, field specs, or prototypes in this step. Those are produced in the next stage `product-prototype`.
72
95
  - Do not create a Pencil prototype in this step.
@@ -452,6 +452,7 @@ def check_no_conflict_with_existing_knowledge(feature_slug: str):
452
452
  def validate_design_docs_complete(design_id: str):
453
453
  docs = [
454
454
  "design-review.html",
455
+ "decisions.html",
455
456
  "scenarios.html",
456
457
  "feature-catalog.html",
457
458
  "data-model.html",
@@ -17,6 +17,7 @@ variables:
17
17
  - process_slug
18
18
  artifact_templates:
19
19
  '{process_slug}/pages/docs/design-review.html': .claude/templates/issue-package/page-doc.html.tpl
20
+ '{process_slug}/pages/docs/decisions.html': .claude/templates/issue-package/page-doc.html.tpl
20
21
  '{process_slug}/pages/docs/scenarios.html': .claude/templates/issue-package/page-doc.html.tpl
21
22
  '{process_slug}/pages/docs/feature-catalog.html': .claude/templates/issue-package/page-doc-structured.html.tpl
22
23
  '{process_slug}/pages/docs/data-model.html': .claude/templates/issue-package/page-doc-structured.html.tpl
@@ -44,6 +45,7 @@ skills:
44
45
  artifacts:
45
46
  required:
46
47
  - '{process_slug}/pages/docs/design-review.html'
48
+ - '{process_slug}/pages/docs/decisions.html'
47
49
  - '{process_slug}/pages/docs/scenarios.html'
48
50
  - '{process_slug}/pages/docs/feature-catalog.html'
49
51
  - '{process_slug}/pages/docs/data-model.html'
@@ -29,6 +29,7 @@ workflow:
29
29
  action: draft-product-design
30
30
  artifacts:
31
31
  - "{process_slug}/pages/docs/design-review.html"
32
+ - "{process_slug}/pages/docs/decisions.html"
32
33
  exit_checks:
33
34
  - check: design_docs_complete
34
35
  - check: design_docs_human_approved
@@ -29,6 +29,7 @@ workflow:
29
29
  action: draft-product-design
30
30
  artifacts:
31
31
  - "{process_slug}/pages/docs/design-review.html"
32
+ - "{process_slug}/pages/docs/decisions.html"
32
33
  exit_checks:
33
34
  - check: design_docs_complete
34
35
  - check: design_docs_human_approved
@@ -44,6 +44,7 @@ workflow:
44
44
  action: draft-product-design
45
45
  artifacts:
46
46
  - "{process_slug}/pages/docs/design-review.html"
47
+ - "{process_slug}/pages/docs/decisions.html"
47
48
  exit_checks:
48
49
  - check: design_docs_complete
49
50
  - check: design_docs_human_approved
@@ -69,6 +69,7 @@ workflow:
69
69
  human_gate: true
70
70
  artifacts:
71
71
  - "{process_slug}/pages/docs/design-review.html"
72
+ - "{process_slug}/pages/docs/decisions.html"
72
73
  - "{process_slug}/pages/docs/scenarios.html"
73
74
  - "{process_slug}/pages/docs/feature-catalog.html"
74
75
  - "{process_slug}/pages/docs/data-model.html"
@@ -38,6 +38,7 @@ workflow:
38
38
  action: draft-product-design
39
39
  artifacts:
40
40
  - "{process_slug}/pages/docs/design-review.html"
41
+ - "{process_slug}/pages/docs/decisions.html"
41
42
  exit_checks:
42
43
  - check: design_docs_complete
43
44
  - check: design_docs_human_approved
@@ -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.7.0",
12
+ "version": "1.8.2",
13
13
  "author": {
14
14
  "name": "Lincoln contributors"
15
15
  },
@@ -28,5 +28,5 @@
28
28
  ]
29
29
  }
30
30
  ],
31
- "version": "1.7.0"
31
+ "version": "1.8.2"
32
32
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lincoln",
3
- "version": "1.7.0",
3
+ "version": "1.8.2",
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.7.0",
2
+ "version": "1.8.2",
3
3
  "manifests": [
4
4
  {
5
5
  "path": ".claude-plugin/plugin.json",