@sushanglewis/lincoln 1.8.2 → 1.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +6 -1
- package/dist/main.js.map +1 -1
- package/dist/postinstall.js +6 -1
- package/dist/postinstall.js.map +1 -1
- package/framework/.claude/agents/pm.md +3 -0
- package/framework/.claude/harnesses/command-map.yaml +5 -1
- package/framework/.claude/hooks/on-session-start.sh +15 -0
- package/framework/.claude/policies/less-is-more.md +24 -0
- package/framework/.claude/schemas/stage-definition.schema.json +2 -0
- package/framework/.claude/skills/build-product-prototype/prompts/main.md +4 -1
- package/framework/.claude/skills/clarify-requirements/prompts/main.md +36 -16
- package/framework/.claude/skills/draft-product-design/prompts/main.md +1 -1
- package/framework/.claude/skills/lc-workflow/validators/validate.py +93 -12
- package/framework/.claude/skills/plan-tdd-development/SKILL.md +1 -0
- package/framework/.claude/skills/plan-tdd-development/prompts/main.md +34 -4
- package/framework/.claude/stages/clarify.yaml +3 -0
- package/framework/.claude/stages/tdd-development-plan.yaml +6 -1
- package/framework/.claude/workflows/interview-to-knowledge.yaml +5 -0
- package/framework/.claude-plugin/marketplace.json +2 -2
- package/framework/.claude-plugin/plugin.json +1 -1
- package/framework/.version-bump.json +1 -1
- package/framework/README.en.md +16 -2
- package/framework/README.md +16 -2
- package/framework/RELEASE.md +37 -0
- package/framework/manifest.json +30 -26
- package/framework/scripts/sync-external-agents.sh +7 -1
- package/framework/scripts/validate_stage.py +96 -15
- package/framework/tools/lincoln/package-lock.json +2 -2
- package/framework/tools/lincoln/package.json +1 -1
- package/framework/tools/lincoln-installer/package.json +1 -1
- package/package.json +1 -1
package/dist/postinstall.js
CHANGED
|
@@ -106,7 +106,12 @@ var COPY_SUBDIRS = [
|
|
|
106
106
|
"stages",
|
|
107
107
|
"schemas",
|
|
108
108
|
"templates",
|
|
109
|
-
"harnesses"
|
|
109
|
+
"harnesses",
|
|
110
|
+
// Policies are data files consumed by hooks at runtime (e.g.
|
|
111
|
+
// .claude/policies/less-is-more.md read by on-session-start.sh,
|
|
112
|
+
// security.yaml read by pre-tool-use.sh). Without syncing them into the
|
|
113
|
+
// project, vendored installs silently skip those guardrails (#126).
|
|
114
|
+
"policies"
|
|
110
115
|
];
|
|
111
116
|
function sha256(filePath) {
|
|
112
117
|
const data = fs3.readFileSync(filePath);
|
package/dist/postinstall.js.map
CHANGED
|
@@ -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/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":"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","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"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/install.ts","../src/lib/paths.ts","../src/lib/versionMarker.ts","../src/lib/packageInfo.ts","../src/lib/syncClaude.ts","../src/lib/claudeMdMerge.ts","../src/lib/runHarnessAdapter.ts","../src/lib/syncHarness.ts","../src/lib/syncSkills.ts","../src/lib/semver.ts","../src/lib/harnessDetect.ts","../src/lib/harnessSelect.ts","../src/lib/prompt.ts","../src/postinstall.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport type { LincolnPaths } from '../lib/paths.js'\nimport { resolveLincolnPaths } from '../lib/paths.js'\nimport { writeVersionMarker } from '../lib/versionMarker.js'\nimport { readLocalPackageVersion, resolvePayloadRoot } from '../lib/packageInfo.js'\nimport type { HarnessSyncReport, SyncHarnessesOptions } from '../lib/syncHarness.js'\nimport { syncHarnesses } from '../lib/syncHarness.js'\nimport type { SkillSyncReport, SyncExternalSkillsOptions } from '../lib/syncSkills.js'\nimport { syncExternalSkills } from '../lib/syncSkills.js'\nimport { detectGlobalHarnesses, installedHarnessIds, isValidHarnessId, HARNESS_IDS } from '../lib/harnessDetect.js'\nimport type { HarnessId } from '../lib/harnessDetect.js'\nimport { buildHarnessOptions, resolveHarnessSelection } from '../lib/harnessSelect.js'\nimport { createPrompt } from '../lib/prompt.js'\nimport type { Prompt } from '../lib/prompt.js'\n\nexport interface InstallOptions {\n yes: boolean\n dryRun: boolean\n force: boolean\n harnesses: string[]\n noVenv: boolean\n noInteractive: boolean\n}\n\nexport interface InstallDeps {\n paths: LincolnPaths\n payloadRoot: string\n syncHarnesses: (opts: SyncHarnessesOptions) => Promise<HarnessSyncReport>\n syncExternalSkills?: (opts: SyncExternalSkillsOptions) => Promise<SkillSyncReport>\n createPrompt: () => Prompt\n resolvePythonForVenv: (\n envOverride?: string,\n candidates?: string[],\n queryVersion?: (cmd: string) => Promise<string | undefined>\n ) => Promise<string | undefined>\n isTTY: boolean\n}\n\nexport function createDefaultDeps(): InstallDeps {\n return {\n paths: resolveLincolnPaths(),\n payloadRoot: resolvePayloadRoot() || '',\n syncHarnesses,\n syncExternalSkills,\n createPrompt,\n resolvePythonForVenv,\n isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY)\n }\n}\n\nexport async function install(\n options: InstallOptions,\n deps: InstallDeps = createDefaultDeps()\n): Promise<number> {\n const version = readLocalPackageVersion()\n if (!version) {\n console.error('Could not determine Lincoln version')\n return 1\n }\n\n const payloadRoot = deps.payloadRoot\n if (!payloadRoot || !fs.existsSync(payloadRoot)) {\n console.error('Lincoln payload not found. Run \"npm install -g @sushanglewis/lincoln\" first.')\n return 1\n }\n\n if (!options.dryRun && !options.yes && (options.noInteractive || !deps.isTTY)) {\n console.error(\n 'This will install Lincoln globally. Run with --yes to proceed, or run interactively in a TTY.'\n )\n return 1\n }\n\n const harnesses = await resolveHarnesses(options, deps)\n if (harnesses.length === 0) {\n return 1\n }\n\n const pythonPath = await resolvePythonIfNeeded(options, deps, harnesses)\n if (pythonPath === null) {\n return 1\n }\n\n if (!options.dryRun) {\n const versionDir = path.join(deps.paths.versionsDir, version)\n fs.mkdirSync(versionDir, { recursive: true })\n fs.cpSync(payloadRoot, versionDir, { recursive: true, force: true })\n try {\n fs.rmSync(deps.paths.currentDir, { recursive: true, force: true })\n fs.symlinkSync(versionDir, deps.paths.currentDir)\n } catch {\n fs.rmSync(deps.paths.currentDir, { recursive: true, force: true })\n fs.cpSync(versionDir, deps.paths.currentDir, { recursive: true, force: true })\n }\n }\n\n const reports = await deps.syncHarnesses({\n harnesses,\n payloadRoot: deps.paths.currentDir,\n paths: deps.paths,\n projectDir: deps.paths.lincolnHome,\n version,\n dryRun: options.dryRun,\n pythonPath\n })\n\n if (!options.dryRun) {\n writeVersionMarker(deps.paths, {\n version,\n installedAt: new Date().toISOString(),\n harnesses,\n managedFiles: collectManagedFiles(reports)\n })\n }\n\n const skillReport = await syncSkillLibraries(options, deps, harnesses)\n\n printSummary(options, version, harnesses, reports, skillReport)\n return 0\n}\n\nasync function syncSkillLibraries(\n options: InstallOptions,\n deps: InstallDeps,\n harnesses: HarnessId[]\n): Promise<SkillSyncReport | undefined> {\n if (!harnesses.includes('claude-code') || !deps.syncExternalSkills) {\n return undefined\n }\n const payloadRoot = deps.paths.currentDir\n const manifestPath = path.join(payloadRoot, '.claude', 'skills', 'dependencies.yaml')\n if (!fs.existsSync(manifestPath)) {\n return undefined\n }\n try {\n return await deps.syncExternalSkills({\n payloadRoot,\n skillsDir: path.join(deps.paths.claudeDir, 'skills'),\n dryRun: options.dryRun\n })\n } catch (err) {\n console.warn(` warning: external skill sync failed: ${err instanceof Error ? err.message : String(err)}`)\n return undefined\n }\n}\n\nasync function resolvePythonIfNeeded(\n options: InstallOptions,\n deps: InstallDeps,\n harnesses: HarnessId[]\n): Promise<string | undefined | null> {\n const needsPython =\n !options.dryRun && !options.noVenv && harnesses.some((id) => id === 'codex' || id === 'opencode')\n if (!needsPython) {\n return undefined\n }\n\n const pythonCommand = await deps.resolvePythonForVenv()\n if (!pythonCommand) {\n console.error(\n 'Python 3.10+ is required for Codex/OpenCode sync but was not found. Set LINCOLN_PYTHON to a compatible Python executable, or run with --no-venv.'\n )\n return null\n }\n\n await setupVenv(deps.paths, deps.payloadRoot, pythonCommand)\n return venvPythonPath(deps.paths)\n}\n\nasync function resolveHarnesses(options: InstallOptions, deps: InstallDeps): Promise<HarnessId[]> {\n const detected = detectGlobalHarnesses(deps.paths.homeDir)\n\n if (options.harnesses.length > 0) {\n const invalid = options.harnesses.filter((id) => !isValidHarnessId(id))\n if (invalid.length > 0) {\n console.error(`Unknown harness id(s): ${invalid.join(', ')}`)\n console.error(`Valid ids: ${HARNESS_IDS.join(', ')}`)\n return []\n }\n return options.harnesses as HarnessId[]\n }\n\n const selected = installedHarnessIds(deps.paths.homeDir)\n if (selected.length > 0 && !options.dryRun && !options.yes && !options.noInteractive && deps.isTTY) {\n const prompt = deps.createPrompt()\n try {\n const answer = await prompt.multiSelect(\n 'Select agent harnesses to install Lincoln into:',\n buildHarnessOptions(detected)\n )\n const resolved = resolveHarnessSelection(detected, answer)\n if (resolved.length === 0) {\n console.error('No harnesses selected. Aborting.')\n return []\n }\n return resolved\n } catch (err) {\n console.error(`Interactive selection failed: ${err instanceof Error ? err.message : String(err)}`)\n return []\n } finally {\n prompt.close()\n }\n }\n\n if (selected.length === 0 && !options.dryRun) {\n console.error('No agent harness detected. Install Claude Code, Codex, or OpenCode first.')\n return []\n }\n\n return selected\n}\n\nfunction collectManagedFiles(reports: HarnessSyncReport): string[] {\n const files: string[] = []\n for (const report of Object.values(reports)) {\n files.push(...report.written, ...report.skipped, ...report.preserved)\n }\n return files\n}\n\nfunction printSummary(\n options: InstallOptions,\n version: string,\n harnesses: HarnessId[],\n reports: HarnessSyncReport,\n skillReport?: SkillSyncReport\n): void {\n const warnings = collectWarnings(reports)\n if (options.dryRun) {\n console.log(`Dry run: would install Lincoln ${version} for harnesses: ${harnesses.join(', ')}`)\n } else {\n console.log(`Installed Lincoln ${version} for harnesses: ${harnesses.join(', ')}`)\n }\n for (const [harnessId, report] of Object.entries(reports)) {\n const count = report.written.length + report.skipped.length + report.preserved.length\n console.log(` ${harnessId}: ${count} file(s)`)\n }\n if (skillReport) {\n for (const entry of skillReport.entries) {\n const detail = entry.detail ? ` (${entry.detail})` : ''\n console.log(` skill ${entry.name}: ${entry.status}${detail}`)\n }\n warnings.push(...skillReport.warnings)\n }\n for (const warning of warnings) {\n console.warn(` warning: ${warning}`)\n }\n}\n\nfunction collectWarnings(reports: HarnessSyncReport): string[] {\n const warnings: string[] = []\n for (const report of Object.values(reports)) {\n warnings.push(...report.warnings)\n }\n return warnings\n}\n\nfunction runCommand(command: string, args: string[]): Promise<number> {\n return new Promise((resolvePromise, rejectPromise) => {\n const child = spawn(command, args, { stdio: 'inherit' })\n child.on('close', (code) => resolvePromise(code ?? 1))\n child.on('error', (err) => rejectPromise(err))\n })\n}\n\nconst MIN_PYTHON_MAJOR = 3\nconst MIN_PYTHON_MINOR = 10\nconst DEFAULT_PYTHON_CANDIDATES = ['python3.12', 'python3.11', 'python3.10', 'python3']\n\nfunction parsePythonVersion(version: string): { major: number; minor: number } | undefined {\n const match = /(\\d+)\\.(\\d+)/.exec(version)\n if (!match) {\n return undefined\n }\n return { major: Number(match[1]), minor: Number(match[2]) }\n}\n\nasync function queryPythonVersion(command: string): Promise<string | undefined> {\n return new Promise((resolvePromise) => {\n const child = spawn(command, ['--version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n shell: process.platform === 'win32'\n })\n let stdout = ''\n child.stdout?.on('data', (chunk: Buffer | string) => {\n stdout += chunk.toString()\n })\n child.on('close', (code) => {\n const text = stdout.trim()\n resolvePromise(code === 0 && text.length > 0 ? text : undefined)\n })\n child.on('error', () => resolvePromise(undefined))\n })\n}\n\nexport async function resolvePythonForVenv(\n envOverride: string | undefined = process.env.LINCOLN_PYTHON,\n candidates: string[] = DEFAULT_PYTHON_CANDIDATES,\n queryVersion: (cmd: string) => Promise<string | undefined> = queryPythonVersion\n): Promise<string | undefined> {\n const list = envOverride ? [envOverride] : candidates\n for (const cmd of list) {\n const version = await queryVersion(cmd)\n if (!version) {\n continue\n }\n const parsed = parsePythonVersion(version)\n if (\n parsed &&\n parsed.major >= MIN_PYTHON_MAJOR &&\n (parsed.major > MIN_PYTHON_MAJOR || parsed.minor >= MIN_PYTHON_MINOR)\n ) {\n return cmd\n }\n }\n return undefined\n}\n\nfunction venvPythonPath(paths: LincolnPaths): string {\n return path.join(\n paths.venvDir,\n process.platform === 'win32' ? 'Scripts' : 'bin',\n process.platform === 'win32' ? 'python.exe' : 'python'\n )\n}\n\nasync function setupVenv(paths: LincolnPaths, payloadRoot: string, pythonCommand: string): Promise<void> {\n const pythonExe = venvPythonPath(paths)\n\n if (!fs.existsSync(pythonExe)) {\n console.log('Creating Lincoln virtual environment...')\n const venvCode = await runCommand(pythonCommand, ['-m', 'venv', paths.venvDir])\n if (venvCode !== 0) {\n throw new Error(`Failed to create virtual environment (exit code ${venvCode})`)\n }\n }\n\n const requirementsPath = path.join(payloadRoot, 'requirements.txt')\n if (fs.existsSync(requirementsPath)) {\n console.log('Installing Python dependencies...')\n const pipExe = path.join(\n paths.venvDir,\n process.platform === 'win32' ? 'Scripts' : 'bin',\n process.platform === 'win32' ? 'pip.exe' : 'pip'\n )\n const pipCode = await runCommand(pipExe, ['install', '-r', requirementsPath])\n if (pipCode !== 0) {\n throw new Error(`Failed to install Python dependencies (exit code ${pipCode})`)\n }\n }\n}\n","import path from 'node:path'\nimport os from 'node:os'\n\nexport interface LincolnPaths {\n homeDir: string\n lincolnHome: string\n versionsDir: string\n currentDir: string\n versionMarker: string\n venvDir: string\n claudeDir: string\n codexDir: string\n opencodeDir: string\n}\n\nexport function resolveLincolnPaths(overrideHomeDir?: string): LincolnPaths {\n const homeDir = overrideHomeDir ?? os.homedir()\n const lincolnHome = process.env.LINCOLN_HOME\n ? path.resolve(process.env.LINCOLN_HOME)\n : path.join(homeDir, '.lincoln')\n\n return {\n homeDir,\n lincolnHome,\n versionsDir: path.join(lincolnHome, 'versions'),\n currentDir: path.join(lincolnHome, 'current'),\n versionMarker: path.join(lincolnHome, 'marker.json'),\n venvDir: path.join(lincolnHome, 'venv'),\n claudeDir: path.join(homeDir, '.claude'),\n codexDir: path.join(homeDir, '.codex'),\n opencodeDir: path.join(homeDir, '.opencode')\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { LincolnPaths } from './paths.js'\n\nexport interface VersionMarker {\n version: string\n installedAt: string\n harnesses: string[]\n managedFiles: string[]\n}\n\nexport function readVersionMarker(paths: LincolnPaths): VersionMarker | undefined {\n try {\n const raw = fs.readFileSync(paths.versionMarker, 'utf8')\n const parsed = JSON.parse(raw) as VersionMarker\n if (\n typeof parsed.version === 'string' &&\n typeof parsed.installedAt === 'string' &&\n Array.isArray(parsed.harnesses)\n ) {\n return parsed\n }\n return undefined\n } catch {\n return undefined\n }\n}\n\nexport function writeVersionMarker(\n paths: LincolnPaths,\n marker: VersionMarker\n): void {\n fs.mkdirSync(path.dirname(paths.versionMarker), { recursive: true })\n fs.writeFileSync(paths.versionMarker, JSON.stringify(marker, null, 2) + '\\n')\n}\n\nexport function isUpToDate(paths: LincolnPaths, version: string): boolean {\n const marker = readVersionMarker(paths)\n return marker?.version === version\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/**\n * Finds the directory containing the running lincoln package's package.json.\n * Returns undefined when no package.json can be located.\n */\nexport function readLocalPackageRoot(): string | undefined {\n try {\n let dir = path.dirname(fileURLToPath(import.meta.url))\n const root = path.parse(dir).root\n while (dir !== root) {\n const pkgPath = path.join(dir, 'package.json')\n if (fs.existsSync(pkgPath)) {\n const parsed = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as { name?: string }\n if (parsed.name === '@sushanglewis/lincoln') {\n return dir\n }\n }\n dir = path.dirname(dir)\n }\n } catch {\n // ignore and return undefined\n }\n return undefined\n}\n\n/**\n * Reads the version of the running lincoln package from its own package.json.\n * Walks upward from the current module file until it finds the package.json.\n * Returns undefined when the package.json cannot be located or parsed.\n */\nexport function readLocalPackageVersion(): string | undefined {\n try {\n const root = readLocalPackageRoot()\n if (!root) return undefined\n const parsed = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')) as {\n version?: string\n }\n return typeof parsed.version === 'string' ? parsed.version : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Resolves the bundled framework payload directory inside the running package.\n */\nexport function resolvePayloadRoot(): string | undefined {\n const root = readLocalPackageRoot()\n if (!root) return undefined\n const payload = path.join(root, 'framework')\n return fs.existsSync(payload) ? payload : undefined\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport { mergeManagedBlock } from './claudeMdMerge.js'\n\nexport interface SyncOptions {\n payloadRoot: string\n targetDir: string\n version: string\n dryRun: boolean\n}\n\nexport interface SyncReport {\n written: string[]\n skipped: string[]\n preserved: string[]\n warnings: string[]\n settingsTouched?: string[]\n}\n\nconst COPY_SUBDIRS = [\n 'agents',\n 'skills',\n 'workflows',\n 'stages',\n 'schemas',\n 'templates',\n 'harnesses',\n // Policies are data files consumed by hooks at runtime (e.g.\n // .claude/policies/less-is-more.md read by on-session-start.sh,\n // security.yaml read by pre-tool-use.sh). Without syncing them into the\n // project, vendored installs silently skip those guardrails (#126).\n 'policies'\n]\n\nfunction sha256(filePath: string): string {\n const data = fs.readFileSync(filePath)\n return crypto.createHash('sha256').update(data).digest('hex')\n}\n\nfunction sameContent(a: string, b: string): boolean {\n return sha256(a) === sha256(b)\n}\n\nfunction deepMergeSettings(existing: unknown, incoming: unknown): unknown {\n if (Array.isArray(existing) && Array.isArray(incoming)) {\n return incoming\n }\n if (\n typeof existing === 'object' &&\n existing !== null &&\n typeof incoming === 'object' &&\n incoming !== null\n ) {\n const result: Record<string, unknown> = { ...existing }\n for (const [key, value] of Object.entries(incoming)) {\n if (key in result) {\n result[key] = deepMergeSettings(result[key], value)\n } else {\n result[key] = value\n }\n }\n return result\n }\n return incoming\n}\n\nexport function syncClaudeCode(opts: SyncOptions): SyncReport {\n const report: SyncReport = {\n written: [],\n skipped: [],\n preserved: [],\n warnings: [],\n settingsTouched: []\n }\n\n const payloadClaude = path.join(opts.payloadRoot, '.claude')\n if (!fs.existsSync(payloadClaude)) {\n report.warnings.push(`payload .claude directory not found: ${payloadClaude}`)\n return report\n }\n\n if (!opts.dryRun) {\n fs.mkdirSync(opts.targetDir, { recursive: true })\n }\n\n for (const subdir of COPY_SUBDIRS) {\n const srcDir = path.join(payloadClaude, subdir)\n if (!fs.existsSync(srcDir)) {\n continue\n }\n\n const destDir = path.join(opts.targetDir, subdir)\n if (!opts.dryRun) {\n fs.mkdirSync(destDir, { recursive: true })\n }\n\n for (const entry of walkSync(srcDir)) {\n const relativePath = path.relative(srcDir, entry)\n const srcFile = entry\n const destFile = path.join(destDir, relativePath)\n\n if (fs.existsSync(destFile) && sameContent(srcFile, destFile)) {\n report.skipped.push(path.join('.claude', subdir, relativePath))\n continue\n }\n\n if (!opts.dryRun) {\n fs.mkdirSync(path.dirname(destFile), { recursive: true })\n fs.copyFileSync(srcFile, destFile)\n }\n report.written.push(path.join('.claude', subdir, relativePath))\n }\n }\n\n // settings.json merge\n const payloadSettings = path.join(payloadClaude, 'settings.json')\n const targetSettings = path.join(opts.targetDir, 'settings.json')\n if (fs.existsSync(payloadSettings)) {\n const incoming = JSON.parse(fs.readFileSync(payloadSettings, 'utf8'))\n let merged = incoming\n if (fs.existsSync(targetSettings)) {\n const existing = JSON.parse(fs.readFileSync(targetSettings, 'utf8'))\n merged = deepMergeSettings(existing, incoming)\n }\n\n const wouldChange =\n !fs.existsSync(targetSettings) ||\n JSON.stringify(merged) !== JSON.stringify(JSON.parse(fs.readFileSync(targetSettings, 'utf8')))\n\n if (wouldChange) {\n if (!opts.dryRun) {\n fs.writeFileSync(targetSettings, JSON.stringify(merged, null, 2) + '\\n')\n }\n report.written.push('.claude/settings.json')\n report.settingsTouched = ['.claude/settings.json']\n } else {\n report.skipped.push('.claude/settings.json')\n }\n }\n\n // CLAUDE.md merge\n const payloadClaudeMd = path.join(opts.payloadRoot, 'CLAUDE.md')\n const targetClaudeMd = path.join(path.dirname(opts.targetDir), 'CLAUDE.md')\n if (fs.existsSync(payloadClaudeMd)) {\n const incomingBlock = fs.readFileSync(payloadClaudeMd, 'utf8')\n const existing = fs.existsSync(targetClaudeMd)\n ? fs.readFileSync(targetClaudeMd, 'utf8')\n : undefined\n const merged = mergeManagedBlock(existing, incomingBlock)\n\n if (merged !== existing) {\n if (!opts.dryRun) {\n fs.writeFileSync(targetClaudeMd, merged)\n }\n report.written.push('CLAUDE.md')\n } else {\n report.skipped.push('CLAUDE.md')\n }\n }\n\n return report\n}\n\nfunction* walkSync(dir: string): Generator<string> {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n yield* walkSync(fullPath)\n } else {\n yield fullPath\n }\n }\n}\n","const BEGIN = '<!-- lincoln:begin -->'\nconst END = '<!-- lincoln:end -->'\n\nexport function mergeManagedBlock(\n existing: string | undefined,\n block: string\n): string {\n const wrapped = `${BEGIN}\\n${block}\\n${END}`\n const text = existing ?? ''\n\n const beginIndex = text.indexOf(BEGIN)\n const endIndex = text.indexOf(END)\n\n if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {\n return (\n text.slice(0, beginIndex) +\n wrapped +\n text.slice(endIndex + END.length)\n )\n }\n\n if (text.trim().length === 0) {\n return wrapped\n }\n\n return `${text.trimEnd()}\\n\\n${wrapped}\\n`\n}\n\nexport function extractManagedBlock(existing: string): string | undefined {\n const beginIndex = existing.indexOf(BEGIN)\n const endIndex = existing.indexOf(END)\n if (beginIndex === -1 || endIndex === -1 || endIndex <= beginIndex) {\n return undefined\n }\n return existing\n .slice(beginIndex + BEGIN.length, endIndex)\n .replace(/^\\n+|\\n+$/g, '')\n}\n","import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process'\nimport type { SyncReport } from './syncClaude.js'\n\nexport interface RunHarnessAdapterOptions {\n harnessId: 'codex' | 'opencode'\n payloadRoot: string\n projectDir: string\n homeDir: string\n pythonPath: string\n dryRun: boolean\n spawnCommand?: SpawnCommand\n}\n\ntype SpawnCommand = (command: string, args: string[], options?: SpawnOptions) => ChildProcess\n\nfunction runCommand(\n command: string,\n args: string[],\n spawnCommand: SpawnCommand\n): Promise<number | null> {\n return new Promise((resolvePromise, rejectPromise) => {\n const child = spawnCommand(command, args, { stdio: 'inherit' })\n child.on('close', (code) => {\n resolvePromise(code)\n })\n child.on('error', (err) => {\n rejectPromise(err)\n })\n })\n}\n\nexport async function runHarnessAdapter(opts: RunHarnessAdapterOptions): Promise<SyncReport> {\n const report: SyncReport = {\n written: [],\n skipped: [],\n preserved: [],\n warnings: []\n }\n\n if (opts.dryRun) {\n report.written.push(`${opts.harnessId} (dry run)`)\n return report\n }\n\n const args = [\n `${opts.payloadRoot}/scripts/lincoln_harness_adapter.py`,\n '--harness',\n opts.harnessId,\n '--root',\n opts.payloadRoot,\n '--project-dir',\n opts.projectDir,\n '--home-dir',\n opts.homeDir\n ]\n\n try {\n const spawnCommand = (opts.spawnCommand ?? spawn) as SpawnCommand\n const code = await runCommand(opts.pythonPath, args, spawnCommand)\n if (code === 0) {\n report.written.push(opts.harnessId)\n } else {\n report.warnings.push(\n `Adapter for ${opts.harnessId} exited with code ${code}. Run manually to diagnose.`\n )\n }\n } catch (err) {\n report.warnings.push(\n `Failed to run adapter for ${opts.harnessId}: ${err instanceof Error ? err.message : String(err)}`\n )\n }\n\n return report\n}\n","import type { SyncReport } from './syncClaude.js'\nimport { syncClaudeCode } from './syncClaude.js'\nimport type { HarnessId } from './harnessDetect.js'\nimport type { LincolnPaths } from './paths.js'\nimport { runHarnessAdapter } from './runHarnessAdapter.js'\n\nexport interface SyncHarnessesOptions {\n harnesses: HarnessId[]\n payloadRoot: string\n paths: LincolnPaths\n projectDir: string\n version: string\n dryRun: boolean\n pythonPath?: string\n syncClaude?: (opts: {\n payloadRoot: string\n targetDir: string\n version: string\n dryRun: boolean\n }) => SyncReport\n}\n\nexport type HarnessSyncReport = Record<HarnessId, SyncReport>\n\nfunction emptyReport(): SyncReport {\n return {\n written: [],\n skipped: [],\n preserved: [],\n warnings: []\n }\n}\n\nexport async function syncHarnesses(opts: SyncHarnessesOptions): Promise<HarnessSyncReport> {\n const reports: HarnessSyncReport = {} as HarnessSyncReport\n const syncClaude = opts.syncClaude ?? syncClaudeCode\n\n for (const harnessId of opts.harnesses) {\n reports[harnessId] = await syncHarness(harnessId, opts, syncClaude)\n }\n\n return reports\n}\n\nasync function syncHarness(\n harnessId: HarnessId,\n opts: SyncHarnessesOptions,\n syncClaude: NonNullable<SyncHarnessesOptions['syncClaude']>\n): Promise<SyncReport> {\n if (harnessId === 'claude-code') {\n return syncClaude({\n payloadRoot: opts.payloadRoot,\n targetDir: opts.paths.claudeDir,\n version: opts.version,\n dryRun: opts.dryRun\n })\n }\n\n if (harnessId === 'codex' || harnessId === 'opencode') {\n if (opts.dryRun) {\n const report = emptyReport()\n report.written.push(`${harnessId} (dry run)`)\n return report\n }\n if (!opts.pythonPath) {\n const report = emptyReport()\n report.warnings.push(\n `Skipped ${harnessId} sync because Python is not available. Install Python 3.10+ or run without --no-venv.`\n )\n return report\n }\n return runHarnessAdapter({\n harnessId,\n payloadRoot: opts.payloadRoot,\n projectDir: opts.projectDir,\n homeDir: opts.paths.homeDir,\n pythonPath: opts.pythonPath,\n dryRun: opts.dryRun\n })\n }\n\n const report = emptyReport()\n report.warnings.push(`Unsupported harness: ${harnessId}`)\n return report\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { execFile } from 'node:child_process'\nimport yaml from 'js-yaml'\nimport { compareVersions } from './semver.js'\n\nexport type CommandRunner = (\n cmd: string,\n args: string[]\n) => Promise<{ code: number; stdout: string; stderr: string }>\n\nexport type SkillSyncStatus =\n | 'installed'\n | 'updated'\n | 'current'\n | 'failed'\n | 'skipped-optional'\n | 'skipped-dirty'\n | 'dry-run'\n\nexport interface SkillSyncEntry {\n name: string\n status: SkillSyncStatus\n detail?: string\n}\n\nexport interface SkillSyncReport {\n entries: SkillSyncEntry[]\n warnings: string[]\n}\n\nexport interface SyncExternalSkillsOptions {\n payloadRoot: string\n skillsDir: string\n dryRun: boolean\n runCommand?: CommandRunner\n platform?: string\n}\n\ninterface ManifestEntry {\n source?: string\n ref?: string\n type?: string\n required?: boolean\n default_install?: boolean\n binary?: string\n platforms?: Record<string, string>\n}\n\ninterface SkillManifest {\n skills?: Record<string, ManifestEntry>\n}\n\nconst GIT_SOURCE = /^(https?:\\/\\/|git@)/\nconst FULL_SHA = /^[0-9a-f]{40}$/i\nconst PINNED_SEMVER = /^v?(\\d+\\.\\d+\\.\\d+)$/\nconst NPM_GLOBAL_INSTALL = /^npm install -g (\\S+)$/\nconst MAX_BUFFER = 16 * 1024 * 1024\n\nconst defaultRunner: CommandRunner = (cmd, args) =>\n new Promise((resolvePromise, rejectPromise) => {\n execFile(cmd, args, { maxBuffer: MAX_BUFFER }, (err, stdout, stderr) => {\n if (err && !('code' in err && typeof err.code === 'number')) {\n rejectPromise(err)\n return\n }\n const code = err && typeof err.code === 'number' ? err.code : 0\n resolvePromise({ code, stdout: String(stdout), stderr: String(stderr) })\n })\n })\n\nexport async function syncExternalSkills(options: SyncExternalSkillsOptions): Promise<SkillSyncReport> {\n const report: SkillSyncReport = { entries: [], warnings: [] }\n const manifestPath = path.join(options.payloadRoot, '.claude', 'skills', 'dependencies.yaml')\n if (!fs.existsSync(manifestPath)) {\n report.warnings.push(`skill dependency manifest not found at ${manifestPath}; skipping external skill sync`)\n return report\n }\n\n let manifest: SkillManifest\n try {\n manifest = (yaml.load(fs.readFileSync(manifestPath, 'utf8')) as SkillManifest) ?? {}\n } catch (err) {\n report.warnings.push(\n `failed to parse ${manifestPath}: ${err instanceof Error ? err.message : String(err)}`\n )\n return report\n }\n\n const runCommand = options.runCommand ?? defaultRunner\n const platform =\n options.platform ?? (process.platform === 'darwin' ? 'macos' : process.platform === 'linux' ? 'linux' : process.platform)\n for (const [name, cfg] of Object.entries(manifest.skills ?? {})) {\n if (!cfg.source || cfg.source === 'inline' || !GIT_SOURCE.test(cfg.source)) {\n continue\n }\n const enabled = cfg.default_install ?? cfg.required ?? true\n if (!enabled) {\n report.entries.push({ name, status: 'skipped-optional', detail: 'default_install is false' })\n continue\n }\n if (cfg.type === 'cli') {\n await syncCli(name, cfg, options, platform, runCommand, report)\n } else {\n await syncGitSkill(name, cfg, options, runCommand, report)\n }\n }\n return report\n}\n\nasync function syncGitSkill(\n name: string,\n cfg: ManifestEntry,\n options: SyncExternalSkillsOptions,\n runCommand: CommandRunner,\n report: SkillSyncReport\n): Promise<void> {\n const source = cfg.source as string\n const ref = cfg.ref ?? ''\n const target = path.join(options.skillsDir, name)\n\n if (options.dryRun) {\n const planned = fs.existsSync(target) ? 'verify pinned ref and update if behind' : `clone and pin to ${ref}`\n report.entries.push({ name, status: 'dry-run', detail: `would ${planned}` })\n return\n }\n\n if (!fs.existsSync(target)) {\n const clone = await runCommand('git', ['clone', source, target])\n if (clone.code !== 0) {\n fail(report, name, `git clone failed: ${clone.stderr.trim() || `exit code ${clone.code}`}`)\n return\n }\n const checkout = await runCommand('git', ['-C', target, 'checkout', ref])\n if (checkout.code !== 0) {\n fail(report, name, `git checkout ${ref} failed: ${checkout.stderr.trim() || `exit code ${checkout.code}`}`)\n return\n }\n report.entries.push({ name, status: 'installed', detail: ref })\n return\n }\n\n const status = await runCommand('git', ['-C', target, 'status', '--porcelain'])\n if (status.code !== 0) {\n fail(report, name, `git status failed (not a git repository?): ${status.stderr.trim() || `exit code ${status.code}`}`)\n return\n }\n if (status.stdout.trim() !== '') {\n const detail = 'working tree is dirty; skipping update (commit or stash local changes first)'\n report.entries.push({ name, status: 'skipped-dirty', detail })\n report.warnings.push(`${name}: ${detail}`)\n return\n }\n\n const head = await runCommand('git', ['-C', target, 'rev-parse', 'HEAD'])\n if (head.code !== 0) {\n fail(report, name, `git rev-parse failed: ${head.stderr.trim() || `exit code ${head.code}`}`)\n return\n }\n if (head.stdout.trim() === ref) {\n report.entries.push({ name, status: 'current', detail: ref })\n return\n }\n\n const advertised = await isPinAdvertised(source, ref, runCommand)\n if (advertised) {\n const fetch = await runCommand('git', ['-C', target, 'fetch', 'origin', ref])\n if (fetch.code === 0 && (await checkoutFetchHead(name, target, runCommand, report))) {\n return\n }\n if (fetch.code !== 0) {\n fail(report, name, `git fetch origin ${ref} failed: ${fetch.stderr.trim() || `exit code ${fetch.code}`}`)\n return\n }\n return\n }\n\n const fetch = await runCommand('git', ['-C', target, 'fetch', 'origin', ref])\n if (fetch.code === 0) {\n await checkoutFetchHead(name, target, runCommand, report)\n return\n }\n if (FULL_SHA.test(ref)) {\n const fetchAll = await runCommand('git', ['-C', target, 'fetch', 'origin'])\n if (fetchAll.code !== 0) {\n fail(report, name, `git fetch origin failed: ${fetchAll.stderr.trim() || `exit code ${fetchAll.code}`}`)\n return\n }\n const checkout = await runCommand('git', ['-C', target, 'checkout', ref])\n if (checkout.code !== 0) {\n fail(report, name, `git checkout ${ref} failed: ${checkout.stderr.trim() || `exit code ${checkout.code}`}`)\n return\n }\n report.entries.push({ name, status: 'updated', detail: ref })\n return\n }\n fail(report, name, `git fetch origin ${ref} failed: ${fetch.stderr.trim() || `exit code ${fetch.code}`}`)\n}\n\nasync function isPinAdvertised(\n source: string,\n ref: string,\n runCommand: CommandRunner\n): Promise<boolean> {\n const remote = await runCommand('git', ['ls-remote', source])\n if (remote.code !== 0) {\n return false\n }\n return remote.stdout\n .split('\\n')\n .some((line) => line.split('\\t')[0]?.trim() === ref)\n}\n\nasync function checkoutFetchHead(\n name: string,\n target: string,\n runCommand: CommandRunner,\n report: SkillSyncReport\n): Promise<boolean> {\n const checkout = await runCommand('git', ['-C', target, 'checkout', 'FETCH_HEAD'])\n if (checkout.code !== 0) {\n fail(report, name, `git checkout FETCH_HEAD failed: ${checkout.stderr.trim() || `exit code ${checkout.code}`}`)\n return false\n }\n report.entries.push({ name, status: 'updated', detail: 'checked out FETCH_HEAD' })\n return true\n}\n\nasync function syncCli(\n name: string,\n cfg: ManifestEntry,\n options: SyncExternalSkillsOptions,\n platform: string,\n runCommand: CommandRunner,\n report: SkillSyncReport\n): Promise<void> {\n const binary = cfg.binary ?? name\n const installCommand = cfg.platforms?.[platform] ?? cfg.platforms?.linux\n const npmPackage = installCommand ? parseNpmGlobalInstall(installCommand) : undefined\n const pinned = cfg.ref ? pinnedSemver(cfg.ref) : undefined\n\n if (options.dryRun) {\n const managed = npmPackage && pinned ? `install ${npmPackage}@${pinned} if missing or older` : 'verify presence'\n report.entries.push({ name, status: 'dry-run', detail: `would ${managed}` })\n return\n }\n\n const whichCmd = process.platform === 'win32' ? 'where' : 'which'\n const found = await runCommand(whichCmd, [binary])\n if (found.code !== 0) {\n if (npmPackage && pinned) {\n await npmInstall(name, npmPackage, pinned, runCommand, report, 'installed')\n return\n }\n fail(report, name, `CLI '${binary}' not found. Install manually (${platform}): ${installCommand ?? 'see dependency manifest'}`)\n return\n }\n\n if (!npmPackage || !pinned) {\n report.entries.push({ name, status: 'current', detail: `${binary} present` })\n return\n }\n\n const version = await runCommand(binary, ['--version'])\n const installed = version.code === 0 ? version.stdout.split('\\n')[0]?.trim() ?? '' : ''\n const comparison = installed ? compareVersions(installed, pinned) : undefined\n if (comparison === undefined) {\n report.entries.push({\n name,\n status: 'current',\n detail: `could not parse installed version '${installed}'; leaving ${binary} as-is`\n })\n return\n }\n if (comparison >= 0) {\n report.entries.push({ name, status: 'current', detail: `${binary} ${installed}` })\n return\n }\n await npmInstall(name, npmPackage, pinned, runCommand, report, 'updated')\n}\n\nasync function npmInstall(\n name: string,\n npmPackage: string,\n version: string,\n runCommand: CommandRunner,\n report: SkillSyncReport,\n status: 'installed' | 'updated'\n): Promise<void> {\n const result = await runCommand('npm', ['install', '-g', `${npmPackage}@${version}`])\n if (result.code !== 0) {\n fail(report, name, `npm install -g ${npmPackage}@${version} failed: ${result.stderr.trim() || `exit code ${result.code}`}`)\n return\n }\n report.entries.push({ name, status, detail: `${npmPackage}@${version}` })\n}\n\nfunction parseNpmGlobalInstall(command: string): string | undefined {\n const match = NPM_GLOBAL_INSTALL.exec(command.trim())\n return match?.[1]\n}\n\nfunction pinnedSemver(ref: string): string | undefined {\n const match = PINNED_SEMVER.exec(ref.trim())\n return match?.[0].replace(/^v/, '')\n}\n\nfunction fail(report: SkillSyncReport, name: string, detail: string): void {\n report.entries.push({ name, status: 'failed', detail })\n report.warnings.push(`${name}: ${detail}`)\n}\n","const SEMVER_CORE = /^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/\nconst NUMERIC_IDENTIFIER = /^\\d+$/\n\ninterface ParsedVersion {\n major: number\n minor: number\n patch: number\n prerelease: string[]\n}\n\n/**\n * Compares two semver strings per semver.org precedence rules (build metadata\n * ignored). Returns a negative number when a < b, 0 when equal, a positive\n * number when a > b, or undefined when either input is not a parseable semver.\n */\nexport function compareVersions(a: string, b: string): number | undefined {\n const pa = parseVersion(a)\n const pb = parseVersion(b)\n if (!pa || !pb) {\n return undefined\n }\n if (pa.major !== pb.major) return pa.major - pb.major\n if (pa.minor !== pb.minor) return pa.minor - pb.minor\n if (pa.patch !== pb.patch) return pa.patch - pb.patch\n return comparePrerelease(pa.prerelease, pb.prerelease)\n}\n\nfunction parseVersion(version: string): ParsedVersion | undefined {\n const match = SEMVER_CORE.exec(version.trim())\n if (!match) {\n return undefined\n }\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n prerelease: match[4] ? match[4].split('.') : []\n }\n}\n\nfunction comparePrerelease(a: string[], b: string[]): number {\n if (a.length === 0 && b.length === 0) return 0\n // A version without a prerelease has higher precedence than one with it.\n if (a.length === 0) return 1\n if (b.length === 0) return -1\n const shared = Math.min(a.length, b.length)\n for (let i = 0; i < shared; i++) {\n const x = a[i]\n const y = b[i]\n if (x === y) continue\n const xNumeric = NUMERIC_IDENTIFIER.test(x)\n const yNumeric = NUMERIC_IDENTIFIER.test(y)\n if (xNumeric && yNumeric) return Number(x) - Number(y)\n // Numeric identifiers have lower precedence than alphanumeric ones.\n if (xNumeric) return -1\n if (yNumeric) return 1\n return x < y ? -1 : 1\n }\n return a.length - b.length\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\n\nexport type HarnessId = 'claude-code' | 'codex' | 'opencode'\n\nexport interface GlobalHarnessInfo {\n id: HarnessId\n installed: boolean\n configDir: string\n pluginManaged: boolean\n}\n\ninterface HarnessSpec {\n id: HarnessId\n configDirName: string\n pluginMarker?: string\n}\n\nconst HARNESS_SPECS: HarnessSpec[] = [\n {\n id: 'claude-code',\n configDirName: '.claude',\n pluginMarker: 'plugins/lincoln'\n },\n { id: 'codex', configDirName: '.codex' },\n { id: 'opencode', configDirName: '.opencode' }\n]\n\nexport function detectGlobalHarnesses(\n overrideHomeDir?: string\n): GlobalHarnessInfo[] {\n const homeDir = overrideHomeDir ?? os.homedir()\n\n return HARNESS_SPECS.map((spec) => {\n const configDir = path.join(homeDir, spec.configDirName)\n const installed = fs.existsSync(configDir)\n const pluginManaged = spec.pluginMarker\n ? fs.existsSync(path.join(configDir, spec.pluginMarker))\n : false\n\n return {\n id: spec.id,\n installed,\n configDir,\n pluginManaged\n }\n })\n}\n\nexport function installedHarnessIds(homeDir?: string): HarnessId[] {\n return detectGlobalHarnesses(homeDir)\n .filter((h) => h.installed)\n .map((h) => h.id)\n}\n\nexport const HARNESS_IDS: HarnessId[] = HARNESS_SPECS.map((spec) => spec.id)\n\nexport function isValidHarnessId(value: string): value is HarnessId {\n return HARNESS_SPECS.some((spec) => spec.id === value)\n}\n","import type { GlobalHarnessInfo, HarnessId } from './harnessDetect.js'\nimport type { MultiSelectOption } from './prompt.js'\n\nexport const HARNESS_LABELS: Record<HarnessId, string> = {\n 'claude-code': 'Claude Code',\n codex: 'Codex',\n opencode: 'OpenCode'\n}\n\nexport function buildHarnessOptions(\n detected: ReadonlyArray<GlobalHarnessInfo>\n): MultiSelectOption[] {\n return detected.map((harness) => ({\n id: harness.id,\n label: HARNESS_LABELS[harness.id],\n checked: harness.installed\n }))\n}\n\nexport function resolveHarnessSelection(\n detected: ReadonlyArray<GlobalHarnessInfo>,\n selection: string[] | undefined\n): HarnessId[] {\n if (selection === undefined) {\n return detected.filter((harness) => harness.installed).map((harness) => harness.id)\n }\n const validIds = new Set<HarnessId>()\n for (const id of selection) {\n const match = detected.find((harness) => harness.id === id)\n if (match) {\n validIds.add(match.id)\n }\n }\n return Array.from(validIds)\n}\n","import type { Readable, Writable } from 'node:stream'\n\nexport interface PromptOptions {\n input?: Readable\n output?: Writable\n}\n\nexport interface MultiSelectOption {\n id: string\n label: string\n checked: boolean\n}\n\nexport interface Prompt {\n confirm(question: string, defaultValue?: boolean): Promise<boolean>\n multiSelect(question: string, options: ReadonlyArray<MultiSelectOption>): Promise<string[]>\n close(): void\n}\n\ninterface LineReader {\n readLine(prompt: string): Promise<string>\n close(): void\n}\n\nfunction createLineReader(input: Readable, output: Writable): LineReader {\n const buffer: string[] = []\n const queue: Array<{ resolve: (line: string) => void; reject: (err: Error) => void }> = []\n let remainder = ''\n let ended = false\n\n function flushQueue(): void {\n while (queue.length > 0 && buffer.length > 0) {\n const next = queue.shift()\n const line = buffer.shift()\n if (next && line !== undefined) {\n next.resolve(line)\n }\n }\n }\n\n input.on('data', (chunk: Buffer | string) => {\n const text = remainder + chunk.toString('utf-8')\n const lines = text.split('\\n')\n remainder = lines.pop() ?? ''\n for (const line of lines) {\n buffer.push(line.replace(/\\r$/, ''))\n }\n flushQueue()\n })\n\n input.on('end', () => {\n ended = true\n if (remainder.length > 0) {\n buffer.push(remainder.replace(/\\r$/, ''))\n remainder = ''\n }\n flushQueue()\n while (queue.length > 0) {\n const next = queue.shift()\n next?.resolve('')\n }\n })\n\n input.on('error', (err) => {\n while (queue.length > 0) {\n queue.shift()?.reject(err)\n }\n })\n\n return {\n readLine(prompt: string): Promise<string> {\n output.write(prompt)\n if (buffer.length > 0) {\n return Promise.resolve(buffer.shift() ?? '')\n }\n if (ended) {\n return Promise.resolve('')\n }\n return new Promise<string>((resolve, reject) => {\n queue.push({ resolve, reject })\n })\n },\n close(): void {\n // nothing to close for raw streams\n }\n }\n}\n\nfunction normalizeAnswer(text: string): string {\n return text.trim().toLowerCase()\n}\n\nexport function createPrompt(streams: PromptOptions = {}): Prompt {\n const input = streams.input ?? process.stdin\n const output = streams.output ?? process.stdout\n const reader = createLineReader(input, output)\n\n async function ask(question: string): Promise<string> {\n return reader.readLine(question)\n }\n\n return {\n async confirm(question: string, defaultValue = true): Promise<boolean> {\n const hint = defaultValue ? '[Y/n]' : '[y/N]'\n const first = await ask(`${question} ${hint} `)\n const normalized = normalizeAnswer(first)\n if (normalized === 'y' || normalized === 'yes') {\n return true\n }\n if (normalized === 'n' || normalized === 'no') {\n return false\n }\n if (normalized === '') {\n return defaultValue\n }\n const second = await ask('Please answer y or n: ')\n const secondNormalized = normalizeAnswer(second)\n if (secondNormalized === 'y' || secondNormalized === 'yes') {\n return true\n }\n if (secondNormalized === 'n' || secondNormalized === 'no') {\n return false\n }\n return defaultValue\n },\n\n async multiSelect(\n question: string,\n options: ReadonlyArray<MultiSelectOption>\n ): Promise<string[]> {\n const lines = options.map((opt, index) => {\n const mark = opt.checked ? 'x' : ' '\n return ` [${mark}] ${index + 1}. ${opt.label}`\n })\n const promptText = `${question}\\n${lines.join('\\n')}\\nEnter numbers (e.g. 1,3), 'all', 'none', or harness names: `\n\n async function parse(answer: string): Promise<string[] | undefined> {\n const normalized = normalizeAnswer(answer)\n if (normalized === 'all') {\n return options.map((opt) => opt.id)\n }\n if (normalized === 'none') {\n return []\n }\n if (normalized === '') {\n return options.filter((opt) => opt.checked).map((opt) => opt.id)\n }\n const parts = normalized.split(/[,\\s]+/).filter((part) => part.length > 0)\n const selected = new Set<string>()\n for (const part of parts) {\n const index = Number(part)\n if (!Number.isNaN(index) && index >= 1 && index <= options.length) {\n selected.add(options[index - 1].id)\n continue\n }\n const match = options.find((opt) => opt.id === part)\n if (match) {\n selected.add(match.id)\n continue\n }\n return undefined\n }\n return Array.from(selected)\n }\n\n let result = await parse(await ask(promptText))\n if (result !== undefined) {\n return result\n }\n const retry = await ask('Invalid selection. Please try again: ')\n result = await parse(retry)\n return result ?? []\n },\n\n close(): void {\n reader.close()\n }\n }\n}\n","import { install as runInstall } from './commands/install.js'\nimport { createPrompt } from './lib/prompt.js'\n\nexport interface PostinstallDeps {\n isTTY: boolean\n confirm: (question: string) => Promise<boolean>\n install: () => Promise<number>\n env: Record<string, string | undefined>\n}\n\nfunction isSkipped(env: Record<string, string | undefined>): boolean {\n if (env.CI) {\n return true\n }\n if (env.NODE_ENV === 'test') {\n return true\n }\n if (env.LINCOLN_SKIP_POSTINSTALL) {\n return true\n }\n return false\n}\n\nexport function createDefaultDeps(): PostinstallDeps {\n return {\n isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY),\n confirm: async (question: string) => {\n const prompt = createPrompt()\n try {\n return await prompt.confirm(question, true)\n } finally {\n prompt.close()\n }\n },\n install: async () =>\n runInstall({ yes: false, dryRun: false, force: false, harnesses: [], noVenv: false, noInteractive: false }),\n env: process.env\n }\n}\n\nexport async function runPostinstall(deps: PostinstallDeps = createDefaultDeps()): Promise<number> {\n if (isSkipped(deps.env)) {\n return 0\n }\n\n if (!deps.isTTY) {\n console.log('Lincoln installed globally.')\n console.log('Run \"lincoln install\" to finish setup.')\n return 0\n }\n\n try {\n const ok = await deps.confirm('Configure Lincoln harnesses now?')\n if (!ok) {\n console.log('Run \"lincoln install\" anytime to finish setup.')\n return 0\n }\n await deps.install()\n return 0\n } catch (err) {\n console.log('Lincoln installed globally.')\n console.log('Run \"lincoln install\" anytime to finish setup.')\n if (err instanceof Error) {\n console.error(`Postinstall setup skipped: ${err.message}`)\n }\n return 0\n }\n}\n\nif (import.meta.url === `file://${process.argv[1]}`) {\n runPostinstall()\n .then((code) => process.exit(code))\n .catch(() => process.exit(0))\n}\n"],"mappings":"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","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"]}
|
|
@@ -20,6 +20,9 @@ extends:
|
|
|
20
20
|
3. 维护跨子页面影响关系:PRD、用户故事、相关者分析、数据模型等核心文档变更时,在门户中标注受影响的设计文档与原型页面,使下游阶段知悉影响范围。
|
|
21
21
|
4. 对 designer 的输入完整性负责:PRD、用户故事、相关者分析、数据模型、流程图、页面地图必须完整、一致、无歧义;designer 回退确认时,PM 优先澄清,而非让 designer 自行假设。
|
|
22
22
|
5. 在 `product-prototype` 阶段以 reviewer 身份确认原型的功能、字段、流程与需求文档一致。
|
|
23
|
+
6. PRD 质量把关:输出 PRD 前完成「需求清晰度六问」自检(用户有哪些、场景是什么、边界在哪里、如何管异常、如何体验好、最终谁决策),六问全部有明确答案才允许定稿。
|
|
24
|
+
7. PRD 只承载业务内容:技术调研、技术方案、架构/接口/数据库设计等只进设计阶段的归档页,不写入 PRD;过程性疑问(待确认、TODO 之类)在对话中解决后才以结论形式落文档。
|
|
25
|
+
8. 交叉验证决策权:研发计划阶段以测试场景反向挑战 PRD 发现的缺口,必须由人类 PM 决策闭环——修复(PRD 升版重冻结)或接受(记录理由与影响)二选一;PM 未决策不得视为闭环。
|
|
23
26
|
|
|
24
27
|
## 专属规则
|
|
25
28
|
|
|
@@ -39,6 +39,10 @@ commands:
|
|
|
39
39
|
description: 研究员角色,用于开源调研、可行性研究与 PM 主导的市场/产品/竞品/用户研究阶段
|
|
40
40
|
action: python3 "$LINCOLN_ROOT/scripts/lincoln_role.py" --role researcher
|
|
41
41
|
args_hint: $ARGUMENTS
|
|
42
|
+
lc-agent-security-reviewer:
|
|
43
|
+
description: Lincoln 安全审查员角色,专注于框架策略、hook 门控与实现中的安全风险识别。
|
|
44
|
+
action: python3 "$LINCOLN_ROOT/scripts/lincoln_role.py" --role security-reviewer
|
|
45
|
+
args_hint: $ARGUMENTS
|
|
42
46
|
lc-approve:
|
|
43
47
|
description: 人类 PM 确认当前阶段 gate 通过(仅 human_gate 阶段)
|
|
44
48
|
action: python3 "${CLAUDE_PLUGIN_ROOT:-${LINCOLN_HOME:-$HOME/.lincoln/current}}/scripts/stage_loader.py"
|
|
@@ -245,7 +249,7 @@ commands:
|
|
|
245
249
|
action: python3 "$LINCOLN_ROOT/scripts/lincoln_workflow.py"
|
|
246
250
|
args_hint: start --workflow existing-project-iteration
|
|
247
251
|
lc-wf-framework-self-improvement:
|
|
248
|
-
description: Lincoln
|
|
252
|
+
description: 持续改进 Lincoln 框架本身的工作流(安全门控、harness 分发、摩擦学习、事件追踪、子代理委托)
|
|
249
253
|
action: python3 "$LINCOLN_ROOT/scripts/lincoln_workflow.py"
|
|
250
254
|
args_hint: start --workflow framework-self-improvement --issue-number <N>
|
|
251
255
|
lc-wf-interview-to-knowledge:
|
|
@@ -350,6 +350,21 @@ PY
|
|
|
350
350
|
echo "=== End Workflow Template ==="
|
|
351
351
|
echo ""
|
|
352
352
|
fi
|
|
353
|
+
|
|
354
|
+
# Inject the artifact-writing discipline (issue #126). This is the single
|
|
355
|
+
# deterministic load point: it fires once per session, only when an issue
|
|
356
|
+
# package is active, so research/exploration outside issue work and the
|
|
357
|
+
# individual skill prompts stay free of it.
|
|
358
|
+
POLICY_FILE="$FRAMEWORK_ROOT/.claude/policies/less-is-more.md"
|
|
359
|
+
if [[ -f "$POLICY_FILE" ]]; then
|
|
360
|
+
echo "=== 制品生成纪律(少即是多) ==="
|
|
361
|
+
echo "Source: .claude/policies/less-is-more.md"
|
|
362
|
+
echo ""
|
|
363
|
+
cat "$POLICY_FILE"
|
|
364
|
+
echo ""
|
|
365
|
+
echo "=== End 制品生成纪律 ==="
|
|
366
|
+
echo ""
|
|
367
|
+
fi
|
|
353
368
|
else
|
|
354
369
|
NEEDS_OPENING_GUIDANCE="true"
|
|
355
370
|
fi
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# 少即是多(Less is More)——制品生成纪律
|
|
2
|
+
|
|
3
|
+
## 适用范围
|
|
4
|
+
|
|
5
|
+
本纪律只在**生成制品**时生效:PRD、需求/设计文档、门户页面、交接文档、研究报告、原型注释等面向读者交付的内容。
|
|
6
|
+
|
|
7
|
+
前期的思考、调研、深度研究阶段**不适用**本纪律:探索阶段应当充分收集、充分展开,信息越完整越好。只有在把已收集的信息凝练为制品时,才按本纪律删减——删减的依据是读者、用途与目的,而不是信息本身的数量。
|
|
8
|
+
|
|
9
|
+
固定模板无法控制现实需求的复杂度,但以下纪律可以让任何制品保持简洁、精准、明确:信息量不等于价值,被淹没的关键信息等于没有信息。
|
|
10
|
+
|
|
11
|
+
## 生成前先回答三个问题
|
|
12
|
+
|
|
13
|
+
1. **读者是谁**——人类 PM、下游 Agent、还是工程师?读者决定详略与措辞。
|
|
14
|
+
2. **用途是什么**——评审决策、交接执行、还是存档追溯?用途决定保留哪些信息。
|
|
15
|
+
3. **读者要做什么**——读完这份制品,读者需要做出的决定或执行的动作是什么?不为这个决定服务的内容都是候选删除项。
|
|
16
|
+
|
|
17
|
+
## 六条纪律
|
|
18
|
+
|
|
19
|
+
1. **结论先行**:每份制品、每个章节把结论或需要读者做的事放在最前面;读者 30 秒内必须知道"这份制品讲什么、我需要做什么"。背景与推理过程放在结论之后,或移入归档页。
|
|
20
|
+
2. **一件制品回答一个问题**:每份制品只回答一个核心问题(与文档页的"页面意图/边界"纪律一致)。想塞入第二个问题时,拆出新制品并互相链接,而不是加长当前制品。
|
|
21
|
+
3. **删除测试**:落笔后逐段自问——"删掉这段,读者会做出错误决策吗?"不会就删。AI 初稿默认冗余,交付前必须做一轮纯删减评审(只删不增)。
|
|
22
|
+
4. **结构优于段落**:表达关系、流程、对比时优先用表格、Mermaid 流程图/时序图;段落只用于必须的推理与叙事。表格单元格一句话,不写段落。
|
|
23
|
+
5. **链接优于复制**:过程性信息与细节保留在源产物中,制品只放链接(与可追溯性一致),绝不复述或跨页复制内容。
|
|
24
|
+
6. **三分钟可读**:每份主阅读路径制品以 3 分钟读完为目标。超出时优先删减与拆分,而不是指望读者自己筛选;辅助细节移入归档分组(如 `feasibility`、`version-log`),主路径只留决策所需内容。
|
|
@@ -115,12 +115,14 @@ You may still read the categorized example templates under `.claude/templates/is
|
|
|
115
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).
|
|
116
116
|
- Provide the full annotation meta tags so the portal right panel explains functionality, layout, fields, boundary cases, and exception flows.
|
|
117
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.
|
|
118
|
+
- Depict only the final system as it will ship: no demo-only buttons, explanatory text rows, or walkthrough-only jumps. Explanations belong in the `doc-*` annotation metas rendered in the portal right panel, never as on-screen prose.
|
|
119
|
+
- Declare the user story and business-flow step the page implements via `doc-stories` / `doc-refs`, so the prototype aligns bidirectionally with the PRD: every flow step has at least one page, and every page belongs to a flow step or story.
|
|
118
120
|
- 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.
|
|
119
121
|
- Assign a stable `data-uid` attribute to every interactive element, screen region, and WebView placeholder.
|
|
120
122
|
- Override `LincolnPrototype.data` in the page script for issue-specific mock data (user, org, webviews, settings, unread items).
|
|
121
123
|
|
|
122
124
|
7. Optionally create or update `{process_slug}/designs/<design_id>/prototype.pen` with Pencil tools if the PM explicitly asks for a Pencil prototype. If you use Pencil tools, call `get_editor_state(include_schema: true)` first and use `snapshot_layout` to check for clipping/overlap.
|
|
123
|
-
8. Update the root `{process_slug}/pages/docs/prd.html`
|
|
125
|
+
8. Update the「相关产物链接」section of the root `{process_slug}/pages/docs/prd.html` (PRD sections are matched by name — numbering is cosmetic) with the `ui-spec.html`, `fields.html`, and HTML prototype links. If the PRD already has an approved snapshot, warn the PM that changes require a version bump and re-freeze via `python scripts/lincoln_prd.py freeze`.
|
|
124
126
|
9. Ask the PM to open `{process_slug}/index.html` in a browser, toggle the theme switch in the macOS menubar, and review both light and dark renderings of each prototype page inside the portal.
|
|
125
127
|
10. When the PM confirms the prototype, add `<!-- prototype-status: approved -->` to `ui-spec.html`.
|
|
126
128
|
11. Run `python scripts/stage_loader.py --stage product-prototype --action record-artifacts`.
|
|
@@ -143,4 +145,5 @@ You may still read the categorized example templates under `.claude/templates/is
|
|
|
143
145
|
- Prototype links use relative paths so they work both inside the portal iframe and when opened standalone.
|
|
144
146
|
- Do not add collapse toggles or custom panel chrome to the portal; the right annotation panel is always visible.
|
|
145
147
|
- The system tray is portal-level chrome. Never redraw the tray inside an app prototype page with `.menubar`, `.tray-icon`, `.tray-panel`, `bindTray`, or `trayMenu`. Tray scenario pages must be thin controllers that post `lincoln-tray-state` messages to the portal.
|
|
148
|
+
- 原型即最终系统样貌:禁止仅用于演示的模拟按钮、屏内说明文字与演示跳转;解释一律走 `doc-*` 注释由门户右侧面板呈现;每个原型页面经 `doc-stories` / `doc-refs` 标注所属用户故事与业务流程步骤,与 PRD 文字双向对齐。
|
|
146
149
|
- After approval, tell the user to run: `claude plan-tdd-development <session_id> <design_id>`.
|
|
@@ -80,7 +80,17 @@ Produce a clear, agreed-upon `{process_slug}/pages/docs/requirements.html` and t
|
|
|
80
80
|
--markdown {process_slug}/pages/docs/user-stories.md
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
9.
|
|
83
|
+
9. 需求清晰度六问自检(Six-Question Gate)。起草原稿前逐项回答,答案落入 PRD 对应章节;任何一项答不出,先按 Human Interaction Rules 问人类 PM,禁止带着未决问题落笔:
|
|
84
|
+
|
|
85
|
+
| 六问 | 落笔位置 | 答不出时的动作 |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| 用户有哪些? | 用户故事 | 请 PM 补充分角色 |
|
|
88
|
+
| 场景是什么?何时触发、如何完成? | 业务流程图 | 与 PM 走查主流程 |
|
|
89
|
+
| 边界在哪里?明确不做什么 | 需求背景(非目标)+ 业务规则 | 请 PM 划定非目标 |
|
|
90
|
+
| 如何管异常?覆盖每个失败的系统行为 | 业务规则(异常处理) | 逐场景请 PM 裁决 |
|
|
91
|
+
| 如何体验好?质量与体验判据 | 非功能需求(体验要求) | 请 PM 给出体验判据 |
|
|
92
|
+
| 最终谁决策? | 版本说明(决策人) | 请 PM 指定决策人 |
|
|
93
|
+
10. Generate the root-level PRD at `{process_slug}/pages/docs/prd.html` using the Markdown-first renderer:
|
|
84
94
|
|
|
85
95
|
```bash
|
|
86
96
|
python scripts/lincoln_render.py \
|
|
@@ -90,25 +100,33 @@ Produce a clear, agreed-upon `{process_slug}/pages/docs/requirements.html` and t
|
|
|
90
100
|
--markdown {process_slug}/pages/docs/prd.md
|
|
91
101
|
```
|
|
92
102
|
|
|
93
|
-
Write `{process_slug}/pages/docs/prd.md`
|
|
94
|
-
|
|
95
|
-
- `## 1.
|
|
96
|
-
- `## 2.
|
|
97
|
-
- `## 3.
|
|
98
|
-
- `## 4.
|
|
99
|
-
- `## 5.
|
|
100
|
-
- `## 6.
|
|
101
|
-
- `## 7.
|
|
102
|
-
- `## 8.
|
|
103
|
-
- `## 9.
|
|
104
|
-
- `## 10.
|
|
103
|
+
Write `{process_slug}/pages/docs/prd.md` following this progressive skeleton. Keep all thirteen chapters in this order as the default narrative; you may insert additional business chapters inside the skeleton when this requirement's shape calls for it. Section headings are matched by name — numbering is cosmetic, not part of the contract:
|
|
104
|
+
|
|
105
|
+
- `## 1. 版本说明` — 当前版本、文档状态、决策人(最终谁拍板)。
|
|
106
|
+
- `## 2. 修订记录` — 版本/日期/作者/变更摘要 表格。
|
|
107
|
+
- `## 3. 功能列表` — 功能/优先级/状态/对应用户故事 表格。
|
|
108
|
+
- `## 4. 需求背景`
|
|
109
|
+
- `## 5. 用户故事`
|
|
110
|
+
- `## 6. 功能拆解`
|
|
111
|
+
- `## 7. 业务流程图` (use ` ```mermaid ` diagrams)
|
|
112
|
+
- `## 8. 验收标准`
|
|
113
|
+
- `## 9. 业务规则`(边界与异常处理)
|
|
114
|
+
- `## 10. 非功能需求`(含体验要求)
|
|
115
|
+
- `## 11. 关联系统/接口`
|
|
116
|
+
- `## 12. 相关产物链接`
|
|
117
|
+
- `## 13. 风险与开放问题`
|
|
118
|
+
|
|
119
|
+
PRD 正文禁则(读者是研发团队,文档只讲业务场景):
|
|
120
|
+
- 不写技术调研、技术方案、架构设计、接口设计、数据库设计等内容——这类内容只进 design 阶段维护的归档页 `feasibility.html`。
|
|
121
|
+
- 不写任何过程性提醒("待确认""待人类 PM 确认""TODO"、agent 注等)——疑问在对话中解决,解决后才落文档。
|
|
122
|
+
- 同一信息只用一种方式描述:文字、表格、mermaid 图组合使用,但不重复表达同一内容。
|
|
105
123
|
|
|
106
124
|
It must also carry:
|
|
107
125
|
- `<!-- version: v1.0 -->` marker (added automatically by the renderer from the Markdown file or `--version`).
|
|
108
126
|
- Meta tags: `doc-title`, `nav-group="Docs"`, `doc-version="v1.0"`, and a stable `doc-uid` (all injected by the renderer).
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
127
|
+
11. When the PM confirms, add an approval marker inside `requirements.html`: `<!-- status: approved -->`.
|
|
128
|
+
12. After human approval, run `python scripts/lincoln_prd.py freeze` to create the immutable snapshot `{process_slug}/pages/docs/snapshots/prd-v1.0.html`.
|
|
129
|
+
13. Run `python scripts/stage_loader.py --stage clarify --action record-artifacts` to persist the artifact paths and refresh `{process_slug}/assets/js/package-data.js`.
|
|
112
130
|
|
|
113
131
|
## Human Interaction Rules
|
|
114
132
|
|
|
@@ -122,6 +140,8 @@ Produce a clear, agreed-upon `{process_slug}/pages/docs/requirements.html` and t
|
|
|
122
140
|
- Every document page opens with `## 页面意图` (目标读者 + 本页回答什么问题) and `## 边界` (本页不覆盖什么 + 单一事实来源链接).
|
|
123
141
|
- 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
142
|
- 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.
|
|
143
|
+
- 过程性内容不进入任何页面:待确认事项、agent 提醒、对话记录只留在对话里,解决后才以结论形式落文档。
|
|
144
|
+
- 同一信息只描述一次:文字、表格、mermaid 图可以组合使用,但不得用多种方式重复表达同一内容;需要引用时链接到单一事实来源。
|
|
125
145
|
|
|
126
146
|
## 认知象限确认(Johari)
|
|
127
147
|
|
|
@@ -79,7 +79,7 @@ Create `{process_slug}/pages/docs/` HTML design documents with enough product, d
|
|
|
79
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.
|
|
80
80
|
5. Create the human-readable PM→UX handoff portal page at `{process_slug}/pages/docs/handoff-pm-to-ux-v1.0.html` and the narrative master handoff document at `{process_slug}/handoffs/pm-to-ux/master-handoff-pm-to-ux-v1.0.md`. These summarize core decisions, scope, open questions, and the context pack for the receiving UX Agent.
|
|
81
81
|
6. Keep all documents traceable to the approved requirement and transcript timestamps where available.
|
|
82
|
-
7. Update the root `{process_slug}/pages/docs/prd.html`
|
|
82
|
+
7. Update the「相关产物链接」section of the root `{process_slug}/pages/docs/prd.html` (PRD sections are matched by name — numbering is cosmetic) with links to the new design documents and handoff artifacts. If the PRD already has an approved snapshot (`pages/docs/snapshots/prd-v*.html`), warn the PM that any content change requires bumping the version marker and re-freezing via `python scripts/lincoln_prd.py freeze`.
|
|
83
83
|
8. Ask the PM to review `design-review.html` and linked docs (they can open `{process_slug}/index.html` in a browser).
|
|
84
84
|
9. When the PM confirms, add `<!-- status: approved -->` to `design-review.html`.
|
|
85
85
|
10. Run `python scripts/stage_loader.py --stage product-design-docs --action record-artifacts`.
|